自主协议库编译通过
This commit is contained in:
889
mmslib/util/cfg_util.c
Normal file
889
mmslib/util/cfg_util.c
Normal file
@@ -0,0 +1,889 @@
|
||||
/************************************************************************/
|
||||
/* SISCO SOFTWARE MODULE HEADER *****************************************/
|
||||
/************************************************************************/
|
||||
/* (c) Copyright Systems Integration Specialists Company, Inc., */
|
||||
/* 1991-2006, All Rights Reserved */
|
||||
/* */
|
||||
/* MODULE NAME : cfg_util.c */
|
||||
/* PRODUCT(S) : */
|
||||
/* */
|
||||
/* MODULE DESCRIPTION : */
|
||||
/* */
|
||||
/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */
|
||||
/* */
|
||||
/* MODIFICATION LOG : */
|
||||
/* Date Who Rev Comments */
|
||||
/* -------- --- ------ ------------------------------------------- */
|
||||
/* 02/07/06 EJV 18 cfg_special_char_str: added '$'. */
|
||||
/* 02/20/03 JRB 17 Del PSOS code. */
|
||||
/* 11/29/01 EJV 16 Del code for old LATT, XENIX, ultrix, RMX86. */
|
||||
/* Removed call to strcasecmp (sun) */
|
||||
/* 10/18/01 JRB 15 Add str_util.h (for strcmpi, etc. protos) */
|
||||
/* 01/19/01 EJV 14 Moved strcmpi,stricmp,strnicmp to str_util.c */
|
||||
/* 11/07/00 JRB 13 Del QNX from ifdef. It supports stricmp, etc.*/
|
||||
/* 04/28/00 JRB 12 Lint cleanup */
|
||||
/* 09/13/99 MDE 11 Added SD_CONST modifiers */
|
||||
/* 04/14/99 MDE 10 Replaced SYSTEM_SEL with compiler defines */
|
||||
/* 10/08/98 MDE 09 Migrated to updated SLOG interface */
|
||||
/* 08/24/98 EJV 08 Added __hpux to str* cmp functions */
|
||||
/* 08/06/98 JRB 07 Added cfg_get_octet_string function. */
|
||||
/* 06/15/98 MDE 06 Changes to allow compile under C++ */
|
||||
/* 05/22/98 EJV 05 added _AIX, sun, and __alpha to */
|
||||
/* stricmp, strcmpi, strnicmp functions */
|
||||
/* 04/03/98 RKR 04 added stricmp, strcmpi, strnicmp */
|
||||
/* 12/22/97 JRB 03 Clean up PSOS code. */
|
||||
/* 12/04/97 KCR 02 Added cfg_goto_keyword function */
|
||||
/* 11/05/97 MDE 01 Added VXWORKS support */
|
||||
/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */
|
||||
/* history. */
|
||||
/************************************************************************/
|
||||
|
||||
#include "glbtypes.h"
|
||||
#include "sysincs.h"
|
||||
#include "mem_chk.h"
|
||||
#include "cfg_util.h"
|
||||
#include "cfglog.h"
|
||||
#include "str_util.h"
|
||||
#include <ctype.h>
|
||||
|
||||
#include "slog.h"
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
/* #define DEBUG */
|
||||
|
||||
/************************************************************************/
|
||||
/* For debug version, use a static pointer to avoid duplication of */
|
||||
/* __FILE__ strings. */
|
||||
|
||||
#ifdef DEBUG_SISCO
|
||||
SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__;
|
||||
#endif
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
/* Externally visable variables */
|
||||
ST_CHAR *cfg_line_buf; /* File line read buffer */
|
||||
ST_INT cfg_curr_line; /* Current line number */
|
||||
ST_INT cfg_line_offset; /* Offset into cfg_line_buf */
|
||||
|
||||
ST_CHAR *cfg_special_char_str;
|
||||
ST_CHAR *cfg_end_of_rval_str;
|
||||
|
||||
ST_BOOLEAN config_stop;
|
||||
ST_RET config_err;
|
||||
ST_BOOLEAN config_eof;
|
||||
|
||||
ST_UINT cfg_log_mask;
|
||||
#ifdef DEBUG_SISCO
|
||||
SD_CONST ST_CHAR *SD_CONST _cfg_err_logstr = "CFG_LOG_ERR";
|
||||
SD_CONST ST_CHAR *SD_CONST _cfg_flow_logstr = "CFG_LOG_FLOW";
|
||||
#endif
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
/* Internal definitions */
|
||||
#define MAX_STRING_LEN 256
|
||||
#define LINE_BUF_SIZE 256
|
||||
|
||||
ST_INT cfg_max_string_len;
|
||||
ST_INT cfg_line_buf_size;
|
||||
ST_INT cfg_max_rval_len;
|
||||
|
||||
#define MAX_CONFIG_NEST 10
|
||||
|
||||
/* Internal variables */
|
||||
static ST_CHAR *cfg_string_buf;
|
||||
static struct cfg_kw_el *curr_table;
|
||||
static ST_BOOLEAN cfg_need_new_line;
|
||||
static FILE *config_fptr; /* Configuration file handle */
|
||||
|
||||
/* Keyword table stack control */
|
||||
static ST_INT num_on_stack;
|
||||
static struct cfg_kw_el **cfg_kw_stack;
|
||||
|
||||
|
||||
/* Internal funtions */
|
||||
static struct cfg_kw_el *cfg_lookup_keyword (struct cfg_kw_el *, ST_CHAR *);
|
||||
static ST_RET cfg_get_next_keyword (FILE *);
|
||||
static ST_CHAR *cfg_get_rval (ST_VOID);
|
||||
static ST_RET cfg_end_of_rval (ST_CHAR c);
|
||||
static ST_RET cfg_special_char (ST_CHAR c);
|
||||
|
||||
/************************************************************************/
|
||||
/************************************************************************/
|
||||
/************************************************************************/
|
||||
/* cfg_process_file */
|
||||
/************************************************************************/
|
||||
|
||||
ST_RET cfg_process_file (ST_CHAR *fileName, struct cfg_kw_el *root_kw_tbl)
|
||||
{
|
||||
ST_RET ret;
|
||||
|
||||
if (cfg_special_char_str == NULL)
|
||||
cfg_special_char_str = ":\\/-_ .{}[]<>@,()$";
|
||||
|
||||
if (cfg_end_of_rval_str == NULL)
|
||||
cfg_end_of_rval_str = "|";
|
||||
|
||||
if (cfg_max_string_len == 0)
|
||||
cfg_max_string_len = MAX_STRING_LEN;
|
||||
|
||||
if (cfg_line_buf_size == 0)
|
||||
cfg_line_buf_size = LINE_BUF_SIZE;
|
||||
|
||||
if (cfg_max_rval_len == 0)
|
||||
cfg_max_rval_len = MAX_RVAL_LEN;
|
||||
|
||||
/* Open the configuration file */
|
||||
if ((config_fptr = fopen (fileName,"r"))==NULL)
|
||||
{
|
||||
CFG_LOG_ERR1 ("Config File (%s) Open Error",fileName);
|
||||
return (SD_FAILURE);
|
||||
}
|
||||
|
||||
CFG_LOG_FLOW1 ("Config File (%s) Opened OK",fileName);
|
||||
|
||||
/* If a previous call to the function ended in error there may be some */
|
||||
/* old keyword table pushed on the stack. The keywords table stack is */
|
||||
/* initialized to zero to process the current configuration file */
|
||||
|
||||
num_on_stack = 0;
|
||||
|
||||
/* Allocate required buffers */
|
||||
|
||||
cfg_line_buf = (ST_CHAR *) chk_calloc (cfg_line_buf_size,
|
||||
sizeof(ST_CHAR));
|
||||
cfg_string_buf = (ST_CHAR *) chk_calloc (cfg_max_string_len+1,
|
||||
sizeof(ST_CHAR));
|
||||
cfg_kw_stack = (struct cfg_kw_el **) chk_calloc (MAX_CONFIG_NEST,
|
||||
sizeof (struct cfg_kw_el *));
|
||||
|
||||
/* Start with the ROOT keyword table */
|
||||
|
||||
cfg_tbl_push (root_kw_tbl);
|
||||
|
||||
/* Process the configuration file */
|
||||
|
||||
cfg_need_new_line = SD_TRUE;
|
||||
cfg_line_offset = 0;
|
||||
cfg_curr_line = 0;
|
||||
config_err = SD_FALSE;
|
||||
config_stop = SD_FALSE;
|
||||
config_eof = SD_FAILURE;
|
||||
|
||||
/* Process keywords while not done and no error is detected */
|
||||
|
||||
while ( ( config_stop == SD_FALSE ) && ( config_err == SD_FALSE ) )
|
||||
{
|
||||
if ( cfg_get_next_keyword( config_fptr ) )
|
||||
break;
|
||||
}
|
||||
|
||||
/* All done, see if it went OK */
|
||||
|
||||
if ( ( config_stop == SD_TRUE ) && ( config_err == SD_FALSE ) )
|
||||
{
|
||||
CFG_LOG_CFLOW0 ("Config File Read OK");
|
||||
ret = SD_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
CFG_LOG_ERR3 ("Config Error, Line %d, \"%s\", Column %d",
|
||||
cfg_curr_line, cfg_line_buf, cfg_line_offset);
|
||||
|
||||
ret = SD_FAILURE;
|
||||
}
|
||||
|
||||
/* Free allocated buffers */
|
||||
chk_free (cfg_line_buf);
|
||||
chk_free (cfg_string_buf);
|
||||
chk_free (cfg_kw_stack);
|
||||
|
||||
/* Close the file so the calling program can reopen it if necessary. */
|
||||
|
||||
fclose( config_fptr );
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/************************************************************************/
|
||||
/* cfg_get_next_keyword */
|
||||
/************************************************************************/
|
||||
/* This function is used to get the next keyword */
|
||||
|
||||
static ST_RET cfg_get_next_keyword (FILE *fptr)
|
||||
{
|
||||
struct cfg_kw_el *ptr;
|
||||
ST_INT i;
|
||||
ST_CHAR c;
|
||||
|
||||
/* Look for 'yyy =' string */
|
||||
|
||||
while (SD_TRUE) /* While looking for the next word */
|
||||
{
|
||||
if (cfg_need_new_line)
|
||||
{
|
||||
if ( fgets( cfg_line_buf, cfg_line_buf_size - 1, fptr ) == NULL )
|
||||
{
|
||||
CFG_LOG_CFLOW0 ("No More Keywords : End Of File");
|
||||
|
||||
/* The following piece of logic exists to allow the state functions to */
|
||||
/* declare when it is ok for the file to be out of keywords. If a user */
|
||||
/* state function set 'config_eof == SD_SUCCESS' then config_stop is set */
|
||||
/* to true when ENDFILE is encountered. */
|
||||
|
||||
if ( config_eof == SD_SUCCESS )
|
||||
{
|
||||
config_stop = SD_TRUE;
|
||||
}
|
||||
return( SD_FAILURE );
|
||||
}
|
||||
|
||||
/* Wack the \n */
|
||||
for (i = 0; i < cfg_line_buf_size; ++i)
|
||||
{
|
||||
if (cfg_line_buf[i] == '\n')
|
||||
{
|
||||
cfg_line_buf[i] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
cfg_line_offset = 0; /* Offset is 0 for new line */
|
||||
++cfg_curr_line;
|
||||
if (cfg_line_buf[0] == '#')
|
||||
continue; /* Discard comment lines */
|
||||
|
||||
cfg_need_new_line = SD_FALSE; /* Got a new line */
|
||||
}
|
||||
|
||||
/* We now have a line to work on, with cfg_line_offset the 1st char */
|
||||
/* Extract the keyword from the string (alpha numeric characters) */
|
||||
/* '=' means end of rval */
|
||||
/* 0 is end of line */
|
||||
|
||||
i = 0;
|
||||
c = cfg_line_buf[cfg_line_offset++];
|
||||
while (c && c != '#' && /* End of line or comment start */
|
||||
c != '=' && /* end of keyword */
|
||||
c != '|' &&
|
||||
i < cfg_max_string_len)
|
||||
{
|
||||
if (c != ' ' && c != '\t') /* Ignore spaces and tabs */
|
||||
{
|
||||
cfg_string_buf[i] = c;
|
||||
++i;
|
||||
}
|
||||
c = cfg_line_buf[cfg_line_offset++];
|
||||
}
|
||||
|
||||
if (i >= cfg_max_string_len)
|
||||
{
|
||||
CFG_LOG_ERR1 ("Error : Line %d too long", cfg_curr_line);
|
||||
return (SD_FAILURE);
|
||||
}
|
||||
|
||||
if (c == '#' || !c) /* See if we need a new line next time */
|
||||
cfg_need_new_line = SD_TRUE;
|
||||
|
||||
/* i is the index to the char position that terminated the scan */
|
||||
cfg_string_buf[i]=0x0; /* NULL terminate the keyword */
|
||||
|
||||
/* if we have a keyword, then search look it up in the currently active */
|
||||
/* keyword table and execute the selected function */
|
||||
|
||||
if (strlen (cfg_string_buf))
|
||||
{ /* Find the keyword */
|
||||
if ((ptr = cfg_lookup_keyword (curr_table, cfg_string_buf)) != NULL)
|
||||
{
|
||||
CFG_LOG_CFLOW1 ("Keyword : %s",cfg_string_buf);
|
||||
(*ptr->extract)();
|
||||
break;
|
||||
}
|
||||
else /* invalid keyword */
|
||||
{
|
||||
CFG_LOG_ERR1 ("Unknown Keyword : %s",cfg_string_buf);
|
||||
return (SD_FAILURE);
|
||||
}
|
||||
}
|
||||
} /* While SD_TRUE */
|
||||
|
||||
return(SD_SUCCESS);
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* cfg_get_rval() */
|
||||
/************************************************************************/
|
||||
|
||||
static ST_CHAR *cfg_get_rval(ST_VOID)
|
||||
{
|
||||
ST_INT i;
|
||||
ST_CHAR c;
|
||||
|
||||
cfg_string_buf[0]=0x0;
|
||||
|
||||
/* Now get the rval (value). */
|
||||
/* search for 0 to note end of line */
|
||||
|
||||
i = 0;
|
||||
c = cfg_line_buf[cfg_line_offset++];
|
||||
|
||||
/* First strip leading white space (' ', '\t') */
|
||||
while (c == ' ' || c == '\t')
|
||||
c = cfg_line_buf[cfg_line_offset++];
|
||||
|
||||
while (c &&
|
||||
c != '#' &&
|
||||
!cfg_end_of_rval (c) &&
|
||||
i < cfg_max_rval_len-1)
|
||||
{
|
||||
if (isalnum (c) || cfg_special_char (c))
|
||||
{
|
||||
cfg_string_buf[i] = c;
|
||||
++i;
|
||||
}
|
||||
c = cfg_line_buf[cfg_line_offset++];
|
||||
}
|
||||
|
||||
if (c == '#' || !c) /* See if we need a new line next time */
|
||||
cfg_need_new_line = SD_TRUE;
|
||||
|
||||
/* Strip trailing spaces and tabs */
|
||||
while (i && (cfg_string_buf[i-1] == ' ' ||
|
||||
cfg_string_buf[i-1] == '\t'))
|
||||
i--;
|
||||
|
||||
/* Null terminate the string */
|
||||
cfg_string_buf[i] = 0x0;
|
||||
|
||||
if (!strlen (cfg_string_buf))
|
||||
{
|
||||
CFG_LOG_ERR2 ("Bad rval, line #%d \"%s\"",cfg_curr_line,cfg_line_buf);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
CFG_LOG_CFLOW1 ("Rval : '%s'",cfg_string_buf);
|
||||
return (cfg_string_buf);
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* cfg_lookup_keyword */
|
||||
/************************************************************************/
|
||||
|
||||
static struct cfg_kw_el *cfg_lookup_keyword(struct cfg_kw_el *tbl_ptr,
|
||||
ST_CHAR *name)
|
||||
{
|
||||
ST_INT i;
|
||||
struct cfg_kw_el *ret = NULL;
|
||||
|
||||
for (i = 0; i < MAX_NUM_KEYWORDS; ++i)
|
||||
{
|
||||
if (tbl_ptr[i].extract == NULL) /* End of table */
|
||||
break;
|
||||
else if (!strcmpi (name, tbl_ptr[i].name))
|
||||
{ /* we have a match */
|
||||
if (tbl_ptr[i].valid !=NULL) /* Want to validate? */
|
||||
{
|
||||
if ((*tbl_ptr[i].valid)())
|
||||
ret = &tbl_ptr[i];
|
||||
}
|
||||
else
|
||||
ret = &tbl_ptr[i];
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* cfg_end_of_rval */
|
||||
/************************************************************************/
|
||||
/* CONFIG calls back to this function while looking the rval over */
|
||||
/* If this function returns SD_TRUE, CONFIG will assume that the */
|
||||
/* character is a keyword/rval pair seperator */
|
||||
/* Used to allow multiple pairs per line */
|
||||
|
||||
|
||||
static ST_RET cfg_end_of_rval (ST_CHAR c)
|
||||
{
|
||||
ST_INT i;
|
||||
ST_INT str_len;
|
||||
|
||||
str_len = strlen (cfg_end_of_rval_str);
|
||||
for (i = 0; i < str_len; ++i)
|
||||
{
|
||||
if (c == cfg_end_of_rval_str[i])
|
||||
return (SD_TRUE);
|
||||
}
|
||||
return (SD_FALSE);
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* cfg_special_char */
|
||||
/************************************************************************/
|
||||
|
||||
static ST_RET cfg_special_char (ST_CHAR c)
|
||||
{
|
||||
ST_INT i;
|
||||
ST_INT str_len;
|
||||
|
||||
str_len = strlen (cfg_special_char_str);
|
||||
for (i = 0; i < str_len; ++i)
|
||||
{
|
||||
if (c == cfg_special_char_str[i])
|
||||
return (SD_TRUE);
|
||||
}
|
||||
|
||||
return (SD_FALSE);
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/************************************************************************/
|
||||
/************************************************************************/
|
||||
/* cfg_tbl_push (new_table) */
|
||||
/************************************************************************/
|
||||
|
||||
ST_RET cfg_tbl_push (struct cfg_kw_el *new_table)
|
||||
{
|
||||
if (num_on_stack >= MAX_CONFIG_NEST)
|
||||
{
|
||||
CFG_LOG_ERR0 ("Too many pushes - configuration nesting exceeded");
|
||||
config_stop = SD_TRUE;
|
||||
config_err = CFG_UTIL_ERR;
|
||||
return (SD_FAILURE);
|
||||
}
|
||||
|
||||
cfg_kw_stack[num_on_stack] = new_table;
|
||||
++num_on_stack;
|
||||
curr_table = new_table;
|
||||
return (SD_SUCCESS);
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* cfg_tbl_pop (num_to_pop) */
|
||||
/************************************************************************/
|
||||
|
||||
ST_RET cfg_tbl_pop (ST_INT num_to_pop)
|
||||
{
|
||||
if ((num_on_stack-num_to_pop-1)<0)
|
||||
{
|
||||
CFG_LOG_ERR0 ("Too many pops off configuration stack");
|
||||
config_stop = SD_TRUE;
|
||||
config_err = CFG_UTIL_ERR;
|
||||
return (SD_FAILURE);
|
||||
}
|
||||
num_on_stack -= num_to_pop;
|
||||
curr_table = cfg_kw_stack[num_on_stack-1];
|
||||
return (SD_SUCCESS);
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* cfg_get_short */
|
||||
/************************************************************************/
|
||||
|
||||
ST_RET cfg_get_short (ST_INT16 *out_ptr)
|
||||
{
|
||||
ST_INT d;
|
||||
ST_INT16 ret;
|
||||
|
||||
ret = cfg_get_value ("%d", &d);
|
||||
if (!ret)
|
||||
*out_ptr = (ST_INT16) d;
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* cfg_get_ushort */
|
||||
/************************************************************************/
|
||||
|
||||
ST_RET cfg_get_ushort (ST_UINT16 *out_ptr)
|
||||
{
|
||||
ST_UINT d;
|
||||
ST_RET ret;
|
||||
|
||||
ret = cfg_get_value ("%u", &d);
|
||||
if (!ret)
|
||||
*out_ptr = (ST_UINT16) d;
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* cfg_get_int */
|
||||
/************************************************************************/
|
||||
|
||||
ST_RET cfg_get_int (ST_INT *out_ptr)
|
||||
{
|
||||
ST_INT d;
|
||||
ST_RET ret;
|
||||
|
||||
ret = cfg_get_value ("%d", &d);
|
||||
if (!ret)
|
||||
*out_ptr = d;
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* cfg_get_uint */
|
||||
/************************************************************************/
|
||||
|
||||
ST_RET cfg_get_uint (ST_UINT *out_ptr)
|
||||
{
|
||||
ST_UINT d;
|
||||
ST_RET ret;
|
||||
|
||||
ret = cfg_get_value ("%u", &d);
|
||||
if (!ret)
|
||||
*out_ptr = d;
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* cfg_get_long */
|
||||
/************************************************************************/
|
||||
|
||||
ST_RET cfg_get_long (ST_LONG *out_ptr)
|
||||
{
|
||||
return (cfg_get_value ("%ld", out_ptr));
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* cfg_get_ulong */
|
||||
/************************************************************************/
|
||||
|
||||
ST_RET cfg_get_ulong (ST_ULONG *out_ptr)
|
||||
{
|
||||
return (cfg_get_value ("%lu", out_ptr));
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* cfg_get_double */
|
||||
/************************************************************************/
|
||||
|
||||
ST_RET cfg_get_double (ST_DOUBLE *out_ptr)
|
||||
{
|
||||
return (cfg_get_value ("%lf", out_ptr));
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* cfg_get_hex_ushort */
|
||||
/************************************************************************/
|
||||
|
||||
ST_RET cfg_get_hex_ushort (ST_UINT16 *out_ptr)
|
||||
{
|
||||
ST_UINT d;
|
||||
ST_RET ret;
|
||||
|
||||
ret = cfg_get_value ("%x", &d);
|
||||
if (!ret)
|
||||
*out_ptr = (ST_UINT16) d;
|
||||
return (ret);
|
||||
|
||||
/* return (cfg_get_value ("%x", out_ptr)); */
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* cfg_get_hex_uint */
|
||||
/************************************************************************/
|
||||
|
||||
ST_RET cfg_get_hex_uint (ST_UINT *out_ptr)
|
||||
{
|
||||
ST_UINT d;
|
||||
ST_RET ret;
|
||||
|
||||
ret = cfg_get_value ("%x", &d);
|
||||
if (!ret)
|
||||
*out_ptr = d;
|
||||
return (ret);
|
||||
|
||||
/* return (cfg_get_value ("%x", out_ptr)); */
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* cfg_get_hex_ulong */
|
||||
/************************************************************************/
|
||||
|
||||
ST_RET cfg_get_hex_ulong (ST_ULONG *out_ptr)
|
||||
{
|
||||
return (cfg_get_value ("%lx", out_ptr));
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* cfg_get_value */
|
||||
/************************************************************************/
|
||||
|
||||
ST_RET cfg_get_value (ST_CHAR *format_string, ST_VOID *out_ptr)
|
||||
{
|
||||
ST_CHAR *rval;
|
||||
|
||||
rval = cfg_get_rval (); /* get the rvalue string */
|
||||
if (!rval)
|
||||
{
|
||||
config_err = CFG_GET_RVAL_ERR;
|
||||
CFG_LOG_ERR0 ("Get Rval Error");
|
||||
}
|
||||
else
|
||||
{ /* Convert to desired data format*/
|
||||
if (!sscanf (rval,format_string,out_ptr))
|
||||
{
|
||||
config_err = CFG_CONVERT_ERR;
|
||||
CFG_LOG_ERR0 ("Data Conversion Error");
|
||||
}
|
||||
}
|
||||
|
||||
if (config_err) /* if error detected ... */
|
||||
{
|
||||
config_stop = SD_TRUE;
|
||||
return (SD_FAILURE);
|
||||
}
|
||||
|
||||
return (SD_SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/************************************************************************/
|
||||
/* *cfg_get_alloc_string */
|
||||
/************************************************************************/
|
||||
|
||||
ST_CHAR *cfg_get_alloc_string (ST_VOID)
|
||||
{
|
||||
ST_CHAR *ret_ptr;
|
||||
ST_CHAR *rval;
|
||||
|
||||
rval = cfg_get_rval (); /* get the rvalue string */
|
||||
if (!rval)
|
||||
{
|
||||
config_stop = SD_TRUE;
|
||||
config_err = CFG_GET_RVAL_ERR;
|
||||
CFG_LOG_ERR0 ("Get Rval Error");
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/* allocate storage for string */
|
||||
ret_ptr = (ST_CHAR *) chk_calloc (1,strlen (rval) +1);
|
||||
strcpy (ret_ptr,rval);
|
||||
return (ret_ptr);
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* *cfg_get_string_ptr */
|
||||
/************************************************************************/
|
||||
|
||||
ST_CHAR *cfg_get_string_ptr (ST_VOID)
|
||||
{
|
||||
ST_CHAR *rval;
|
||||
|
||||
rval = cfg_get_rval (); /* get the rvalue string */
|
||||
if (!rval)
|
||||
{
|
||||
config_stop = SD_TRUE;
|
||||
config_err = CFG_GET_RVAL_ERR;
|
||||
CFG_LOG_ERR0 ("Get Rval Error");
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
return (rval);
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* cfg_get_octet_string */
|
||||
/************************************************************************/
|
||||
|
||||
ST_RET cfg_get_octet_string (ST_UCHAR *ostr, /* ptr to user's ostr */
|
||||
ST_UINT *len_out_ptr, /* addr of len var to be set */
|
||||
ST_UINT len_max) /* maximum len to allow. */
|
||||
{
|
||||
ST_UINT j;
|
||||
ST_INT digit;
|
||||
ST_BOOLEAN nibble; /* SD_TRUE if nibble read, SD_FALSE if whole byte read*/
|
||||
ST_CHAR *rval;
|
||||
|
||||
rval = cfg_get_rval (); /* get the rvalue string */
|
||||
if (!rval)
|
||||
{
|
||||
config_stop = SD_TRUE;
|
||||
config_err = CFG_GET_RVAL_ERR;
|
||||
CFG_LOG_ERR0 ("Get Rval Error");
|
||||
return (SD_FAILURE);
|
||||
}
|
||||
|
||||
j = 0;
|
||||
nibble = SD_FALSE;
|
||||
while (isxdigit (*rval)) /* get hex number */
|
||||
{
|
||||
if (j >= len_max)
|
||||
return (SD_FAILURE); /* Selector longer than allowed */
|
||||
|
||||
digit = *rval++; /* separate nibbles */
|
||||
digit = isdigit (digit) ? digit - '0' : 10 + (toupper (digit) - 'A');
|
||||
if (nibble)
|
||||
{
|
||||
nibble = SD_FALSE;
|
||||
ostr[j] = (ostr[j] | (ST_UCHAR) digit); /* set low */
|
||||
j++;
|
||||
|
||||
while (isspace (*rval) && *rval != '\n')
|
||||
++rval;
|
||||
}
|
||||
else
|
||||
{
|
||||
nibble = SD_TRUE;
|
||||
ostr[j] = (ST_UCHAR) digit << 4; /* set high byte */
|
||||
}
|
||||
}
|
||||
|
||||
if (nibble)
|
||||
{ /* Only got half of byte. */
|
||||
config_stop = SD_TRUE;
|
||||
config_err = CFG_CONVERT_ERR;
|
||||
CFG_LOG_ERR0 ("Incomplete byte in Octet string");
|
||||
return (SD_FAILURE);
|
||||
}
|
||||
|
||||
/* set selector length */
|
||||
*len_out_ptr = j;
|
||||
return (SD_SUCCESS);
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* cfg_set_config_err */
|
||||
/************************************************************************/
|
||||
|
||||
ST_VOID cfg_set_config_err(ST_VOID)
|
||||
{
|
||||
config_err = SD_TRUE;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* cfg_set_endfile_ok */
|
||||
/************************************************************************/
|
||||
|
||||
ST_VOID cfg_set_endfile_ok(ST_VOID)
|
||||
{
|
||||
config_eof = SD_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/************************************************************************/
|
||||
/* cfg_goto_keyword */
|
||||
/************************************************************************/
|
||||
/* This function is used to skip over a section to the specified keyword*/
|
||||
|
||||
ST_RET cfg_goto_keyword (ST_CHAR *keyword)
|
||||
{
|
||||
ST_INT i, cfgStringLen, keywordLen;
|
||||
ST_CHAR c;
|
||||
|
||||
/* Look for 'yyy =' string */
|
||||
|
||||
keywordLen = strlen (keyword);
|
||||
while (SD_TRUE) /* While looking for the specified word */
|
||||
{
|
||||
if (cfg_need_new_line)
|
||||
{
|
||||
if ( fgets( cfg_line_buf, cfg_line_buf_size - 1, config_fptr ) == NULL )
|
||||
{
|
||||
CFG_LOG_CFLOW0 ("No More Keywords : End Of File");
|
||||
|
||||
/* The following piece of logic exists to allow the state functions to */
|
||||
/* declare when it is ok for the file to be out of keywords. If a user */
|
||||
/* state function set 'config_eof == SD_SUCCESS' then config_stop is set */
|
||||
/* to true when ENDFILE is encountered. */
|
||||
|
||||
if ( config_eof == SD_SUCCESS )
|
||||
{
|
||||
config_stop = SD_TRUE;
|
||||
}
|
||||
return( SD_FAILURE );
|
||||
}
|
||||
|
||||
/* Wack the \n */
|
||||
for (i = 0; i < cfg_line_buf_size; ++i)
|
||||
{
|
||||
if (cfg_line_buf[i] == '\n')
|
||||
{
|
||||
cfg_line_buf[i] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
cfg_line_offset = 0; /* Offset is 0 for new line */
|
||||
++cfg_curr_line;
|
||||
if (cfg_line_buf[0] == '#')
|
||||
continue; /* Discard comment lines */
|
||||
|
||||
cfg_need_new_line = SD_FALSE; /* Got a new line */
|
||||
}
|
||||
|
||||
/* We now have a line to work on, with cfg_line_offset the 1st char */
|
||||
/* Extract the keyword from the string (alpha numeric characters) */
|
||||
/* '=' means end of rval */
|
||||
/* 0 is end of line */
|
||||
|
||||
i = 0;
|
||||
c = cfg_line_buf[cfg_line_offset++];
|
||||
while (c && c != '#' && /* End of line or comment start */
|
||||
c != '=' && /* end of keyword */
|
||||
c != '|' &&
|
||||
i < cfg_max_string_len)
|
||||
{
|
||||
if (c != ' ' && c != '\t') /* Ignore spaces and tabs */
|
||||
{
|
||||
cfg_string_buf[i] = c;
|
||||
++i;
|
||||
}
|
||||
c = cfg_line_buf[cfg_line_offset++];
|
||||
}
|
||||
|
||||
if (i >= cfg_max_string_len)
|
||||
{
|
||||
CFG_LOG_ERR1 ("Error : Line %d too long", cfg_curr_line);
|
||||
return (SD_FAILURE);
|
||||
}
|
||||
|
||||
if (c == '#' || !c) /* See if we need a new line next time */
|
||||
cfg_need_new_line = SD_TRUE;
|
||||
|
||||
/* i is the index to the char position that terminated the scan */
|
||||
cfg_string_buf[i]=0x0; /* NULL terminate the keyword */
|
||||
|
||||
/* if we have a keyword, then search look it up in the currently active */
|
||||
/* keyword table and execute the selected function */
|
||||
|
||||
if ((cfgStringLen = strlen (cfg_string_buf)) > 0)
|
||||
{ /* Find the keyword */
|
||||
if ((cfgStringLen == keywordLen) && !strcmpi (keyword, cfg_string_buf))
|
||||
break;
|
||||
else /* keyword not found */
|
||||
cfg_need_new_line = SD_TRUE;
|
||||
}
|
||||
} /* While SD_TRUE */
|
||||
|
||||
return(SD_SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
464
mmslib/util/genlists.c
Normal file
464
mmslib/util/genlists.c
Normal file
@@ -0,0 +1,464 @@
|
||||
/************************************************************************/
|
||||
/* SISCO SOFTWARE MODULE HEADER *****************************************/
|
||||
/************************************************************************/
|
||||
/* (c) Copyright Systems Integration Specialists Company, Inc., */
|
||||
/* 1986-2005 All Rights Reserved */
|
||||
/* */
|
||||
/* MODULE NAME : gen_list.c */
|
||||
/* PRODUCT(S) : general list handling functions */
|
||||
/* */
|
||||
/* MODULE DESCRIPTION : */
|
||||
/* This module contains generic que manipulation routines */
|
||||
/* */
|
||||
/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */
|
||||
/* */
|
||||
/* MODIFICATION LOG : */
|
||||
/* Date Who Rev Comments */
|
||||
/* -------- --- ------ ------------------------------------------- */
|
||||
/* 10/04/07 MDE 07 Tweaked LOGCFG_VALUE_GROUP/LOGCFGX_VALUE_MAP */
|
||||
/* 06/30/05 EJV 06 Add genlistDebugMaps, genlistDebugMapCtrl */
|
||||
/* for parsing logcfg.xml */
|
||||
/* 04/08/04 JRB 05 list_find_last: if head=NULL, don't log. */
|
||||
/* 12/12/02 JRB 04 list_get_first/last: if *head==NULL, return */
|
||||
/* NULL & do NOT log a message. */
|
||||
/* 11/21/01 MDE 03 Changed logging to use SLOGALWAYS */
|
||||
/* 10/09/98 JRB 02 Add list_find_prev, list_find_last. */
|
||||
/* 06/15/98 MDE 01 Changes to allow compile under C++ */
|
||||
/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */
|
||||
/* history. */
|
||||
/************************************************************************/
|
||||
|
||||
#include "glbtypes.h"
|
||||
#include "sysincs.h"
|
||||
#define I_AM_THE_TRUE_GEN_LIST
|
||||
#include "gen_list.h"
|
||||
#include "slog.h"
|
||||
|
||||
/************************************************************************/
|
||||
/************************************************************************/
|
||||
/* For debug version, use a static pointer to avoid duplication of */
|
||||
/* __FILE__ strings. */
|
||||
/************************************************************************/
|
||||
|
||||
#ifdef DEBUG_SISCO
|
||||
static ST_CHAR *thisFileName = __FILE__;
|
||||
#endif
|
||||
|
||||
/************************************************************************/
|
||||
/* The variable below is used in selecting generic queuing debug */
|
||||
/* checking. When this variable is set to SD_TRUE all data strucutres */
|
||||
/* using the list manipulation primitives will under go this checking */
|
||||
|
||||
ST_BOOLEAN list_debug_sel;
|
||||
|
||||
#ifdef DEBUG_SISCO
|
||||
LOGCFGX_VALUE_MAP genlistDebugMaps[] =
|
||||
{
|
||||
/* Memory debugging */
|
||||
{"ListDebugSel", 0, &list_debug_sel, _LOGCFG_DATATYPE_BOOLEAN, NULL, NULL}
|
||||
};
|
||||
|
||||
LOGCFG_VALUE_GROUP genlistDebugMapCtrl =
|
||||
{
|
||||
{NULL,NULL},
|
||||
"GenListLogMasks", /* Parent Tag */
|
||||
sizeof(genlistDebugMaps)/sizeof(LOGCFGX_VALUE_MAP),
|
||||
genlistDebugMaps
|
||||
};
|
||||
#endif /* DEBUG_SISCO */
|
||||
|
||||
/************************************************************************/
|
||||
/* list_unlink */
|
||||
/* Primitive to unlink a node out of a circular double linked list */
|
||||
/************************************************************************/
|
||||
|
||||
ST_RET list_unlink (DBL_LNK **list_head_ptr, DBL_LNK *node_ptr)
|
||||
{
|
||||
#ifdef DEBUG_SISCO
|
||||
if (*list_head_ptr == NULL)
|
||||
{
|
||||
SLOGALWAYS0 ("GENLIST: ATTEMPT TO UNLINK A NODE FROM A NULL LIST");
|
||||
return (SD_FAILURE);
|
||||
}
|
||||
|
||||
if (node_ptr == NULL)
|
||||
{
|
||||
SLOGALWAYS0 ("GENLIST: ATTEMPT TO UNLINK A NULL ADDRESS FROM A LIST");
|
||||
return (SD_FAILURE);
|
||||
}
|
||||
|
||||
if (list_debug_sel == SD_TRUE)
|
||||
{
|
||||
if (list_find_node (*list_head_ptr, node_ptr) == SD_FAILURE)
|
||||
{
|
||||
SLOGALWAYS0 ("GENLIST: NODE NOT FOUND IN LIST");
|
||||
return (SD_FAILURE);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* If list checking is enabled and we get to here we have valid */
|
||||
/* arguments and a valid list */
|
||||
|
||||
if ((node_ptr -> next == *list_head_ptr) &&
|
||||
(node_ptr == *list_head_ptr)) /* only node in list? */
|
||||
{
|
||||
*list_head_ptr = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (node_ptr == *list_head_ptr) /* first node in a multi*/
|
||||
*list_head_ptr = node_ptr->next; /* node list */
|
||||
(node_ptr->next)->prev = node_ptr->prev; /* link cur next to prev*/
|
||||
(node_ptr->prev)->next = node_ptr->next; /* link cur prev to next*/
|
||||
}
|
||||
return (SD_SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* list_add_first */
|
||||
/* Primitive to add a node as the first node of a circular double */
|
||||
/* linked list */
|
||||
/************************************************************************/
|
||||
|
||||
ST_RET list_add_first (DBL_LNK **list_head_ptr, DBL_LNK *node_ptr)
|
||||
{
|
||||
DBL_LNK *list_tail_ptr;
|
||||
|
||||
#ifdef DEBUG_SISCO
|
||||
if (node_ptr == NULL)
|
||||
{
|
||||
SLOGALWAYS0 ("GENLIST: ATTEMPT TO ADD A NULL ADDRESS TO A LIST");
|
||||
return (SD_FAILURE);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* If list checking is enabled and we get to here we have valid */
|
||||
/* arguments */
|
||||
|
||||
if (*list_head_ptr == NULL) /* will this be the only node? */
|
||||
{
|
||||
node_ptr->next = node_ptr;
|
||||
node_ptr->prev = node_ptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
list_tail_ptr = (*list_head_ptr)->prev;
|
||||
node_ptr->next = *list_head_ptr;
|
||||
node_ptr->prev = list_tail_ptr;
|
||||
list_tail_ptr->next = node_ptr;
|
||||
(*list_head_ptr)->prev = node_ptr;
|
||||
}
|
||||
*list_head_ptr = node_ptr; /* assign the new head of list */
|
||||
return (SD_SUCCESS);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* list_add_last */
|
||||
/* Primitive to add a node as the last node of a circular double */
|
||||
/* linked list */
|
||||
/************************************************************************/
|
||||
|
||||
ST_RET list_add_last (DBL_LNK **list_head_ptr, DBL_LNK *node_ptr)
|
||||
{
|
||||
DBL_LNK *list_tail_ptr;
|
||||
|
||||
#ifdef DEBUG_SISCO
|
||||
if (node_ptr == NULL)
|
||||
{
|
||||
SLOGALWAYS0 ("GENLIST: ATTEMPT TO ADD A NULL ADDRESS TO A LIST");
|
||||
return (SD_FAILURE);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* If list checking is enabled and we get to here we have valid */
|
||||
/* arguments */
|
||||
|
||||
if (*list_head_ptr == NULL) /* will this be the only node? */
|
||||
{
|
||||
node_ptr->next = node_ptr;
|
||||
node_ptr->prev = node_ptr;
|
||||
*list_head_ptr = node_ptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
list_tail_ptr = (*list_head_ptr)->prev;
|
||||
list_tail_ptr->next = node_ptr;
|
||||
node_ptr->prev = list_tail_ptr;
|
||||
node_ptr->next = *list_head_ptr;
|
||||
(*list_head_ptr)->prev = node_ptr;
|
||||
}
|
||||
return (SD_SUCCESS);
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* list_get_first */
|
||||
/* Primitive to unlink the first node out of the list and return it's */
|
||||
/* address */
|
||||
/************************************************************************/
|
||||
|
||||
#ifndef FASTLIST
|
||||
|
||||
ST_VOID *list_get_first (DBL_LNK **list_head_ptr)
|
||||
{
|
||||
DBL_LNK *node_ptr;
|
||||
|
||||
if (*list_head_ptr == NULL)
|
||||
return (NULL);
|
||||
|
||||
node_ptr = *list_head_ptr;
|
||||
list_unlink (list_head_ptr, node_ptr);
|
||||
return (node_ptr);
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
/************************************************************************/
|
||||
/* list_get_last */
|
||||
/* Primitive to unlink the last node out of the list and return it's */
|
||||
/* address */
|
||||
/************************************************************************/
|
||||
|
||||
|
||||
ST_VOID *list_get_last (DBL_LNK **list_head_ptr)
|
||||
{
|
||||
DBL_LNK *node_ptr;
|
||||
|
||||
if (*list_head_ptr == NULL)
|
||||
return (NULL);
|
||||
|
||||
node_ptr = *list_head_ptr;
|
||||
node_ptr = node_ptr->prev;
|
||||
list_unlink (list_head_ptr, node_ptr);
|
||||
return (node_ptr);
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* list_move_to_first */
|
||||
/* Primitive to unlink the first node out of the list and return it's */
|
||||
/* address */
|
||||
/************************************************************************/
|
||||
|
||||
ST_RET list_move_to_first (DBL_LNK **src_list_head_ptr,
|
||||
DBL_LNK **dest_list_head_ptr,
|
||||
DBL_LNK *node_ptr)
|
||||
{
|
||||
ST_RET ret_code;
|
||||
|
||||
if (!(ret_code = list_unlink (src_list_head_ptr, node_ptr)))
|
||||
{
|
||||
list_add_first (dest_list_head_ptr, node_ptr);
|
||||
}
|
||||
return (ret_code);
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* list_find_node */
|
||||
/* Primitive to verify that a node is in a list, returns SD_SUCCESS if it */
|
||||
/* is; SD_FAILURE otherwise. */
|
||||
/************************************************************************/
|
||||
|
||||
ST_RET list_find_node (DBL_LNK *list_head_ptr, DBL_LNK *node_ptr)
|
||||
{
|
||||
DBL_LNK *temp_ptr;
|
||||
DBL_LNK *list_tail_ptr;
|
||||
ST_RET ret_code;
|
||||
|
||||
if ((list_head_ptr == NULL) || (node_ptr == NULL))
|
||||
ret_code = SD_FAILURE;
|
||||
else
|
||||
{
|
||||
temp_ptr = list_head_ptr;
|
||||
list_tail_ptr = list_head_ptr->prev;
|
||||
|
||||
/* search forward from the begining to the end of the list for our node */
|
||||
|
||||
while ((temp_ptr != list_tail_ptr) && (temp_ptr != node_ptr))
|
||||
{
|
||||
temp_ptr = temp_ptr->next;
|
||||
}
|
||||
if (temp_ptr == node_ptr)
|
||||
ret_code = SD_SUCCESS;
|
||||
else
|
||||
ret_code = SD_FAILURE;
|
||||
}
|
||||
return (ret_code);
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* list_print_links */
|
||||
/************************************************************************/
|
||||
|
||||
#if 0
|
||||
|
||||
ST_VOID list_print_links (DBL_LNK *list_head_ptr)
|
||||
{
|
||||
DBL_LNK *temp_ptr;
|
||||
DBL_LNK *list_tail_ptr;
|
||||
ST_INT i;
|
||||
|
||||
i = 1;
|
||||
if (list_head_ptr == NULL)
|
||||
{
|
||||
printf ("\nThe list is empty");
|
||||
}
|
||||
else
|
||||
{
|
||||
temp_ptr = list_head_ptr;
|
||||
list_tail_ptr = list_head_ptr->prev;
|
||||
printf ("\npointer to the head of the list is: %lx",list_head_ptr);
|
||||
printf ("\n");
|
||||
printf ("\npointer to node number %d is: %lx",i, temp_ptr);
|
||||
printf ("\nnode number: next ptr is: %lx",temp_ptr->next);
|
||||
printf ("\n prev ptr is: %lx",temp_ptr->prev);
|
||||
while ((temp_ptr != list_tail_ptr))
|
||||
{
|
||||
temp_ptr = temp_ptr->next;
|
||||
i++;
|
||||
printf ("\npointer to node number %d is: %lx",i, temp_ptr);
|
||||
printf ("\nnode number: next ptr is: %lx",temp_ptr->next);
|
||||
printf ("\n prev ptr is: %lx",temp_ptr->prev);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/************************************************************************/
|
||||
/* list_add_node_after(list insert node prim) */
|
||||
/* Primitive to add a node to a list after the current node. This */
|
||||
/* function assumes that we are working with a non NIL list. SD_SUCCESS */
|
||||
/* is returned if the node gets added to the list; SD_FAILURE otherwise. */
|
||||
/************************************************************************/
|
||||
|
||||
ST_RET list_add_node_after (DBL_LNK *cur_node, DBL_LNK *new_node)
|
||||
{
|
||||
DBL_LNK *next_node;
|
||||
ST_RET ret_val;
|
||||
|
||||
ret_val = SD_FAILURE;
|
||||
if (new_node == NULL)
|
||||
{
|
||||
SLOGALWAYS0 ("GENLIST: ATTEMPT TO ADD A NULL ADDRESS TO A LIST");
|
||||
}
|
||||
else if (cur_node == NULL)
|
||||
{
|
||||
SLOGALWAYS0 ("GENLIST: ATTEMPT TO ADD A NODE TO A NULL LIST");
|
||||
}
|
||||
else /* this is a good node and good predecessor */
|
||||
{
|
||||
next_node = cur_node -> next;
|
||||
new_node -> next = next_node;
|
||||
new_node -> prev = cur_node;
|
||||
next_node -> prev = new_node;
|
||||
cur_node -> next = new_node;
|
||||
ret_val = SD_SUCCESS;
|
||||
}
|
||||
return (ret_val);
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* list_get_next */
|
||||
/* Primitive to get the node pointed to by the next component of the */
|
||||
/* current node. This function returns NULL if the list_head_ptr is */
|
||||
/* NULL, the address of the current node is NULL or the next node in the*/
|
||||
/* list is the list_head_ptr(the list has wrapped around). This */
|
||||
/* function is useful for traversing a doubly linked circular list */
|
||||
/* from begining to the end as if the list were NULL terminated. */
|
||||
/************************************************************************/
|
||||
|
||||
#ifndef FASTLIST
|
||||
|
||||
ST_VOID *list_get_next (DBL_LNK *list_head_ptr, DBL_LNK *cur_node)
|
||||
{
|
||||
DBL_LNK *next_node = NULL;
|
||||
|
||||
if (list_head_ptr == NULL)
|
||||
{
|
||||
SLOGALWAYS0 ("GENLIST: ATTEMPT TO REFERENCE A NULL LIST");
|
||||
}
|
||||
else if (cur_node == NULL)
|
||||
{
|
||||
SLOGALWAYS0 ("GENLIST: ATTEMPT TO REFERENCE THROUGH A NULL PTR");
|
||||
}
|
||||
else if (cur_node->next != list_head_ptr)
|
||||
{
|
||||
next_node = cur_node->next;
|
||||
}
|
||||
return (next_node);
|
||||
}
|
||||
#endif
|
||||
|
||||
/************************************************************************/
|
||||
/* list_get_sizeof */
|
||||
/* Primitive to return the number of nodes in this generic list. */
|
||||
/************************************************************************/
|
||||
|
||||
ST_INT list_get_sizeof (DBL_LNK *list_head_ptr)
|
||||
{
|
||||
ST_INT count;
|
||||
DBL_LNK *cur_node;
|
||||
|
||||
count = 0;
|
||||
cur_node = list_head_ptr;
|
||||
|
||||
while (cur_node != NULL)
|
||||
{
|
||||
count ++;
|
||||
cur_node = (DBL_LNK *) list_get_next (list_head_ptr, cur_node);
|
||||
}
|
||||
|
||||
return (count);
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* list_find_prev */
|
||||
/* Primitive to find the node "before" the current node in the linked */
|
||||
/* list. This function returns NULL if the list_head_ptr is */
|
||||
/* NULL, the current node is NULL, or the current node */
|
||||
/* is the head of the linked list (i.e. does not wrap around). */
|
||||
/************************************************************************/
|
||||
|
||||
DBL_LNK *list_find_prev (DBL_LNK *list_head_ptr, DBL_LNK *cur_node)
|
||||
{
|
||||
DBL_LNK *prev_node = NULL;
|
||||
|
||||
if (list_head_ptr == NULL)
|
||||
{
|
||||
SLOGALWAYS0 ("GENLIST: ATTEMPT TO REFERENCE A NULL LIST");
|
||||
}
|
||||
else if (cur_node == NULL)
|
||||
{
|
||||
SLOGALWAYS0 ("GENLIST: ATTEMPT TO REFERENCE THROUGH A NULL PTR");
|
||||
}
|
||||
else if (cur_node != list_head_ptr)
|
||||
{
|
||||
prev_node = cur_node->prev;
|
||||
}
|
||||
return (prev_node);
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* list_find_last */
|
||||
/* Primitive to find the last node in the linked list and return it's */
|
||||
/* address. */
|
||||
/************************************************************************/
|
||||
|
||||
DBL_LNK *list_find_last (DBL_LNK *list_head_ptr)
|
||||
{
|
||||
DBL_LNK *last_node;
|
||||
|
||||
if (list_head_ptr)
|
||||
last_node = list_head_ptr->prev;
|
||||
else
|
||||
{ /* head is NULL (i.e. list is empty) so last is NULL too. */
|
||||
last_node = NULL;
|
||||
}
|
||||
|
||||
return (last_node);
|
||||
}
|
||||
|
||||
2814
mmslib/util/gensock2.c
Normal file
2814
mmslib/util/gensock2.c
Normal file
File diff suppressed because it is too large
Load Diff
462
mmslib/util/glbsem.c
Normal file
462
mmslib/util/glbsem.c
Normal file
@@ -0,0 +1,462 @@
|
||||
/************************************************************************/
|
||||
/* SISCO SOFTWARE MODULE HEADER *****************************************/
|
||||
/************************************************************************/
|
||||
/* (c) Copyright Systems Integration Specialists Company, Inc., */
|
||||
/* 1997-2005, All Rights Reserved */
|
||||
/* */
|
||||
/* MODULE NAME : glbsem.c */
|
||||
/* PRODUCT(S) : */
|
||||
/* */
|
||||
/* MODULE DESCRIPTION : Multi-thread support. */
|
||||
/* */
|
||||
/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */
|
||||
/* */
|
||||
/* MODIFICATION LOG : */
|
||||
/* Date Who Rev Comments */
|
||||
/* -------- --- ------ ------------------------------------------- */
|
||||
/* 03/12/08 JRB 77 gs_free_semx: make sure fname initialized. */
|
||||
/* 10/04/07 MDE 76 Tweaked LOGCFG_VALUE_GROUP/LOGCFGX_VALUE_MAP */
|
||||
/* 05/23/07 NAV 75 gs_get_semx: conditionally call sGetMsTime */
|
||||
/* 02/13/06 DSF 74 Migrate to VS.NET 2005 */
|
||||
/* 06/17/05 EJV 73 UNIX, Linux: need str_util.h */
|
||||
/* 06/10/05 DSF 72 Added an array to track calls to gs_free_semx*/
|
||||
/* 06/07/05 EJV 71 Added S_MT_SUPPORT to avoid Linux errors. */
|
||||
/* 05/23/05 EJV 70 Add gsLogMaskMapCtrl for parsing logcfg.xml */
|
||||
/* Moved gs_debug_sel from slog.c. */
|
||||
/* 05/23/05 JRB 69 Move all gs_timer* functions to glbtimer.c */
|
||||
/* 02/22/05 EJV 68 gs_timer_worker_thread: eliminated warnings */
|
||||
/* 01/10/05 DSF 67 Signal timer event after timer object is */
|
||||
/* unlinked */
|
||||
/* Don't call user callback if timer is */
|
||||
/* terminated */
|
||||
/* 08/23/04 EJV 66 GS_TIMER: rpl elapsed w/ ST_DOUBLE expiration*/
|
||||
/* 07/23/04 DSF 65 Set names of timer threads */
|
||||
/* 07/22/04 DSF 64 Set timer resolution back to 10 */
|
||||
/* 07/02/04 EJV 63 gs_timer_thread: chg sleep from 10 to 0 ms. */
|
||||
/* 06/17/04 DSF 62 Reset gs_timer_thread_stop in gs_timer_init()*/
|
||||
/* 05/05/04 EJV 61 gs_timer_cleanup: added timeout parameter. */
|
||||
/* Added timer worker threads to proc callbacks.*/
|
||||
/* gs_timer_init: added min_workers, max_workers*/
|
||||
/* 04/22/04 DSF 60 Initialized timer resolution to 1000 ms */
|
||||
/* 01/21/04 EJV 59 Win Timers: changed to use UNIX code. */
|
||||
/* Win impl preserved with _WIN32_timers define */
|
||||
/* 12/01/03 EJV 58 gs_is_win_ver: chk for corr ret 1, 0, -1. */
|
||||
/* 11/17/03 EJV 57 gs_timer_end: reverted moved gs_timer_remove.*/
|
||||
/* _WIN32: reworked periodic timers >430000ms; */
|
||||
/* All timer_id will go on delayed delete list*/
|
||||
/* 10/15/03 JRB 56 Move gs_debug_sel to slog.c, slogl.c. */
|
||||
/* 10/09/03 JRB 55 Enable gs_timer* functions for ALL systems. */
|
||||
/* 07/29/03 DSF,EJV 54 gs_timer_end: moved gs_timer_remove fun up. */
|
||||
/* 06/20/03 EJV 53 Del param from gs_mutex_get, gs_get_semx. */
|
||||
/* 06/12/03 EJV 52 Redesigned mutex sems implementation. */
|
||||
/* 06/06/03 JRB 51 Move _WIN32 code to new glbsem_w32.c */
|
||||
/* Move UNIX code to new glbsem_unix.c */
|
||||
/* Del OS2 code & "default" code. */
|
||||
/* Del unused gs_*_sig functions for DEC UNIX. */
|
||||
/* Add gs_util_mutex, init it in gs_init. */
|
||||
/* Chg GLBSEM_LOG_ALWAYS* to SLOGALWAYS*. */
|
||||
/* 06/03/03 EJV 50 _WIN32: changed for 64-bit compiler: */
|
||||
/* last param cast in RaiseException */
|
||||
/* gs_timer_callback last 3 parms to DWORD_PTR*/
|
||||
/* 04/14/03 JRB 49 Del intermediate functions for mutexes, */
|
||||
/* macros in glbsem.h use gs_mutex_get/free. */
|
||||
/* assert if gs_init fails (no way to recover). */
|
||||
/* 04/04/03 JRB 48 Chg _ASSERTE calls to assert, otherwise must */
|
||||
/* link DebugMultithreaded libs on Windows. */
|
||||
/* 03/24/03 EJV 47 Removed logging from some MUTEX functions. */
|
||||
/* gs_get_sem, gs_get_semx: added ASSERTE. */
|
||||
/* 02/03/03 EJV 46 _WIN32: added gs_is_win_ver() */
|
||||
/* added gs_get_named_event_sem() */
|
||||
/* 01/24/03 EJV 45 _WIN32 gs_start_thread: added comment. */
|
||||
/* 01/14/03 EJV 44 Added gs_sleep(). */
|
||||
/* 11/01/02 EJV 43 Use SISCO's link list with timers. */
|
||||
/* 10/30/02 EJV 42 gs_timer_check_list: limit delay to 1 sec. */
|
||||
/* Check if callback pending before deleting. */
|
||||
/* 10/31/02 EJV 41 gs_wait_mult_event_sem: corr activity memset */
|
||||
/* 07/29/02 EJV 40 Added gs_timer_get_resolution(), */
|
||||
/* Corrected timer termination wait. */
|
||||
/* Reverted timer _WIN32, added ptr wait list */
|
||||
/* 02/06/02 EJV 39 Compile this module if S_MT_SUPPORT defined */
|
||||
/* 12/04/01 KCR 38 cleared activity[] in gs_wait_mult_event_sem */
|
||||
/* 10/31/01 EJV 37 _WIN32: changed to call _beginthreadex; */
|
||||
/* Added gs_close_thread, gs_pulse_event_sem. */
|
||||
/* Replaced _ALWAYS macros with _ERR or _NERR. */
|
||||
/* _WIN32: gs_wait_thread now returns SD_FAILURE*/
|
||||
/* on timeout. */
|
||||
/* UNIX: gs_reset_event_sem now clears predicate*/
|
||||
/* 10/18/01 JRB 36 Eliminate warning. */
|
||||
/* 09/20/01 EJV 35 _WIN32 gs_timer_callback: check if pending */
|
||||
/* 08/01/01 JRB 34 gs_get_semx fill in fname even if NOT logging*/
|
||||
/* 07/30/01 EJV 33 Added gs_timer_set_resolution() fun. */
|
||||
/* _WIN32: reworked gs_timer functions. */
|
||||
/* 07/25/01 EJV 32 Changed gs_timer_resolution from 1000 to 10ms*/
|
||||
/* 07/24/01 EJV 31 _WIN32: added gs_timer support. */
|
||||
/* 05/17/01 EJV 30 _WIN32: eliminated compile warnings. */
|
||||
/* 04/04/01 DSF 29 Added gs_set_thread_name for WIN32 */
|
||||
/* 03/27/01 EJV 28 UNIX: gs_wait_event_sem, mutex the whole fun */
|
||||
/* 03/16/01 EJV 27 UNIX: added check to gs_free_event_sem. */
|
||||
/* UNIX: set thread attribute to joinable. */
|
||||
/* Removed #undef NDEBUG (now in make file) */
|
||||
/* 03/12/01 EJV 26 UNIX: added/changed few FLOW slogs. */
|
||||
/* UNIX: corr gs_wait_event_sem, predicate=0 */
|
||||
/* Removed <assert.h>, already in sysincs.h */
|
||||
/* Changed assert to _ASSERTE - def in sysincs.h*/
|
||||
/* 03/08/01 EJV 25 UNIX: Corrected type to ST_BOOLEAN for */
|
||||
/* static var gs_timer_thread_stop. Corr logs. */
|
||||
/* 03/07/01 EJV 24 UNIX: init attr before calling create thread.*/
|
||||
/* In gs_wait_event_sem check for predicate=1 */
|
||||
/* before entering the wait. */
|
||||
/* 02/19/01 EJV 23 _AIX: eliminated need to call gs_timer_init. */
|
||||
/* 02/14/01 EJV 22 Removed some DEBUG_SISCO around slog macros */
|
||||
/* AIX: added timer functions gs_timer_xxx. */
|
||||
/* 01/16/01 EJV 21 Moved GET_THREAD_ID define to glbsem.h */
|
||||
/* 12/27/00 EJV 20 _WIN32: Renamed glbCritSetion for easy calls.*/
|
||||
/* Added check for gs_already_inited. */
|
||||
/* 12/20/00 EJV 19 Ported to AIX. Revised DEC UNIX. */
|
||||
/* 12/13/00 EJV 18 Added gs_mutex_... user mutex functions. */
|
||||
/* Added gs_track for faster SISCO MUTEX. */
|
||||
/* Removed currSemOwner, semCount */
|
||||
/* Added few DEBUG_SISCO for __alpha. */
|
||||
/* 12/06/00 EJV 17 Changed gs_get_event_sem to accept arg. */
|
||||
/* USE_MANUAL_RESET_SEM define not necessary. */
|
||||
/* 10/25/00 JRB 16 Del gs_chk_thread_id. Found better way to */
|
||||
/* prevent errors (see "_MT" chk in glbsem.h). */
|
||||
/* 10/06/00 EJV 15 Ported to DEC UNIX (__alpha) pthread funcs. */
|
||||
/* Deleted unused: myThreadId,... */
|
||||
/* 10/06/00 EJV 14 _WIN32: corrected logging statements */
|
||||
/* 04/27/00 MDE 13 Lint cleanup */
|
||||
/* 03/14/00 JRB 12 Chg to allow breakpoint before assert. */
|
||||
/* 01/21/00 JRB 11 Del gs_install. Del function pointers. */
|
||||
/* gs_get_sem call gs_init if not already done. */
|
||||
/* Add "gs_chk_thread_id". */
|
||||
/* 12/16/99 NAV 10 in gs_free_semx watch for GS_LOG_FLOW */
|
||||
/* 09/13/99 MDE 09 Added SD_CONST modifiers */
|
||||
/* 08/05/99 JRB 08 Chged "gs_get_event_sem" to "auto-reset" */
|
||||
/* unless USE_MANUAL_RESET_SEM defined. */
|
||||
/* #ifdef'd out "gs_reset_event_sem". */
|
||||
/* Added partial support for __OS2__. */
|
||||
/* 03/01/99 DSF 07 Corrected #define releaseMutexSem for */
|
||||
/* non-DEBUG_SISCO version */
|
||||
/* 01/22/99 DSF 06 Use Critical Section instead of Mutex (faster)*/
|
||||
/* 10/08/98 MDE 05 Migrated to updated SLOG interface */
|
||||
/* 06/05/98 MDE 04 Fixed uninitialized 'rc' */
|
||||
/* 05/05/98 DSF 03 Added SD_TIMEOUT */
|
||||
/* 12/11/97 KCR 02 Added gs_wait_mult_event_sem for _WIN32 */
|
||||
/* 10/27/97 EJV 01 For !_WIN32 implementations: */
|
||||
/* Added typecast to define GET_THREAD_ID(); */
|
||||
/* Changed func gs_get_event_sem return from */
|
||||
/* from SD_FAILURE to (ST_EVENT_SEM) 0. */
|
||||
/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */
|
||||
/* history. */
|
||||
/************************************************************************/
|
||||
|
||||
#if defined (_WIN32)
|
||||
#pragma warning(disable : 4996)
|
||||
#endif
|
||||
|
||||
#include "glbtypes.h"
|
||||
#include "sysincs.h"
|
||||
#include "mem_chk.h"
|
||||
#include "slog.h"
|
||||
#include "glbsem.h"
|
||||
#include "str_util.h"
|
||||
|
||||
#if defined(S_MT_SUPPORT)
|
||||
|
||||
/************************************************************************/
|
||||
/* For debug version, use a static pointer to avoid duplication of */
|
||||
/* __FILE__ strings. */
|
||||
|
||||
#ifdef DEBUG_SISCO
|
||||
SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__;
|
||||
#endif
|
||||
|
||||
/************************************************************************/
|
||||
/************************************************************************/
|
||||
/* GLOBAL VARIABLES */
|
||||
|
||||
ST_UINT gs_debug_sel = GS_LOG_ERR | GS_LOG_NERR;
|
||||
|
||||
#ifdef DEBUG_SISCO
|
||||
SD_CONST ST_CHAR *SD_CONST _glbem_flow_logstr = "GS_LOG_FLOW";
|
||||
SD_CONST ST_CHAR *SD_CONST _glbem_err_logstr = "GS_LOG_ERR";
|
||||
SD_CONST ST_CHAR *SD_CONST _glbem_nerr_logstr = "GS_LOG_NERR";
|
||||
|
||||
LOGCFGX_VALUE_MAP gsLogMaskMaps[] =
|
||||
{
|
||||
{"GS_LOG_ERR", GS_LOG_ERR, &gs_debug_sel, _LOGCFG_DATATYPE_UINT_MASK, NULL, "Error"},
|
||||
{"GS_LOG_NERR", GS_LOG_NERR, &gs_debug_sel, _LOGCFG_DATATYPE_UINT_MASK, NULL, "Notice"},
|
||||
{"GS_LOG_FLOW", GS_LOG_FLOW, &gs_debug_sel, _LOGCFG_DATATYPE_UINT_MASK, NULL, "Flow"},
|
||||
};
|
||||
|
||||
LOGCFG_VALUE_GROUP gsLogMaskMapCtrl =
|
||||
{
|
||||
{NULL,NULL},
|
||||
"SemaphoreLogMasks", /* Parent Tag */
|
||||
sizeof(gsLogMaskMaps)/sizeof(LOGCFGX_VALUE_MAP),
|
||||
gsLogMaskMaps
|
||||
};
|
||||
#endif /* DEBUG_SISCO */
|
||||
|
||||
/* variables to evalueate semaphores locking performance */
|
||||
ST_DOUBLE gs_hwMutexTime;
|
||||
ST_DOUBLE gs_hwEventTime;
|
||||
|
||||
ST_MUTEX_SEM gs_glb_mutex; /* global SISCO MUTEX semaphore */
|
||||
ST_MUTEX_SEM gs_util_mutex; /* UTILITY MUTEX semaphore: for "low-level"*/
|
||||
/* util functs (slog,mem_chk,stime,etc.)*/
|
||||
|
||||
ST_BOOLEAN gs_already_inited = SD_FALSE;
|
||||
|
||||
#if defined(DEBUG_SISCO)
|
||||
/* The debug version keeps a stack of sem owners call locations */
|
||||
/* which can be logged to aid in debugging. */
|
||||
/* These variables are only changed by a thread that owns the sem, but */
|
||||
/* can be read (for logging) by 'gs_log_sem_state', possibly resulting */
|
||||
/* in a 'torn' log if the called is not careful. */
|
||||
|
||||
#define MAX_SEM_NEST_TRACK 20
|
||||
ST_UINT gs_track; /* This variable when set to value >0 */
|
||||
/* during an application startup allows */
|
||||
/* tracking of MUTEX or EVENT sem. */
|
||||
ST_INT gs_currSemOwnerIndex;
|
||||
ST_CHAR gs_currSemOwnerFile[MAX_SEM_NEST_TRACK][SLOG_MAX_FNAME+1];
|
||||
ST_INT gs_currSemOwnerLine[MAX_SEM_NEST_TRACK];
|
||||
ST_CHAR gs_currSemFreeFile[MAX_SEM_NEST_TRACK][SLOG_MAX_FNAME+1];
|
||||
ST_INT gs_currSemFreeLine[MAX_SEM_NEST_TRACK];
|
||||
|
||||
#endif /* DEBUG_SISCO */
|
||||
|
||||
|
||||
/*---*---*---*---*---*---*---*---*---*---*---*---*---*--*/
|
||||
/* */
|
||||
/* SISCO's GLOBAL MUTEX SEMAPHORE FUNCTIONS */
|
||||
/* */
|
||||
/*---*---*---*---*---*---*---*---*---*---*---*---*---*--*/
|
||||
|
||||
/************************************************************************/
|
||||
/* gs_init */
|
||||
/*----------------------------------------------------------------------*/
|
||||
/* Initialize global SISCO MUTEX semaphore. */
|
||||
/* This function will be called from the gs_get_sem or gs_get_semx, */
|
||||
/* it does not have to be called from user application. */
|
||||
/* Parameters: */
|
||||
/* none */
|
||||
/* Return values: */
|
||||
/* SD_SUCCESS function successful */
|
||||
/* SD_FAILURE error occurred */
|
||||
/************************************************************************/
|
||||
|
||||
ST_RET gs_init (ST_VOID)
|
||||
{
|
||||
ST_RET rc;
|
||||
|
||||
/* !!! To avoid infinite loop with SLOG do not log from this function. */
|
||||
|
||||
if (gs_already_inited)
|
||||
return (SD_SUCCESS);
|
||||
|
||||
/* WARNING: The gs_util_mutex should not be changed to use named mutex */
|
||||
/* because logging in the code handling named mutex will cause */
|
||||
/* infinite loop. */
|
||||
|
||||
/* Initialize the MUTEX semaphores. Both must succeed, so OR the returns.*/
|
||||
rc = gs_mutex_create (&gs_glb_mutex);
|
||||
rc |= gs_mutex_create (&gs_util_mutex);
|
||||
|
||||
/* Set up to track the semaphore owners by nesting level */
|
||||
#if defined(DEBUG_SISCO)
|
||||
gs_currSemOwnerIndex = -1;
|
||||
#endif
|
||||
|
||||
if (rc == SD_SUCCESS)
|
||||
gs_already_inited = SD_TRUE;
|
||||
else
|
||||
assert (0); /* nothing will work properly if this fails. */
|
||||
|
||||
return (rc);
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* gs_log_sem_state */
|
||||
/*----------------------------------------------------------------------*/
|
||||
/* Log the global SISCO MUTEX semaphore owner stack. */
|
||||
/* Parameters: */
|
||||
/* none */
|
||||
/* Return values: */
|
||||
/* none */
|
||||
/************************************************************************/
|
||||
|
||||
ST_VOID gs_log_sem_state (ST_VOID)
|
||||
{
|
||||
#if defined(DEBUG_SISCO)
|
||||
ST_INT i;
|
||||
|
||||
if (!gs_already_inited) /* Make sure gs is initialized. */
|
||||
return;
|
||||
|
||||
SLOGALWAYS0 ("GLBSEM: Semaphore owner stack (oldest to latest) :");
|
||||
for (i = 0; i <= gs_currSemOwnerIndex && i < MAX_SEM_NEST_TRACK; ++i)
|
||||
{
|
||||
SLOGCALWAYS3 (" %d) File %s, Line %d",
|
||||
i+1, gs_currSemOwnerFile[i], gs_currSemOwnerLine[i]);
|
||||
}
|
||||
if (gs_currSemOwnerIndex >= MAX_SEM_NEST_TRACK)
|
||||
SLOGCALWAYS0 (" Sem's nested too deep to track further");
|
||||
#endif
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* gs_get_semx */
|
||||
/*----------------------------------------------------------------------*/
|
||||
/* Lock (obtain ownership) the global SISCO MUTEX semaphore. */
|
||||
/* This debug version function keeps track of the sem owner stack. */
|
||||
/* If compiled without DEBUG_SISCO it just falls through to gs_get_sem. */
|
||||
/* If compiled with DEBUG_SISCO the gs_track variable need to be set to */
|
||||
/* value >0 to enable the tracking code. This way logging can be used */
|
||||
/* by an application without degradation of the MUTEX sem performance. */
|
||||
/* In addition the gs_debug_sel need to be set to GS_LOG_FLOW to */
|
||||
/* log the tracking results. */
|
||||
/* Parameters: */
|
||||
/* srcFile ptr to source code file name calling this fun */
|
||||
/* srcLineNum source code line number */
|
||||
/* Return values: */
|
||||
/* none */
|
||||
/* CRITICAL: gs_get_semx must NOT be called from any slog or stime */
|
||||
/* functions. It calls slog and stime functions which would cause */
|
||||
/* an infinite loop. Slog and stime must call gs_mutex_get. */
|
||||
/************************************************************************/
|
||||
|
||||
ST_VOID gs_get_semx (SD_CONST ST_CHAR *srcFile, ST_INT srcLineNum)
|
||||
{
|
||||
#if defined(DEBUG_SISCO)
|
||||
ST_CHAR fname[SLOG_MAX_FNAME+1];
|
||||
ST_DOUBLE startTime;
|
||||
ST_DOUBLE endTime;
|
||||
ST_DOUBLE elapsedTime;
|
||||
|
||||
if (!gs_already_inited) /* Make sure gs is initialized. */
|
||||
gs_init ();
|
||||
|
||||
if (gs_track)
|
||||
startTime = sGetMsTime ();
|
||||
|
||||
gs_mutex_get (&gs_glb_mutex);
|
||||
|
||||
if (gs_track)
|
||||
{
|
||||
endTime = sGetMsTime ();
|
||||
|
||||
elapsedTime = endTime - startTime;
|
||||
if (elapsedTime > gs_hwMutexTime)
|
||||
gs_hwMutexTime = elapsedTime;
|
||||
|
||||
if (srcFile != NULL)
|
||||
slogTrimFileName (fname, srcFile);
|
||||
else
|
||||
strcpy (fname, "Unknown");
|
||||
|
||||
if (gs_debug_sel & GS_LOG_FLOW)
|
||||
{
|
||||
GLBSEM_LOG_FLOW2 ("GLBSEM: File %s, Line %d has the mutex",
|
||||
fname, srcLineNum);
|
||||
GLBSEM_LOG_CFLOW2 (" took %.3f sec (hw = %.3f)",
|
||||
elapsedTime/1000, gs_hwMutexTime/1000);
|
||||
}
|
||||
|
||||
++gs_currSemOwnerIndex;
|
||||
if (gs_currSemOwnerIndex < MAX_SEM_NEST_TRACK)
|
||||
{
|
||||
strcpy (gs_currSemOwnerFile[gs_currSemOwnerIndex], fname);
|
||||
gs_currSemOwnerLine[gs_currSemOwnerIndex] = srcLineNum;
|
||||
}
|
||||
else
|
||||
{
|
||||
GLBSEM_LOG_CFLOW0 (" Nested too deep to track");
|
||||
}
|
||||
}
|
||||
#else /* Not DEBUG_SISCO */
|
||||
|
||||
gs_mutex_get (&gs_glb_mutex);
|
||||
|
||||
#endif /* DEBUG_SISCO */
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* gs_free_semx */
|
||||
/*----------------------------------------------------------------------*/
|
||||
/* Unlock (release ownership) the global SISCO MUTEX semaphore. */
|
||||
/* This debug version function keeps track of the sem owner stack. */
|
||||
/* If compiled without DEBUG_SISCO is just falls through to gs_free_sem.*/
|
||||
/* If compiled with DEBUG_SISCO the gs_track variable need to be set to */
|
||||
/* value >0 to enable the tracking code. This way logging can be used */
|
||||
/* by an application without degradation of the MUTEX sem performance. */
|
||||
/* In addition the gs_debug_sel need to be set to GS_LOG_FLOW to log */
|
||||
/* the tracking results. */
|
||||
/* Parameters: */
|
||||
/* srcFile ptr to source code file name calling this fun */
|
||||
/* srcLineNum source code line number */
|
||||
/* Return values: */
|
||||
/* none */
|
||||
/* CRITICAL: gs_free_semx must NOT be called from any slog or stime */
|
||||
/* functions. It calls slog and stime functions which would cause */
|
||||
/* an infinite loop. Slog and stime must call gs_mutex_free. */
|
||||
/************************************************************************/
|
||||
|
||||
ST_VOID gs_free_semx (SD_CONST ST_CHAR *srcFile, ST_INT srcLineNum)
|
||||
{
|
||||
#if defined(DEBUG_SISCO)
|
||||
ST_CHAR fname[SLOG_MAX_FNAME+1];
|
||||
ST_INT idx;
|
||||
|
||||
if (!gs_already_inited) /* Make sure gs is initialized. */
|
||||
{
|
||||
GLBSEM_LOG_ERR0 ("GLBSEM gs_free_semx error: global mutex semaphore not initialized");
|
||||
return;
|
||||
}
|
||||
|
||||
if (gs_track)
|
||||
{
|
||||
if (srcFile != NULL)
|
||||
slogTrimFileName (fname, srcFile);
|
||||
else
|
||||
strcpy (fname, "Unknown");
|
||||
|
||||
GLBSEM_LOG_FLOW2 ("GLBSEM: File %s, Line %d freeing the semaphore",
|
||||
fname, srcLineNum);
|
||||
|
||||
idx = gs_currSemOwnerIndex;
|
||||
--gs_currSemOwnerIndex;
|
||||
if (gs_currSemOwnerIndex == -1)
|
||||
{
|
||||
GLBSEM_LOG_CFLOW0 (" The semaphore should now be free");
|
||||
}
|
||||
else if (gs_currSemOwnerIndex >= 0 && gs_currSemOwnerIndex < MAX_SEM_NEST_TRACK)
|
||||
{
|
||||
GLBSEM_LOG_CFLOW2 (" File %s, Line %d now has the semaphore",
|
||||
gs_currSemOwnerFile[gs_currSemOwnerIndex],
|
||||
gs_currSemOwnerLine[gs_currSemOwnerIndex]);
|
||||
strcpy (gs_currSemFreeFile[idx], fname);
|
||||
gs_currSemFreeLine[idx] = srcLineNum;
|
||||
if (strcmpi (gs_currSemFreeFile[idx], gs_currSemOwnerFile[idx]))
|
||||
{
|
||||
GLBSEM_LOG_ERR2 ("Possible problem: %s (%d)", gs_currSemOwnerFile[idx],
|
||||
gs_currSemOwnerLine[idx]);
|
||||
}
|
||||
}
|
||||
else if (gs_currSemOwnerIndex >= 0 && gs_currSemOwnerIndex >= MAX_SEM_NEST_TRACK)
|
||||
{
|
||||
GLBSEM_LOG_CFLOW0 (" Nested too deep to track");
|
||||
}
|
||||
else if (gs_currSemOwnerIndex < -1)
|
||||
{
|
||||
GLBSEM_LOG_ERR0 ("GLBSEM gs_free_semx error: Sem track index negative");
|
||||
gs_currSemOwnerIndex = -1;
|
||||
}
|
||||
}
|
||||
#endif /* DEBUG_SISCO */
|
||||
|
||||
gs_mutex_free (&gs_glb_mutex);
|
||||
}
|
||||
|
||||
#endif /* defined(S_MT_SUPPORT) */
|
||||
1064
mmslib/util/glbsem_unix.c
Normal file
1064
mmslib/util/glbsem_unix.c
Normal file
File diff suppressed because it is too large
Load Diff
1139
mmslib/util/glbsem_w32.c
Normal file
1139
mmslib/util/glbsem_w32.c
Normal file
File diff suppressed because it is too large
Load Diff
353
mmslib/util/scl_log.c
Normal file
353
mmslib/util/scl_log.c
Normal file
@@ -0,0 +1,353 @@
|
||||
/************************************************************************/
|
||||
/* SISCO SOFTWARE MODULE HEADER *****************************************/
|
||||
/************************************************************************/
|
||||
/* (c) Copyright Systems Integration Specialists Company, Inc., */
|
||||
/* 2004-2004 All Rights Reserved */
|
||||
/* */
|
||||
/* MODULE NAME : scl_log.c */
|
||||
/* PRODUCT(S) : MMS-EASE-LITE */
|
||||
/* */
|
||||
/* MODULE DESCRIPTION : */
|
||||
/* Functions to log info parsed from SCL file. */
|
||||
/* */
|
||||
/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */
|
||||
/* scl_log_all_data_types */
|
||||
/* scl_log_all_logical_devices */
|
||||
/* scl_log_all */
|
||||
/* */
|
||||
/* MODIFICATION LOG : */
|
||||
/* Date Who Rev Comments */
|
||||
/* -------- --- ------ ------------------------------------------- */
|
||||
/* 05/08/07 JRB 02 Fix log message. */
|
||||
/* 06/10/04 DWL 01 Initial Revision. */
|
||||
/************************************************************************/
|
||||
#include "glbtypes.h"
|
||||
#include "sysincs.h"
|
||||
#include "scl.h"
|
||||
#include "slog.h"
|
||||
#include "sx_log.h"
|
||||
|
||||
#ifdef DEBUG_SISCO
|
||||
SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__;
|
||||
#endif
|
||||
|
||||
/************************************************************************/
|
||||
/* scl_log_do */
|
||||
/************************************************************************/
|
||||
static ST_VOID scl_log_do (SCL_DO *scl_do)
|
||||
{
|
||||
SXLOG_DEC2 ("SCL LOG: <DO name='%s' type='%s'>",
|
||||
scl_do->name, scl_do->type);
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* scl_log_da */
|
||||
/************************************************************************/
|
||||
static ST_VOID scl_log_da (SCL_DA *scl_da)
|
||||
{
|
||||
ST_CHAR dchg[6];
|
||||
ST_CHAR qchg[6];
|
||||
ST_CHAR dupd[6];
|
||||
|
||||
SXLOG_DEC8 ("SCL LOG: <DA name='%s' desc='%s' sAddr='%s' bType='%s' valKind='%s' type='%s' count='%u' fc='%s'",
|
||||
scl_da->name, scl_da->desc, scl_da->sAddr, scl_da->bType,
|
||||
scl_da->valKind, scl_da->type, scl_da->count, scl_da->fc);
|
||||
|
||||
if (scl_da->dchg == SD_TRUE)
|
||||
strncpy (dchg, "true", sizeof(dchg));
|
||||
else
|
||||
strncpy (dchg, "false", sizeof(dchg));
|
||||
|
||||
if (scl_da->qchg == SD_TRUE)
|
||||
strncpy (qchg, "true", sizeof(qchg));
|
||||
else
|
||||
strncpy (qchg, "false", sizeof(qchg));
|
||||
|
||||
if (scl_da->dupd == SD_TRUE)
|
||||
strncpy (dupd, "true", sizeof(dupd));
|
||||
else
|
||||
strncpy (dupd, "false", sizeof(dupd));
|
||||
|
||||
SXLOG_CDEC3 ("SCL LOG: dchg='%s' qchg='%s' dupd='%s'>",
|
||||
dchg, qchg, dupd);
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* scl_log_sdo */
|
||||
/************************************************************************/
|
||||
static ST_VOID scl_log_sdo (SCL_DA *scl_da)
|
||||
{
|
||||
SXLOG_DEC3 ("SCL LOG: <SDO name='%s' desc='%s' type='%s'>",
|
||||
scl_da->name, scl_da->desc, scl_da->type);
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* scl_log_lntype */
|
||||
/************************************************************************/
|
||||
static ST_VOID scl_log_lntype (SCL_LNTYPE *scl_lntype)
|
||||
{
|
||||
SCL_DO *scl_do;
|
||||
|
||||
SXLOG_DEC2 ("SCL LOG: <LNodeType id='%s' lnClass='%s'>",
|
||||
scl_lntype->id, scl_lntype->lnClass);
|
||||
|
||||
for (scl_do = (SCL_DO *) list_find_last ((DBL_LNK *) scl_lntype->doHead);
|
||||
scl_do != NULL;
|
||||
scl_do = (SCL_DO *) list_find_prev ((DBL_LNK *) scl_lntype->doHead, (DBL_LNK *) scl_do))
|
||||
{
|
||||
scl_log_do (scl_do);
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* scl_log_dotype */
|
||||
/************************************************************************/
|
||||
static ST_VOID scl_log_dotype (SCL_DOTYPE *scl_dotype)
|
||||
{
|
||||
SCL_DA *scl_da;
|
||||
|
||||
SXLOG_DEC2 ("SCL LOG: <DOType id='%s' cdc='%s'>",
|
||||
scl_dotype->id, scl_dotype->cdc);
|
||||
|
||||
for (scl_da = (SCL_DA *) list_find_last ((DBL_LNK *) scl_dotype->daHead);
|
||||
scl_da != NULL;
|
||||
scl_da = (SCL_DA *) list_find_prev ((DBL_LNK *) scl_dotype->daHead, (DBL_LNK *) scl_da))
|
||||
{
|
||||
if (scl_da->objtype == SCL_OBJTYPE_SDO)
|
||||
scl_log_sdo (scl_da);
|
||||
else /* Must be SCL_OBJTYPE_DA */
|
||||
scl_log_da (scl_da);
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* scl_log_bda */
|
||||
/************************************************************************/
|
||||
static ST_VOID scl_log_bda (SCL_BDA *scl_bda)
|
||||
{
|
||||
SXLOG_DEC7 ("SCL LOG: <BDA name='%s' desc='%s' sAddr='%s' bType='%s' valKind='%s' type='%s' count='%u'>",
|
||||
scl_bda->name, scl_bda->desc, scl_bda->sAddr,
|
||||
scl_bda->bType, scl_bda->valKind, scl_bda->type,
|
||||
scl_bda->count);
|
||||
SXLOG_DEC1 ("SCL LOG: <Val='%s'>", scl_bda->Val);
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* scl_log_datype */
|
||||
/************************************************************************/
|
||||
static ST_VOID scl_log_datype (SCL_DATYPE *scl_datype)
|
||||
{
|
||||
SCL_BDA *scl_bda;
|
||||
|
||||
SXLOG_DEC1 ("SCL LOG: <DAType id='%s'>",
|
||||
scl_datype->id);
|
||||
|
||||
for (scl_bda = (SCL_BDA *) list_find_last ((DBL_LNK *) scl_datype->bdaHead);
|
||||
scl_bda != NULL;
|
||||
scl_bda = (SCL_BDA *) list_find_prev ((DBL_LNK *) scl_datype->bdaHead, (DBL_LNK *) scl_bda))
|
||||
{
|
||||
scl_log_bda (scl_bda);
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* scl_log_enumval */
|
||||
/************************************************************************/
|
||||
static ST_VOID scl_log_enumval (SCL_ENUMVAL *scl_enumval)
|
||||
{
|
||||
SXLOG_DEC2 ("SCL LOG: <EnumVal ord='%u' EnumVal='%s'>",
|
||||
scl_enumval->ord, scl_enumval->EnumVal);
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* scl_log_enumtype */
|
||||
/************************************************************************/
|
||||
static ST_VOID scl_log_enumtype (SCL_ENUMTYPE *scl_enumtype)
|
||||
{
|
||||
SCL_ENUMVAL *scl_enumval;
|
||||
|
||||
SXLOG_DEC1 ("SCL LOG: <EnumType id='%s'>",
|
||||
scl_enumtype->id);
|
||||
|
||||
for (scl_enumval = (SCL_ENUMVAL *) list_find_last ((DBL_LNK *) scl_enumtype->enumvalHead);
|
||||
scl_enumval != NULL;
|
||||
scl_enumval = (SCL_ENUMVAL *) list_find_prev ((DBL_LNK *) scl_enumtype->enumvalHead, (DBL_LNK *) scl_enumval))
|
||||
{
|
||||
scl_log_enumval (scl_enumval);
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* scl_log_all_data_types */
|
||||
/************************************************************************/
|
||||
ST_VOID scl_log_all_data_types (SCL_INFO *scl_info)
|
||||
{
|
||||
SCL_LNTYPE *scl_lntype;
|
||||
SCL_DOTYPE *scl_dotype;
|
||||
SCL_DATYPE *scl_datype;
|
||||
SCL_ENUMTYPE *scl_enumtype;
|
||||
|
||||
/* NOTE: linked list is in reverse order from data in SCL file, */
|
||||
/* so get off list in reverse order. */
|
||||
for (scl_lntype = (SCL_LNTYPE *) list_find_last ((DBL_LNK *) scl_info->lnTypeHead);
|
||||
scl_lntype != NULL;
|
||||
scl_lntype = (SCL_LNTYPE *) list_find_prev ((DBL_LNK *) scl_info->lnTypeHead, (DBL_LNK *) scl_lntype))
|
||||
{
|
||||
scl_log_lntype (scl_lntype);
|
||||
}
|
||||
|
||||
for (scl_dotype = (SCL_DOTYPE *) list_find_last ((DBL_LNK *) scl_info->doTypeHead);
|
||||
scl_dotype != NULL;
|
||||
scl_dotype = (SCL_DOTYPE *) list_find_prev ((DBL_LNK *) scl_info->doTypeHead, (DBL_LNK *) scl_dotype))
|
||||
{
|
||||
scl_log_dotype (scl_dotype);
|
||||
}
|
||||
|
||||
for (scl_datype = (SCL_DATYPE *) list_find_last ((DBL_LNK *) scl_info->daTypeHead);
|
||||
scl_datype != NULL;
|
||||
scl_datype = (SCL_DATYPE *) list_find_prev ((DBL_LNK *) scl_info->daTypeHead, (DBL_LNK *) scl_datype))
|
||||
{
|
||||
scl_log_datype (scl_datype);
|
||||
}
|
||||
|
||||
for (scl_enumtype = (SCL_ENUMTYPE *) list_find_last ((DBL_LNK *) scl_info->enumTypeHead);
|
||||
scl_enumtype != NULL;
|
||||
scl_enumtype = (SCL_ENUMTYPE *) list_find_prev ((DBL_LNK *) scl_info->enumTypeHead, (DBL_LNK *) scl_enumtype))
|
||||
{
|
||||
scl_log_enumtype (scl_enumtype);
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* scl_log_fcda */
|
||||
/************************************************************************/
|
||||
static ST_VOID scl_log_fcda (SCL_FCDA *scl_fcda)
|
||||
{
|
||||
SXLOG_DEC7 ("SCL LOG: <FCDA ldInst='%s' prefix='%s' lnInst='%s' lnClass='%s' doName='%s' daName='%s' fc='%s'>",
|
||||
scl_fcda->ldInst, scl_fcda->prefix, scl_fcda->lnInst,
|
||||
scl_fcda->lnClass, scl_fcda->doName, scl_fcda->daName,
|
||||
scl_fcda->fc);
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* scl_log_dataset */
|
||||
/************************************************************************/
|
||||
static ST_VOID scl_log_dataset (SCL_DATASET *scl_dataset)
|
||||
{
|
||||
SCL_FCDA *scl_fcda;
|
||||
|
||||
SXLOG_DEC2 ("SCL LOG: <Dataset name='%s' desc='%s'>",
|
||||
scl_dataset->name, scl_dataset->desc);
|
||||
|
||||
for (scl_fcda = (SCL_FCDA *) list_find_last ((DBL_LNK *) scl_dataset->fcdaHead);
|
||||
scl_fcda != NULL;
|
||||
scl_fcda = (SCL_FCDA *) list_find_prev ((DBL_LNK *) scl_dataset->fcdaHead, (DBL_LNK *) scl_fcda))
|
||||
{
|
||||
scl_log_fcda (scl_fcda);
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* scl_log_rcb */
|
||||
/************************************************************************/
|
||||
static ST_VOID scl_log_rcb (SCL_RCB *scl_rcb)
|
||||
{
|
||||
ST_CHAR buffered[6];
|
||||
|
||||
if (scl_rcb->buffered == SD_TRUE)
|
||||
strncpy (buffered, "true", sizeof (buffered));
|
||||
else
|
||||
strncpy (buffered, "false", sizeof (buffered));
|
||||
|
||||
SXLOG_DEC8 ("SCL LOG: <ReportControl name='%s' desc='%s' datSet='%s' intgPd='%u' rptID='%s' confRev='%u' buffered='%s' bufTime='%u'",
|
||||
scl_rcb->name, scl_rcb->desc, scl_rcb->datSet,
|
||||
scl_rcb->intgPd, scl_rcb->rptID, scl_rcb->confRev,
|
||||
buffered, scl_rcb->bufTime);
|
||||
|
||||
/* These are bitstrings. Just log as hex. */
|
||||
SXLOG_CDEC3 ("SCL LOG: TrgOps=0x%02X, OptFlds=0x%02X%02X",
|
||||
(ST_UINT) scl_rcb->TrgOps [0],
|
||||
(ST_UINT) scl_rcb->OptFlds[0],
|
||||
(ST_UINT) scl_rcb->OptFlds[1] );
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* scl_log_ln */
|
||||
/************************************************************************/
|
||||
static ST_VOID scl_log_ln (SCL_LN *scl_ln)
|
||||
{
|
||||
SCL_DATASET *scl_dataset;
|
||||
SCL_RCB *scl_rcb;
|
||||
|
||||
SXLOG_DEC5 ("SCL LOG: <LNode desc='%s' lnType='%s' lnClass='%s' inst='%s' prefix='%s'>",
|
||||
scl_ln->desc, scl_ln->lnType, scl_ln->lnClass,
|
||||
scl_ln->inst, scl_ln->prefix);
|
||||
|
||||
/* Log Datasets */
|
||||
for (scl_dataset = (SCL_DATASET *) list_find_last ((DBL_LNK *) scl_ln->datasetHead);
|
||||
scl_dataset != NULL;
|
||||
scl_dataset = (SCL_DATASET *) list_find_prev ((DBL_LNK *) scl_ln->datasetHead, (DBL_LNK *) scl_dataset))
|
||||
{
|
||||
scl_log_dataset (scl_dataset);
|
||||
}
|
||||
|
||||
/* Log RCBs */
|
||||
for (scl_rcb = (SCL_RCB *) list_find_last ((DBL_LNK *) scl_ln->rcbHead);
|
||||
scl_rcb != NULL;
|
||||
scl_rcb = (SCL_RCB *) list_find_prev ((DBL_LNK *) scl_ln->rcbHead, (DBL_LNK *) scl_rcb))
|
||||
{
|
||||
scl_log_rcb (scl_rcb);
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* scl_log_ld */
|
||||
/************************************************************************/
|
||||
static ST_VOID scl_log_ld (
|
||||
SCL_INFO *scl_info, /* main struct where all SCL info stored*/
|
||||
SCL_LD *scl_ld)
|
||||
{
|
||||
SCL_LN *scl_ln;
|
||||
|
||||
SXLOG_DEC2 ("SCL LOG: <LDevice desc='%s' inst='%s'>",
|
||||
scl_ld->desc, scl_ld->inst);
|
||||
|
||||
/* Log Logical nodes */
|
||||
/* NOTE: linked lists are in reverse order from data in SCL file, */
|
||||
/* so get off list in reverse order. */
|
||||
for (scl_ln = (SCL_LN *) list_find_last ((DBL_LNK *) scl_ld->lnHead);
|
||||
scl_ln != NULL;
|
||||
scl_ln = (SCL_LN *) list_find_prev ((DBL_LNK *) scl_ld->lnHead, (DBL_LNK *) scl_ln))
|
||||
{
|
||||
scl_log_ln (scl_ln);
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* scl_log_all_logical_devices */
|
||||
/* Log all Logical Devices from SCL info saved in "scl_info". */
|
||||
/* RETURNS: SD_SUCCESS or error code */
|
||||
/************************************************************************/
|
||||
ST_VOID scl_log_all_logical_devices (SCL_INFO *scl_info)
|
||||
{
|
||||
SCL_LD *scl_ld;
|
||||
|
||||
/* NOTE: linked list is in reverse order from data in SCL file, */
|
||||
/* so get off list in reverse order. */
|
||||
for (scl_ld = (SCL_LD *) list_find_last ((DBL_LNK *) scl_info->ldHead);
|
||||
scl_ld != NULL;
|
||||
scl_ld = (SCL_LD *) list_find_prev ((DBL_LNK *) scl_info->ldHead, (DBL_LNK *) scl_ld))
|
||||
{
|
||||
scl_log_ld (scl_info, scl_ld);
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* scl_log_all */
|
||||
/* Log everything from SCL info saved in "scl_info". */
|
||||
/************************************************************************/
|
||||
ST_VOID scl_log_all (SCL_INFO *scl_info)
|
||||
{
|
||||
scl_log_all_logical_devices (scl_info);
|
||||
scl_log_all_data_types (scl_info);
|
||||
}
|
||||
2507
mmslib/util/sclparse.c
Normal file
2507
mmslib/util/sclparse.c
Normal file
File diff suppressed because it is too large
Load Diff
737
mmslib/util/sclstore.c
Normal file
737
mmslib/util/sclstore.c
Normal file
@@ -0,0 +1,737 @@
|
||||
/************************************************************************/
|
||||
/* SISCO SOFTWARE MODULE HEADER *****************************************/
|
||||
/************************************************************************/
|
||||
/* (c) Copyright Systems Integration Specialists Company, Inc., */
|
||||
/* 2004-2006 All Rights Reserved */
|
||||
/* */
|
||||
/* MODULE NAME : sclstore.c */
|
||||
/* PRODUCT(S) : MMS-EASE-LITE */
|
||||
/* */
|
||||
/* MODULE DESCRIPTION : */
|
||||
/* Functions to store information parsed from SCL file. */
|
||||
/* */
|
||||
/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */
|
||||
/* scl_lntype_create */
|
||||
/* scl_lntype_add_do */
|
||||
/* scl_dotype_create */
|
||||
/* scl_dotype_add_da */
|
||||
/* scl_dotype_add_sdo */
|
||||
/* scl_datype_create */
|
||||
/* scl_datype_add_bda */
|
||||
/* scl_enumtype_create */
|
||||
/* scl_enumtype_add_enumval */
|
||||
/* scl_fcda_add */
|
||||
/* scl_dai_add */
|
||||
/* scl_dataset_add */
|
||||
/* scl_rcb_add */
|
||||
/* scl_lcb_add */
|
||||
/* scl_gcb_add */
|
||||
/* scl_ln_add */
|
||||
/* scl_ld_create */
|
||||
/* scl_info_destroy */
|
||||
/* */
|
||||
/* MODIFICATION LOG : */
|
||||
/* Date Who Rev Comments */
|
||||
/* -------- --- ------ ------------------------------------------- */
|
||||
/* 04/23/08 JRB 11 Add scl_sgcb_add. */
|
||||
/* 07/26/06 JRB 10 Add scl_subnet_add, scl_cap_add, scl_gse_add,*/
|
||||
/* scl_smv_add. */
|
||||
/* 04/04/06 JRB 09 Add scl_svcb_add: alloc SCL_SVCB & add to list.*/
|
||||
/* 03/15/06 JRB 08 Simplify functions: Do not copy data. */
|
||||
/* Most functions take only (SCL_INFO *) arg & */
|
||||
/* just alloc struct and add to linked list. */
|
||||
/* Del scl_dotype_add_da_val, */
|
||||
/* scl_datype_add_bda_val, scl_header_save. */
|
||||
/* 01/30/06 GLB 07 Integrated porting changes for VMS */
|
||||
/* 07/25/05 JRB 06 If nameStructure!=IEDName, ignore it and */
|
||||
/* assume nameStructure=IEDName anyway. */
|
||||
/* 06/29/05 CRM 05 Add scl_info_destroy. */
|
||||
/* 06/24/05 JRB 04 Chg "ord" from unsigned to signed value. */
|
||||
/* 02/15/05 JRB 03 Chg scl_ld_create to generate scl_ld->domName.*/
|
||||
/* Chg scl_fcda_add to generate scl_fcda->domName.*/
|
||||
/* Chg scl_ln_add to generate scl_ln->varName. */
|
||||
/* Add scl_header_save. */
|
||||
/* 07/19/04 JRB 02 Add scl_lcb_add, scl_gcb_add. */
|
||||
/* 06/10/04 JRB 01 Initial Revision. */
|
||||
/************************************************************************/
|
||||
#include "glbtypes.h"
|
||||
#include "sysincs.h"
|
||||
#include "scl.h"
|
||||
#include "sx_log.h"
|
||||
#include "str_util.h"
|
||||
|
||||
#ifdef DEBUG_SISCO
|
||||
SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__;
|
||||
#endif
|
||||
|
||||
|
||||
/* NOTE:
|
||||
* Functions with "scl_" prefix used while parsing SCL file to
|
||||
* store data in linked lists.
|
||||
* Functions with "scl2_" prefix (see sclproc.c) used to read info from
|
||||
* linked lists and create MMS objects (Domains, variables, NVLs, etc.).
|
||||
*/
|
||||
|
||||
/************************************************************************/
|
||||
/* scl_lntype_create */
|
||||
/* Begin creation of a Logical Node Type (LNodeType). */
|
||||
/* RETURNS: SD_SUCCESS or error code */
|
||||
/************************************************************************/
|
||||
SCL_LNTYPE *scl_lntype_create (
|
||||
SCL_INFO *scl_info) /* struct to store all SCL info */
|
||||
{
|
||||
SCL_LNTYPE *scl_lntype;
|
||||
|
||||
scl_lntype = (SCL_LNTYPE *) chk_calloc (1, sizeof (SCL_LNTYPE));
|
||||
/* Add LNType to front of LNType List. */
|
||||
list_add_first (&scl_info->lnTypeHead, scl_lntype);
|
||||
return (scl_lntype);
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* scl_lntype_add_do */
|
||||
/* Add a Data Object (DO) to a Logical Node Type (LNodeType). */
|
||||
/* Adds to lntype created by most recent call to "scl_lntype_create". */
|
||||
/* RETURNS: SD_SUCCESS or error code */
|
||||
/************************************************************************/
|
||||
SCL_DO *scl_lntype_add_do (
|
||||
SCL_INFO *scl_info) /* main struct where all SCL info stored*/
|
||||
{
|
||||
SCL_DO *scl_do = NULL; /* assume failure */
|
||||
|
||||
/* All higher level linked lists must be initialized. */
|
||||
if (scl_info->lnTypeHead)
|
||||
{
|
||||
scl_do = (SCL_DO *) chk_calloc (1, sizeof (SCL_DO));
|
||||
/* Add DO to front of DO List in first entry of LNType list */
|
||||
list_add_first (&scl_info->lnTypeHead->doHead, scl_do);
|
||||
}
|
||||
else
|
||||
SXLOG_ERR0 ("Cannot add DO to NULL LNTYPE");
|
||||
return (scl_do);
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* scl_dotype_create */
|
||||
/* Begin creation of a Data Object Type (DOType). */
|
||||
/* RETURNS: SD_SUCCESS or error code */
|
||||
/************************************************************************/
|
||||
SCL_DOTYPE *scl_dotype_create (
|
||||
SCL_INFO *scl_info) /* main struct where all SCL info stored*/
|
||||
{
|
||||
SCL_DOTYPE *scl_dotype;
|
||||
|
||||
scl_dotype = (SCL_DOTYPE *) chk_calloc (1, sizeof (SCL_DOTYPE));
|
||||
/* Add DOType to front of DOType List. */
|
||||
list_add_first (&scl_info->doTypeHead, scl_dotype);
|
||||
return (scl_dotype);
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* scl_dotype_add_da */
|
||||
/* Add a Data Attribute (DA) to a Data Object Type (DOType). */
|
||||
/* RETURNS: SD_SUCCESS or error code */
|
||||
/************************************************************************/
|
||||
SCL_DA *scl_dotype_add_da (
|
||||
SCL_INFO *scl_info) /* main struct where all SCL info stored*/
|
||||
{
|
||||
SCL_DA *scl_da = NULL; /* assume failure */
|
||||
|
||||
/* All higher level linked lists must be initialized. */
|
||||
if (scl_info->doTypeHead)
|
||||
{
|
||||
scl_da = (SCL_DA *) chk_calloc (1, sizeof (SCL_DA));
|
||||
/* CRITICAL: DA and SDO use same struct, "objtype" tells which one it is.*/
|
||||
scl_da->objtype = SCL_OBJTYPE_DA;
|
||||
/* Add DA to front of DA List in first entry of DOType list */
|
||||
list_add_first (&scl_info->doTypeHead->daHead, scl_da);
|
||||
}
|
||||
else
|
||||
SXLOG_ERR0 ("Cannot add DA to NULL DO");
|
||||
return (scl_da);
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* scl_dotype_add_sdo */
|
||||
/* Add a (SDO) to a Data Object Type (DOType). */
|
||||
/* RETURNS: SD_SUCCESS or error code */
|
||||
/************************************************************************/
|
||||
SCL_DA *scl_dotype_add_sdo (
|
||||
SCL_INFO *scl_info) /* main struct where all SCL info stored*/
|
||||
{
|
||||
SCL_DA *scl_da = NULL; /* assume failure */
|
||||
|
||||
/* All higher level linked lists must be initialized. */
|
||||
if (scl_info->doTypeHead)
|
||||
{
|
||||
scl_da = (SCL_DA *) chk_calloc (1, sizeof (SCL_DA));
|
||||
/* CRITICAL: DA and SDO use same struct, "objtype" tells which one it is.
|
||||
* NOTE: Because this is SDO, the sAddr, bType, and valKind members of
|
||||
* the scl_da structure are NOT used.
|
||||
*/
|
||||
scl_da->objtype = SCL_OBJTYPE_SDO;
|
||||
/* Add DA to front of DA List in first entry of DOType list */
|
||||
list_add_first (&scl_info->doTypeHead->daHead, scl_da);
|
||||
}
|
||||
else
|
||||
SXLOG_ERR0 ("Cannot add SDO to NULL DO");
|
||||
return (scl_da);
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* scl_datype_create */
|
||||
/* Begin creation of a Data Attribute Type (DAType). */
|
||||
/* RETURNS: SD_SUCCESS or error code */
|
||||
/************************************************************************/
|
||||
SCL_DATYPE *scl_datype_create (
|
||||
SCL_INFO *scl_info) /* main struct where all SCL info stored*/
|
||||
{
|
||||
SCL_DATYPE *scl_datype;
|
||||
|
||||
scl_datype = (SCL_DATYPE *) chk_calloc (1, sizeof (SCL_DATYPE));
|
||||
/* Add DAType to front of DAType List. */
|
||||
list_add_first (&scl_info->daTypeHead, scl_datype);
|
||||
return (scl_datype);
|
||||
}
|
||||
/************************************************************************/
|
||||
/* scl_datype_add_bda */
|
||||
/* Add a Basic Data Attribute (BDA) to a Data Attribute Type (DAType). */
|
||||
/* RETURNS: SD_SUCCESS or error code */
|
||||
/************************************************************************/
|
||||
SCL_BDA *scl_datype_add_bda (
|
||||
SCL_INFO *scl_info) /* main struct where all SCL info stored*/
|
||||
{
|
||||
SCL_BDA *scl_bda = NULL; /* assume failure */
|
||||
|
||||
/* All higher level linked lists must be initialized. */
|
||||
if (scl_info->daTypeHead)
|
||||
{
|
||||
scl_bda = (SCL_BDA *) chk_calloc (1, sizeof (SCL_BDA));
|
||||
/* Add BDA to front of BDA List in first entry of DAType list */
|
||||
list_add_first (&scl_info->daTypeHead->bdaHead, scl_bda);
|
||||
}
|
||||
else
|
||||
SXLOG_ERR0 ("Cannot add BDA to NULL DATYPE");
|
||||
return (scl_bda);
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* scl_enumtype_create */
|
||||
/* Begin creation of an EnumType. */
|
||||
/* RETURNS: SD_SUCCESS or error code */
|
||||
/************************************************************************/
|
||||
SCL_ENUMTYPE *scl_enumtype_create (
|
||||
SCL_INFO *scl_info) /* main struct where all SCL info stored*/
|
||||
{
|
||||
SCL_ENUMTYPE *scl_enumtype;
|
||||
|
||||
scl_enumtype = (SCL_ENUMTYPE *) chk_calloc (1, sizeof (SCL_ENUMTYPE));
|
||||
/* Add EnumType to front of EnumType List. */
|
||||
list_add_first (&scl_info->enumTypeHead, scl_enumtype);
|
||||
return (scl_enumtype);
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* scl_enumtype_add_enumval */
|
||||
/* Add an EnumVal to an EnumType. */
|
||||
/* Add to EnumType created by most recent call to scl_enumtype_create. */
|
||||
/* RETURNS: SD_SUCCESS or error code */
|
||||
/************************************************************************/
|
||||
SCL_ENUMVAL *scl_enumtype_add_enumval (
|
||||
SCL_INFO *scl_info) /* main struct where all SCL info stored*/
|
||||
{
|
||||
SCL_ENUMVAL *scl_enumval = NULL; /* assume failure */
|
||||
|
||||
/* All higher level linked lists must be initialized. */
|
||||
if (scl_info->enumTypeHead)
|
||||
{
|
||||
scl_enumval = (SCL_ENUMVAL *) chk_calloc (1, sizeof (SCL_ENUMVAL));
|
||||
/* Add EnumVal to front of EnumVal List in first entry of EnumType list */
|
||||
list_add_first (&scl_info->enumTypeHead->enumvalHead, scl_enumval);
|
||||
}
|
||||
else
|
||||
SXLOG_ERR0 ("Cannot add ENUMVAL to NULL ENUMTYPE");
|
||||
return (scl_enumval);
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* scl_fcda_add */
|
||||
/* Allocates a SCL_FCDA struct */
|
||||
/* and adds it to the linked list "fcdaHead" in SCL_DATASET. */
|
||||
/************************************************************************/
|
||||
SCL_FCDA *scl_fcda_add (
|
||||
SCL_INFO *scl_info) /* main struct where all SCL info stored*/
|
||||
{
|
||||
SCL_FCDA *scl_fcda = NULL; /* assume failure */
|
||||
|
||||
/* All higher level linked lists must be initialized. */
|
||||
if (scl_info->ldHead
|
||||
&& scl_info->ldHead->lnHead
|
||||
&& scl_info->ldHead->lnHead->datasetHead)
|
||||
{
|
||||
scl_fcda = (SCL_FCDA *) chk_calloc (1, sizeof (SCL_FCDA));
|
||||
/* Add FCDA to front of FCDA List. */
|
||||
list_add_first (&scl_info->ldHead->lnHead->datasetHead->fcdaHead, scl_fcda);
|
||||
}
|
||||
else
|
||||
SXLOG_ERR0 ("Cannot add FCDA to NULL DATASET");
|
||||
|
||||
return (scl_fcda);
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* scl_dai_add */
|
||||
/* Allocates a SCL_DAI struct */
|
||||
/* and adds it to the linked list "daiHead" in SCL_LN. */
|
||||
/************************************************************************/
|
||||
SCL_DAI *scl_dai_add (
|
||||
SCL_INFO *scl_info) /* main struct where all SCL info stored*/
|
||||
{
|
||||
SCL_DAI *scl_dai = NULL; /* assume failure */
|
||||
|
||||
/* All higher level linked lists must be initialized. */
|
||||
if (scl_info->ldHead
|
||||
&& scl_info->ldHead->lnHead)
|
||||
{
|
||||
scl_dai = (SCL_DAI *) chk_calloc (1, sizeof (SCL_DAI));
|
||||
/* Add DAI to front of DAI List. */
|
||||
list_add_first (&scl_info->ldHead->lnHead->daiHead, scl_dai);
|
||||
}
|
||||
else
|
||||
SXLOG_ERR0 ("Cannot add DAI to NULL LN");
|
||||
return (scl_dai);
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* scl_dataset_add */
|
||||
/* Allocates a SCL_DATASET struct */
|
||||
/* and adds it to the linked list "datasetHead" in SCL_LN. */
|
||||
/************************************************************************/
|
||||
SCL_DATASET *scl_dataset_add (
|
||||
SCL_INFO *scl_info) /* main struct where all SCL info stored*/
|
||||
/* TRUNCATED if longer than buffer */
|
||||
{
|
||||
SCL_DATASET *scl_dataset = NULL; /* assume failure */
|
||||
|
||||
/* All higher level linked lists must be initialized. */
|
||||
if (scl_info->ldHead
|
||||
&& scl_info->ldHead->lnHead)
|
||||
{
|
||||
scl_dataset = (SCL_DATASET *) chk_calloc (1, sizeof (SCL_DATASET));
|
||||
/* Add DATASET to front of DATASET List. */
|
||||
list_add_first (&scl_info->ldHead->lnHead->datasetHead, scl_dataset);
|
||||
}
|
||||
else
|
||||
SXLOG_ERR0 ("Cannot add DATASET to NULL LN");
|
||||
return (scl_dataset);
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* scl_rcb_add */
|
||||
/* Alloc & add SCL_RCB struct to the linked list "rcbHead" in SCL_LN. */
|
||||
/* NOTE: struct is not filled in yet. */
|
||||
/* NOTE: the RptEnabled element of the SCL file is ignored. SISCO software*/
|
||||
/* does not need to know which clients may access the RCB. */
|
||||
/************************************************************************/
|
||||
SCL_RCB *scl_rcb_add (
|
||||
SCL_INFO *scl_info) /* main struct where all SCL info stored*/
|
||||
{
|
||||
SCL_RCB *scl_rcb = NULL;
|
||||
|
||||
/* All higher level linked lists must be initialized. */
|
||||
if (scl_info->ldHead
|
||||
&& scl_info->ldHead->lnHead)
|
||||
{
|
||||
scl_rcb = (SCL_RCB *) chk_calloc (1, sizeof (SCL_RCB));
|
||||
/* Add RCB to front of RCB List. */
|
||||
list_add_first (&scl_info->ldHead->lnHead->rcbHead, scl_rcb);
|
||||
}
|
||||
else
|
||||
SXLOG_ERR0 ("Cannot add RCB to NULL LN");
|
||||
return (scl_rcb);
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* scl_lcb_add */
|
||||
/* Alloc & add a SCL_LCB struct to the linked list "lcbHead" in SCL_LN. */
|
||||
/* NOTE: struct is not filled in yet. */
|
||||
/************************************************************************/
|
||||
SCL_LCB *scl_lcb_add (
|
||||
SCL_INFO *scl_info) /* main struct where all SCL info stored*/
|
||||
{
|
||||
SCL_LCB *scl_lcb = NULL;
|
||||
|
||||
/* All higher level linked lists must be initialized. */
|
||||
if (scl_info->ldHead
|
||||
&& scl_info->ldHead->lnHead)
|
||||
{
|
||||
scl_lcb = (SCL_LCB *) chk_calloc (1, sizeof (SCL_LCB));
|
||||
/* Add LCB to front of LCB List. */
|
||||
list_add_first (&scl_info->ldHead->lnHead->lcbHead, scl_lcb);
|
||||
}
|
||||
else
|
||||
SXLOG_ERR0 ("Cannot add LCB to NULL LN");
|
||||
return (scl_lcb);
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* scl_gcb_add */
|
||||
/* Add a GOOSE Control Block (GCB). */
|
||||
/* Allocates a SCL_GCB struct */
|
||||
/* and adds it to the linked list "gcbHead" in SCL_LN. */
|
||||
/* NOTE: The SCL file may also contain one or more "IEDName" elements to*/
|
||||
/* indicate IEDs that should subscribe for GOOSE data. We have no */
|
||||
/* way to use this information, so it is ignored. */
|
||||
/************************************************************************/
|
||||
SCL_GCB *scl_gcb_add (
|
||||
SCL_INFO *scl_info) /* main struct where all SCL info stored*/
|
||||
{
|
||||
SCL_GCB *scl_gcb = NULL; /* assume failure */
|
||||
|
||||
/* All higher level linked lists must be initialized. */
|
||||
if (scl_info->ldHead
|
||||
&& scl_info->ldHead->lnHead)
|
||||
{
|
||||
scl_gcb = (SCL_GCB *) chk_calloc (1, sizeof (SCL_GCB));
|
||||
/* Add GCB to front of GCB List. */
|
||||
list_add_first (&scl_info->ldHead->lnHead->gcbHead, scl_gcb);
|
||||
}
|
||||
else
|
||||
SXLOG_ERR0 ("Cannot add GCB (GOOSE Control Block) to NULL LN");
|
||||
return (scl_gcb);
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* scl_sgcb_add */
|
||||
/* Add a Setting Group Control Block (SGCB). */
|
||||
/* Allocates a SCL_SGCB struct, stores ptr in "sgcb" in SCL_LN. */
|
||||
/************************************************************************/
|
||||
SCL_SGCB *scl_sgcb_add (
|
||||
SCL_INFO *scl_info) /* main struct where all SCL info stored*/
|
||||
{
|
||||
SCL_SGCB *scl_sgcb = NULL; /* assume failure */
|
||||
|
||||
/* All higher level linked lists must be initialized. */
|
||||
if (scl_info->ldHead
|
||||
&& scl_info->ldHead->lnHead)
|
||||
{
|
||||
/* Only one SGCB allowed. Make sure not already set. */
|
||||
if (scl_info->ldHead->lnHead->sgcb != NULL)
|
||||
{
|
||||
SXLOG_ERR0 ("Duplicate SGCB (Setting Group Control Block) not allowed");
|
||||
return (NULL);
|
||||
}
|
||||
else
|
||||
scl_info->ldHead->lnHead->sgcb = scl_sgcb = (SCL_SGCB *) chk_calloc (1, sizeof (SCL_SGCB));
|
||||
}
|
||||
else
|
||||
SXLOG_ERR0 ("Cannot add SGCB (Setting Group Control Block) to NULL LN");
|
||||
return (scl_sgcb);
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* scl_svcb_add */
|
||||
/* Alloc & add SCL_SVCB struct to the linked list "svcbHead" in SCL_LN. */
|
||||
/* NOTE: struct is not filled in yet. */
|
||||
/************************************************************************/
|
||||
SCL_SVCB *scl_svcb_add (
|
||||
SCL_INFO *scl_info) /* main struct where all SCL info stored*/
|
||||
{
|
||||
SCL_SVCB *scl_svcb = NULL; /* assume failure */
|
||||
|
||||
/* All higher level linked lists must be initialized. */
|
||||
if (scl_info->ldHead
|
||||
&& scl_info->ldHead->lnHead)
|
||||
{
|
||||
scl_svcb = (SCL_SVCB *) chk_calloc (1, sizeof(SCL_SVCB));
|
||||
/* Add to front of list. */
|
||||
list_add_first (&scl_info->ldHead->lnHead->svcbHead, scl_svcb);
|
||||
}
|
||||
else
|
||||
SXLOG_ERR0 ("Cannot add SVCB to NULL LN");
|
||||
return (scl_svcb);
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* scl_ln_add */
|
||||
/* Allocates a SCL_LN struct */
|
||||
/* and adds it to the linked list "lnHead" in SCL_LD. */
|
||||
/************************************************************************/
|
||||
SCL_LN *scl_ln_add (
|
||||
SCL_INFO *scl_info) /* main struct where all SCL info stored*/
|
||||
{
|
||||
SCL_LN *scl_ln = NULL; /* assume failure */
|
||||
|
||||
/* All higher level linked lists must be initialized. */
|
||||
if (scl_info->ldHead)
|
||||
{
|
||||
scl_ln = (SCL_LN *) chk_calloc (1, sizeof (SCL_LN));
|
||||
/* Add LN to front of LN List. */
|
||||
list_add_first (&scl_info->ldHead->lnHead, scl_ln);
|
||||
}
|
||||
else
|
||||
SXLOG_ERR0 ("Cannot add LN to NULL LD");
|
||||
return (scl_ln);
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* scl_ld_create */
|
||||
/* Allocates SCL_LD struct */
|
||||
/* and adds it to the linked list "ldHead" in SCL_INFO. */
|
||||
/************************************************************************/
|
||||
SCL_LD *scl_ld_create (
|
||||
SCL_INFO *scl_info) /* main struct where all SCL info stored*/
|
||||
{
|
||||
SCL_LD *scl_ld = NULL; /* assume failure */
|
||||
|
||||
scl_ld = (SCL_LD *) chk_calloc (1, sizeof (SCL_LD));
|
||||
/* Add LD to front of LD List. */
|
||||
list_add_first (&scl_info->ldHead, scl_ld);
|
||||
|
||||
return (scl_ld);
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* scl_subnet_add */
|
||||
/* Allocates SCL_SUBNET struct */
|
||||
/* and adds it to the linked list "subnetHead" in SCL_INFO. */
|
||||
/************************************************************************/
|
||||
SCL_SUBNET *scl_subnet_add (
|
||||
SCL_INFO *scl_info) /* main struct where all SCL info stored*/
|
||||
{
|
||||
SCL_SUBNET *scl_subnet = NULL; /* assume failure */
|
||||
|
||||
scl_subnet = (SCL_SUBNET *) chk_calloc (1, sizeof (SCL_SUBNET));
|
||||
/* Add to front of list. */
|
||||
list_add_first (&scl_info->subnetHead, scl_subnet);
|
||||
|
||||
return (scl_subnet);
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* scl_cap_add */
|
||||
/* Allocates a SCL_CAP struct */
|
||||
/* and adds it to the linked list "capHead" in SCL_SUBNET. */
|
||||
/************************************************************************/
|
||||
SCL_CAP *scl_cap_add (
|
||||
SCL_INFO *scl_info) /* main struct where all SCL info stored*/
|
||||
{
|
||||
SCL_CAP *scl_cap = NULL; /* assume failure */
|
||||
|
||||
/* All higher level linked lists must be initialized. */
|
||||
if (scl_info->subnetHead)
|
||||
{
|
||||
scl_cap = (SCL_CAP *) chk_calloc (1, sizeof (SCL_CAP));
|
||||
/* Add to front of list. */
|
||||
list_add_first (&scl_info->subnetHead->capHead, scl_cap);
|
||||
}
|
||||
else
|
||||
SXLOG_ERR0 ("Cannot add CAP to NULL SUBNET");
|
||||
return (scl_cap);
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* scl_gse_add */
|
||||
/* Allocates a SCL_GSE struct */
|
||||
/* and adds it to the linked list "gseHead" in SCL_CAP. */
|
||||
/************************************************************************/
|
||||
SCL_GSE *scl_gse_add (
|
||||
SCL_INFO *scl_info) /* main struct where all SCL info stored*/
|
||||
{
|
||||
SCL_GSE *scl_gse = NULL; /* assume failure */
|
||||
|
||||
/* All higher level linked lists must be initialized. */
|
||||
if (scl_info->subnetHead->capHead)
|
||||
{
|
||||
scl_gse = (SCL_GSE *) chk_calloc (1, sizeof (SCL_GSE));
|
||||
/* Add to front of list. */
|
||||
list_add_first (&scl_info->subnetHead->capHead->gseHead, scl_gse);
|
||||
}
|
||||
else
|
||||
SXLOG_ERR0 ("Cannot add GSE to NULL CAP");
|
||||
return (scl_gse);
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* scl_smv_add */
|
||||
/* Allocates a SCL_SMV struct */
|
||||
/* and adds it to the linked list "smvHead" in SCL_CAP. */
|
||||
/************************************************************************/
|
||||
SCL_SMV *scl_smv_add (
|
||||
SCL_INFO *scl_info) /* main struct where all SCL info stored*/
|
||||
{
|
||||
SCL_SMV *scl_smv = NULL; /* assume failure */
|
||||
|
||||
/* All higher level linked lists must be initialized. */
|
||||
if (scl_info->subnetHead->capHead)
|
||||
{
|
||||
scl_smv = (SCL_SMV *) chk_calloc (1, sizeof (SCL_SMV));
|
||||
/* Add to front of list. */
|
||||
list_add_first (&scl_info->subnetHead->capHead->smvHead, scl_smv);
|
||||
}
|
||||
else
|
||||
SXLOG_ERR0 ("Cannot add SMV to NULL CAP");
|
||||
return (scl_smv);
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* scl_info_destroy */
|
||||
/* Destroy all info stored in the SCL_INFO structure by "scl_parse". */
|
||||
/* NOTE: most buffers were allocated by functions in this module. The */
|
||||
/* elements "Val" and "desc" in several structures were allocated */
|
||||
/* by functions in "sclparse.c". */
|
||||
/************************************************************************/
|
||||
ST_VOID scl_info_destroy (SCL_INFO *scl_info)
|
||||
{
|
||||
SCL_LNTYPE *lnType;
|
||||
SCL_DO *scl_do;
|
||||
SCL_LD *scl_ld;
|
||||
SCL_LN *scl_ln;
|
||||
SCL_RCB *scl_rcb;
|
||||
SCL_LCB *scl_lcb;
|
||||
SCL_GCB *scl_gcb;
|
||||
SCL_SVCB *scl_svcb;
|
||||
SCL_DAI *scl_dai;
|
||||
SCL_DATASET *scl_dataset;
|
||||
SCL_FCDA *scl_fcda;
|
||||
SCL_DATYPE * scl_daType;
|
||||
SCL_BDA *scl_bda;
|
||||
SCL_ENUMTYPE *scl_enum;
|
||||
SCL_ENUMVAL *scl_enumval;
|
||||
SCL_DOTYPE *scl_doType;
|
||||
SCL_DA *scl_da;
|
||||
SCL_SUBNET *scl_subnet;
|
||||
SCL_CAP *scl_cap;
|
||||
SCL_GSE *scl_gse;
|
||||
SCL_SMV *scl_smv;
|
||||
|
||||
while ((scl_subnet = (SCL_SUBNET *) list_get_first(&scl_info->subnetHead)) != NULL)
|
||||
{
|
||||
while ((scl_cap = (SCL_CAP *) list_get_first(&scl_subnet->capHead)) != NULL)
|
||||
{
|
||||
while ((scl_gse = (SCL_GSE *) list_get_first(&scl_cap->gseHead)) != NULL)
|
||||
{
|
||||
chk_free(scl_gse);
|
||||
}
|
||||
while ((scl_smv = (SCL_SMV *) list_get_first(&scl_cap->smvHead)) != NULL)
|
||||
{
|
||||
chk_free(scl_smv);
|
||||
}
|
||||
if (scl_cap->desc)
|
||||
chk_free (scl_cap->desc);
|
||||
chk_free (scl_cap);
|
||||
}
|
||||
if (scl_subnet->desc)
|
||||
chk_free (scl_subnet->desc);
|
||||
chk_free (scl_subnet);
|
||||
}
|
||||
|
||||
while ((scl_daType = (SCL_DATYPE *) list_get_first (&scl_info->daTypeHead)) != NULL)
|
||||
{
|
||||
while ((scl_bda = (SCL_BDA *) list_get_first (&scl_daType->bdaHead)) != NULL)
|
||||
{
|
||||
if (scl_bda->desc)
|
||||
chk_free (scl_bda->desc);
|
||||
if (scl_bda->Val)
|
||||
chk_free (scl_bda->Val);
|
||||
chk_free (scl_bda);
|
||||
}
|
||||
chk_free (scl_daType);
|
||||
}
|
||||
|
||||
while ((lnType = (SCL_LNTYPE *) list_get_first (&scl_info->lnTypeHead)) != NULL)
|
||||
{
|
||||
while ((scl_do = (SCL_DO *) list_get_first (&lnType->doHead)) != NULL)
|
||||
{
|
||||
chk_free (scl_do);
|
||||
}
|
||||
chk_free (lnType);
|
||||
}
|
||||
while ((scl_doType = (SCL_DOTYPE *) list_get_first (&scl_info->doTypeHead)) != NULL)
|
||||
{
|
||||
while ((scl_da = (SCL_DA *) list_get_first (&scl_doType->daHead)) != NULL)
|
||||
{
|
||||
if (scl_da->desc)
|
||||
chk_free (scl_da->desc);
|
||||
if (scl_da->Val)
|
||||
chk_free (scl_da->Val);
|
||||
chk_free (scl_da);
|
||||
}
|
||||
chk_free (scl_doType);
|
||||
}
|
||||
while ((scl_enum = (SCL_ENUMTYPE *) list_get_first (&scl_info->enumTypeHead)) != NULL)
|
||||
{
|
||||
while ((scl_enumval = (SCL_ENUMVAL *) list_get_first (&scl_enum->enumvalHead)) != NULL)
|
||||
{
|
||||
chk_free (scl_enumval);
|
||||
}
|
||||
chk_free (scl_enum);
|
||||
}
|
||||
while ((scl_ld = (SCL_LD *) list_get_first (&scl_info->ldHead)) != NULL)
|
||||
{
|
||||
while ((scl_ln = (SCL_LN *) list_get_first (&scl_ld->lnHead)) != NULL)
|
||||
{
|
||||
while ((scl_dai = (SCL_DAI *) list_get_first (&scl_ln->daiHead)) != NULL)
|
||||
{
|
||||
if (scl_dai->Val)
|
||||
chk_free (scl_dai->Val);
|
||||
chk_free (scl_dai);
|
||||
}
|
||||
|
||||
while ((scl_dataset = (SCL_DATASET *) list_get_first (&scl_ln->datasetHead)) != NULL)
|
||||
{
|
||||
while ((scl_fcda = (SCL_FCDA *) list_get_first (&scl_dataset->fcdaHead)) != NULL)
|
||||
{
|
||||
chk_free (scl_fcda);
|
||||
}
|
||||
if (scl_dataset->desc)
|
||||
chk_free (scl_dataset->desc);
|
||||
chk_free (scl_dataset);
|
||||
}
|
||||
|
||||
while ((scl_rcb = (SCL_RCB *) list_get_first (&scl_ln->rcbHead)) != NULL)
|
||||
{
|
||||
if (scl_rcb->desc)
|
||||
chk_free (scl_rcb->desc);
|
||||
chk_free (scl_rcb);
|
||||
}
|
||||
|
||||
while ((scl_lcb = (SCL_LCB *) list_get_first (&scl_ln->lcbHead)) != NULL)
|
||||
{
|
||||
if (scl_lcb->desc)
|
||||
chk_free (scl_lcb->desc);
|
||||
chk_free (scl_lcb);
|
||||
}
|
||||
|
||||
while ((scl_gcb = (SCL_GCB *) list_get_first (&scl_ln->gcbHead)) != NULL)
|
||||
{
|
||||
if (scl_gcb->desc)
|
||||
chk_free (scl_gcb->desc);
|
||||
chk_free (scl_gcb);
|
||||
}
|
||||
while ((scl_svcb = (SCL_SVCB *) list_get_first (&scl_ln->svcbHead)) != NULL)
|
||||
{
|
||||
if (scl_svcb->desc)
|
||||
chk_free (scl_svcb->desc);
|
||||
chk_free (scl_svcb);
|
||||
}
|
||||
/* Only one SGCB allowed (no linked list) */
|
||||
if (scl_ln->sgcb)
|
||||
{
|
||||
if (scl_ln->sgcb->desc)
|
||||
chk_free (scl_ln->sgcb->desc);
|
||||
chk_free (scl_ln->sgcb);
|
||||
}
|
||||
if (scl_ln->desc)
|
||||
chk_free (scl_ln->desc);
|
||||
chk_free (scl_ln);
|
||||
}
|
||||
if (scl_ld->desc)
|
||||
chk_free (scl_ld->desc);
|
||||
chk_free (scl_ld);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
3815
mmslib/util/stdtime.c
Normal file
3815
mmslib/util/stdtime.c
Normal file
File diff suppressed because it is too large
Load Diff
194
mmslib/util/stdtime_mms_btime.c
Normal file
194
mmslib/util/stdtime_mms_btime.c
Normal file
@@ -0,0 +1,194 @@
|
||||
/*****************************************************************************/
|
||||
/* SISCO SOFTWARE MODULE HEADER **********************************************/
|
||||
/*****************************************************************************/
|
||||
/* (c) Copyright Systems Integration Specialists Company, Inc., */
|
||||
/* 2006 All Rights Reserved */
|
||||
/* */
|
||||
/* MODULE NAME : stdtime_mms_btime.c */
|
||||
/* PRODUCT(S) : Standard Time Management Library */
|
||||
/* */
|
||||
/* MODULE DESCRIPTION: */
|
||||
/* Support for MMS Btime4, BTime6 and BTOD conversions to/from STDTIME */
|
||||
/* */
|
||||
/* MODIFICATION LOG: */
|
||||
/* Date Who Rev Comments */
|
||||
/* -------- --- --- ----------------------------------------------------- */
|
||||
/* 02/20/08 JRB 02 Make STDTIME same as FILETIME (simplifies a lot). */
|
||||
/* Move T84_* defines to header file. */
|
||||
/* Del TimeOfDay4, Btod, and StdTimeFields functions. */
|
||||
/* 10/05/06 RLH 01 Created */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
#include "stdtime.h"
|
||||
#include "stdtime_mms_btime.h"
|
||||
|
||||
/*** MmsTimeOfDay6 initialization functions ***************************/
|
||||
|
||||
|
||||
STDTIME_MMS_TIMEOFDAY6 StdTimeApiZeroMmsTimeOfDay6 ()
|
||||
{
|
||||
STDTIME_MMS_TIMEOFDAY6 zero = {0};
|
||||
|
||||
return zero;
|
||||
|
||||
} /* StdTimeApiZeroMmsTimeOfDay6 */
|
||||
|
||||
|
||||
/*** MmsTimeOfDay6Ex functions ***********************************************/
|
||||
|
||||
|
||||
/*-***************************************************************************/
|
||||
/* StdTimeToMmsTimeOfDay6Ex */
|
||||
/* convert: StdTime struct to MMS_TIMEOFDAY6 and extra fields */
|
||||
/* method: subtract 1984-01-01 from stdTime to form delta */
|
||||
/*****************************************************************************/
|
||||
|
||||
STDTIME_RC StdTimeToMmsTimeOfDay6Ex (
|
||||
const STDTIME * /*I*/ pStdTime,
|
||||
STDTIME_MMS_TIMEOFDAY6 * /*O*/ pMmsTimeOfDay6,
|
||||
int32_t * /*O*/ pUsec,
|
||||
int32_t * /*O*/ pNsec)
|
||||
{
|
||||
/* pre-calculated STDTIME value of 1984-01-01 00:00:00.0000000 */
|
||||
STDTIME t84; /* initialized below */
|
||||
|
||||
STDTIME_DELTA mms;
|
||||
|
||||
STDTIME_ENUM_FUNC (StdTimeToMmsTimeOfDay6Ex)
|
||||
|
||||
if (pStdTime->dwHighDateTime < T84_HIGHDATETIME ||
|
||||
(pStdTime->dwHighDateTime == T84_HIGHDATETIME &&
|
||||
pStdTime->dwLowDateTime < T84_LOWDATETIME))
|
||||
{
|
||||
STDTIME_RET_EC (MMS_year_LT_1984);
|
||||
}
|
||||
|
||||
t84.dwHighDateTime = T84_HIGHDATETIME; /* initialize */
|
||||
t84.dwLowDateTime = T84_LOWDATETIME;
|
||||
|
||||
if (pMmsTimeOfDay6 == NULL)
|
||||
{
|
||||
STDTIME_RET_EC (null_argument);
|
||||
}
|
||||
|
||||
*pMmsTimeOfDay6 = StdTimeApiZeroMmsTimeOfDay6();
|
||||
|
||||
/* form difference between supplied date and 1984 */
|
||||
|
||||
if STDTIME_IFNOT (StdTime_GetDelta (pStdTime, &t84, &mms))
|
||||
{
|
||||
STDTIME_RET_RC;
|
||||
}
|
||||
|
||||
pMmsTimeOfDay6->day = mms.day;
|
||||
|
||||
pMmsTimeOfDay6->ms =
|
||||
(mms.hour * 60 * 60 * 1000) +
|
||||
(mms.min * 60 * 1000) +
|
||||
(mms.sec * 1000) + mms.msec;
|
||||
|
||||
if (pUsec != NULL)
|
||||
{
|
||||
*pUsec = mms.usec;
|
||||
}
|
||||
|
||||
if (pNsec != NULL)
|
||||
{
|
||||
*pNsec = mms.nsec;
|
||||
}
|
||||
|
||||
STDTIME_RET_OK;
|
||||
|
||||
} /* StdTimeToMmsTimeOfDay6Ex */
|
||||
|
||||
|
||||
/*-***************************************************************************/
|
||||
/* MmsTimeOfDay6ExToStdTime */
|
||||
/* convert: MMS_TIMEOFDAY6 and extra fields to StdTime struct */
|
||||
/* method: add MMS days and msec to base value of 1984-01-01 */
|
||||
/*****************************************************************************/
|
||||
|
||||
STDTIME_RC MmsTimeOfDay6ExToStdTime (
|
||||
const STDTIME_MMS_TIMEOFDAY6 * /*I*/ pMmsTimeOfDay6,
|
||||
int32_t /*I*/ nUsec,
|
||||
int32_t /*I*/ nNsec,
|
||||
STDTIME * /*O*/ pStdTime)
|
||||
{
|
||||
/* pre-calculated STDTIME value of 1984-01-01 00:00:00.0000000 */
|
||||
STDTIME t84; /* initialized below */
|
||||
STDTIME_DELTA mms = {0};
|
||||
|
||||
STDTIME_ENUM_FUNC (MmsTimeOfDay6ExToStdTime)
|
||||
|
||||
t84.dwHighDateTime = T84_HIGHDATETIME; /* initialize */
|
||||
t84.dwLowDateTime = T84_LOWDATETIME;
|
||||
|
||||
if (pStdTime == NULL)
|
||||
{
|
||||
STDTIME_RET_EC (null_argument);
|
||||
}
|
||||
|
||||
*pStdTime = ZeroStdTime ();
|
||||
|
||||
if (pMmsTimeOfDay6 == NULL)
|
||||
{
|
||||
STDTIME_RET_EC (null_argument);
|
||||
}
|
||||
|
||||
*pStdTime = ZeroStdTime();
|
||||
|
||||
/* create delta from 1984-01-01 */
|
||||
|
||||
mms.day = pMmsTimeOfDay6->day;
|
||||
mms.msec = pMmsTimeOfDay6->ms;
|
||||
mms.usec = nUsec;
|
||||
mms.nsec = nNsec;
|
||||
|
||||
/* add mms displacement to mms epoch date of Jan 1 1984 */
|
||||
|
||||
if STDTIME_IFNOT (StdTime_AddDelta (&t84, &mms))
|
||||
{
|
||||
STDTIME_RET_RC;
|
||||
}
|
||||
|
||||
*pStdTime = t84;
|
||||
|
||||
STDTIME_RET_OK;
|
||||
|
||||
} /* MmsTimeOfDay6ExToStdTime */
|
||||
|
||||
|
||||
/*** MmsTimeOfDay6 functions *************************************************/
|
||||
|
||||
|
||||
/*-***************************************************************************/
|
||||
/* StdTimeToMmsTimeOfDay6 */
|
||||
/* convert: StdTime struct to MMS_TIMEOFDAY6 (without extra fields) */
|
||||
/*****************************************************************************/
|
||||
|
||||
STDTIME_RC StdTimeToMmsTimeOfDay6 (
|
||||
const STDTIME * /*I*/ pStdTime,
|
||||
STDTIME_MMS_TIMEOFDAY6 * /*O*/ pMmsTimeOfDay6)
|
||||
{
|
||||
STDTIME_ENUM_FUNC (StdTimeToMmsTimeOfDay6)
|
||||
|
||||
STDTIME_RET (StdTimeToMmsTimeOfDay6Ex (pStdTime, pMmsTimeOfDay6, NULL, NULL));
|
||||
|
||||
} /* StdTimeToMmsTimeOfDay6 */
|
||||
|
||||
|
||||
/*-***************************************************************************/
|
||||
/* MmsTimeOfDay6ToStdTime */
|
||||
/* convert: MMS_TIMEOFDAY6 (without extra fields) to StdTime struct */
|
||||
/*****************************************************************************/
|
||||
|
||||
STDTIME_RC MmsTimeOfDay6ToStdTime (
|
||||
const STDTIME_MMS_TIMEOFDAY6 * /*I*/ pMmsTimeOfDay6,
|
||||
STDTIME * /*O*/ pStdTime)
|
||||
{
|
||||
STDTIME_ENUM_FUNC (MmsTimeOfDay6ToStdTime)
|
||||
|
||||
STDTIME_RET (MmsTimeOfDay6ExToStdTime (pMmsTimeOfDay6, 0, 0, pStdTime));
|
||||
|
||||
} /* MmsTimeOfDay6ToStdTime */
|
||||
169
mmslib/util/stdtime_mms_utctime.c
Normal file
169
mmslib/util/stdtime_mms_utctime.c
Normal file
@@ -0,0 +1,169 @@
|
||||
/*****************************************************************************/
|
||||
/* SISCO SOFTWARE MODULE HEADER **********************************************/
|
||||
/*****************************************************************************/
|
||||
/* (c) Copyright Systems Integration Specialists Company, Inc., */
|
||||
/* 2006 All Rights Reserved */
|
||||
/* */
|
||||
/* MODULE NAME : stdtime_mms_utctime.c */
|
||||
/* PRODUCT(S) : Standard Time Management Library */
|
||||
/* */
|
||||
/* MODULE DESCRIPTION: */
|
||||
/* Support for MMS UTC TIME conversions to/from STDTIME */
|
||||
/* */
|
||||
/* MODIFICATION LOG: */
|
||||
/* Date Who Rev Comments */
|
||||
/* -------- --- --- ----------------------------------------------------- */
|
||||
/* 02/20/08 JRB 02 Simplified StdTimeToMmsUtcTime (fixes rounding bug). */
|
||||
/* Simplified MmsUtcTimeToStdTime. */
|
||||
/* Delete StdTimeFields functions. */
|
||||
/* 10/05/06 RLH 01 Created */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
#include "stdtime.h"
|
||||
#include "stdtime_mms_utctime.h"
|
||||
|
||||
|
||||
/*** MmsUtcTime initialization function **************************************/
|
||||
|
||||
|
||||
STDTIME_MMS_UTC_TIME StdTimeApiZeroMmsUtcTime ()
|
||||
{
|
||||
STDTIME_MMS_UTC_TIME zero = {0};
|
||||
|
||||
return zero;
|
||||
|
||||
} /* StdTimeApiZeroMmsUtcTime */
|
||||
|
||||
|
||||
/*** MmsUtcTime functions ****************************************************/
|
||||
|
||||
|
||||
/*-***************************************************************************/
|
||||
/* StdTimeToMmsUtcTime */
|
||||
/* convert: StdTime structure to MMS_UTC_TIME */
|
||||
/* method: convert to TIMETYPE, then calculate binary fraction of second */
|
||||
/*****************************************************************************/
|
||||
|
||||
STDTIME_RC StdTimeToMmsUtcTime (
|
||||
const STDTIME * /*I*/ pStdTime,
|
||||
STDTIME_MMS_UTC_TIME * /*O*/ pMmsUtcTime)
|
||||
{
|
||||
QUADLIB_I64 qFrac;
|
||||
QUADLIB_I64 qRem;
|
||||
QUADLIB_I64 q10_7;
|
||||
QUADLIB_I64 q2_24;
|
||||
time_t timet;
|
||||
int32_t nsec;
|
||||
|
||||
STDTIME_ENUM_FUNC (StdTimeToMmsUtcTime)
|
||||
|
||||
|
||||
if (pMmsUtcTime == NULL)
|
||||
{
|
||||
STDTIME_RET_EC (null_argument);
|
||||
}
|
||||
|
||||
if STDTIME_IFNOT (StdTimeToTimeTypeEx (pStdTime, &timet, &nsec))
|
||||
{
|
||||
STDTIME_RET_RC;
|
||||
}
|
||||
|
||||
/* Init qFrac to number of 100-nsec intervals. */
|
||||
QUADLIB_I64_HI(qFrac) = 0;
|
||||
QUADLIB_I64_LO(qFrac) = nsec / 100;
|
||||
|
||||
QUADLIB_I64_HI(q10_7) = 0;
|
||||
QUADLIB_I64_LO(q10_7) = 10000000;
|
||||
|
||||
QUADLIB_I64_HI(q2_24) = 0;
|
||||
QUADLIB_I64_LO(q2_24) = 0x1000000;
|
||||
|
||||
/* multiply by range of UTC fraction */
|
||||
|
||||
QUADLIB_I64_MUL_EQ (qFrac, q2_24);
|
||||
|
||||
/* divide out number of 100-ns intervals */
|
||||
/* as 100-ns intervals approaches 10_7, frac approaches 2_24 */
|
||||
|
||||
qFrac = QuadLibI64DivMod (qFrac, q10_7, &qRem);
|
||||
|
||||
/* assign UTC values to output argument */
|
||||
|
||||
pMmsUtcTime->secs = (int32_t) timet;
|
||||
pMmsUtcTime->fraction = (int32_t) QUADLIB_I64_LO(qFrac);
|
||||
pMmsUtcTime->qflags = 0; /* IS THIS CORRECT ? */
|
||||
|
||||
STDTIME_RET_OK;
|
||||
|
||||
} /* StdTimeToMmsUtcTime */
|
||||
|
||||
|
||||
/*-***************************************************************************/
|
||||
/* MmsUtcTimeToStdTime */
|
||||
/* convert: MMS_UTC_TIME to StdTime structure */
|
||||
/*****************************************************************************/
|
||||
|
||||
STDTIME_RC MmsUtcTimeToStdTime (
|
||||
const STDTIME_MMS_UTC_TIME * /*I*/ pMmsUtcTime,
|
||||
STDTIME * /*O*/ pStdTime)
|
||||
{
|
||||
QUADLIB_I64 qFrac;
|
||||
QUADLIB_I64 qRem;
|
||||
QUADLIB_I64 q10_7;
|
||||
QUADLIB_I64 q2_24;
|
||||
int32_t nsec; /* nanoseconds */
|
||||
|
||||
STDTIME_ENUM_FUNC (MmsUtcTimeToStdTime)
|
||||
|
||||
if (pStdTime == NULL)
|
||||
{
|
||||
STDTIME_RET_EC (null_argument);
|
||||
}
|
||||
|
||||
*pStdTime = ZeroStdTime ();
|
||||
|
||||
if (pMmsUtcTime == NULL)
|
||||
{
|
||||
STDTIME_RET_EC (null_argument);
|
||||
}
|
||||
|
||||
/* Convert fraction to nsec, then call TimeTypeExToStdTime. */
|
||||
|
||||
/* obtain number of binary fractional units */
|
||||
|
||||
QUADLIB_I64_HI(q10_7) = 0;
|
||||
QUADLIB_I64_LO(q10_7) = 10000000;
|
||||
|
||||
QUADLIB_I64_HI(q2_24) = 0;
|
||||
QUADLIB_I64_LO(q2_24) = 0x1000000;
|
||||
|
||||
QUADLIB_I64_HI(qFrac) = 0;
|
||||
QUADLIB_I64_LO(qFrac) = pMmsUtcTime->fraction;
|
||||
|
||||
|
||||
/* multiply by range of 100-ns intervals */
|
||||
|
||||
QUADLIB_I64_MUL_EQ (qFrac, q10_7);
|
||||
|
||||
/* divide out number of binary fractional units */
|
||||
/* as fractional units approach 2**24, frac approaches 10**7 */
|
||||
|
||||
qFrac = QuadLibI64DivMod (qFrac, q2_24, &qRem);
|
||||
|
||||
if (QUADLIB_I64_LO(qRem) >= (10000000 / 2))
|
||||
{
|
||||
QUADLIB_I64_LO(qFrac)++; /* ROUND UP */
|
||||
}
|
||||
|
||||
nsec = (QUADLIB_I32_CASTI64 (qFrac)) * 100;
|
||||
|
||||
/* Convert and put result at pointer pStdTime. */
|
||||
if STDTIME_IFNOT (TimeTypeExToStdTime (pMmsUtcTime->secs, nsec, pStdTime))
|
||||
{
|
||||
STDTIME_RET_RC;
|
||||
}
|
||||
STDTIME_RET_OK;
|
||||
|
||||
} /* MmsUtcTimeToStdTime */
|
||||
|
||||
1599
mmslib/util/stdtime_quadlib.c
Normal file
1599
mmslib/util/stdtime_quadlib.c
Normal file
File diff suppressed because it is too large
Load Diff
1348
mmslib/util/stdtime_w32.c
Normal file
1348
mmslib/util/stdtime_w32.c
Normal file
File diff suppressed because it is too large
Load Diff
479
mmslib/util/stime.c
Normal file
479
mmslib/util/stime.c
Normal file
@@ -0,0 +1,479 @@
|
||||
/************************************************************************/
|
||||
/* SISCO SOFTWARE MODULE HEADER *****************************************/
|
||||
/************************************************************************/
|
||||
/* (c) Copyright Systems Integration Specialists Company, Inc., */
|
||||
/* 1993 - 2007, All Rights Reserved */
|
||||
/* */
|
||||
/* MODULE NAME : stime.c */
|
||||
/* PRODUCT(S) : */
|
||||
/* */
|
||||
/* MODULE DESCRIPTION : */
|
||||
/* This module implements functions that can be used in */
|
||||
/* differencial timimg. */
|
||||
/* */
|
||||
/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */
|
||||
/* */
|
||||
/* MODIFICATION LOG : */
|
||||
/* Date Who Rev Comments */
|
||||
/* -------- --- ------ ------------------------------------------- */
|
||||
/* 01/15/07 EJV 30 Chg S_LOCK_RESOURCES to S_LOCK_UTIL_RESOURCES*/
|
||||
/* 10/26/06 EJV 29 HP-UX: changed from gettimeofday() to times()*/
|
||||
/* 07/13/06 EJV 28 Sun: changed from gettimeofday() to times(). */
|
||||
/* 06/20/06 RKR 27 removed a piece of code from _sGetSysMsTime */
|
||||
/* 05/31/06 GLB 26 Integrated porting changes for VMS */
|
||||
/* 03/23/06 EJV 25 Corrected VMS chg to _sGetSysMsTime. */
|
||||
/* Rearranged includes, del windows.h. */
|
||||
/* 01/30/06 GLB 24 Integrated porting changes for VMS */
|
||||
/* 01/30/06 EJV 23 _WIN32 _sGetSysMsTime: added (ST_INT64) cast */
|
||||
/* before (ST_DOUBLE) to eliminate VS6 compiler*/
|
||||
/* error after changing ST_UINT64 define to */
|
||||
/* unsigned __int64. */
|
||||
/* 06/10/05 EJV 22 Revised the repeating code. */
|
||||
/* Linux, QNX: rpl gettimeofday() with times(). */
|
||||
/* Del MSDOS and __OS2__ code. */
|
||||
/* Del sGetMsStartTime, sSetMsStartTime */
|
||||
/* Renamed lastTime to initTime. */
|
||||
/* 03/11/04 GLB 21 Remove "thisFileName" */
|
||||
/* 12/09/03 JRB 20 Add LYNX support. */
|
||||
/* 11/04/03 JRB 19 Add sMsSleep (replaces gs_sleep). */
|
||||
/* 10/13/03 EJV 18 Chg defined(vms) to defined(__VMS) */
|
||||
/* 04/08/03 EJV 17 Use S_LOCK_RESOURCES (better for non-MT apps)*/
|
||||
/* 03/21/03 EJV 16 _WIN32: sGetMsTime, sGetSysMsTime must be */
|
||||
/* protected by mutex,prevent incorect wrapCount*/
|
||||
/* 03/18/03 EJV 15 Corrected __QNX4__ to __QNX__ (per JRB). */
|
||||
/* 03/18/03 EJV 14 sGetMsTime: fixed lastTime casting problem */
|
||||
/* (made lastTime ST_UINT on _WIN32). */
|
||||
/* 02/17/03 CRM 13 Added "defined(linux)" code. */
|
||||
/* 02/17/03 JRB 12 Add "sysincs.h" & del other includes. */
|
||||
/* Del obsolete _WINDOWS, MSOS2 code. */
|
||||
/* 02/17/03 EJV 11 sGetMsTime, sGetSysMsTime: fixed wrap counter*/
|
||||
/* Auto-initialize funs with call to stimeInit()*/
|
||||
/* Chg S_LOCK_RESOURCES to gs_get_sem,avoid loop*/
|
||||
/* 06/05/02 MDE,EJV 10 sGetMsTime: workaround some math problem */
|
||||
/* 11/29/01 EJV 09 Del code for old LATT, XENIX, ultrix, RMX86. */
|
||||
/* 06/19/01 JRB 08 Chg S_LOCK_COMMON.. to S_LOCK_RESOURCES so */
|
||||
/* glbsem doesn't log (caused infinite loop). */
|
||||
/* 04/19/00 JRB 07 Lint cleanup. */
|
||||
/* 11/18/99 EJV 06 Added code to capture wrapping of ms counter */
|
||||
/* for _WIN32 and PHARLAP_ETS. */
|
||||
/* 09/13/99 MDE 05 Added SD_CONST modifiers */
|
||||
/* 11/05/97 DSF 04 Added sGetSysMsTime () */
|
||||
/* 09/22/97 JRB 03 Fixed some #if's. */
|
||||
/* 09/09/97 JRB 02 Use GetTickCount for PHARLAP_ETS. */
|
||||
/* 09/08/97 EJV 01 Added code for QNX. */
|
||||
/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */
|
||||
/* history. */
|
||||
/************************************************************************/
|
||||
|
||||
|
||||
#include "glbtypes.h"
|
||||
#include "sysincs.h"
|
||||
#include "glbsem.h"
|
||||
|
||||
#if defined (_WIN32)
|
||||
#include <mmsystem.h>
|
||||
#if defined (PHARLAP_ETS)
|
||||
#define timeGetTime GetTickCount /* timeGetTime not supported */
|
||||
#endif /* PHARLAP_ETS */
|
||||
#endif
|
||||
|
||||
#if defined(__VMS)
|
||||
#include <starlet.h>
|
||||
#endif
|
||||
|
||||
#if defined(linux) || defined(sun) || defined(__hpux) || \
|
||||
defined(__QNX__) || defined(__LYNX)
|
||||
#include <sys/times.h> /* for struct tms */
|
||||
#endif
|
||||
|
||||
/************************************************************************/
|
||||
/* NOTE: Users porting this code to new platform should not use the */
|
||||
/* gettimeofday() or similar functions. When the system time */
|
||||
/* is changed, for example during clock synchronization, the */
|
||||
/* gettimeofday() would also reflect this change. */
|
||||
/* Application should use times() function if available. */
|
||||
/* */
|
||||
/* DEBUG: On UNIX systems we should implement the sTime functions */
|
||||
/* the same way as on LINUX. */
|
||||
/************************************************************************/
|
||||
|
||||
/*------------------------------------------------------*/
|
||||
/* stime module variables */
|
||||
/*------------------------------------------------------*/
|
||||
|
||||
#if defined(linux) || defined(sun) || defined(__hpux)
|
||||
static ST_UINT64 wrapCount; /* ms, cumulative wrapped time ticks elapsed since program start*/
|
||||
|
||||
#elif (defined (__QNX__) || defined(__LYNX))
|
||||
static ST_DOUBLE wrapCount; /* ms, cumulative wrapped time ticks elapsed since program start*/
|
||||
|
||||
#elif defined (_WIN32)
|
||||
static ST_UINT64 wrapCount; /* wrap count (see timeGetTime or GetTickTime) */
|
||||
#endif
|
||||
|
||||
#if defined (__ECOS)
|
||||
#define ST_UINT64 unsigned long long
|
||||
static unsigned long long wrapCount;
|
||||
#endif
|
||||
|
||||
static ST_ULONG ticksPerSec; /* system dependent value, returned by sysconf(_SC_CLK_TCK) */
|
||||
static ST_ULONG lastCheckTime; /* last time checked, used to detect clock_t overflow */
|
||||
static ST_DOUBLE initMsTime; /* in ms, store initialization time */
|
||||
static ST_INT initialized; /* SD_TRUE if stimeInit func successful */
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* _sGetSysMsTime */
|
||||
/*----------------------------------------------------------------------*/
|
||||
/* Combined code from sGetMsTime and sGetSysMsTime, now also called by */
|
||||
/* stimeInit. */
|
||||
/* */
|
||||
/* NOTE: this new implementation on LINUX uses the times() function */
|
||||
/* to obtain the "number of clock ticks that have elapsed since */
|
||||
/* an arbitrary point in the past. For Linux this point is the */
|
||||
/* moment the system was booted. The return from times() may */
|
||||
/* overflow the possible range of clock_t." */
|
||||
/* The revision of the IEEE Std 1003.1, 2004 allows the that */
|
||||
/* reference point can be the start-up time of the process */
|
||||
/* rather than system start-up time. */
|
||||
/* IMPORTANT: */
|
||||
/* This implementation is assuming that POSIX compliant clock_t */
|
||||
/* type is defined as long (4 bytes integer). If this is not the */
|
||||
/* case then the code needs to be revised! */
|
||||
/* */
|
||||
/* DEBUG: In the future LINUX implementation should be used for all */
|
||||
/* UNIX systems. */
|
||||
/************************************************************************/
|
||||
|
||||
static ST_DOUBLE _sGetSysMsTime (ST_VOID)
|
||||
{
|
||||
ST_DOUBLE sysMsTime = (ST_DOUBLE) 0.0; /* system time to be returned */
|
||||
|
||||
#if defined(linux) || defined(sun) || defined(__hpux)
|
||||
{
|
||||
struct tms tmsTime; /* must be passed to times() but we do not use it */
|
||||
ST_ULONG sysTime;
|
||||
|
||||
sysTime = (ST_ULONG) times (&tmsTime);
|
||||
if (sysTime != (ST_ULONG) -1)
|
||||
{
|
||||
/* NOTE: The value returned from the times() function (number of ticks */
|
||||
/* from some fixed point in time) will wrap. */
|
||||
/* Wrapping depends on the frequency (ticksPerSec) and can be as */
|
||||
/* often as every 39 minutes. This function needs to be called */
|
||||
/* frequently enough to detect when the value wraps. */
|
||||
#if 0 /* DEBUG: code to test wrapping, */
|
||||
/* trigger the wrapping every 60 seconds if this funct is called */
|
||||
if ( (sysTime > ticksPerSec) && /* don't wrap before 1-st second elapses*/
|
||||
((sysTime / ticksPerSec) % 60 == 0) )
|
||||
lastCheckTime=sysTime+1; /* tweek the lastCheckTime */
|
||||
#endif
|
||||
if (sysTime < lastCheckTime)
|
||||
/* the ticks counter wrapped to 0 */
|
||||
wrapCount += ((ST_UINT64) 1 << 32); /* increment the high part of ST_UINT64 */
|
||||
/* convert the sys time to ms accounting for possible wrap */
|
||||
/* (switch math operations order / with * for better precission, avoid floating point math) */
|
||||
sysMsTime = (ST_DOUBLE)((wrapCount + (ST_UINT64) sysTime) * 1000 / (ST_UINT64) ticksPerSec);
|
||||
lastCheckTime = sysTime; /* save for next check */
|
||||
}
|
||||
else
|
||||
{
|
||||
ST_INT err;
|
||||
err = errno; /* can't log this error but we could see it in debugger */
|
||||
}
|
||||
}
|
||||
#elif defined(__ECOS)
|
||||
{
|
||||
struct timeval tp;
|
||||
struct timezone tzp;
|
||||
gettimeofday (&tp, &tzp); /* avoid floating math */
|
||||
sysMsTime = (ST_DOUBLE) ( (ST_UINT64) ((ST_ULONG) tp.tv_sec) * (ST_UINT64) 1000 +
|
||||
(ST_UINT64) ((ST_ULONG) tp.tv_usec) / (ST_UINT64) 1000 );
|
||||
#if 0
|
||||
cyg_tick_count_t sysTime; /* in ecos, cyg_tick_count_t is defined by cyg_uint64 */
|
||||
|
||||
sysTime = cyg_current_time();
|
||||
sysMsTime = (ST_DOUBLE)((wrapCount + (ST_UINT64) sysTime) * 1000 / (ST_UINT64) ticksPerSec);
|
||||
#endif
|
||||
}
|
||||
#elif defined(_AIX) || (defined(__alpha) && !defined(__VMS)) /* Tru64 alpha */
|
||||
{
|
||||
struct timeval tp;
|
||||
struct timezone tzp;
|
||||
gettimeofday (&tp, &tzp); /* avoid floating math */
|
||||
sysMsTime = (ST_DOUBLE) ( (ST_UINT64) ((ST_ULONG) tp.tv_sec) * (ST_UINT64) 1000 +
|
||||
(ST_UINT64) ((ST_ULONG) tp.tv_usec) / (ST_UINT64) 1000 );
|
||||
}
|
||||
#elif defined(__VMS) /* OpenVMS non-specific */
|
||||
{
|
||||
struct timeval tp;
|
||||
ST_LONG tzp;
|
||||
gettimeofday (&tp, &tzp); /* avoid floating math */
|
||||
sysMsTime = (ST_DOUBLE)
|
||||
(
|
||||
/*(ST_UINT64)*/ ((ST_ULONG) tp.tv_sec) * /*(ST_UINT64)*/ 1000 +
|
||||
/*(ST_UINT64)*/ ((ST_ULONG) tp.tv_usec) / /*(ST_UINT64)*/ 1000
|
||||
);
|
||||
}
|
||||
#elif defined (VXWORKS)
|
||||
{
|
||||
/*renxiaobao add*/
|
||||
struct timeval tp;
|
||||
vx_gettimeofday (&tp,0);
|
||||
sysMsTime = ((ST_DOUBLE)tp.tv_sec)*1000 + ((ST_DOUBLE)tp.tv_usec)/1000;
|
||||
/*sysMsTime = (ST_DOUBLE) time (NULL) * 1000;*/
|
||||
}
|
||||
#elif (defined (__QNX__) || defined(__LYNX))
|
||||
{
|
||||
struct tms tmsTime; /* must be passed to times() but we do not use it */
|
||||
ST_ULONG sysTime;
|
||||
|
||||
sysTime = (ST_ULONG) times (&tmsTime);
|
||||
if (sysTime != (ST_ULONG) -1)
|
||||
{
|
||||
/* NOTE: The value returned from the times() function (number of ticks */
|
||||
/* from some fixed point in time) will wrap. */
|
||||
/* Wrapping depends on the frequency (ticksPerSec) and can be as */
|
||||
/* often as every 39 minutes. This function needs to be called */
|
||||
/* frequently enough to detect when the value wraps. */
|
||||
if (sysTime < lastCheckTime)
|
||||
/* the ticks counter wrapped to 0 */
|
||||
wrapCount += (ST_DOUBLE) (ULONG_MAX);
|
||||
/* convert the sys time to ms accounting for possible wrap, */
|
||||
/* note that we do not have ST_INT64 support on QNX or LYNX systems */
|
||||
sysMsTime = (ST_DOUBLE)((wrapCount + (ST_DOUBLE) sysTime) * 1000.0 / (ST_DOUBLE) ticksPerSec);
|
||||
lastCheckTime = sysTime; /* save for next check */
|
||||
}
|
||||
}
|
||||
#elif defined (_WIN32)
|
||||
{
|
||||
ST_ULONG msTime;
|
||||
|
||||
/* the timeGetTime function retrieves the system time, in milliseconds.*/
|
||||
/* The system time is the time elapsed since Windows was started. */
|
||||
|
||||
/* NOTE: The timeGetTime and GetTickCount (used for PHARLAP_ETS) */
|
||||
/* return DWORD value that wraps to 0 every 49 days. */
|
||||
/* We need to detect the wrap up moment and save it. */
|
||||
msTime = (ST_ULONG) timeGetTime ();
|
||||
if ( msTime < lastCheckTime )
|
||||
/* the ms counter wrapped to 0 */
|
||||
wrapCount += ( (ST_UINT64) 1 << 32 ); /* increment the high part of ST_UINT64 */
|
||||
sysMsTime = (ST_DOUBLE) (ST_INT64) (wrapCount + (ST_UINT64) msTime);
|
||||
/* NOTE VC V6.0 compiler: the compiler generates error for the */
|
||||
/* conversion of unsigned __int64 to double. We will cast to */
|
||||
/* ST_INT64 before the ST_DOUBLE cast. This should work */
|
||||
/* because the sum of both numbers will 'never' be negative. */
|
||||
|
||||
lastCheckTime = msTime; /* save for next check */
|
||||
}
|
||||
#else
|
||||
#error Missing stime module implementation for this platform
|
||||
#endif
|
||||
|
||||
return (sysMsTime);
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* _stimeReset */
|
||||
/*----------------------------------------------------------------------*/
|
||||
/* Resets stime module variables. */
|
||||
/************************************************************************/
|
||||
|
||||
static ST_RET _stimeReset (ST_VOID)
|
||||
{
|
||||
ST_RET rtn = SD_SUCCESS;
|
||||
|
||||
#if (defined(linux) || defined(sun) || defined(__hpux) || defined(_WIN32))
|
||||
wrapCount = 0;
|
||||
lastCheckTime = 0;
|
||||
#elif (defined(__QNX__) || defined(__LYNX))
|
||||
wrapCount = 0.0;
|
||||
lastCheckTime = 0;
|
||||
#endif
|
||||
|
||||
initMsTime = _sGetSysMsTime ();
|
||||
|
||||
return (rtn);
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* stimeInit */
|
||||
/*----------------------------------------------------------------------*/
|
||||
/* Initialize stime module variables. */
|
||||
/************************************************************************/
|
||||
|
||||
ST_RET stimeInit (ST_VOID)
|
||||
{
|
||||
ST_RET rtn = SD_SUCCESS;
|
||||
|
||||
/* Allow multiple calls */
|
||||
if (initialized)
|
||||
return (rtn);
|
||||
|
||||
S_LOCK_UTIL_RESOURCES (); /* NOTE: this macro is now using non-logging gs_get_sem() */
|
||||
|
||||
#if defined(linux) || defined(sun) || defined(__hpux) || defined(__QNX__) || defined(__LYNX)
|
||||
{
|
||||
ticksPerSec = 0;
|
||||
|
||||
ticksPerSec = (ST_ULONG) sysconf(_SC_CLK_TCK);
|
||||
if (ticksPerSec == (ST_ULONG) -1L || ticksPerSec == 0)
|
||||
rtn = SD_FAILURE; /* some error getting the number of clock ticks per second */
|
||||
}
|
||||
#endif
|
||||
|
||||
if (rtn == SD_SUCCESS)
|
||||
{
|
||||
rtn = _stimeReset ();
|
||||
if (rtn == SD_SUCCESS)
|
||||
initialized = SD_TRUE;
|
||||
}
|
||||
|
||||
S_UNLOCK_UTIL_RESOURCES ();
|
||||
|
||||
return (rtn);
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* sGetMsTime */
|
||||
/*----------------------------------------------------------------------*/
|
||||
/* Returns time in milliseconds form the start of the program. */
|
||||
/************************************************************************/
|
||||
|
||||
ST_DOUBLE sGetMsTime (ST_VOID)
|
||||
{
|
||||
ST_DOUBLE sysMsTime, retMsTime;
|
||||
|
||||
if (!initialized)
|
||||
if (stimeInit () != SD_SUCCESS)
|
||||
return ((ST_DOUBLE)0.0);
|
||||
|
||||
S_LOCK_UTIL_RESOURCES ();
|
||||
|
||||
sysMsTime = _sGetSysMsTime();
|
||||
retMsTime = sysMsTime - initMsTime;
|
||||
|
||||
S_UNLOCK_UTIL_RESOURCES ();
|
||||
|
||||
return (retMsTime);
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* sGetSysMsTime */
|
||||
/*----------------------------------------------------------------------*/
|
||||
/* Returns system time in milliseconds (time from an arbitrary point */
|
||||
/* like system start or program start). */
|
||||
/************************************************************************/
|
||||
|
||||
ST_DOUBLE sGetSysMsTime (ST_VOID)
|
||||
{
|
||||
ST_DOUBLE sysMsTime;
|
||||
|
||||
if (!initialized)
|
||||
if (stimeInit () != SD_SUCCESS)
|
||||
return ((ST_DOUBLE)0.0);
|
||||
|
||||
S_LOCK_UTIL_RESOURCES ();
|
||||
|
||||
sysMsTime = _sGetSysMsTime();
|
||||
|
||||
S_UNLOCK_UTIL_RESOURCES ();
|
||||
|
||||
return (sysMsTime);
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* sResetMsTime */
|
||||
/*----------------------------------------------------------------------*/
|
||||
/* Reset stime module variables. */
|
||||
/************************************************************************/
|
||||
|
||||
ST_VOID sResetMsTime (ST_VOID)
|
||||
{
|
||||
if (!initialized)
|
||||
{
|
||||
stimeInit (); /* calls the _stimeReset() */
|
||||
return;
|
||||
}
|
||||
|
||||
S_LOCK_UTIL_RESOURCES ();
|
||||
|
||||
_stimeReset ();
|
||||
|
||||
S_UNLOCK_UTIL_RESOURCES ();
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* stimeExit */
|
||||
/*----------------------------------------------------------------------*/
|
||||
/* Terminate timer use. */
|
||||
/************************************************************************/
|
||||
|
||||
ST_VOID stimeExit (ST_VOID)
|
||||
{
|
||||
if (!initialized)
|
||||
return;
|
||||
|
||||
S_LOCK_UTIL_RESOURCES ();
|
||||
|
||||
initialized = SD_FALSE;
|
||||
|
||||
S_UNLOCK_UTIL_RESOURCES ();
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* sMsSleep */
|
||||
/*----------------------------------------------------------------------*/
|
||||
/* Calls system function to suspend current task or thread for */
|
||||
/* specified amount of time. */
|
||||
/* Parameters: */
|
||||
/* ST_LONG ms Number of milliseconds to sleep */
|
||||
/* Return values: */
|
||||
/* none */
|
||||
/************************************************************************/
|
||||
|
||||
#if defined(_WIN32)
|
||||
|
||||
ST_VOID sMsSleep (ST_LONG ms)
|
||||
{
|
||||
Sleep (ms);
|
||||
}
|
||||
|
||||
#elif defined(__VMS)
|
||||
|
||||
ST_VOID sMsSleep (ST_LONG ms)
|
||||
{
|
||||
ST_ULONG msec = (ST_ULONG) ms;
|
||||
unsigned int us;
|
||||
|
||||
while (msec > 0)
|
||||
{
|
||||
if (msec >= 1000)
|
||||
{
|
||||
us = 999999; /* microseconds, it must be less than 1000000 for usleep */
|
||||
msec -= 1000;
|
||||
}
|
||||
else
|
||||
{
|
||||
us = msec * 1000;
|
||||
msec = 0;
|
||||
}
|
||||
usleep (us); /* unistd.h */
|
||||
}
|
||||
}
|
||||
|
||||
#else /* all other systems */
|
||||
|
||||
/* This version of the function uses the POSIX nanosleep function. */
|
||||
ST_VOID sMsSleep (ST_LONG ms)
|
||||
{
|
||||
struct timespec rqtp;
|
||||
|
||||
rqtp.tv_sec = ms / 1000;
|
||||
rqtp.tv_nsec = (ms % 1000) * 1000000; /* 1000 ms/us, 1000 us/ns ... */
|
||||
|
||||
nanosleep (&rqtp, NULL); /* should be available on AIX v5.x */
|
||||
}
|
||||
|
||||
#endif /* all other systems */
|
||||
947
mmslib/util/str_util.c
Normal file
947
mmslib/util/str_util.c
Normal file
@@ -0,0 +1,947 @@
|
||||
/************************************************************************/
|
||||
/* SISCO SOFTWARE MODULE HEADER *****************************************/
|
||||
/************************************************************************/
|
||||
/* (c) Copyright Systems Integration Specialists Company, Inc., */
|
||||
/* 2000 - 2007 All Rights Reserved */
|
||||
/* */
|
||||
/* MODULE NAME : str_util.c */
|
||||
/* PRODUCT(S) : General Use */
|
||||
/* */
|
||||
/* MODULE DESCRIPTION : */
|
||||
/* General purpose string manipulation functions. */
|
||||
/* */
|
||||
/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */
|
||||
/* ascii_to_hex_str */
|
||||
/* hex_to_ascii_str */
|
||||
/* strnicmp (UNIX) */
|
||||
/* strcmpi (UNIX) */
|
||||
/* stricmp (UNIX) */
|
||||
/* strncat_maxstrlen */
|
||||
/* strncpy_safe */
|
||||
/* asciiToSlong */
|
||||
/* asciiToUlong */
|
||||
/* asciiToSint */
|
||||
/* asciiToUint */
|
||||
/* asciiToSint32 */
|
||||
/* asciiToUint32 */
|
||||
/* asciiToSint16 */
|
||||
/* asciiToUint16 */
|
||||
/* asciiToSint8 */
|
||||
/* asciiToUint8 */
|
||||
/* asciiToUchar */
|
||||
/* asciiToFloat */
|
||||
/* asciiToDouble */
|
||||
/* sInt8ToAscii */
|
||||
/* uInt8ToAscii */
|
||||
/* sInt16ToAscii */
|
||||
/* uInt16ToAscii */
|
||||
/* sInt32ToAscii */
|
||||
/* uInt32ToAscii */
|
||||
/* sIntToAscii */
|
||||
/* uIntToAscii */
|
||||
/* sLongToAscii */
|
||||
/* uLongToAscii */
|
||||
/* getKeywordFromFile */
|
||||
/* */
|
||||
/* MODIFICATION LOG : */
|
||||
/* Date Who Rev Comments */
|
||||
/* -------- --- ------ ------------------------------------------- */
|
||||
/* 11/07/07 EJV 23 Check before defining INT32_MAX, UINT32_MAX. */
|
||||
/* 10/29/07 JRB 22 Add strncat_maxstrlen. Del strncat_safe (len */
|
||||
/* was wrong), use strncat or strncat_maxstrlen.*/
|
||||
/* 10/11/07 JRB 21 Add asciiToSint32, asciiToUint32 */
|
||||
/* 08/03/07 JRB 20 get_next_string: don't ignore extra delimiters*/
|
||||
/* They now indicate empty field (as in Excel). */
|
||||
/* 02/13/06 DSF 19 Migrate to VS.NET 2005 */
|
||||
/* 07/28/05 DWL 18 Corrected microsecond resolution, use const */
|
||||
/* ST_CHAR* in asciiTo* functions. */
|
||||
/* 03/14/05 JRB 17 Add get_next_string. */
|
||||
/* 12/03/04 JRB 16 Use strcasecmp, strncasecmp if supported. */
|
||||
/* Don't need SISCO strnicmp, etc. */
|
||||
/* 07/09/04 JRB 15 Add strncat_safe, strncpy_safe. */
|
||||
/* 03/09/04 EJV 14 Added getKeywordFromFile function. */
|
||||
/* 12/12/03 JRB 13 Add LYNX support. */
|
||||
/* 12/10/03 MDE 12 Added itoa/ltoa/utoa/ultoa replacements */
|
||||
/* 04/10/03 DSF 11 Added strnstr */
|
||||
/* 02/20/03 JRB 10 Del PSOS code. */
|
||||
/* 12/20/02 CRM 09 Added "defined(linux)" for strcmpi, etc. */
|
||||
/* 03/01/02 EJV 08 Can't check doubleNum < FLT_MIN (0.0 fails). */
|
||||
/* 02/28/02 EJV 07 Added asciiToFloat, asciiToDouble. */
|
||||
/* 02/25/02 EJV 06 Replaced non-ANSI ltoa with sprintf. */
|
||||
/* Added asciiToUlong, asciiToUint16, */
|
||||
/* asciiToUint8, asciiToSint, asciiToUint */
|
||||
/* hex_to_ascii_str: added param hex_no_spaces. */
|
||||
/* asciiToxxx:eliminated dependency on sx_defs.h*/
|
||||
/* 12/09/01 GLB 05 Added asciiToSlong, asciiToSint16, */
|
||||
/* asciiToSint8, asciiToUchar */
|
||||
/* 05/21/01 MDE 04 Added bitstring_to_ascii_str */
|
||||
/* 01/19/01 EJV 03 Moved strcmpi,stricmp,strnicmp from cfg_util */
|
||||
/* 11/02/00 MDE 02 Added _hex_no_spaces */
|
||||
/* 02/03/00 JRB 01 Created */
|
||||
/************************************************************************/
|
||||
|
||||
#include "glbtypes.h"
|
||||
#include "sysincs.h"
|
||||
#include "str_util.h"
|
||||
#include "slog.h"
|
||||
|
||||
#include <float.h>
|
||||
#include <math.h>
|
||||
#ifdef DEBUG_SISCO
|
||||
SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__;
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* NOTE: limits.h (included in sysincs.h) should have these defined. */
|
||||
/* Used to compare to LONG_MAX, ULONG_MAX to detect the long size.*/
|
||||
#if !defined(INT32_MAX)
|
||||
#define INT32_MAX 0x7fffffff
|
||||
#endif
|
||||
#if !defined(UINT32_MAX)
|
||||
#define UINT32_MAX 0xffffffff
|
||||
#endif
|
||||
|
||||
/************************************************************************/
|
||||
/* ascii_to_hex_str */
|
||||
/************************************************************************/
|
||||
|
||||
ST_RET ascii_to_hex_str (
|
||||
ST_UCHAR *hstr, /* hex string */
|
||||
ST_UINT *hlen_out, /* ptr to hex len to be set */
|
||||
ST_UINT hlen_max, /* maximum hex len to allow. */
|
||||
ST_CHAR *astr) /* ascii string */
|
||||
{
|
||||
ST_INT digit;
|
||||
ST_BOOLEAN nibble; /* SD_TRUE if nibble read, SD_FALSE if whole byte read*/
|
||||
|
||||
*hlen_out = 0;
|
||||
nibble = SD_FALSE;
|
||||
for ( ; *astr; astr++) /* read until NULL terminator */
|
||||
{
|
||||
if (isxdigit (*astr)) /* get hex number */
|
||||
{
|
||||
if (*hlen_out >= hlen_max)
|
||||
{ /* hstr already full. Can't add digit. */
|
||||
return (SD_FAILURE);
|
||||
}
|
||||
|
||||
digit = *astr;
|
||||
digit = isdigit (digit) ? digit - '0' : 10 + (toupper (digit) - 'A');
|
||||
if (nibble)
|
||||
{ /* set low nibble */
|
||||
nibble = SD_FALSE;
|
||||
hstr[*hlen_out] |= (ST_UCHAR) digit;
|
||||
(*hlen_out)++;
|
||||
}
|
||||
else
|
||||
{ /* set high nibble */
|
||||
nibble = SD_TRUE;
|
||||
hstr[*hlen_out] = (ST_UCHAR) digit << 4;
|
||||
}
|
||||
}
|
||||
else if (isspace (*astr))
|
||||
continue;
|
||||
else
|
||||
{ /* not hex digit, not white space, NOT GOOD. */
|
||||
return (SD_FAILURE);
|
||||
}
|
||||
} /* end "while" */
|
||||
|
||||
if (nibble)
|
||||
{ /* Only got half of byte. */
|
||||
return (SD_FAILURE);
|
||||
}
|
||||
|
||||
return (SD_SUCCESS);
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* hex_to_ascii_str */
|
||||
/* To make it more readable, a 'blank' is inserted after every 2 digits */
|
||||
/* in the ascii string. The ascii string is NULL terminated. */
|
||||
/* The ascii buffer must be at least 3 times the length of the hex */
|
||||
/* string (hlen) to allow for the blanks and the NULL terminator. */
|
||||
/************************************************************************/
|
||||
#define cvt_nibble(a) ((ST_UCHAR) ((a) > 9 ? (a) + 'A' - 10 : (a) + '0'))
|
||||
|
||||
ST_VOID hex_to_ascii_str (
|
||||
ST_CHAR *astr, /* ascii string */
|
||||
ST_UCHAR *hstr, /* hex string */
|
||||
ST_UINT hlen, /* len of hex string */
|
||||
ST_BOOLEAN hex_no_spaces)
|
||||
|
||||
{
|
||||
ST_UINT j;
|
||||
ST_INT hex_index = 0;
|
||||
ST_UCHAR ch;
|
||||
ST_UCHAR hex;
|
||||
|
||||
for (j = 0; j < hlen; j++)
|
||||
{
|
||||
if (j && hex_no_spaces != SD_TRUE)
|
||||
astr[hex_index++] = ' '; /* space between bytes, but not before first*/
|
||||
|
||||
ch = *hstr++; /* get next character */
|
||||
hex = (ch >> 4) & (ST_UCHAR) 0x0f;/* write HEX chars for the byte */
|
||||
hex = cvt_nibble(hex);
|
||||
astr[hex_index++] = hex;
|
||||
hex = ch & (ST_UCHAR) 0x0f;
|
||||
hex = cvt_nibble(hex);
|
||||
astr[hex_index++] = hex;
|
||||
}
|
||||
astr[hex_index] = '\0'; /* NULL terminate it. */
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* strnstr */
|
||||
/************************************************************************/
|
||||
|
||||
char * strnstr (char *str1, char *str2, int len)
|
||||
{
|
||||
char *cp = (char *) str1;
|
||||
char *s1, *s2;
|
||||
int cl;
|
||||
|
||||
if ( !*str2 )
|
||||
return((char *)str1);
|
||||
|
||||
while (*cp && len)
|
||||
{
|
||||
cl = len;
|
||||
s1 = cp;
|
||||
s2 = (char *) str2;
|
||||
|
||||
while (*s1 && *s2 && cl && !(*s1-*s2) )
|
||||
s1++, s2++, cl--;
|
||||
|
||||
if (!*s2)
|
||||
return(cp);
|
||||
|
||||
cp++;
|
||||
len--;
|
||||
}
|
||||
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/* These functions used when system libraries don't provide them.
|
||||
* Most UNIX-like systems provide similar functions strcasecmp &
|
||||
* strncasecmp. On those systems, strnicmp etc. are remapped to strcasecmp &
|
||||
* strncasecmp (see str_util.h), so these functions NOT needed.
|
||||
*/
|
||||
#if defined(VXWORKS) || defined(__LYNX) || defined(__ECOS)
|
||||
|
||||
/************************************************************************/
|
||||
/* strnicmp */
|
||||
/************************************************************************/
|
||||
|
||||
ST_INT strnicmp (ST_CHAR *str1, ST_CHAR *str2, ST_INT n )
|
||||
{
|
||||
ST_INT i = 0;
|
||||
ST_INT test = 1;
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
if ( tolower ( *(str1+i) ) != tolower ( *(str2+i) ) )
|
||||
{
|
||||
test = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (test == 1)
|
||||
return (0);
|
||||
else
|
||||
if ( tolower ( *(str1+i) ) > tolower ( *(str2+i) ) )
|
||||
return (1);
|
||||
else
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* strcmpi */
|
||||
/************************************************************************/
|
||||
ST_INT strcmpi (ST_CHAR *str1, ST_CHAR *str2)
|
||||
{
|
||||
ST_INT iLen1, iLen2;
|
||||
|
||||
iLen1 = strlen(str1);
|
||||
iLen2 = strlen(str2);
|
||||
return(strnicmp(str1, str2, ((iLen1 > iLen2) ? iLen1 : iLen2)));
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* stricmp */
|
||||
/************************************************************************/
|
||||
ST_INT stricmp (ST_CHAR *str1, ST_CHAR *str2)
|
||||
{
|
||||
return(strcmpi(str1, str2));
|
||||
}
|
||||
|
||||
#endif /* system libs don't provide these functs & don't support strcasecmp, strncasecmp.*/
|
||||
|
||||
/************************************************************************/
|
||||
/* strncat_maxstrlen */
|
||||
/* Similar to strncat but third arg is the maximum string length. */
|
||||
/* Destination string "dest" is always NULL terminated. */
|
||||
/* NOTE: Destination buffer size should always be at least */
|
||||
/* (maxstrlen+1) so there is room for NULL. */
|
||||
/* RETURNS: SD_SUCCESS or SD_FAILURE if maxstrlen already exceeded. */
|
||||
/************************************************************************/
|
||||
ST_RET strncat_maxstrlen (char *dest, char *src, size_t maxstrlen)
|
||||
{
|
||||
size_t dest_len;
|
||||
ST_RET retcode;
|
||||
|
||||
dest_len = strlen (dest);
|
||||
if (dest_len < maxstrlen)
|
||||
{
|
||||
strncat (dest, src, maxstrlen-dest_len); /* always NULL-terminates dest*/
|
||||
retcode = SD_SUCCESS;
|
||||
}
|
||||
else
|
||||
retcode = SD_FAILURE; /* "dest" is already too long. Don't do anything. */
|
||||
return (retcode);
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* strncpy_safe */
|
||||
/* Same as strncpy but always NULL terminates "dest" string. */
|
||||
/* strncpy return is useless so this function doesn't bother with return.*/
|
||||
/************************************************************************/
|
||||
ST_VOID strncpy_safe (char *dest, char *src, int max_len)
|
||||
{
|
||||
strncpy (dest, src, max_len);
|
||||
dest[max_len] = '\0';
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* asciiToSlong */
|
||||
/************************************************************************/
|
||||
|
||||
ST_RET asciiToSlong (const ST_CHAR *astr, /* ascii string */
|
||||
ST_LONG *sLong) /* ptr to long value obtained
|
||||
from converted ascii string */
|
||||
{
|
||||
ST_CHAR *retPtr;
|
||||
|
||||
*sLong = 0;
|
||||
errno = 0;
|
||||
|
||||
/* convert ascii string to signed long */
|
||||
*sLong = strtol (astr, &retPtr, 10);
|
||||
if (retPtr == astr || errno != 0)
|
||||
return (SD_FAILURE); /* conversion error */
|
||||
|
||||
return SD_SUCCESS;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* asciiToUlong */
|
||||
/************************************************************************/
|
||||
|
||||
ST_RET asciiToUlong (const ST_CHAR *astr, /* ascii string */
|
||||
ST_ULONG *uLong) /* ptr to long value obtained
|
||||
from converted ascii string */
|
||||
{
|
||||
ST_CHAR *retPtr;
|
||||
|
||||
*uLong = 0;
|
||||
errno = 0;
|
||||
|
||||
/* convert ascii string to unsigned long */
|
||||
*uLong = strtoul (astr, &retPtr, 10);
|
||||
if (retPtr == astr || errno != 0)
|
||||
return (SD_FAILURE); /* conversion error */
|
||||
|
||||
return SD_SUCCESS;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* asciiToSint */
|
||||
/************************************************************************/
|
||||
|
||||
ST_RET asciiToSint (const ST_CHAR *astr, /* ascii string */
|
||||
ST_INT *sInt) /* ptr to value obtained
|
||||
from converted ascii string */
|
||||
{
|
||||
ST_CHAR *retPtr;
|
||||
ST_LONG sLong = 0;
|
||||
|
||||
*sInt = 0;
|
||||
errno = 0;
|
||||
|
||||
/* convert ascii string to signed long */
|
||||
sLong = strtol (astr, &retPtr, 10);
|
||||
if (retPtr == astr || errno != 0)
|
||||
return (SD_FAILURE); /* conversion error */
|
||||
|
||||
#if (INT_MAX != LONG_MAX) /* if they are same, don't need to check */
|
||||
if (sLong < INT_MIN || sLong > INT_MAX)
|
||||
/* value does not fit in the range of ST_INT */
|
||||
return SD_FAILURE;
|
||||
#endif
|
||||
|
||||
*sInt = (ST_INT) sLong;
|
||||
return SD_SUCCESS;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* asciiToUint */
|
||||
/************************************************************************/
|
||||
|
||||
ST_RET asciiToUint (const ST_CHAR *astr, /* ascii string */
|
||||
ST_UINT *uInt) /* ptr to value obtained
|
||||
from converted ascii string */
|
||||
{
|
||||
ST_CHAR *retPtr;
|
||||
ST_ULONG uLong = 0;
|
||||
|
||||
*uInt = 0;
|
||||
errno = 0;
|
||||
|
||||
/* convert ascii string to unsigned long */
|
||||
uLong = strtoul (astr, &retPtr, 10);
|
||||
if (retPtr == astr || errno != 0)
|
||||
return (SD_FAILURE); /* conversion error */
|
||||
|
||||
#if (UINT_MAX != ULONG_MAX) /* if they are same, don't need to check */
|
||||
if (uLong > UINT_MAX)
|
||||
/* value does not fit in the range of ST_UINT */
|
||||
return SD_FAILURE;
|
||||
#endif
|
||||
|
||||
*uInt = (ST_UINT) uLong;
|
||||
return SD_SUCCESS;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* asciiToSint32 */
|
||||
/************************************************************************/
|
||||
ST_RET asciiToSint32 (const ST_CHAR *astr, /* ascii string */
|
||||
ST_INT32 *value) /* ptr to converted value*/
|
||||
{
|
||||
ST_CHAR *retPtr;
|
||||
ST_LONG sLong = 0;
|
||||
|
||||
*value = 0;
|
||||
errno = 0;
|
||||
|
||||
/* convert ascii string to signed long */
|
||||
sLong = strtol (astr, &retPtr, 10);
|
||||
if (retPtr == astr || errno != 0)
|
||||
return (SD_FAILURE); /* conversion error */
|
||||
|
||||
#if (LONG_MAX < INT32_MAX) /* LONG smaller than 32 bits */
|
||||
#error This code will not work on this platform.
|
||||
#endif
|
||||
#if (LONG_MAX > INT32_MAX) /* LONG bigger than 32 bits */
|
||||
/* DEBUG: test this on 64-bit system. */
|
||||
if (sLong > INT32_MAX || sLong < (-0x80000000))
|
||||
/* value does not fit in the range of ST_INT32 */
|
||||
return (SD_FAILURE);
|
||||
#endif
|
||||
/* if (LONG_MAX == INT32_MAX), long is same as ST_INT32, */
|
||||
/* so no need to chk range. */
|
||||
|
||||
*value = (ST_INT32) sLong;
|
||||
return (SD_SUCCESS);
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* asciiToUint32 */
|
||||
/************************************************************************/
|
||||
ST_RET asciiToUint32 (const ST_CHAR *astr, /* ascii string */
|
||||
ST_UINT32 *value) /* ptr to converted value*/
|
||||
{
|
||||
ST_CHAR *retPtr;
|
||||
ST_ULONG uLong = 0;
|
||||
|
||||
*value = 0;
|
||||
errno = 0;
|
||||
|
||||
/* convert ascii string to unsigned long */
|
||||
uLong = strtoul (astr, &retPtr, 10);
|
||||
if (retPtr == astr || errno != 0)
|
||||
return (SD_FAILURE); /* conversion error */
|
||||
|
||||
#if (ULONG_MAX < UINT32_MAX) /* ULONG smaller than 32 bits */
|
||||
#error This code will not work on this platform.
|
||||
#endif
|
||||
#if (ULONG_MAX > UINT32_MAX) /* ULONG bigger than 32 bits */
|
||||
if (uLong > UINT32_MAX)
|
||||
/* value does not fit in the range of ST_UINT32 */
|
||||
return (SD_FAILURE);
|
||||
#endif
|
||||
/* if (ULONG_MAX == UINT32_MAX), unsigned long is same as ST_UINT32,*/
|
||||
/* so no need to chk range. */
|
||||
|
||||
*value = (ST_UINT32) uLong;
|
||||
return (SD_SUCCESS);
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* asciiToSint16 */
|
||||
/************************************************************************/
|
||||
|
||||
ST_RET asciiToSint16 (const ST_CHAR *astr,/* ascii string */
|
||||
ST_INT16 *sInt16) /* ptr to value obtained
|
||||
from converted ascii string */
|
||||
{
|
||||
ST_CHAR *retPtr;
|
||||
ST_LONG sLong = 0;
|
||||
|
||||
*sInt16 = 0;
|
||||
errno = 0;
|
||||
|
||||
/* convert ascii string to signed long */
|
||||
sLong = strtol (astr, &retPtr, 10);
|
||||
if (retPtr == astr || errno != 0)
|
||||
return (SD_FAILURE); /* conversion error */
|
||||
|
||||
if (sLong < SHRT_MIN || sLong > SHRT_MAX)
|
||||
/* value does not fit in the range of ST_INT16 */
|
||||
return SD_FAILURE;
|
||||
|
||||
*sInt16 = (ST_INT16) sLong;
|
||||
return SD_SUCCESS;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* asciiToUint16 */
|
||||
/************************************************************************/
|
||||
|
||||
ST_RET asciiToUint16 (const ST_CHAR *astr, /* ascii string */
|
||||
ST_UINT16 *uInt16) /* ptr to value obtained
|
||||
from converted ascii string */
|
||||
{
|
||||
ST_CHAR *retPtr;
|
||||
ST_ULONG uLong = 0;
|
||||
|
||||
*uInt16 = 0;
|
||||
errno = 0;
|
||||
|
||||
/* convert ascii string to unsigned long */
|
||||
uLong = strtoul (astr, &retPtr, 10);
|
||||
if (retPtr == astr || errno != 0)
|
||||
return (SD_FAILURE); /* conversion error */
|
||||
|
||||
if (uLong > USHRT_MAX)
|
||||
/* value does not fit in the range of ST_UINT16 */
|
||||
return SD_FAILURE;
|
||||
|
||||
*uInt16 = (ST_UINT16) uLong;
|
||||
return SD_SUCCESS;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* asciiToUchar */
|
||||
/************************************************************************/
|
||||
|
||||
ST_RET asciiToUchar (const ST_CHAR *astr, /* ascii string */
|
||||
ST_UCHAR *uChar) /* ptr to value obtained
|
||||
from converted ascii string */
|
||||
{
|
||||
ST_CHAR *retPtr;
|
||||
ST_ULONG uLong = 0;
|
||||
|
||||
*uChar = 0;
|
||||
errno = 0;
|
||||
|
||||
/* convert ascii string to unsigned long */
|
||||
uLong = strtoul (astr, &retPtr, 10);
|
||||
if (retPtr == astr || errno != 0)
|
||||
return (SD_FAILURE); /* conversion error */
|
||||
|
||||
if (uLong > UCHAR_MAX)
|
||||
/* value does not fit in range of ST_UCHAR */
|
||||
return SD_FAILURE;
|
||||
|
||||
*uChar = (ST_UCHAR) uLong;
|
||||
return SD_SUCCESS;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* asciiToSint8 */
|
||||
/************************************************************************/
|
||||
|
||||
ST_RET asciiToSint8 (const ST_CHAR *astr, /* ascii string */
|
||||
ST_INT8 *sInt8) /* ptr to value obtained
|
||||
from converted ascii string */
|
||||
{
|
||||
ST_CHAR *retPtr;
|
||||
ST_LONG sLong = 0;
|
||||
|
||||
*sInt8 = 0;
|
||||
errno = 0;
|
||||
|
||||
/* convert ascii string to signed long */
|
||||
sLong = strtol (astr, &retPtr, 10);
|
||||
if (retPtr == astr || errno != 0)
|
||||
return (SD_FAILURE); /* conversion error */
|
||||
|
||||
if (sLong < CHAR_MIN || sLong > CHAR_MAX)
|
||||
/* value does not fit in range of ST_INT8 */
|
||||
return SD_FAILURE;
|
||||
|
||||
*sInt8 = (ST_INT8) sLong;
|
||||
return SD_SUCCESS;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* asciiToUint8 */
|
||||
/************************************************************************/
|
||||
|
||||
ST_RET asciiToUint8 (const ST_CHAR *astr, /* ascii string */
|
||||
ST_UINT8 *uInt8) /* ptr to value obtained
|
||||
from converted ascii string */
|
||||
{
|
||||
ST_CHAR *retPtr;
|
||||
ST_ULONG uLong = 0;
|
||||
|
||||
*uInt8 = 0;
|
||||
errno = 0;
|
||||
|
||||
/* convert ascii string to unsigned long */
|
||||
uLong = strtoul (astr, &retPtr, 10);
|
||||
if (retPtr == astr || errno != 0)
|
||||
return (SD_FAILURE); /* conversion error */
|
||||
|
||||
if (uLong > UCHAR_MAX)
|
||||
/* value does not fit in range of ST_UINT8 */
|
||||
return SD_FAILURE;
|
||||
|
||||
*uInt8 = (ST_UINT8) uLong;
|
||||
return SD_SUCCESS;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* asciiToFloat */
|
||||
/************************************************************************/
|
||||
|
||||
ST_RET asciiToFloat (const ST_CHAR *astr,
|
||||
ST_FLOAT *floatNum)
|
||||
{
|
||||
ST_CHAR *retPtr;
|
||||
ST_DOUBLE doubleNum = 0.0;
|
||||
|
||||
*floatNum = 0.0;
|
||||
errno = 0;
|
||||
|
||||
/* convert ascii string to double */
|
||||
doubleNum = strtod (astr, &retPtr);
|
||||
if (retPtr == astr || errno != 0)
|
||||
return (SD_FAILURE); /* conversion error */
|
||||
|
||||
if (fabs(doubleNum) > FLT_MAX)
|
||||
/* value does not fit in range of ST_FLOAT */
|
||||
return SD_FAILURE;
|
||||
|
||||
*floatNum = (ST_FLOAT) doubleNum;
|
||||
return SD_SUCCESS;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* asciiToDouble */
|
||||
/************************************************************************/
|
||||
|
||||
ST_RET asciiToDouble (const ST_CHAR *astr,
|
||||
ST_DOUBLE *doubleNum)
|
||||
{
|
||||
ST_CHAR *retPtr;
|
||||
|
||||
*doubleNum = 0.0;
|
||||
errno = 0;
|
||||
|
||||
/* convert ascii string to double */
|
||||
*doubleNum = strtod (astr, &retPtr);
|
||||
if (retPtr == astr || errno != 0)
|
||||
return (SD_FAILURE); /* conversion error */
|
||||
|
||||
return SD_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/************************************************************************/
|
||||
/* Base 10 Integer to ASCII Functions */
|
||||
/************************************************************************/
|
||||
|
||||
static char *lToStr(long int val,char *dst, int radix);
|
||||
|
||||
ST_CHAR *sInt8ToAscii (ST_INT8 v, ST_CHAR *p) {lToStr ((long) v, p, -10); return p;}
|
||||
ST_CHAR *uInt8ToAscii (ST_UINT8 v, ST_CHAR *p) {lToStr ((long) v, p, 10); return p;}
|
||||
ST_CHAR *sInt16ToAscii (ST_INT16 v, ST_CHAR *p) {lToStr ((long) v, p, -10); return p;}
|
||||
ST_CHAR *uInt16ToAscii (ST_UINT16 v, ST_CHAR *p) {lToStr ((long) v, p, 10); return p;}
|
||||
ST_CHAR *sInt32ToAscii (ST_INT32 v, ST_CHAR *p) {lToStr ((long) v, p, -10); return p;}
|
||||
ST_CHAR *uInt32ToAscii (ST_UINT32 v, ST_CHAR *p) {lToStr ((long) v, p, 10); return p;}
|
||||
ST_CHAR *sIntToAscii (ST_INT v, ST_CHAR *p) {lToStr ((long) v, p, -10); return p;}
|
||||
ST_CHAR *uIntToAscii (ST_UINT v, ST_CHAR *p) {lToStr ((long) v, p, 10); return p;}
|
||||
ST_CHAR *sLongToAscii (ST_LONG v, ST_CHAR *p) {lToStr ((long) v, p, -10); return p;}
|
||||
ST_CHAR *uLongToAscii (ST_ULONG v, ST_CHAR *p) {lToStr ((long) v, p, 10); return p;}
|
||||
|
||||
static char *lToStr(long int val,char *dst, int radix)
|
||||
{
|
||||
char buffer[65];
|
||||
char *p;
|
||||
long int new_val;
|
||||
|
||||
if (radix < 0) /* -10 */
|
||||
{
|
||||
if (val < 0)
|
||||
{
|
||||
*dst++ = '-';
|
||||
val = -val;
|
||||
}
|
||||
}
|
||||
|
||||
p = &buffer[sizeof(buffer)-1];
|
||||
*p = '\0';
|
||||
new_val= (long) ((unsigned long int) val / 10);
|
||||
*--p = '0'+ (char) ((unsigned long int) val - (unsigned long) new_val * 10);
|
||||
val = new_val;
|
||||
|
||||
while (val != 0)
|
||||
{
|
||||
new_val=val/10;
|
||||
*--p = '0' + (char) (val-new_val*10);
|
||||
val= new_val;
|
||||
}
|
||||
while ((*dst++ = *p++) != 0) ;
|
||||
return dst-1;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/************************************************************************/
|
||||
|
||||
#if 0
|
||||
#include "stime.h"
|
||||
|
||||
int testItoA ()
|
||||
{
|
||||
char dest[100];
|
||||
long numMs;
|
||||
double endTime;
|
||||
double startTime;
|
||||
int i;
|
||||
|
||||
startTime = sGetMsTime ();
|
||||
for (i = 0; i < 100000; ++i)
|
||||
sprintf (dest, "%ld", 698);
|
||||
endTime = sGetMsTime ();
|
||||
numMs = (long) (endTime - startTime);
|
||||
printf ("\n sprintf took %ld ms", numMs);
|
||||
|
||||
startTime = sGetMsTime ();
|
||||
for (i = 0; i < 100000; ++i)
|
||||
ltoa (698, dest, 10);
|
||||
endTime = sGetMsTime ();
|
||||
numMs = (long) (endTime - startTime);
|
||||
printf ("\n ltoa took %ld ms", numMs);
|
||||
|
||||
startTime = sGetMsTime ();
|
||||
for (i = 0; i < 100000; ++i)
|
||||
lToStr (698, dest);
|
||||
endTime = sGetMsTime ();
|
||||
numMs = (long) (endTime - startTime);
|
||||
printf ("\n lToStr took %ld ms", numMs);
|
||||
|
||||
lToStr (0, dest);
|
||||
if (strcmp (dest, "0"))
|
||||
printf ("\nError in lToStr (0, dest);");
|
||||
|
||||
lToStr (-1, dest);
|
||||
if (strcmp (dest, "-1"))
|
||||
printf ("\nError in lToStr (-1, dest);");
|
||||
|
||||
lToStr (1, dest);
|
||||
if (strcmp (dest, "1"))
|
||||
printf ("\nError in lToStr (1, dest);");
|
||||
|
||||
sInt16ToAscii (SHRT_MIN, dest);
|
||||
if (strcmp (dest, "-32768"))
|
||||
printf ("\nError in sInt16ToAscii (SHRT_MIN, dest);");
|
||||
|
||||
sInt16ToAscii (SHRT_MAX, dest);
|
||||
if (strcmp (dest, "32767"))
|
||||
printf ("\nError in sInt16ToAscii (SHRT_MAX, dest);");
|
||||
|
||||
uInt16ToAscii (USHRT_MAX, dest);
|
||||
if (strcmp (dest, "65535"))
|
||||
printf ("\nError in sUint16ToAscii (USHRT_MAX, dest);");
|
||||
|
||||
sIntToAscii (INT_MIN, dest);
|
||||
if (strcmp (dest, "-2147483648"))
|
||||
printf ("\nError in sIntToAscii (INT_MIN, dest);");
|
||||
|
||||
sIntToAscii (INT_MAX, dest);
|
||||
if (strcmp (dest, "2147483647"))
|
||||
printf ("\nError in sIntToAscii (INT_MAX, dest);");
|
||||
|
||||
uIntToAscii (UINT_MAX, dest);
|
||||
if (strcmp (dest, "0xffffffff"))
|
||||
printf ("\nError in sUintToAscii (UINT_MAX, dest);");
|
||||
|
||||
sLongToAscii (LONG_MIN, dest);
|
||||
if (strcmp (dest, "-2147483648"))
|
||||
printf ("\nError in sIntToAscii (INT_MIN, dest);");
|
||||
|
||||
sLongToAscii (LONG_MAX, dest);
|
||||
if (strcmp (dest, "2147483647"))
|
||||
printf ("\nError in sIntToAscii (INT_MAX, dest);");
|
||||
|
||||
uLongToAscii (ULONG_MAX, dest);
|
||||
if (strcmp (dest, "4294967295"))
|
||||
printf ("\nError in sUintToAscii (UINT_MAX, dest);");
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* getKeywordFromFile */
|
||||
/*----------------------------------------------------------------------*/
|
||||
/* Function to check if given keyword is found in a specified text file.*/
|
||||
/* When found, keyword value (string) is copied to user buffer valBuf. */
|
||||
/* This function assumes that there is one keyword per line in the file */
|
||||
/* in the form: */
|
||||
/* keyword=val */
|
||||
/* Where val is an int, long, string, etc. */
|
||||
/* keywordStr should include the '=' char. */
|
||||
/* Line length is limited to 255 bytes. */
|
||||
/* Any NL or CR characters are eliminated from the end of line. */
|
||||
/* Parameters: */
|
||||
/* ST_CHAR *fileStr file to open */
|
||||
/* ST_CHAR *keywordStr keyword to look for in file */
|
||||
/* ST_CHAR *valBuf ptr where to put keyword value */
|
||||
/* ST_UINT valBufLen len of buffer for the value. */
|
||||
/* Return: */
|
||||
/* SD_TRUE if keyword found. */
|
||||
/* SD_FALSE otherwise */
|
||||
/************************************************************************/
|
||||
ST_BOOLEAN getKeywordFromFile (ST_CHAR *fileStr, ST_CHAR *keywordStr,
|
||||
ST_CHAR *valBuf, ST_UINT valBufLen)
|
||||
{
|
||||
ST_BOOLEAN ret = SD_FALSE;
|
||||
ST_CHAR lineBuf[256];
|
||||
ST_CHAR *keywordPtr = NULL; /* set if keywordStr found */
|
||||
FILE *fd = NULL;
|
||||
ST_INT i;
|
||||
ST_INT copyLen;
|
||||
|
||||
/* make sure we got some valid parameters */
|
||||
if (!fileStr || strlen(fileStr) == 0)
|
||||
return (ret);
|
||||
if (!keywordStr || strlen(keywordStr) == 0)
|
||||
return (ret);
|
||||
if (!valBuf || valBufLen == 0 || valBufLen >= sizeof(lineBuf))
|
||||
return (ret);
|
||||
|
||||
/* open and read the file line by line */
|
||||
if ((fd = fopen (fileStr, "r")) != NULL)
|
||||
{
|
||||
memset (lineBuf, 0, sizeof(lineBuf));
|
||||
while (fgets(lineBuf, sizeof(lineBuf)-1, fd) != NULL)
|
||||
{
|
||||
/* eliminate any NL or CR characters from the end of line */
|
||||
for (i=0; i<sizeof(lineBuf); i++)
|
||||
{
|
||||
if (lineBuf[i] == '\n' || lineBuf[i] == '\r')
|
||||
lineBuf[i] = 0;
|
||||
}
|
||||
/* find the keywordStr in lineBuf */
|
||||
keywordPtr = strstr(lineBuf, keywordStr);
|
||||
if (keywordPtr)
|
||||
{
|
||||
copyLen = min (valBufLen-1, strlen(lineBuf)-strlen(keywordStr));
|
||||
memcpy (valBuf, &keywordPtr[strlen(keywordStr)], copyLen);
|
||||
valBuf[copyLen] = 0; /* NULL terminate the value */
|
||||
ret = SD_TRUE;
|
||||
}
|
||||
/* reset for next line */
|
||||
memset (lineBuf, 0, sizeof(lineBuf));
|
||||
}
|
||||
fclose (fd);
|
||||
}
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* get_next_string */
|
||||
/* Return pointer to next string in input buffer, separated by */
|
||||
/* delimiters (string may be surrounded by "double quotes"). */
|
||||
/* ARGUMENTS: */
|
||||
/* ptrptr - address of current ptr. Current ptr changed by this funct.*/
|
||||
/* delimiters - set of delimiter chars (like strtok or strpbrk). */
|
||||
/* RETURNS: ptr to string found, NULL on error or end of input string.*/
|
||||
/************************************************************************/
|
||||
ST_CHAR *get_next_string (ST_CHAR **ptrptr, ST_CHAR *delimiters)
|
||||
{
|
||||
ST_CHAR *curptr;
|
||||
ST_CHAR *string;
|
||||
ST_CHAR *next_delimiter;
|
||||
|
||||
/* If (*ptrptr==NULL), can't do anything. Just return NULL. */
|
||||
/* May often happen if last call failed or hit end of input buffer. */
|
||||
if (*ptrptr == NULL)
|
||||
string = NULL;
|
||||
else
|
||||
{
|
||||
curptr = *ptrptr; /* copy to local var for readability */
|
||||
/* renxiaobao <20>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
|
||||
while (*curptr == ' ' || *curptr == ','|| *curptr == '\t'|| *curptr == '\n')
|
||||
{
|
||||
curptr++;
|
||||
}
|
||||
/* add end*/
|
||||
/* if next char is double quote, get up to next double quote */
|
||||
if (*curptr == '\"')
|
||||
{
|
||||
curptr++; /* point after starting quote */
|
||||
string = curptr;
|
||||
curptr = strpbrk (curptr, "\""); /* find ending quote */
|
||||
/* NOTE: curptr should now point to ending quote, but */
|
||||
/* it may be NULL, if ending quote not found. */
|
||||
if (curptr)
|
||||
{
|
||||
*curptr = '\0'; /* replace ending quote with NULL */
|
||||
curptr++; /* point after ending quote */
|
||||
}
|
||||
if (curptr)
|
||||
{ /* make sure next character is delimiter, then skip it. */
|
||||
next_delimiter = strpbrk (curptr, delimiters); /* find next delimiter */
|
||||
if (next_delimiter != curptr)
|
||||
{
|
||||
SLOGALWAYS1 ("get_next_string ERROR: '%c' after ending quote. Expecting delimiter.", *curptr);
|
||||
string = NULL; /* error */
|
||||
curptr = NULL; /* error */
|
||||
}
|
||||
else
|
||||
curptr++; /* skip this delimiter */
|
||||
}
|
||||
}
|
||||
else if (*curptr == '\0')
|
||||
{ /* no more strings */
|
||||
string = NULL;
|
||||
curptr = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
string = curptr;
|
||||
curptr = strpbrk (curptr, delimiters); /* find next delimiter */
|
||||
/* NOTE: curptr should now point to ending delimiter, but */
|
||||
/* it may be NULL, if expected delimiter not found. */
|
||||
if (curptr)
|
||||
{
|
||||
*curptr = '\0'; /* replace delimiter with NULL */
|
||||
curptr++; /* point after delimiter */
|
||||
}
|
||||
}
|
||||
|
||||
*ptrptr = curptr; /* NULL on any error OR end of input string */
|
||||
}
|
||||
return (string); /* return ptr to string (NULL on any error) */
|
||||
}
|
||||
1964
mmslib/util/sx_axs4d.c
Normal file
1964
mmslib/util/sx_axs4d.c
Normal file
File diff suppressed because it is too large
Load Diff
2601
mmslib/util/sx_data.c
Normal file
2601
mmslib/util/sx_data.c
Normal file
File diff suppressed because it is too large
Load Diff
2520
mmslib/util/sx_dec.c
Normal file
2520
mmslib/util/sx_dec.c
Normal file
File diff suppressed because it is too large
Load Diff
1344
mmslib/util/sx_enc.c
Normal file
1344
mmslib/util/sx_enc.c
Normal file
File diff suppressed because it is too large
Load Diff
2748
mmslib/util/time_str.c
Normal file
2748
mmslib/util/time_str.c
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user