mirror of
git://git.code.sf.net/p/cdesktopenv/code
synced 2025-03-09 15:50:02 +00:00
1809 lines
39 KiB
C
1809 lines
39 KiB
C
/*
|
||
* CDE - Common Desktop Environment
|
||
*
|
||
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
|
||
*
|
||
* These libraries and programs are free software; you can
|
||
* redistribute them and/or modify them under the terms of the GNU
|
||
* Lesser General Public License as published by the Free Software
|
||
* Foundation; either version 2 of the License, or (at your option)
|
||
* any later version.
|
||
*
|
||
* These libraries and programs are distributed in the hope that
|
||
* they will be useful, but WITHOUT ANY WARRANTY; without even the
|
||
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||
* PURPOSE. See the GNU Lesser General Public License for more
|
||
* details.
|
||
*
|
||
* You should have received a copy of the GNU Lesser General Public
|
||
* License along with these libraries and programs; if not, write
|
||
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
||
* Floor, Boston, MA 02110-1301 USA
|
||
*/
|
||
/******************************<+>*************************************
|
||
**********************************************************************
|
||
**
|
||
** File: WmParse.c
|
||
**
|
||
** Project: HP/Motif Workspace Manager (dtwm)
|
||
**
|
||
** Description:
|
||
** -----------
|
||
** This file contains the generic parsing routines
|
||
**
|
||
**
|
||
*********************************************************************
|
||
**
|
||
** (c) Copyright 1987, 1988, 1989, 1990, 1991 HEWLETT-PACKARD COMPANY
|
||
** ALL RIGHTS RESERVED
|
||
**
|
||
**********************************************************************
|
||
**********************************************************************
|
||
**
|
||
**
|
||
**********************************************************************
|
||
******************************<+>*************************************/
|
||
|
||
/* ANSI C definitions, This should be the first thing in WmGlobal.h */
|
||
#ifdef __STDC__
|
||
#define Const const
|
||
#else
|
||
#define Const /**/
|
||
#endif
|
||
|
||
|
||
/*
|
||
* Included Files:
|
||
*/
|
||
#include <stdio.h>
|
||
#include <X11/Intrinsic.h>
|
||
#include "WmGlobal.h"
|
||
#include "WmParse.h"
|
||
#include "WmParseP.h"
|
||
#include <stdlib.h>
|
||
#include <ctype.h>
|
||
|
||
/*
|
||
* Internal routines
|
||
*/
|
||
|
||
static DtWmpParseBuf * _DtWmpIncBuf (
|
||
DtWmpParseBuf *pWmPB);
|
||
|
||
|
||
|
||
#ifndef MAXLINE
|
||
#define MAXLINE (MAXWMPATH+1)
|
||
#endif
|
||
#define MAX_QUOTE_DEPTH 10
|
||
|
||
/*
|
||
* This flags non-OSF code in those sections that were lifted
|
||
* from mwm.
|
||
*/
|
||
#define PARSE_LIB
|
||
|
||
|
||
/*
|
||
* Defines used to maintain code similarity between OSF/mwm source
|
||
* routines and these routines.
|
||
*/
|
||
#define cfileP ((pWmPB)->pFile)
|
||
#define linec ((pWmPB)->lineNumber)
|
||
#define line ((pWmPB)->pchLine)
|
||
#define parseP ((pWmPB)->pchNext)
|
||
#define ScanWhitespace(s) (_DtWmParseSkipWhitespaceC(s))
|
||
#define PeekAhead(s,l) (_DtWmParsePeekAhead(s,l))
|
||
|
||
|
||
/*************************************<->*************************************
|
||
*
|
||
* _DtWmParseSkipWhitespace(pWmPB)
|
||
*
|
||
*
|
||
* Description:
|
||
* -----------
|
||
* Scan the current string, skipping over all white space characters.
|
||
*
|
||
*
|
||
* Inputs:
|
||
* ------
|
||
* pWmPB = ptr to parse buffer
|
||
*
|
||
*
|
||
* Outputs:
|
||
* -------
|
||
* pWmPB = parse buffer modified; current line ptr may be moved.
|
||
*
|
||
*
|
||
* Comments:
|
||
* --------
|
||
* Assumes there's a current line in the parse buffer
|
||
*
|
||
*************************************<->***********************************/
|
||
|
||
void _DtWmParseSkipWhitespace(DtWmpParseBuf *pWmPB)
|
||
{
|
||
_DtWmParseSkipWhitespaceC (&(pWmPB->pchNext));
|
||
|
||
} /* END OF FUNCTION _DtWmParseSkipWhitespace */
|
||
|
||
|
||
/*************************************<->*************************************
|
||
*
|
||
* _DtWmParseNextToken (pWmPB)
|
||
*
|
||
*
|
||
* Description:
|
||
* -----------
|
||
* Returns the next quoted or whitespace-terminated nonquoted string in the
|
||
* current line buffer.
|
||
*
|
||
*
|
||
* Inputs:
|
||
* ------
|
||
* pWmPB = ptr to parse buffer
|
||
*
|
||
*
|
||
* Outputs:
|
||
* -------
|
||
* Return = ptr to null terminated string.
|
||
* pWmPB = current line modified internally.
|
||
*
|
||
*
|
||
* Comments:
|
||
* --------
|
||
* May alter the line buffer contents.
|
||
* Handles quoted strings and characters, removing trailing whitespace from
|
||
* quoted strings.
|
||
* Returns NULL string if the line is empty or is a comment.
|
||
* Does not use session manager style algorithm for dealing with
|
||
* quoted strings.
|
||
*
|
||
*************************************<->***********************************/
|
||
|
||
unsigned char *
|
||
_DtWmParseNextToken (
|
||
DtWmpParseBuf *pWmPB
|
||
)
|
||
{
|
||
return (_DtWmParseNextTokenC (&(pWmPB->pchNext), False));
|
||
}
|
||
|
||
|
||
/*************************************<->*************************************
|
||
*
|
||
* _DtWmParseNextTokenExpand (pWmPB)
|
||
*
|
||
*
|
||
* Description:
|
||
* -----------
|
||
* Returns the next quoted or whitespace-terminated nonquoted string in the
|
||
* current line buffer. Environment variables found in the are expanded.
|
||
* Characters quoted by '\' are passed through unaffected with the
|
||
* quoting '\' removed.
|
||
*
|
||
*
|
||
* Inputs:
|
||
* ------
|
||
* pWmPB = ptr to parse buffer
|
||
*
|
||
*
|
||
* Outputs:
|
||
* -------
|
||
* Return = ptr to null terminated string.
|
||
* Free this string with XtFree().
|
||
* pWmPB = current line modified internally.
|
||
*
|
||
*
|
||
* Comments:
|
||
* --------
|
||
* May alter the line buffer contents.
|
||
* Handles quoted strings and characters, removing trailing whitespace from
|
||
* quoted strings.
|
||
* Returns NULL string if the line is empty or is a comment.
|
||
*
|
||
*************************************<->***********************************/
|
||
|
||
unsigned char *
|
||
_DtWmParseNextTokenExpand (
|
||
DtWmpParseBuf *pWmPB
|
||
)
|
||
{
|
||
unsigned char *pch;
|
||
unsigned char *pchReturn = NULL;
|
||
|
||
/* isolate the next token */
|
||
pch = _DtWmParseNextTokenC (&(pWmPB->pchNext), False);
|
||
|
||
/* expand environment variables, a copy of the string is returned */
|
||
pchReturn = _DtWmParseExpandEnvironmentVariables (pch, NULL);
|
||
|
||
/*
|
||
* If a token was found, but no copy returned, there were no
|
||
* environment variables. This routine needs to return a copy,
|
||
* so make one now.
|
||
*/
|
||
if (pch && !pchReturn)
|
||
pchReturn = (unsigned char *) XtNewString ((String) pch);
|
||
|
||
return (pchReturn);
|
||
}
|
||
|
||
|
||
/*************************************<->*************************************
|
||
*
|
||
* _DtWmParseBackUp (pWmPB, pchTok)
|
||
*
|
||
*
|
||
* Description:
|
||
* -----------
|
||
* Backs up to the previous token (the one before pchTok)
|
||
*
|
||
*
|
||
* Inputs:
|
||
* ------
|
||
* pWmPB = ptr to parse buffer
|
||
* pchTok = ptr to a token in the parse buffer
|
||
*
|
||
*
|
||
* Outputs:
|
||
* -------
|
||
* Returns = ptr to prev token
|
||
*
|
||
*
|
||
* Comments:
|
||
* --------
|
||
* Operates on the line buffer in the pWmPB structure. Backs up
|
||
* the next pointer and writes a space over the interpolated
|
||
* NULL (if any).
|
||
*
|
||
*************************************<->***********************************/
|
||
|
||
unsigned char *
|
||
_DtWmParseBackUp (
|
||
DtWmpParseBuf *pWmPB,
|
||
unsigned char *pchTok
|
||
)
|
||
{
|
||
if ((pchTok > pWmPB->pchLine) &&
|
||
(pchTok < (pWmPB->pchLine + pWmPB->cLineSize)))
|
||
{
|
||
unsigned char *pch;
|
||
unsigned char *pchLast;
|
||
int chlen;
|
||
|
||
pch = pchLast = pWmPB->pchLine;
|
||
|
||
/*
|
||
* Search from beginning (because of multibyte chars) to
|
||
* find the token before the string we're interested in.
|
||
*/
|
||
while ((pch < pchTok))
|
||
{
|
||
chlen = mblen ((char *)pch, MB_CUR_MAX);
|
||
if (*pch == '\0')
|
||
{
|
||
pch++;
|
||
if (pch == pchTok)
|
||
{
|
||
/*
|
||
* Found the NULL preceding the string passed in!
|
||
* Replace it with a blank and return the previous
|
||
* token (pointed to by pchLast).
|
||
*/
|
||
*(pch - 1) = DTWM_CHAR_SPACE;
|
||
break;
|
||
}
|
||
else
|
||
{
|
||
/*
|
||
* Remember the beginning of this token.
|
||
*/
|
||
pchLast = pch;
|
||
}
|
||
}
|
||
else if (chlen < 1)
|
||
{
|
||
break;
|
||
}
|
||
else
|
||
{
|
||
pch += chlen;
|
||
}
|
||
}
|
||
|
||
pWmPB->pchNext = pchLast;
|
||
}
|
||
return (pWmPB->pchNext);
|
||
}
|
||
|
||
|
||
|
||
/*************************************<->*************************************
|
||
*
|
||
* _DtWmParseSkipWhitespaceC(linePP)
|
||
*
|
||
*
|
||
* Description:
|
||
* -----------
|
||
* Scan the string, skipping over all white space characters.
|
||
*
|
||
*
|
||
* Inputs:
|
||
* ------
|
||
* linePP = nonNULL pointer to current line buffer pointer
|
||
*
|
||
*
|
||
* Outputs:
|
||
* -------
|
||
* linePP = nonNULL pointer to revised line buffer pointer
|
||
*
|
||
*
|
||
* Comments:
|
||
* --------
|
||
* Assumes linePP is nonNULL
|
||
*
|
||
*************************************<->***********************************/
|
||
|
||
void _DtWmParseSkipWhitespaceC(unsigned char **linePP)
|
||
{
|
||
while (*linePP &&
|
||
(mblen ((char *)*linePP, MB_CUR_MAX) == 1) &&
|
||
isspace (**linePP))
|
||
{
|
||
(*linePP)++;
|
||
}
|
||
|
||
} /* END OF FUNCTION _DtWmParseSkipWhitespaceC */
|
||
|
||
|
||
|
||
/*************************************<->*************************************
|
||
*
|
||
* _DtWmParseNextTokenC (linePP, SmBehavior)
|
||
*
|
||
*
|
||
* Description:
|
||
* -----------
|
||
* Returns the next quoted or whitespace-terminated nonquoted string in the
|
||
* line buffer.
|
||
* Additional functionality added to GetString in that anything in a
|
||
* quoted string is considered sacred and nothing will be stripped from
|
||
* the middle of a quoted string.
|
||
*
|
||
*
|
||
* Inputs:
|
||
* ------
|
||
* linePP = pointer to current line buffer pointer.
|
||
* SmBehavior = flag that enables parsing session manager hints if True.
|
||
* If False, this behaves as the normal OSF mwm GetString
|
||
* routine.
|
||
*
|
||
*
|
||
* Outputs:
|
||
* -------
|
||
* linePP = pointer to revised line buffer pointer.
|
||
* Return = string
|
||
*
|
||
*
|
||
* Comments:
|
||
* --------
|
||
* May alter the line buffer contents.
|
||
* Handles quoted strings and characters, removing trailing whitespace from
|
||
* quoted strings.
|
||
* Returns NULL string if the line is empty or is a comment.
|
||
* Code stolen from dtmwm.
|
||
*
|
||
*************************************<->***********************************/
|
||
|
||
unsigned char *
|
||
_DtWmParseNextTokenC (
|
||
unsigned char **linePP,
|
||
Boolean SmBehavior
|
||
)
|
||
{
|
||
/***********************************************************************
|
||
*
|
||
* The following code is duplicated from WmResParse.c (GetStringC)
|
||
* GetStringC is the HP DT version of GetString.
|
||
*
|
||
* It works here through the magic of #defines.
|
||
*
|
||
***********************************************************************/
|
||
unsigned char *lineP = *linePP;
|
||
unsigned char *endP;
|
||
unsigned char *curP;
|
||
unsigned char *lnwsP;
|
||
unsigned int level = 0, checkLev, i, quoteLevel[MAX_QUOTE_DEPTH];
|
||
int chlen;
|
||
|
||
/* get rid of leading white space */
|
||
ScanWhitespace (&lineP);
|
||
|
||
/*
|
||
* Return NULL if line is empty, whitespace, or begins with a comment.
|
||
*/
|
||
if (
|
||
*lineP == '\0' ||
|
||
((chlen = mblen ((char *)lineP, MB_CUR_MAX)) < 1) ||
|
||
((chlen == 1) && ((*lineP == '!') ||
|
||
((!SmBehavior) && (*lineP == '#'))))
|
||
)
|
||
{
|
||
*linePP = lineP;
|
||
return (NULL);
|
||
}
|
||
|
||
if ((chlen == 1) && (*lineP == '"'))
|
||
/* Quoted string */
|
||
{
|
||
quoteLevel[level] = 1;
|
||
/*
|
||
* Start beyond double quote and find the end of the quoted string.
|
||
* '\' quotes the next character.
|
||
* Otherwise, matching double quote or NULL terminates the string.
|
||
*
|
||
* We use lnwsP to point to the last non-whitespace character in the
|
||
* quoted string. When we have found the end of the quoted string,
|
||
* increment lnwsP and if lnwsP < endP, write NULL into *lnwsP.
|
||
* This removes any trailing whitespace without overwriting the
|
||
* matching quote, needed later. If the quoted string was all
|
||
* whitespace, then this will write a NULL at the beginning of the
|
||
* string that will be returned -- OK.
|
||
*/
|
||
lnwsP = lineP++; /* lnwsP points to first '"' */
|
||
curP = endP = lineP; /* other pointers point beyond */
|
||
|
||
while ((*endP = *curP) &&
|
||
((chlen = mblen ((char *)curP, MB_CUR_MAX)) > 0) &&
|
||
((chlen > 1) || (*curP != '"')))
|
||
/* Haven't found matching quote yet.
|
||
* First byte of next character has been copied to endP.
|
||
*/
|
||
{
|
||
curP++;
|
||
if ((chlen == 1) && (*endP == '\\') &&
|
||
((chlen = mblen ((char *)curP, MB_CUR_MAX)) > 0))
|
||
/* character quote:
|
||
* copy first byte of quoted nonNULL character down.
|
||
* point curP to next byte
|
||
*/
|
||
{
|
||
if (SmBehavior)
|
||
{
|
||
/*
|
||
* Check to see if this is a quoted quote - if it is
|
||
* strip off a level - if not - it's sacred leave it alone
|
||
*/
|
||
checkLev = PeekAhead((curP - 1), quoteLevel[level]);
|
||
if(checkLev > 0)
|
||
{
|
||
if(quoteLevel[level] >= checkLev)
|
||
{
|
||
if (level > 0) level--;
|
||
}
|
||
else if (level < MAX_QUOTE_DEPTH)
|
||
{
|
||
level++;
|
||
quoteLevel[level] = checkLev;
|
||
}
|
||
|
||
for(i = 0;i < (checkLev - 2);i++)
|
||
{
|
||
*endP++ = *curP++;curP++;
|
||
}
|
||
*endP = *curP++;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
*endP = *curP++;
|
||
}
|
||
}
|
||
|
||
if (chlen == 1)
|
||
/* Singlebyte character: character copy finished. */
|
||
{
|
||
if (isspace (*endP))
|
||
/* whitespace character: leave lnwsP unchanged. */
|
||
{
|
||
endP++;
|
||
}
|
||
else
|
||
/* non-whitespace character: point lnwsP to it. */
|
||
{
|
||
lnwsP = endP++;
|
||
}
|
||
}
|
||
else if (chlen > 1)
|
||
/* Multibyte (nonwhitespace) character: point lnwsP to it.
|
||
* Finish character byte copy.
|
||
*/
|
||
{
|
||
lnwsP = endP++;
|
||
while (--chlen)
|
||
{
|
||
*endP++ = *curP++;
|
||
lnwsP++;
|
||
}
|
||
}
|
||
}
|
||
|
||
/*
|
||
* Found matching quote or NULL.
|
||
* NULL out any trailing whitespace.
|
||
*/
|
||
|
||
lnwsP++;
|
||
if (lnwsP < endP)
|
||
{
|
||
*lnwsP = '\0';
|
||
}
|
||
}
|
||
|
||
else
|
||
/* Unquoted string */
|
||
{
|
||
/*
|
||
* Find the end of the nonquoted string.
|
||
* '\' quotes the next character.
|
||
* Otherwise, whitespace, NULL, or '#' terminates the string.
|
||
*/
|
||
curP = endP = lineP;
|
||
|
||
while ((*endP = *curP) &&
|
||
((chlen = mblen ((char *)curP, MB_CUR_MAX)) > 0) &&
|
||
((chlen > 1) || (!isspace (*curP) &&
|
||
(SmBehavior || (*curP != '#')))))
|
||
/* Haven't found whitespace or '#' yet.
|
||
* First byte of next character has been copied to endP.
|
||
*/
|
||
{
|
||
curP++;
|
||
if ((chlen == 1) && (*endP == '\\') &&
|
||
((chlen = mblen ((char *)curP, MB_CUR_MAX)) > 0))
|
||
/* character quote:
|
||
* copy first byte of quoted nonNULL character down.
|
||
* point curP to next byte
|
||
*/
|
||
{
|
||
*endP = *curP++;
|
||
}
|
||
endP++;
|
||
if (chlen > 1)
|
||
/* Multibyte character: finish character copy. */
|
||
{
|
||
while (--chlen)
|
||
{
|
||
*endP++ = *curP++;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/*
|
||
* Three cases for *endP:
|
||
* '#' --> write NULL over # and point to NULL
|
||
* whitespace or
|
||
* matching quote -> write NULL over char and point beyond
|
||
* NULL -> point to NULL
|
||
*/
|
||
|
||
if (!SmBehavior && (*endP == '#'))
|
||
{
|
||
*endP = '\0'; /* write NULL over '#' */
|
||
*linePP = endP; /* point to NULL */
|
||
}
|
||
else if (*endP != '\0')
|
||
{
|
||
*endP = '\0'; /* write NULL over terminator */
|
||
*linePP = ++curP; /* point beyond terminator */
|
||
}
|
||
else
|
||
{
|
||
*linePP = endP;
|
||
}
|
||
return ((unsigned char *)lineP);
|
||
|
||
} /* END OF FUNCTION _DtWmParseNextTokenC */
|
||
|
||
|
||
|
||
/*************************************<->*************************************
|
||
*
|
||
* (DtWmParseBuf *) _DtWmParseNewBuf (void)
|
||
*
|
||
*
|
||
* Description:
|
||
* -----------
|
||
* Allocates a new parse record for parsing.
|
||
*
|
||
* Inputs:
|
||
* ------
|
||
* none
|
||
*
|
||
*
|
||
* Outputs:
|
||
* -------
|
||
* Return = ptr to parse buffer record, NULL if memory allocation
|
||
* error.
|
||
*
|
||
*
|
||
* Comments:
|
||
* --------
|
||
* Call this first before using the other DtWmp routines that require
|
||
* a parse buffer. Treat this as an opaque type; use the provided
|
||
* routines to create, access, and destroy this structure.
|
||
*
|
||
*************************************<->***********************************/
|
||
|
||
DtWmpParseBuf *
|
||
_DtWmParseNewBuf ( void )
|
||
|
||
{
|
||
DtWmpParseBuf *pWmPB;
|
||
|
||
pWmPB = (DtWmpParseBuf *) XtMalloc (sizeof (DtWmpParseBuf));
|
||
if (pWmPB)
|
||
{
|
||
pWmPB->pchLine = (unsigned char *) XtMalloc (MAXLINE+1);
|
||
if (!pWmPB->pchLine)
|
||
{
|
||
XtFree ((char *)pWmPB);
|
||
pWmPB = NULL;
|
||
}
|
||
}
|
||
|
||
if (pWmPB)
|
||
{
|
||
pWmPB->lineNumber = 0;
|
||
pWmPB->pchNext = pWmPB->pchLine;
|
||
pWmPB->cLineSize = MAXLINE+1;
|
||
pWmPB->pFile = NULL;
|
||
*(pWmPB->pchLine) = '\0';
|
||
}
|
||
|
||
return (pWmPB);
|
||
|
||
} /* END OF FUNCTION _DtWmParseNewBuf */
|
||
|
||
|
||
/*************************************<->*************************************
|
||
*
|
||
* (DtWmParseBuf *) _DtWmpIncBuf (pWmPB)
|
||
*
|
||
*
|
||
* Description:
|
||
* -----------
|
||
* Increases the size of the line buffer in the parse buffer
|
||
*
|
||
* Inputs:
|
||
* ------
|
||
* pWmPB = pointer to a parse buffer
|
||
*
|
||
*
|
||
* Outputs:
|
||
* -------
|
||
* Return = ptr to parse buffer record, NULL if memory allocation
|
||
* error.
|
||
*
|
||
*
|
||
* Comments:
|
||
* --------
|
||
*
|
||
*************************************<->***********************************/
|
||
|
||
static DtWmpParseBuf *
|
||
_DtWmpIncBuf (
|
||
DtWmpParseBuf *pWmPB)
|
||
|
||
{
|
||
if (pWmPB)
|
||
{
|
||
int ix;
|
||
|
||
if (pWmPB->pFile)
|
||
{
|
||
/* save index into old string */
|
||
ix = pWmPB->pchNext - pWmPB->pchLine;
|
||
}
|
||
|
||
pWmPB->pchLine = (unsigned char *)
|
||
XtRealloc ((char *)pWmPB->pchLine, (pWmPB->cLineSize + MAXLINE));
|
||
if (pWmPB->pchLine)
|
||
{
|
||
pWmPB->cLineSize += MAXLINE;
|
||
|
||
if (pWmPB->pFile)
|
||
{
|
||
/* restore index into new string */
|
||
pWmPB->pchNext = pWmPB->pchLine + ix;
|
||
}
|
||
}
|
||
}
|
||
|
||
return (pWmPB);
|
||
|
||
} /* END OF FUNCTION _DtWmpIncBuf */
|
||
|
||
|
||
/*************************************<->*************************************
|
||
*
|
||
* _DtWmParseDestroyBuf (pWmPB)
|
||
*
|
||
*
|
||
* Description:
|
||
* -----------
|
||
* Destroys a parse buffer record, freeing any allocated memory.
|
||
*
|
||
*
|
||
* Inputs:
|
||
* ------
|
||
* pWmPB = ptr to previously allocated parse buffer
|
||
*
|
||
*
|
||
* Outputs:
|
||
* -------
|
||
* none
|
||
*
|
||
*
|
||
* Comments:
|
||
* --------
|
||
* Destroys parse buffers allocated by _DtWmParseNewBuf.
|
||
*
|
||
*************************************<->***********************************/
|
||
|
||
void
|
||
_DtWmParseDestroyBuf (
|
||
DtWmpParseBuf *pWmPB
|
||
)
|
||
|
||
{
|
||
if (pWmPB)
|
||
{
|
||
if (pWmPB->pchLine)
|
||
{
|
||
XtFree ((char *) pWmPB->pchLine);
|
||
}
|
||
XtFree ((char *) pWmPB);
|
||
}
|
||
|
||
} /* END OF FUNCTION _DtWmParseDestroyBuf */
|
||
|
||
|
||
/*************************************<->*************************************
|
||
*
|
||
* (unsigned char *) _DtWmParseSetLine (pWmPB, pch)
|
||
*
|
||
*
|
||
* Description:
|
||
* -----------
|
||
* Sets a line into the parse buffer structure. This is used in cases
|
||
* where parsing of an embedded string, usually a default, is done
|
||
* instead of parsing out of a file.
|
||
*
|
||
*
|
||
* Inputs:
|
||
* ------
|
||
* pWmPB = previously allocated parse buffer
|
||
* pch = ptr to unsigned char string (zero terminated)
|
||
*
|
||
* Outputs:
|
||
* -------
|
||
* Return = pch
|
||
*
|
||
*
|
||
* Comments:
|
||
* --------
|
||
* This resets any previous setting of the file pointer. EOF wil be
|
||
* returned when the string pointed to by pch is exhausted.
|
||
*
|
||
* Resets line number count.
|
||
*
|
||
*************************************<->***********************************/
|
||
|
||
void
|
||
_DtWmParseSetLine (
|
||
DtWmpParseBuf *pWmPB,
|
||
unsigned char *pch
|
||
)
|
||
|
||
{
|
||
if (pWmPB)
|
||
{
|
||
pWmPB->pchLine = pch;
|
||
pWmPB->pchNext = pWmPB->pchLine;
|
||
pWmPB->pFile = NULL;
|
||
pWmPB->lineNumber = 0;
|
||
}
|
||
|
||
} /* END OF FUNCTION _DtWmParseSetLine */
|
||
|
||
|
||
/*************************************<->*************************************
|
||
*
|
||
* (FILE *) _DtWmParseSetFile (pWmPB, pFile)
|
||
*
|
||
*
|
||
* Description:
|
||
* -----------
|
||
* Sets the file pointer in a parse buffer. This is used when parsing
|
||
* from a file is required.
|
||
*
|
||
*
|
||
* Inputs:
|
||
* ------
|
||
* pWmPB = pointer to a parse buffer
|
||
* pFile = pointer to an opened FILE
|
||
*
|
||
* Outputs:
|
||
* -------
|
||
* Return = pFile
|
||
*
|
||
*
|
||
* Comments:
|
||
* --------
|
||
* You fopen the file first, then pass in the FILE * returned to this
|
||
* routine.
|
||
*
|
||
* Resets line number count.
|
||
*
|
||
*************************************<->***********************************/
|
||
|
||
void
|
||
_DtWmParseSetFile (
|
||
DtWmpParseBuf *pWmPB,
|
||
FILE *pFile
|
||
)
|
||
|
||
{
|
||
if (pWmPB)
|
||
{
|
||
pWmPB->pchLine[0] = '\0';
|
||
pWmPB->pchNext = NULL;
|
||
pWmPB->pFile = pFile;
|
||
pWmPB->lineNumber = 0;
|
||
}
|
||
|
||
} /* END OF FUNCTION _DtWmParseSetFile */
|
||
|
||
|
||
/*************************************<->*************************************
|
||
*
|
||
* (unsigned char *) _DtWmParseNextLine ( pWmPB )
|
||
*
|
||
*
|
||
* Description:
|
||
* -----------
|
||
* Returns a pointer to the next line to parse.
|
||
*
|
||
*
|
||
* Inputs:
|
||
* ------
|
||
* pWmPB = pointer to a parse buffer
|
||
*
|
||
*
|
||
* Outputs:
|
||
* -------
|
||
* Return = pointer to next line to parse or NULL on EOF.
|
||
*
|
||
*
|
||
* Comments:
|
||
* --------
|
||
*
|
||
*
|
||
*************************************<->***********************************/
|
||
|
||
unsigned char *
|
||
_DtWmParseNextLine (
|
||
DtWmpParseBuf *pWmPB
|
||
)
|
||
|
||
{
|
||
/***********************************************************************
|
||
*
|
||
* The following code is duplicated from WmResParse.c (GetNextLine)
|
||
* It works here through the magic of #defines.
|
||
*
|
||
***********************************************************************/
|
||
|
||
unsigned char *string;
|
||
int len;
|
||
int chlen;
|
||
wchar_t last;
|
||
wchar_t wdelim;
|
||
char delim;
|
||
int lastlen;
|
||
|
||
if (cfileP != NULL)
|
||
/* read fopened file */
|
||
{
|
||
if ((string = (unsigned char *)
|
||
fgets ((char *)line, MAXLINE, cfileP)) != NULL)
|
||
{
|
||
#ifdef PARSE_LIB
|
||
if (strlen((char *)string) > (size_t)pWmPB->cLineSize)
|
||
{
|
||
/*
|
||
* Bump size of destination buffer
|
||
*/
|
||
pWmPB->cLineSize = 1 + strlen((char *)string);
|
||
pWmPB->pchLine = (unsigned char *)
|
||
XtRealloc ((char *)pWmPB->pchLine,
|
||
(pWmPB->cLineSize));
|
||
}
|
||
#endif /* PARSE_LIB */
|
||
|
||
lastlen = 0;
|
||
while (*string &&
|
||
((len = mblen((char *)string, MB_CUR_MAX)) > 0))
|
||
{
|
||
mbtowc(&last, (char *)string, MB_CUR_MAX);
|
||
lastlen = len;
|
||
string += len;
|
||
}
|
||
delim = '\\';
|
||
mbtowc(&wdelim, &delim, MB_CUR_MAX);
|
||
if (lastlen == 1 && last == wdelim)
|
||
{
|
||
do
|
||
{
|
||
if (!fgets((char *)string, MAXLINE - (string - line), cfileP))
|
||
break;
|
||
|
||
lastlen = 0;
|
||
while (*string &&
|
||
((len = mblen((char *)string, MB_CUR_MAX)) > 0))
|
||
{
|
||
mbtowc(&last, (char *)string, MB_CUR_MAX);
|
||
lastlen = len;
|
||
string += len;
|
||
}
|
||
linec++;
|
||
}
|
||
while (lastlen == 1 && last == wdelim);
|
||
}
|
||
string = line;
|
||
}
|
||
}
|
||
else if ((parseP != NULL) && (*parseP != '\0'))
|
||
/* read parse string */
|
||
{
|
||
#ifdef PARSE_LIB
|
||
if (strlen((char *)parseP) > (size_t)pWmPB->cLineSize)
|
||
{
|
||
/*
|
||
* Bump size of destination buffer
|
||
*/
|
||
pWmPB->cLineSize = 1 + strlen((char *)parseP);
|
||
pWmPB->pchLine = (unsigned char *)
|
||
XtRealloc ((char *)pWmPB->pchLine,
|
||
(pWmPB->cLineSize));
|
||
}
|
||
#endif /* PARSE_LIB */
|
||
string = line;
|
||
|
||
while ((*parseP != '\0') &&
|
||
((chlen = mblen ((char *)parseP, MB_CUR_MAX)) != 0) &&
|
||
(*parseP != '\n'))
|
||
/* copy all but end-of-line and newlines to line buffer */
|
||
{
|
||
if (chlen == -1)
|
||
parseP++;
|
||
else
|
||
{
|
||
while (chlen--)
|
||
{
|
||
*(string++) = *(parseP++);
|
||
}
|
||
}
|
||
}
|
||
*string = '\0';
|
||
if (*parseP == '\n')
|
||
{
|
||
parseP++;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
string = NULL;
|
||
}
|
||
|
||
linec++;
|
||
#ifdef PARSE_LIB
|
||
if (cfileP)
|
||
{
|
||
/* update pchNext to get next line */
|
||
pWmPB->pchNext = string;
|
||
}
|
||
#endif /* PARSE_LIB */
|
||
return (string);
|
||
|
||
|
||
} /* END OF FUNCTION _DtWmParseNextLine */
|
||
|
||
|
||
/*************************************<->*************************************
|
||
*
|
||
* (unsigned char *) _DtWmParseCurrentChar (pWmPB)
|
||
*
|
||
*
|
||
* Description:
|
||
* -----------
|
||
* Returns a pointer to the rest of the current line.
|
||
*
|
||
*
|
||
* Inputs:
|
||
* ------
|
||
* pWmPB = pointer to a parse buffer
|
||
*
|
||
*
|
||
* Outputs:
|
||
* -------
|
||
* Return = pointer to the rest of the current line
|
||
*
|
||
*
|
||
* Comments:
|
||
* --------
|
||
* Useful in cases where you want to look at a char before getting the
|
||
* next token or if you want to treat the rest of the line as a
|
||
* single token.
|
||
*
|
||
*************************************<->***********************************/
|
||
|
||
unsigned char *
|
||
_DtWmParseCurrentChar (
|
||
DtWmpParseBuf *pWmPB
|
||
)
|
||
|
||
{
|
||
return (pWmPB ? pWmPB->pchNext : (unsigned char *)NULL);
|
||
|
||
} /* END OF FUNCTION _DtWmParseCurrentChar */
|
||
|
||
|
||
|
||
/*************************************<->*************************************
|
||
*
|
||
* (unsigned char *) _DtWmParseNextChar (pWmPB)
|
||
*
|
||
*
|
||
* Description:
|
||
* -----------
|
||
* Advances the pointer to the next char and returns a pointer
|
||
* to the new current char.
|
||
*
|
||
*
|
||
* Inputs:
|
||
* ------
|
||
* pWmPB = pointer to a parse buffer
|
||
*
|
||
*
|
||
* Outputs:
|
||
* -------
|
||
* Return = pointer to the rest of the current line
|
||
*
|
||
*
|
||
* Comments:
|
||
* --------
|
||
*
|
||
*************************************<->***********************************/
|
||
|
||
unsigned char *
|
||
_DtWmParseNextChar (
|
||
DtWmpParseBuf *pWmPB
|
||
)
|
||
|
||
{
|
||
unsigned char *pch = NULL;
|
||
int chlen;
|
||
|
||
if (pWmPB &&
|
||
pWmPB->pchNext &&
|
||
(chlen = mblen((char *)pWmPB->pchNext, MB_CUR_MAX) > 0))
|
||
{
|
||
pch = (pWmPB->pchNext += chlen);
|
||
}
|
||
|
||
return (pch);
|
||
}
|
||
|
||
|
||
/*************************************<->*************************************
|
||
*
|
||
* (int) _DtWmParseLineNumber (pWmPB)
|
||
*
|
||
*
|
||
* Description:
|
||
* -----------
|
||
* Returns the number of the current line of what's being parsed.
|
||
*
|
||
*
|
||
* Inputs:
|
||
* ------
|
||
* pWmPB = ptr to parse buffer
|
||
*
|
||
*
|
||
* Outputs:
|
||
* -------
|
||
* Return = number of current line
|
||
*
|
||
*
|
||
* Comments:
|
||
* --------
|
||
* Used for error reporting.
|
||
*
|
||
* The line number is computed by counting '\n' characters.
|
||
*
|
||
*************************************<->***********************************/
|
||
|
||
int
|
||
_DtWmParseLineNumber (
|
||
DtWmpParseBuf *pWmPB
|
||
)
|
||
|
||
{
|
||
return (pWmPB ? pWmPB->lineNumber : 0);
|
||
|
||
} /* END OF FUNCTION _DtWmParseLineNumber */
|
||
|
||
|
||
/*************************************<->*************************************
|
||
*
|
||
* _DtWmParseToLower (string)
|
||
*
|
||
*
|
||
* Description:
|
||
* -----------
|
||
* Lower all characters in a string.
|
||
*
|
||
*
|
||
* Inputs:
|
||
* ------
|
||
* string = NULL-terminated character string or NULL
|
||
*
|
||
*
|
||
* Outputs:
|
||
* -------
|
||
* string = NULL-terminated lower case character string or NULL
|
||
*
|
||
*
|
||
* Comments:
|
||
* --------
|
||
* Can handle multi-byte characters
|
||
*
|
||
*************************************<->***********************************/
|
||
|
||
void _DtWmParseToLower (char *string)
|
||
{
|
||
char *pch = string;
|
||
int chlen;
|
||
|
||
while ((chlen = mblen (pch, MB_CUR_MAX)) > 0)
|
||
{
|
||
if ((chlen == 1) && (isupper (*pch)))
|
||
{
|
||
*pch = tolower(*pch);
|
||
}
|
||
pch += chlen;
|
||
}
|
||
|
||
} /* END OF FUNCTION _DtWmParseToLower */
|
||
|
||
|
||
|
||
/*************************************<->*************************************
|
||
*
|
||
* _DtWmParsePeekAhead (currentChar, currentLev)
|
||
*
|
||
*
|
||
* Description:
|
||
* -----------
|
||
* Returns a new level value if this is a new nesting level of quoted string
|
||
* Otherwise it returns a zero
|
||
*
|
||
*
|
||
* Inputs:
|
||
* ------
|
||
* currentChar = current position in the string
|
||
* currentLev = current level of nesting
|
||
*
|
||
*
|
||
* Outputs:
|
||
* -------
|
||
* Returns either a new level of nesting or zero if the character is copied in
|
||
*
|
||
*
|
||
* Comments:
|
||
* --------
|
||
*
|
||
*************************************<->***********************************/
|
||
unsigned int _DtWmParsePeekAhead(unsigned char *currentChar,
|
||
unsigned int currentLev)
|
||
|
||
|
||
{
|
||
Boolean done = False;
|
||
unsigned int tmpLev = 1;
|
||
unsigned int chlen;
|
||
|
||
while (((chlen = mblen ((char *)currentChar, MB_CUR_MAX)) > 0) &&
|
||
(chlen == 1) && ((*currentChar == '"') || (*currentChar == '\\'))
|
||
&& (done == False))
|
||
{
|
||
currentChar++;
|
||
|
||
if(((chlen = mblen ((char *)currentChar, MB_CUR_MAX)) > 0) &&
|
||
(chlen == 1) &&
|
||
((*currentChar == '"') || (*currentChar == '\\')))
|
||
{
|
||
tmpLev++;
|
||
if(*currentChar == '"')
|
||
{
|
||
done = True;
|
||
}
|
||
else
|
||
{
|
||
currentChar++;
|
||
}
|
||
}
|
||
}
|
||
|
||
/*
|
||
* Figure out if this is truly a new level of nesting - else ignore it
|
||
* This section probably could do some error checking and return -1
|
||
* If so, change type of routine from unsigned int to int
|
||
*/
|
||
if(done == True)
|
||
{
|
||
return(tmpLev);
|
||
}
|
||
else
|
||
{
|
||
return(0);
|
||
}
|
||
} /* END OF FUNCTION _DtWmParsePeekAhead */
|
||
|
||
|
||
|
||
/*************************************<->*************************************
|
||
*
|
||
* (unsigned char *) _DtWmParseFilenameExpand (pchFilename)
|
||
*
|
||
*
|
||
* Description:
|
||
* -----------
|
||
* Returns a copy of a file name with environment variables
|
||
* expanded.
|
||
*
|
||
*
|
||
* Inputs:
|
||
* ------
|
||
* pchFilename = ptr to a zero terminated character string (filename)
|
||
*
|
||
*
|
||
* Outputs:
|
||
* -------
|
||
* Return = ptr to a new file name with environment variables
|
||
* expanded.
|
||
*
|
||
*
|
||
* Comments:
|
||
* --------
|
||
* The passed in string is temporarily modified inside here.
|
||
*
|
||
* Free the returned string with XtFree().
|
||
*
|
||
* Returns NULL on a memory allocation error.
|
||
*
|
||
* Environment variables that can't be expanded are removed from
|
||
* the returned copy.
|
||
*
|
||
* If no environment variables, you get a copy of the string back.
|
||
*
|
||
*************************************<->***********************************/
|
||
unsigned char *
|
||
_DtWmParseFilenameExpand (
|
||
unsigned char *pchFilename
|
||
)
|
||
|
||
{
|
||
unsigned char *pchN, *pchNew, *pchO;
|
||
unsigned char *pchEnv, *pchEnv0, *pchEnv1;
|
||
unsigned char chSave;
|
||
int len, n, nx, ix;
|
||
unsigned char pchBrk[] = { DTWM_CHAR_ENVIRONMENT,
|
||
DTWM_CHAR_DIRECTORY,
|
||
'\0'
|
||
};
|
||
|
||
len = strlen ((char *)pchFilename);
|
||
pchNew = (unsigned char *) XtMalloc (1+len);
|
||
pchO = pchFilename;
|
||
chSave = '\0';
|
||
ix = 0;
|
||
|
||
while (pchNew && pchO && *pchO)
|
||
{
|
||
/* find next environment variable */
|
||
pchEnv0 = (unsigned char *)
|
||
strchr ((char *)pchO, (int) DTWM_CHAR_ENVIRONMENT);
|
||
if (pchEnv0)
|
||
{
|
||
/* length to this point */
|
||
n = pchEnv0 - pchO;
|
||
|
||
/* copy up to environment character */
|
||
if (n)
|
||
{
|
||
memcpy (&pchNew[ix], pchO, n);
|
||
ix += n;
|
||
}
|
||
|
||
/* skip environment character */
|
||
pchEnv0++;
|
||
|
||
/* end of variable is at one of:
|
||
* start of next variable,
|
||
* start of next directory,
|
||
* end of string
|
||
*/
|
||
pchEnv1 = (unsigned char *)
|
||
strpbrk ((char *)pchEnv0, (char *)pchBrk);
|
||
|
||
if (pchEnv1)
|
||
{
|
||
/* next string starts after this one */
|
||
pchO = pchEnv1;
|
||
n = pchEnv1 - pchEnv0 + 1;
|
||
|
||
/* replace this char with NULL for now */
|
||
chSave = *pchEnv1;
|
||
*pchEnv1 = '\0';
|
||
}
|
||
else
|
||
{
|
||
/* This environment variable is the last thing on
|
||
* the line. Signal all done.
|
||
*/
|
||
n = strlen ((char *) pchO);
|
||
pchO += n;
|
||
}
|
||
|
||
pchEnv = (unsigned char *) getenv ((char *)pchEnv0);
|
||
if (pchEnv)
|
||
{
|
||
nx = strlen ((char *) pchEnv);
|
||
if (nx > n)
|
||
{
|
||
len += nx - n;
|
||
pchNew = (unsigned char *)
|
||
XtRealloc ((char *)pchNew, 1+len);
|
||
}
|
||
if (pchNew)
|
||
{
|
||
memcpy (&pchNew[ix], pchEnv, nx);
|
||
ix += nx;
|
||
}
|
||
else
|
||
{
|
||
continue;
|
||
}
|
||
}
|
||
|
||
if (chSave)
|
||
{
|
||
*pchO = chSave;
|
||
chSave = '\0';
|
||
}
|
||
/* keep a kosher string */
|
||
pchNew[ix] = '\0';
|
||
}
|
||
else
|
||
{
|
||
/* copy the rest of the string */
|
||
n = strlen ((char *) pchO);
|
||
memcpy (&pchNew[ix], pchO, n);
|
||
pchO += n;
|
||
|
||
/* remember the NULL! (a famous battle cry) */
|
||
pchNew[ix + n] = '\0';
|
||
}
|
||
}
|
||
|
||
return (pchNew);
|
||
|
||
} /* END OF FUNCTION _DtWmParseFilenameExpand */
|
||
|
||
|
||
/*************************************<->*************************************
|
||
*
|
||
* unsigned char * _DtWmParseExpandEnvironmentVariables (pch, pchBrk)
|
||
*
|
||
*
|
||
* Description:
|
||
* -----------
|
||
* Expands environment variables in a string.
|
||
*
|
||
*
|
||
* Inputs:
|
||
* ------
|
||
* pch = ptr to a zero terminated character string
|
||
* pchBrk = array of "break" characters (see strpbrk()).
|
||
* defaults are used if this is NULL.
|
||
*
|
||
* Outputs:
|
||
* -------
|
||
* Return = string with expanded environment variables. (free with XtFree)
|
||
* NULL string if no environment variables or backslashes
|
||
* found in the string passed in.
|
||
*
|
||
*
|
||
* Comments:
|
||
* --------
|
||
* Free returned string with XtFree()
|
||
*
|
||
* Environment variables that can't be expanded are removed from
|
||
* the returned copy.
|
||
*
|
||
* Default delimiter set is [Space], [Tab], '$', [Newline], '\', '/'.
|
||
*
|
||
* Variables of form $(..) and ${..} supported.
|
||
*
|
||
* A backslash '\' in front of any character quotes it. The backslash
|
||
* is removed in the returned string. A literal backslash needs to be
|
||
* quoted with a backslash.
|
||
*
|
||
*************************************<->***********************************/
|
||
unsigned char *
|
||
_DtWmParseExpandEnvironmentVariables (
|
||
unsigned char *pch,
|
||
unsigned char *pchBrk
|
||
)
|
||
|
||
{
|
||
int chlen;
|
||
unsigned char *pchStart;
|
||
unsigned char chSave;
|
||
unsigned char *pchEnvStart;
|
||
unsigned char *pchEnvValue;
|
||
unsigned char *pchReturn = NULL;
|
||
unsigned char *pchNext;
|
||
unsigned char *pchBreak;
|
||
Boolean bEatBreak;
|
||
Boolean bAlreadyAdvanced;
|
||
int lenOriginal;
|
||
int lenNonEnv;
|
||
int lenEnvVar;
|
||
int lenEnvValue;
|
||
int lenReturn = 0;
|
||
int lenSave;
|
||
static unsigned char pchDefaultBrk[] = {
|
||
DTWM_CHAR_ENVIRONMENT,
|
||
DTWM_CHAR_SPACE,
|
||
DTWM_CHAR_TAB,
|
||
DTWM_CHAR_NEW_LINE,
|
||
DTWM_CHAR_BACKSLASH,
|
||
DTWM_CHAR_DIRECTORY,
|
||
'\0' };
|
||
unsigned char pchParenBrk[] = {
|
||
DTWM_CHAR_R_PAREN,
|
||
'\0' };
|
||
unsigned char pchBraceBrk[] = {
|
||
DTWM_CHAR_R_BRACE,
|
||
'\0' };
|
||
|
||
/* There needs to be something to look at */
|
||
if (!pch)
|
||
return (NULL);
|
||
|
||
pchStart = pch;
|
||
lenOriginal = strlen ((char *)pch);
|
||
chlen = mblen ((char *)pch, MB_CUR_MAX);
|
||
chSave = '\0';
|
||
|
||
while (*pch && (chlen > 0))
|
||
{
|
||
if (chlen == 1)
|
||
{
|
||
bAlreadyAdvanced = False;
|
||
switch (*pch)
|
||
{
|
||
case DTWM_CHAR_BACKSLASH:
|
||
/*
|
||
* Copy up to start of quoted char
|
||
*/
|
||
if (!pchReturn)
|
||
{
|
||
lenReturn = lenOriginal + 1;
|
||
pchReturn = (unsigned char *)
|
||
XtMalloc (lenReturn * sizeof (unsigned char));
|
||
pchReturn[0] = '\0';
|
||
}
|
||
chSave = *pch;
|
||
*pch = '\0';
|
||
strcat ((char *) pchReturn, (char *)pchStart);
|
||
*pch = chSave;
|
||
chSave = '\0';
|
||
|
||
/*
|
||
* The next character is "escaped", skip over it.
|
||
*/
|
||
pchStart = pch += chlen;
|
||
chlen = mblen ((char *)pch, MB_CUR_MAX);
|
||
break;
|
||
|
||
case DTWM_CHAR_ENVIRONMENT:
|
||
/* save start of environment variable */
|
||
pchEnvStart = pch;
|
||
pch += chlen;
|
||
chlen = mblen ((char *)pch, MB_CUR_MAX);
|
||
|
||
/*
|
||
* Copy up to start of environment variable
|
||
*/
|
||
if (!pchReturn)
|
||
{
|
||
lenReturn = lenOriginal + 1;
|
||
pchReturn = (unsigned char *)
|
||
XtMalloc (lenReturn * sizeof (unsigned char));
|
||
pchReturn[0] = '\0';
|
||
lenSave = 0;
|
||
}
|
||
else
|
||
{
|
||
lenSave = strlen ((char *)pchReturn);
|
||
}
|
||
lenNonEnv = pchEnvStart - pchStart;
|
||
memcpy (&pchReturn[lenSave], pchStart, lenNonEnv);
|
||
pchReturn[lenSave+lenNonEnv] = '\0';
|
||
|
||
/*
|
||
* Determine how we find the end of this
|
||
* environment variable.
|
||
*/
|
||
bEatBreak = False;
|
||
if ((chlen == 1) &&
|
||
(*pch == DTWM_CHAR_L_PAREN))
|
||
{
|
||
pch += chlen;
|
||
chlen = mblen ((char *)pch, MB_CUR_MAX);
|
||
pchBreak = pchParenBrk;
|
||
bEatBreak = True;
|
||
}
|
||
else if ((chlen == 1) &&
|
||
(*pch == DTWM_CHAR_L_BRACE))
|
||
{
|
||
pch += chlen;
|
||
chlen = mblen ((char *)pch, MB_CUR_MAX);
|
||
pchBreak = pchBraceBrk;
|
||
bEatBreak = True;
|
||
}
|
||
else if (pchBrk && *pchBrk)
|
||
{
|
||
pchBreak = pchBrk;
|
||
}
|
||
else
|
||
{
|
||
pchBreak = pchDefaultBrk;
|
||
}
|
||
|
||
/*
|
||
* Look for end of environment variable
|
||
*/
|
||
pchNext = (unsigned char *)
|
||
strpbrk ((char *)pch, (char *)pchBreak);
|
||
|
||
if (!pchNext)
|
||
{
|
||
/* it's the rest of the string */
|
||
chSave = '\0';
|
||
bEatBreak = False;
|
||
pchNext = pch + strlen ((char *) pch);
|
||
}
|
||
else
|
||
{
|
||
/* temporarily put a string terminator here */
|
||
chSave = *pchNext;
|
||
*pchNext = '\0';
|
||
}
|
||
|
||
/*
|
||
* Lookup environment variable
|
||
*/
|
||
lenEnvVar = strlen ((char *)pch);
|
||
pchEnvValue = (unsigned char *) getenv ((char *)pch);
|
||
|
||
if (pchEnvValue)
|
||
{
|
||
/*
|
||
* Insure there's enough room in the return string
|
||
*/
|
||
lenEnvValue = strlen ((char *)pchEnvValue);
|
||
if (!pchReturn)
|
||
{
|
||
lenReturn = lenOriginal + 1 - lenEnvVar +
|
||
lenEnvValue;
|
||
pchReturn = (unsigned char *)
|
||
XtMalloc (lenReturn * sizeof (unsigned char));
|
||
pchReturn[0] = '\0';
|
||
}
|
||
else
|
||
{
|
||
lenReturn = lenReturn + 1 - lenEnvVar +
|
||
lenEnvValue;
|
||
pchReturn = (unsigned char *)
|
||
XtRealloc ((char *)pchReturn,
|
||
lenReturn * sizeof (unsigned char));
|
||
}
|
||
|
||
/*
|
||
* Tack it onto the return string
|
||
*/
|
||
strcat ((char *)pchReturn, (char *)pchEnvValue);
|
||
}
|
||
|
||
/*
|
||
* Advance the pointer for the next pass
|
||
*/
|
||
if (chSave)
|
||
{
|
||
/* restore saved character */
|
||
*pchNext = chSave;
|
||
chSave = '\0';
|
||
|
||
/*
|
||
* If this was a closing paren, then skip it
|
||
*/
|
||
if (bEatBreak)
|
||
{
|
||
chlen = mblen ((char *)pchNext, MB_CUR_MAX);
|
||
pchNext += chlen;
|
||
}
|
||
}
|
||
pchStart = pch = pchNext;
|
||
chlen = mblen ((char *)pch, MB_CUR_MAX);
|
||
/*
|
||
* We're already pointing at the next character
|
||
* to process, don't advance again!
|
||
*/
|
||
bAlreadyAdvanced = True;
|
||
|
||
break;
|
||
|
||
default:
|
||
/* this character is not interesting */
|
||
break;
|
||
}
|
||
|
||
/*
|
||
* Move to the next character if we're not already
|
||
* there.
|
||
*/
|
||
if (!bAlreadyAdvanced)
|
||
{
|
||
pch += chlen;
|
||
chlen = mblen ((char *)pch, MB_CUR_MAX);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
pch += chlen;
|
||
chlen = mblen ((char *)pch, MB_CUR_MAX);
|
||
}
|
||
}
|
||
|
||
if (pchReturn && *pchStart)
|
||
{
|
||
/*
|
||
* Copy remaining parts of the string
|
||
*/
|
||
strcat ((char *)pchReturn, (char *)pchStart);
|
||
}
|
||
|
||
return (pchReturn);
|
||
|
||
} /* END OF FUNCTION _DtWmParseExpandEnvironmentVariables */
|
||
|
||
|
||
|
||
/******************************<->*************************************
|
||
*
|
||
* _DtWmParseMakeQuotedString (pchLine)
|
||
*
|
||
*
|
||
* Description:
|
||
* -----------
|
||
* Encapsulates the passed in "line" into a string argument quoted
|
||
* by double quotes. Special characters are "escaped" as needed.
|
||
*
|
||
* Inputs:
|
||
* ------
|
||
* pchLine = ptr to string to enclose in quotes
|
||
*
|
||
* Outputs:
|
||
* -------
|
||
* Return = ptr to quoted string
|
||
*
|
||
* Comment:
|
||
* -------
|
||
* Returned string should be freed with XtFree().
|
||
*
|
||
******************************<->***********************************/
|
||
|
||
unsigned char *
|
||
_DtWmParseMakeQuotedString (unsigned char *pchLine)
|
||
{
|
||
unsigned char *pchRet;
|
||
int iLen0, iLen1;
|
||
int cSpecial;
|
||
int i,j;
|
||
int chlen;
|
||
|
||
iLen0 = strlen ((char *)pchLine);
|
||
iLen1 = iLen0 + 2; /* for starting, ending quotes */
|
||
|
||
for (i=0; i < iLen0; i++)
|
||
{
|
||
/*
|
||
* Count special chars to get estimate of new length
|
||
*/
|
||
chlen = mblen ((char *) &pchLine[i], MB_CUR_MAX);
|
||
if ((chlen == 1) &&
|
||
((pchLine[i] == '\\') ||
|
||
(pchLine[i] == '"')))
|
||
{
|
||
iLen1++;
|
||
}
|
||
else if (chlen < 1)
|
||
{
|
||
break;
|
||
}
|
||
else
|
||
{
|
||
i += chlen-1;
|
||
}
|
||
}
|
||
|
||
pchRet = (unsigned char *) XtMalloc (1+iLen1);
|
||
|
||
if (pchRet)
|
||
{
|
||
pchRet[0] = '"'; /* starting quote */
|
||
/*
|
||
* Copy chars from old string to new one
|
||
*/
|
||
for (i=0, j=1; i < iLen0; i++, j++)
|
||
{
|
||
chlen = mblen ((char *) &pchLine[i], MB_CUR_MAX);
|
||
if ((chlen == 1) &&
|
||
((pchLine[i] == '\\') ||
|
||
(pchLine[i] == '"')))
|
||
{
|
||
/* quote next char */
|
||
pchRet[j++] = '\\';
|
||
}
|
||
else if (chlen < 1)
|
||
{
|
||
break;
|
||
}
|
||
else while (chlen > 1)
|
||
{
|
||
/* copy first bytes of multibyte char */
|
||
pchRet[j++] = pchLine[i++];
|
||
chlen--;
|
||
}
|
||
/* copy char */
|
||
pchRet[j] = pchLine[i];
|
||
}
|
||
pchRet[j++] = '"'; /* ending quote */
|
||
pchRet[j] = '\0'; /* end of string */
|
||
}
|
||
|
||
return (pchRet);
|
||
|
||
} /* END OF FUNCTION _DtWmParseMakeQuotedString */
|
||
|
||
|
||
/*==================== END OF FILE WmParse.c ====================*/
|