📄 udcfgtxt.c
字号:
/* $Header: "%n Ver=%v %f LastEdit=%w Locker=%l" */
/* "UDCFGTXT.C Ver=2 10-Nov-97,10:57:16 LastEdit=JIMV Locker=***_NOBODY_***" */
/***********************************************************************\
* *
* Copyright Wonderware Software Development Corp. 1992-1997 *
* *
* ThisFileName="L:\ww\dde_serv\src\udsample\udcfgtxt.c" *
* LastEditDate="1997 Nov 10 10:57:00" *
* *
\***********************************************************************/
/**************************************************************************\
These routines support reading and writing CFG files as ASCII text
\**************************************************************************/
#include <windows.h>
#include <io.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <stat.h>
#include "ntconv.h"
#include "hmemcpy.h"
#include "chainmgr.h"
#include "config.h"
#include "uddefs.h"
#include "rc.h"
#include "lmem.h"
/***********************************************************************\
The routines in this section support storing and scanning a server
configuration file in the form of ASCII commands. Writing such a file
is easy, just format the appropriate data into a string buffer and
write the buffer to the file. Reading the configuration back involves
scanning for a command identifying the type of item to be configured,
then scanning for the parameters that correspond to the member variables
of the configuration structure.
Note that the command starts with a command name and ends with a ';'.
Scanning ignores CRLF (carriage-return-line-feed) sequences, and skips
over extra whitespace. So a command can extend over several lines,
if desired (to improve human readability).
For example, the following commands would be valid entries in the file:
COMPORT PORTID=1 BAUD=1200 DATA_BITS=8 STOP_BITS=2
PARITY=NONE REPLYTIMEOUT=3000;
COMPORT PORTID=2 BAUD=2400 DATA_BITS=7 STOP_BITS=1
PARITY=ODD REPLYTIMEOUT=3000;
BOARD NAME="UD:0" PORTID=1 MEM_SEGMENT=0xD000 IO_ADDR=0x200
REPLYTIMEOUT=3000;
BOARD NAME="UD:1" PORTID=2 MEM_SEGMENT=0xD400 IO_ADDR=0x240
REPLYTIMEOUT=3000;
TOPIC NAME="Topic1" PORTID=1 UPDATEINTERVAL=1000 ADDRESS=3
COIL_READ_SIZE=2000 REG_READ_SIZE=125;
TOPIC NAME="Fast" PORTID=2 UPDATEINTERVAL=100 ADDRESS=7
COIL_READ_SIZE=1000 REG_READ_SIZE=127;
The configuration scanner processes the commands and parameters using
a small set of tables that you create. You must define a table of the
command names -- e.g. "COMPORT", "BOARD", and "TOPIC" -- and for each
command you must define a table of parameters, e.g. "PORTID", "IO_ADDR",
etc. for the "BOARD" command.
For each parameter, your table must indicate the TYPE of data that is
acceptable: a number, a string, or a name.
Examples:
PORTID=1 number parameter value
NAME="Topic1" string parameter value
PARITY=ODD name parameter value
The sample tables below define the commands and parameters in a way
that makes it easy to add or delete a new command or a new parameter.
When the configuration file is read, the assumption is that any parameter
not actually mentioned in the configuration file will be set to a
default value.
One main advantage of this approach, compared to reading and writing
binary structures, is that it is easy to handle changes to the
structures without the need to alter the VERSION of the configuration
file. Disused parameters can simply be skipped over and ignored, and
new parameters can be given default values if they do not appear in
a configuration file. This greatly simplifies the issue of software
maintenance whenever the configuration structures need to be updated.
This approach also provides a way of configuring a server for use on
another computer without the need to have the server up and running
on the computer where the configuration file is prepared.
\***********************************************************************/
/**************************************************************************/
/* tables of configuration commands, parameters */
typedef struct tagCONFIG_CMD /* element of configuration command list */
{
char cmd_name [15]; /* name of configuration command */
char cmd_index; /* index for command */
} CONFIG_CMD;
typedef struct tagCONFIG_PARAM /* element of configuration parameter list */
{
char param_name [25]; /* name of configuration parameter */
char param_index; /* index for parameter */
} CONFIG_PARAM;
/* commands */
#define TOPIC_CMD 1
#define COMPORT_CMD 2
#define BOARD_CMD 3
CONFIG_CMD command_table [] =
{{"TOPIC", TOPIC_CMD},
{"COMPORT", COMPORT_CMD},
{"BOARD", BOARD_CMD}
};
static int NUM_CONFIG_CMDS = sizeof(command_table) / sizeof(CONFIG_CMD);
/**************************************************************************/
/* parameters for COMPORT command */
#define COMPORT_PORTID_PARAM 1
#define COMPORT_BAUD_PARAM 2
#define COMPORT_DATABITS_PARAM 3
#define COMPORT_STOPBITS_PARAM 4
#define COMPORT_PARITY_PARAM 5
#define COMPORT_REPLYTIMEOUT_PARAM 6
CONFIG_PARAM comport_param_table [] =
{{"PORTID=", COMPORT_PORTID_PARAM },
{"BAUD=", COMPORT_BAUD_PARAM },
{"DATA_BITS=", COMPORT_DATABITS_PARAM },
{"STOP_BITS=", COMPORT_STOPBITS_PARAM },
{"PARITY=", COMPORT_PARITY_PARAM },
{"REPLYTIMEOUT=", COMPORT_REPLYTIMEOUT_PARAM}
};
static int NUM_COMPORT_PARAMS = sizeof(comport_param_table) / sizeof(CONFIG_PARAM);
/**************************************************************************/
/* parameters for BOARD command */
#define BOARD_NAME_PARAM 1
#define BOARD_PORTID_PARAM 2
#define BOARD_MEM_SEGMENT_PARAM 3
#define BOARD_IO_ADDR_PARAM 4
#define BOARD_REPLYTIMEOUT_PARAM 5
CONFIG_PARAM board_param_table [] =
{{"NAME=", BOARD_NAME_PARAM },
{"PORTID=", BOARD_PORTID_PARAM },
{"MEM_SEGMENT=", BOARD_MEM_SEGMENT_PARAM },
{"IO_ADDR=", BOARD_IO_ADDR_PARAM },
{"REPLYTIMEOUT=", BOARD_REPLYTIMEOUT_PARAM}
};
static int NUM_BOARD_PARAMS = sizeof(board_param_table) / sizeof(CONFIG_PARAM);
/**************************************************************************/
/* parameters for TOPIC command */
#define TOPIC_NAME_PARAM 1
#define TOPIC_PORTID_PARAM 2
#define TOPIC_UPDTINT_PARAM 3
#define TOPIC_ADDR_PARAM 4
#define TOPIC_COILREADSIZE_PARAM 5
#define TOPIC_REGREADSIZE_PARAM 6
CONFIG_PARAM topic_param_table [] =
{{"NAME=", TOPIC_NAME_PARAM },
{"PORTID=", TOPIC_PORTID_PARAM },
{"UPDATEINTERVAL=", TOPIC_UPDTINT_PARAM },
{"ADDRESS=", TOPIC_ADDR_PARAM },
{"COIL_READ_SIZE=", TOPIC_COILREADSIZE_PARAM},
{"REG_READ_SIZE=", TOPIC_REGREADSIZE_PARAM }
};
static int NUM_TOPIC_PARAMS = sizeof(topic_param_table) / sizeof(CONFIG_PARAM);
/********************************************************************
* External Variables *
********************************************************************/
extern BOOL bUsesComPorts; /* =TRUE if ComPorts are used */
extern BOOL bUsesBoards; /* =TRUE if Boards are used */
extern WW_CP_PARAMS comPort[]; /* array of comport configurations */
extern CHAIN BoardCfgList; /* linked list of board configurations */
extern CHAIN TopicCfgList; /* linked list of topic configurations */
/********************************************************************
* Prototypes *
********************************************************************/
static BOOL WINAPI ReadPortCfgASCII ( BUFFERED_FILE *SourceFile,
LPCOMPORT_CFG_WITHID lpComPortCfgWithID,
char *scan_ptr,
char *scan_buf, int scan_buf_size );
static BOOL WINAPI ReadBoardCfgASCII ( BUFFERED_FILE *SourceFile,
LPBOARD_CFG lpBoardCfg, char *scan_ptr,
char *scan_buf, int scan_buf_size );
static BOOL WINAPI ReadTopicCfgASCII ( BUFFERED_FILE *SourceFile,
LPTOPIC_CFG lpTopicCfg, char *scan_ptr,
char *scan_buf, int scan_buf_size );
static BOOL WINAPI WritePortCfgASCII ( BUFFERED_FILE *DestFile, LPCOMPORT_CFG_WITHID lpComPortCfgWithID );
static BOOL WINAPI WriteBoardCfgASCII ( BUFFERED_FILE *DestFile, LPBOARD_CFG lpBoardCfg );
static BOOL WINAPI WriteTopicCfgASCII ( BUFFERED_FILE *DestFile, LPTOPIC_CFG lpTopicCfg );
static BOOL WINAPI IsOctalDigit (char ch);
static BOOL WINAPI IsHexDigit (char ch);
static BOOL WINAPI GetDelimitedString (char **source_ptr, char *dest_ptr,
unsigned long buf_len, unsigned long *dest_len,
BOOL *truncated, char *status);
static BOOL WINAPI StoreNewComPortCfg (COMPORT_CFG_WITHID *pComPortCfgWithID);
static BOOL WINAPI StoreNewBoardCfg (BOARD_CFG *pBoard);
static BOOL WINAPI StoreNewTopicCfg (TOPIC_CFG *pTopic);
static VOID WINAPI GetParamName (char **source_ptr, char *dest_ptr, int buf_len);
static BOOL WINAPI GetParamStr (char **source_ptr, char *dest_ptr, int buf_len);
static BOOL WINAPI GetParamNumber (char **source_ptr, unsigned long *lValue);
static VOID WINAPI SetupDefaultComportCfgParams (LPCOMPORT_CFG_WITHID lpComPortCfgWithID,
int port_num );
static unsigned long WINAPI BaudFromIndex (unsigned long uBaud_index);
static unsigned long WINAPI IndexFromBaud (unsigned long uBaud_rate);
static int WINAPI DataBitsFromIndex (unsigned long uDataBit_index);
static unsigned long WINAPI IndexFromDataBits (int DataBits);
static int WINAPI StopBitsFromIndex (unsigned long uStopBit_index);
static unsigned long WINAPI IndexFromStopBits (int StopBits);
static void WINAPI ParityFromIndex (unsigned long uParity_index, LPSTR Parity);
static unsigned long WINAPI IndexFromParity (LPSTR Parity);
/**************************************************************************
**************************************************************************
* Routines for writing CFG files in ASCII text *
**************************************************************************
**************************************************************************/
/********************************************************************/
/** write configuration as ASCII commands to configuration file.
returns TRUE if successful **/
BOOL
WINAPI
WriteConfigsASCII (BUFFERED_FILE *DestFile)
{
BOOL ok;
int i;
short int CRLF;
COMPORT_CFG_WITHID ComPortCfgWithID;
BOARD_CFG BoardCfg;
LPBOARD_CFG lpBoardCfg;
TOPIC_CFG Topic;
LPTOPIC_CFG lpTopicCfg;
char bIsUsed[NUM_COMPORTS];
DWORD dwChannelID;
CHAINSCANNER board_scanner;
CHAINSCANNER topic_scanner;
/* write file version header, indicate text mode */
ok = WriteVersion (DestFile, CFGTXT, ' ');
/* prefix first command with a carriage return, line feed */
if (ok) {
CRLF = 0x0A0D;
ok = WriteNextBuffer (DestFile, (char *) &CRLF, sizeof(CRLF));
}
if (bUsesComPorts) {
/* initialize comport flags, comparison value */
memset (bIsUsed, 0, sizeof(bIsUsed));
SetupDefaultComportCfgParams (&ComPortCfgWithID, 1);
/* check which comports are used by the topics, if any */
lpTopicCfg = (LPTOPIC_CFG) FindFirstItem (&TopicCfgList, SCAN_FROM_HEAD,
NULL, NULL, &topic_scanner);
while (lpTopicCfg != NULL) {
/* check whether channel used is a com port */
dwChannelID = lpTopicCfg->tc_channelID;
if ((0 < dwChannelID) && (dwChannelID <= MAX_COMPORT))
/* yes, indicate com port is used */
bIsUsed [dwChannelID-1] = TRUE;
/* get the next topic, if any */
lpTopicCfg = (LPTOPIC_CFG) FindNextItem (&topic_scanner);
}
/* check which topics have non-default settings */
for (i = 0; i < MAX_COMPORT; i++)
{
/* compare com port with default values */
if (lmemcmp ((LPSTR) &comPort[i], (LPSTR) &ComPortCfgWithID.comport,
sizeof(WW_CP_PARAMS)) != 0)
/* settings are different, indicate com port is used */
bIsUsed[i] = TRUE;
}
/* write the serial comports */
i = 0;
while (ok && (i < MAX_COMPORT)) {
/* check whether com port is used or has non-default settings */
if (bIsUsed[i]) {
/* attempt to write com port as ASCII command */
ComPortCfgWithID.channelID = i+1;
ComPortCfgWithID.comport = comPort[i];
ok = WritePortCfgASCII (DestFile, &ComPortCfgWithID);
}
/* advance port index */
i++;
}
}
if (bUsesBoards) {
/* write the boards */
lpBoardCfg = (LPBOARD_CFG) FindFirstItem (&BoardCfgList, SCAN_FROM_HEAD,
NULL, NULL, &board_scanner);
while (ok && (lpBoardCfg != NULL)) {
/* copy board values to local structure */
BoardCfg = *lpBoardCfg;
/* write board as ASCII command */
ok = WriteBoardCfgASCII (DestFile, &BoardCfg);
/* get the next board, if any */
lpBoardCfg = (LPBOARD_CFG) FindNextItem (&board_scanner);
}
}
/* write the topics */
lpTopicCfg = (LPTOPIC_CFG) FindFirstItem (&TopicCfgList, SCAN_FROM_HEAD,
NULL, NULL, &topic_scanner);
while (ok && (lpTopicCfg != NULL)) {
/* copy topic values to local structure */
Topic = *lpTopicCfg;
/* write topic as ASCII command */
ok = WriteTopicCfgASCII (DestFile, &Topic);
/* get the next topic, if any */
lpTopicCfg = (LPTOPIC_CFG) FindNextItem (&topic_scanner);
}
/* indicate success or failure */
return (ok);
} /* WriteConfigsASCII */
/********************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -