2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these libraries and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 /******************************<+>*************************************
24 **********************************************************************
28 ** Project: HP/Motif Workspace Manager (dtwm)
32 ** This file contains the generic parsing routines
35 *********************************************************************
37 ** (c) Copyright 1987, 1988, 1989, 1990, 1991 HEWLETT-PACKARD COMPANY
38 ** ALL RIGHTS RESERVED
40 **********************************************************************
41 **********************************************************************
44 **********************************************************************
45 ******************************<+>*************************************/
47 /* ANSI C definitions, This should be the first thing in WmGlobal.h */
59 #include <X11/Intrinsic.h>
70 static DtWmpParseBuf * _DtWmpIncBuf (
71 DtWmpParseBuf *pWmPB);
76 #define MAXLINE (MAXWMPATH+1)
78 #define MAX_QUOTE_DEPTH 10
81 * This flags non-OSF code in those sections that were lifted
88 * Defines used to maintain code similarity between OSF/mwm source
89 * routines and these routines.
91 #define cfileP ((pWmPB)->pFile)
92 #define linec ((pWmPB)->lineNumber)
93 #define line ((pWmPB)->pchLine)
94 #define parseP ((pWmPB)->pchNext)
95 #define ScanWhitespace(s) (_DtWmParseSkipWhitespaceC(s))
96 #define PeekAhead(s,l) (_DtWmParsePeekAhead(s,l))
99 /*************************************<->*************************************
101 * _DtWmParseSkipWhitespace(pWmPB)
106 * Scan the current string, skipping over all white space characters.
111 * pWmPB = ptr to parse buffer
116 * pWmPB = parse buffer modified; current line ptr may be moved.
121 * Assumes there's a current line in the parse buffer
123 *************************************<->***********************************/
125 void _DtWmParseSkipWhitespace(DtWmpParseBuf *pWmPB)
127 _DtWmParseSkipWhitespaceC (&(pWmPB->pchNext));
129 } /* END OF FUNCTION _DtWmParseSkipWhitespace */
132 /*************************************<->*************************************
134 * _DtWmParseNextToken (pWmPB)
139 * Returns the next quoted or whitespace-terminated nonquoted string in the
140 * current line buffer.
145 * pWmPB = ptr to parse buffer
150 * Return = ptr to null terminated string.
151 * pWmPB = current line modified internally.
156 * May alter the line buffer contents.
157 * Handles quoted strings and characters, removing trailing whitespace from
159 * Returns NULL string if the line is empty or is a comment.
160 * Does not use session manager style algorithm for dealing with
163 *************************************<->***********************************/
166 _DtWmParseNextToken (
170 return (_DtWmParseNextTokenC (&(pWmPB->pchNext), False));
174 /*************************************<->*************************************
176 * _DtWmParseNextTokenExpand (pWmPB)
181 * Returns the next quoted or whitespace-terminated nonquoted string in the
182 * current line buffer. Environment variables found in the are expanded.
183 * Characters quoted by '\' are passed through unaffected with the
184 * quoting '\' removed.
189 * pWmPB = ptr to parse buffer
194 * Return = ptr to null terminated string.
195 * Free this string with XtFree().
196 * pWmPB = current line modified internally.
201 * May alter the line buffer contents.
202 * Handles quoted strings and characters, removing trailing whitespace from
204 * Returns NULL string if the line is empty or is a comment.
206 *************************************<->***********************************/
209 _DtWmParseNextTokenExpand (
214 unsigned char *pchReturn = NULL;
216 /* isolate the next token */
217 pch = _DtWmParseNextTokenC (&(pWmPB->pchNext), False);
219 /* expand environment variables, a copy of the string is returned */
220 pchReturn = _DtWmParseExpandEnvironmentVariables (pch, NULL);
223 * If a token was found, but no copy returned, there were no
224 * environment variables. This routine needs to return a copy,
227 if (pch && !pchReturn)
228 pchReturn = (unsigned char *) XtNewString ((String) pch);
234 /*************************************<->*************************************
236 * _DtWmParseBackUp (pWmPB, pchTok)
241 * Backs up to the previous token (the one before pchTok)
246 * pWmPB = ptr to parse buffer
247 * pchTok = ptr to a token in the parse buffer
252 * Returns = ptr to prev token
257 * Operates on the line buffer in the pWmPB structure. Backs up
258 * the next pointer and writes a space over the interpolated
261 *************************************<->***********************************/
265 DtWmpParseBuf *pWmPB,
266 unsigned char *pchTok
269 if ((pchTok > pWmPB->pchLine) &&
270 (pchTok < (pWmPB->pchLine + pWmPB->cLineSize)))
273 unsigned char *pchLast;
276 pch = pchLast = pWmPB->pchLine;
279 * Search from beginning (because of multibyte chars) to
280 * find the token before the string we're interested in.
282 while ((pch < pchTok))
284 chlen = mblen ((char *)pch, MB_CUR_MAX);
291 * Found the NULL preceding the string passed in!
292 * Replace it with a blank and return the previous
293 * token (pointed to by pchLast).
295 *(pch - 1) = DTWM_CHAR_SPACE;
301 * Remember the beginning of this token.
316 pWmPB->pchNext = pchLast;
318 return (pWmPB->pchNext);
323 /*************************************<->*************************************
325 * _DtWmParseSkipWhitespaceC(linePP)
330 * Scan the string, skipping over all white space characters.
335 * linePP = nonNULL pointer to current line buffer pointer
340 * linePP = nonNULL pointer to revised line buffer pointer
345 * Assumes linePP is nonNULL
347 *************************************<->***********************************/
349 void _DtWmParseSkipWhitespaceC(unsigned char **linePP)
352 (mblen ((char *)*linePP, MB_CUR_MAX) == 1) &&
358 } /* END OF FUNCTION _DtWmParseSkipWhitespaceC */
362 /*************************************<->*************************************
364 * _DtWmParseNextTokenC (linePP, SmBehavior)
369 * Returns the next quoted or whitespace-terminated nonquoted string in the
371 * Additional functionality added to GetString in that anything in a
372 * quoted string is considered sacred and nothing will be stripped from
373 * the middle of a quoted string.
378 * linePP = pointer to current line buffer pointer.
379 * SmBehavior = flag that enables parsing session manager hints if True.
380 * If False, this behaves as the normal OSF mwm GetString
386 * linePP = pointer to revised line buffer pointer.
392 * May alter the line buffer contents.
393 * Handles quoted strings and characters, removing trailing whitespace from
395 * Returns NULL string if the line is empty or is a comment.
396 * Code stolen from dtmwm.
398 *************************************<->***********************************/
401 _DtWmParseNextTokenC (
402 unsigned char **linePP,
406 /***********************************************************************
408 * The following code is duplicated from WmResParse.c (GetStringC)
409 * GetStringC is the HP DT version of GetString.
411 * It works here through the magic of #defines.
413 ***********************************************************************/
414 unsigned char *lineP = *linePP;
417 unsigned char *lnwsP;
418 unsigned int level = 0, checkLev, i, quoteLevel[MAX_QUOTE_DEPTH];
421 /* get rid of leading white space */
422 ScanWhitespace (&lineP);
425 * Return NULL if line is empty, whitespace, or begins with a comment.
429 ((chlen = mblen ((char *)lineP, MB_CUR_MAX)) < 1) ||
430 ((chlen == 1) && ((*lineP == '!') ||
431 ((!SmBehavior) && (*lineP == '#'))))
438 if ((chlen == 1) && (*lineP == '"'))
441 quoteLevel[level] = 1;
443 * Start beyond double quote and find the end of the quoted string.
444 * '\' quotes the next character.
445 * Otherwise, matching double quote or NULL terminates the string.
447 * We use lnwsP to point to the last non-whitespace character in the
448 * quoted string. When we have found the end of the quoted string,
449 * increment lnwsP and if lnwsP < endP, write NULL into *lnwsP.
450 * This removes any trailing whitespace without overwriting the
451 * matching quote, needed later. If the quoted string was all
452 * whitespace, then this will write a NULL at the beginning of the
453 * string that will be returned -- OK.
455 lnwsP = lineP++; /* lnwsP points to first '"' */
456 curP = endP = lineP; /* other pointers point beyond */
458 while ((*endP = *curP) &&
459 ((chlen = mblen ((char *)curP, MB_CUR_MAX)) > 0) &&
460 ((chlen > 1) || (*curP != '"')))
461 /* Haven't found matching quote yet.
462 * First byte of next character has been copied to endP.
466 if ((chlen == 1) && (*endP == '\\') &&
467 ((chlen = mblen ((char *)curP, MB_CUR_MAX)) > 0))
469 * copy first byte of quoted nonNULL character down.
470 * point curP to next byte
476 * Check to see if this is a quoted quote - if it is
477 * strip off a level - if not - it's sacred leave it alone
479 checkLev = PeekAhead((curP - 1), quoteLevel[level]);
482 if(quoteLevel[level] >= checkLev)
484 if (level > 0) level--;
486 else if (level < MAX_QUOTE_DEPTH)
489 quoteLevel[level] = checkLev;
492 for(i = 0;i < (checkLev - 2);i++)
494 *endP++ = *curP++;curP++;
506 /* Singlebyte character: character copy finished. */
509 /* whitespace character: leave lnwsP unchanged. */
514 /* non-whitespace character: point lnwsP to it. */
520 /* Multibyte (nonwhitespace) character: point lnwsP to it.
521 * Finish character byte copy.
534 * Found matching quote or NULL.
535 * NULL out any trailing whitespace.
546 /* Unquoted string */
549 * Find the end of the nonquoted string.
550 * '\' quotes the next character.
551 * Otherwise, whitespace, NULL, or '#' terminates the string.
555 while ((*endP = *curP) &&
556 ((chlen = mblen ((char *)curP, MB_CUR_MAX)) > 0) &&
557 ((chlen > 1) || (!isspace (*curP) &&
558 (SmBehavior || (*curP != '#')))))
559 /* Haven't found whitespace or '#' yet.
560 * First byte of next character has been copied to endP.
564 if ((chlen == 1) && (*endP == '\\') &&
565 ((chlen = mblen ((char *)curP, MB_CUR_MAX)) > 0))
567 * copy first byte of quoted nonNULL character down.
568 * point curP to next byte
575 /* Multibyte character: finish character copy. */
586 * Three cases for *endP:
587 * '#' --> write NULL over # and point to NULL
589 * matching quote -> write NULL over char and point beyond
590 * NULL -> point to NULL
593 if (!SmBehavior && (*endP == '#'))
595 *endP = '\0'; /* write NULL over '#' */
596 *linePP = endP; /* point to NULL */
598 else if (*endP != '\0')
600 *endP = '\0'; /* write NULL over terminator */
601 *linePP = ++curP; /* point beyond terminator */
607 return ((unsigned char *)lineP);
609 } /* END OF FUNCTION _DtWmParseNextTokenC */
613 /*************************************<->*************************************
615 * (DtWmParseBuf *) _DtWmParseNewBuf (void)
620 * Allocates a new parse record for parsing.
629 * Return = ptr to parse buffer record, NULL if memory allocation
635 * Call this first before using the other DtWmp routines that require
636 * a parse buffer. Treat this as an opaque type; use the provided
637 * routines to create, access, and destroy this structure.
639 *************************************<->***********************************/
642 _DtWmParseNewBuf ( void )
645 DtWmpParseBuf *pWmPB;
647 pWmPB = (DtWmpParseBuf *) XtMalloc (sizeof (DtWmpParseBuf));
650 pWmPB->pchLine = (unsigned char *) XtMalloc (MAXLINE+1);
653 XtFree ((char *)pWmPB);
660 pWmPB->lineNumber = 0;
661 pWmPB->pchNext = pWmPB->pchLine;
662 pWmPB->cLineSize = MAXLINE+1;
664 *(pWmPB->pchLine) = '\0';
669 } /* END OF FUNCTION _DtWmParseNewBuf */
672 /*************************************<->*************************************
674 * (DtWmParseBuf *) _DtWmpIncBuf (pWmPB)
679 * Increases the size of the line buffer in the parse buffer
683 * pWmPB = pointer to a parse buffer
688 * Return = ptr to parse buffer record, NULL if memory allocation
695 *************************************<->***********************************/
697 static DtWmpParseBuf *
699 DtWmpParseBuf *pWmPB)
708 /* save index into old string */
709 ix = pWmPB->pchNext - pWmPB->pchLine;
712 pWmPB->pchLine = (unsigned char *)
713 XtRealloc ((char *)pWmPB->pchLine, (pWmPB->cLineSize + MAXLINE));
716 pWmPB->cLineSize += MAXLINE;
720 /* restore index into new string */
721 pWmPB->pchNext = pWmPB->pchLine + ix;
728 } /* END OF FUNCTION _DtWmpIncBuf */
731 /*************************************<->*************************************
733 * _DtWmParseDestroyBuf (pWmPB)
738 * Destroys a parse buffer record, freeing any allocated memory.
743 * pWmPB = ptr to previously allocated parse buffer
753 * Destroys parse buffers allocated by _DtWmParseNewBuf.
755 *************************************<->***********************************/
758 _DtWmParseDestroyBuf (
767 XtFree ((char *) pWmPB->pchLine);
769 XtFree ((char *) pWmPB);
772 } /* END OF FUNCTION _DtWmParseDestroyBuf */
775 /*************************************<->*************************************
777 * (unsigned char *) _DtWmParseSetLine (pWmPB, pch)
782 * Sets a line into the parse buffer structure. This is used in cases
783 * where parsing of an embedded string, usually a default, is done
784 * instead of parsing out of a file.
789 * pWmPB = previously allocated parse buffer
790 * pch = ptr to unsigned char string (zero terminated)
799 * This resets any previous setting of the file pointer. EOF wil be
800 * returned when the string pointed to by pch is exhausted.
802 * Resets line number count.
804 *************************************<->***********************************/
808 DtWmpParseBuf *pWmPB,
815 pWmPB->pchLine = pch;
816 pWmPB->pchNext = pWmPB->pchLine;
818 pWmPB->lineNumber = 0;
821 } /* END OF FUNCTION _DtWmParseSetLine */
824 /*************************************<->*************************************
826 * (FILE *) _DtWmParseSetFile (pWmPB, pFile)
831 * Sets the file pointer in a parse buffer. This is used when parsing
832 * from a file is required.
837 * pWmPB = pointer to a parse buffer
838 * pFile = pointer to an opened FILE
847 * You fopen the file first, then pass in the FILE * returned to this
850 * Resets line number count.
852 *************************************<->***********************************/
856 DtWmpParseBuf *pWmPB,
863 pWmPB->pchLine[0] = '\0';
864 pWmPB->pchNext = NULL;
865 pWmPB->pFile = pFile;
866 pWmPB->lineNumber = 0;
869 } /* END OF FUNCTION _DtWmParseSetFile */
872 /*************************************<->*************************************
874 * (unsigned char *) _DtWmParseNextLine ( pWmPB )
879 * Returns a pointer to the next line to parse.
884 * pWmPB = pointer to a parse buffer
889 * Return = pointer to next line to parse or NULL on EOF.
896 *************************************<->***********************************/
904 /***********************************************************************
906 * The following code is duplicated from WmResParse.c (GetNextLine)
907 * It works here through the magic of #defines.
909 ***********************************************************************/
911 unsigned char *string;
920 /* read fopened file */
922 if ((string = (unsigned char *)
923 fgets ((char *)line, MAXLINE, cfileP)) != NULL)
926 if (strlen((char *)string) > (size_t)pWmPB->cLineSize)
929 * Bump size of destination buffer
931 pWmPB->cLineSize = 1 + strlen((char *)string);
932 pWmPB->pchLine = (unsigned char *)
933 XtRealloc ((char *)pWmPB->pchLine,
936 #endif /* PARSE_LIB */
940 ((len = mblen((char *)string, MB_CUR_MAX)) > 0))
942 mbtowc(&last, (char *)string, MB_CUR_MAX);
947 mbtowc(&wdelim, &delim, MB_CUR_MAX);
948 if (lastlen == 1 && last == wdelim)
952 if (!fgets((char *)string, MAXLINE - (string - line), cfileP))
957 ((len = mblen((char *)string, MB_CUR_MAX)) > 0))
959 mbtowc(&last, (char *)string, MB_CUR_MAX);
965 while (lastlen == 1 && last == wdelim);
970 else if ((parseP != NULL) && (*parseP != '\0'))
971 /* read parse string */
974 if (strlen((char *)parseP) > (size_t)pWmPB->cLineSize)
977 * Bump size of destination buffer
979 pWmPB->cLineSize = 1 + strlen((char *)parseP);
980 pWmPB->pchLine = (unsigned char *)
981 XtRealloc ((char *)pWmPB->pchLine,
984 #endif /* PARSE_LIB */
987 while ((*parseP != '\0') &&
988 ((chlen = mblen ((char *)parseP, MB_CUR_MAX)) != 0) &&
990 /* copy all but end-of-line and newlines to line buffer */
998 *(string++) = *(parseP++);
1003 if (*parseP == '\n')
1017 /* update pchNext to get next line */
1018 pWmPB->pchNext = string;
1020 #endif /* PARSE_LIB */
1024 } /* END OF FUNCTION _DtWmParseNextLine */
1027 /*************************************<->*************************************
1029 * (unsigned char *) _DtWmParseCurrentChar (pWmPB)
1034 * Returns a pointer to the rest of the current line.
1039 * pWmPB = pointer to a parse buffer
1044 * Return = pointer to the rest of the current line
1049 * Useful in cases where you want to look at a char before getting the
1050 * next token or if you want to treat the rest of the line as a
1053 *************************************<->***********************************/
1056 _DtWmParseCurrentChar (
1057 DtWmpParseBuf *pWmPB
1061 return (pWmPB ? pWmPB->pchNext : (unsigned char *)NULL);
1063 } /* END OF FUNCTION _DtWmParseCurrentChar */
1067 /*************************************<->*************************************
1069 * (unsigned char *) _DtWmParseNextChar (pWmPB)
1074 * Advances the pointer to the next char and returns a pointer
1075 * to the new current char.
1080 * pWmPB = pointer to a parse buffer
1085 * Return = pointer to the rest of the current line
1091 *************************************<->***********************************/
1094 _DtWmParseNextChar (
1095 DtWmpParseBuf *pWmPB
1099 unsigned char *pch = NULL;
1104 (chlen = mblen((char *)pWmPB->pchNext, MB_CUR_MAX) > 0))
1106 pch = (pWmPB->pchNext += chlen);
1113 /*************************************<->*************************************
1115 * (int) _DtWmParseLineNumber (pWmPB)
1120 * Returns the number of the current line of what's being parsed.
1125 * pWmPB = ptr to parse buffer
1130 * Return = number of current line
1135 * Used for error reporting.
1137 * The line number is computed by counting '\n' characters.
1139 *************************************<->***********************************/
1142 _DtWmParseLineNumber (
1143 DtWmpParseBuf *pWmPB
1147 return (pWmPB ? pWmPB->lineNumber : 0);
1149 } /* END OF FUNCTION _DtWmParseLineNumber */
1152 /*************************************<->*************************************
1154 * _DtWmParseToLower (string)
1159 * Lower all characters in a string.
1164 * string = NULL-terminated character string or NULL
1169 * string = NULL-terminated lower case character string or NULL
1174 * Can handle multi-byte characters
1176 *************************************<->***********************************/
1178 void _DtWmParseToLower (char *string)
1183 while ((chlen = mblen (pch, MB_CUR_MAX)) > 0)
1185 if ((chlen == 1) && (isupper (*pch)))
1187 *pch = tolower(*pch);
1192 } /* END OF FUNCTION _DtWmParseToLower */
1196 /*************************************<->*************************************
1198 * _DtWmParsePeekAhead (currentChar, currentLev)
1203 * Returns a new level value if this is a new nesting level of quoted string
1204 * Otherwise it returns a zero
1209 * currentChar = current position in the string
1210 * currentLev = current level of nesting
1215 * Returns either a new level of nesting or zero if the character is copied in
1221 *************************************<->***********************************/
1222 unsigned int _DtWmParsePeekAhead(unsigned char *currentChar,
1223 unsigned int currentLev)
1227 Boolean done = False;
1228 unsigned int tmpLev = 1;
1231 while (((chlen = mblen ((char *)currentChar, MB_CUR_MAX)) > 0) &&
1232 (chlen == 1) && ((*currentChar == '"') || (*currentChar == '\\'))
1237 if(((chlen = mblen ((char *)currentChar, MB_CUR_MAX)) > 0) &&
1239 ((*currentChar == '"') || (*currentChar == '\\')))
1242 if(*currentChar == '"')
1254 * Figure out if this is truly a new level of nesting - else ignore it
1255 * This section probably could do some error checking and return -1
1256 * If so, change type of routine from unsigned int to int
1266 } /* END OF FUNCTION _DtWmParsePeekAhead */
1270 /*************************************<->*************************************
1272 * (unsigned char *) _DtWmParseFilenameExpand (pchFilename)
1277 * Returns a copy of a file name with environment variables
1283 * pchFilename = ptr to a zero terminated character string (filename)
1288 * Return = ptr to a new file name with environment variables
1294 * The passed in string is temporarily modified inside here.
1296 * Free the returned string with XtFree().
1298 * Returns NULL on a memory allocation error.
1300 * Environment variables that can't be expanded are removed from
1301 * the returned copy.
1303 * If no environment variables, you get a copy of the string back.
1305 *************************************<->***********************************/
1307 _DtWmParseFilenameExpand (
1308 unsigned char *pchFilename
1312 unsigned char *pchN, *pchNew, *pchO;
1313 unsigned char *pchEnv, *pchEnv0, *pchEnv1;
1314 unsigned char chSave;
1316 unsigned char pchBrk[] = { DTWM_CHAR_ENVIRONMENT,
1317 DTWM_CHAR_DIRECTORY,
1321 len = strlen ((char *)pchFilename);
1322 pchNew = (unsigned char *) XtMalloc (1+len);
1327 while (pchNew && pchO && *pchO)
1329 /* find next environment variable */
1330 pchEnv0 = (unsigned char *)
1331 strchr ((char *)pchO, (int) DTWM_CHAR_ENVIRONMENT);
1334 /* length to this point */
1337 /* copy up to environment character */
1340 memcpy (&pchNew[ix], pchO, n);
1344 /* skip environment character */
1347 /* end of variable is at one of:
1348 * start of next variable,
1349 * start of next directory,
1352 pchEnv1 = (unsigned char *)
1353 strpbrk ((char *)pchEnv0, (char *)pchBrk);
1357 /* next string starts after this one */
1359 n = pchEnv1 - pchEnv0 + 1;
1361 /* replace this char with NULL for now */
1367 /* This environment variable is the last thing on
1368 * the line. Signal all done.
1370 n = strlen ((char *) pchO);
1374 pchEnv = (unsigned char *) getenv ((char *)pchEnv0);
1377 nx = strlen ((char *) pchEnv);
1381 pchNew = (unsigned char *)
1382 XtRealloc ((char *)pchNew, 1+len);
1386 memcpy (&pchNew[ix], pchEnv, nx);
1400 /* keep a kosher string */
1405 /* copy the rest of the string */
1406 n = strlen ((char *) pchO);
1407 memcpy (&pchNew[ix], pchO, n);
1410 /* remember the NULL! (a famous battle cry) */
1411 pchNew[ix + n] = '\0';
1417 } /* END OF FUNCTION _DtWmParseFilenameExpand */
1420 /*************************************<->*************************************
1422 * unsigned char * _DtWmParseExpandEnvironmentVariables (pch, pchBrk)
1427 * Expands environment variables in a string.
1432 * pch = ptr to a zero terminated character string
1433 * pchBrk = array of "break" characters (see strpbrk()).
1434 * defaults are used if this is NULL.
1438 * Return = string with expanded environment variables. (free with XtFree)
1439 * NULL string if no environment variables or backslashes
1440 * found in the string passed in.
1445 * Free returned string with XtFree()
1447 * Environment variables that can't be expanded are removed from
1448 * the returned copy.
1450 * Default delimiter set is [Space], [Tab], '$', [Newline], '\', '/'.
1452 * Variables of form $(..) and ${..} supported.
1454 * A backslash '\' in front of any character quotes it. The backslash
1455 * is removed in the returned string. A literal backslash needs to be
1456 * quoted with a backslash.
1458 *************************************<->***********************************/
1460 _DtWmParseExpandEnvironmentVariables (
1462 unsigned char *pchBrk
1467 unsigned char *pchStart;
1468 unsigned char chSave;
1469 unsigned char *pchEnvStart;
1470 unsigned char *pchEnvValue;
1471 unsigned char *pchReturn = NULL;
1472 unsigned char *pchNext;
1473 unsigned char *pchBreak;
1475 Boolean bAlreadyAdvanced;
1482 static unsigned char pchDefaultBrk[] = {
1483 DTWM_CHAR_ENVIRONMENT,
1487 DTWM_CHAR_BACKSLASH,
1488 DTWM_CHAR_DIRECTORY,
1490 unsigned char pchParenBrk[] = {
1493 unsigned char pchBraceBrk[] = {
1497 /* There needs to be something to look at */
1502 lenOriginal = strlen ((char *)pch);
1503 chlen = mblen ((char *)pch, MB_CUR_MAX);
1506 while (*pch && (chlen > 0))
1510 bAlreadyAdvanced = False;
1513 case DTWM_CHAR_BACKSLASH:
1515 * Copy up to start of quoted char
1519 lenReturn = lenOriginal + 1;
1520 pchReturn = (unsigned char *)
1521 XtMalloc (lenReturn * sizeof (unsigned char));
1522 pchReturn[0] = '\0';
1526 strcat ((char *) pchReturn, (char *)pchStart);
1531 * The next character is "escaped", skip over it.
1533 pchStart = pch += chlen;
1534 chlen = mblen ((char *)pch, MB_CUR_MAX);
1537 case DTWM_CHAR_ENVIRONMENT:
1538 /* save start of environment variable */
1541 chlen = mblen ((char *)pch, MB_CUR_MAX);
1544 * Copy up to start of environment variable
1548 lenReturn = lenOriginal + 1;
1549 pchReturn = (unsigned char *)
1550 XtMalloc (lenReturn * sizeof (unsigned char));
1551 pchReturn[0] = '\0';
1556 lenSave = strlen ((char *)pchReturn);
1558 lenNonEnv = pchEnvStart - pchStart;
1559 memcpy (&pchReturn[lenSave], pchStart, lenNonEnv);
1560 pchReturn[lenSave+lenNonEnv] = '\0';
1563 * Determine how we find the end of this
1564 * environment variable.
1568 (*pch == DTWM_CHAR_L_PAREN))
1571 chlen = mblen ((char *)pch, MB_CUR_MAX);
1572 pchBreak = pchParenBrk;
1575 else if ((chlen == 1) &&
1576 (*pch == DTWM_CHAR_L_BRACE))
1579 chlen = mblen ((char *)pch, MB_CUR_MAX);
1580 pchBreak = pchBraceBrk;
1583 else if (pchBrk && *pchBrk)
1589 pchBreak = pchDefaultBrk;
1593 * Look for end of environment variable
1595 pchNext = (unsigned char *)
1596 strpbrk ((char *)pch, (char *)pchBreak);
1600 /* it's the rest of the string */
1603 pchNext = pch + strlen ((char *) pch);
1607 /* temporarily put a string terminator here */
1613 * Lookup environment variable
1615 lenEnvVar = strlen ((char *)pch);
1616 pchEnvValue = (unsigned char *) getenv ((char *)pch);
1621 * Insure there's enough room in the return string
1623 lenEnvValue = strlen ((char *)pchEnvValue);
1626 lenReturn = lenOriginal + 1 - lenEnvVar +
1628 pchReturn = (unsigned char *)
1629 XtMalloc (lenReturn * sizeof (unsigned char));
1630 pchReturn[0] = '\0';
1634 lenReturn = lenReturn + 1 - lenEnvVar +
1636 pchReturn = (unsigned char *)
1637 XtRealloc ((char *)pchReturn,
1638 lenReturn * sizeof (unsigned char));
1642 * Tack it onto the return string
1644 strcat ((char *)pchReturn, (char *)pchEnvValue);
1648 * Advance the pointer for the next pass
1652 /* restore saved character */
1657 * If this was a closing paren, then skip it
1661 chlen = mblen ((char *)pchNext, MB_CUR_MAX);
1665 pchStart = pch = pchNext;
1666 chlen = mblen ((char *)pch, MB_CUR_MAX);
1668 * We're already pointing at the next character
1669 * to process, don't advance again!
1671 bAlreadyAdvanced = True;
1676 /* this character is not interesting */
1681 * Move to the next character if we're not already
1684 if (!bAlreadyAdvanced)
1687 chlen = mblen ((char *)pch, MB_CUR_MAX);
1693 chlen = mblen ((char *)pch, MB_CUR_MAX);
1697 if (pchReturn && *pchStart)
1700 * Copy remaining parts of the string
1702 strcat ((char *)pchReturn, (char *)pchStart);
1707 } /* END OF FUNCTION _DtWmParseExpandEnvironmentVariables */
1711 /******************************<->*************************************
1713 * _DtWmParseMakeQuotedString (pchLine)
1718 * Encapsulates the passed in "line" into a string argument quoted
1719 * by double quotes. Special characters are "escaped" as needed.
1723 * pchLine = ptr to string to enclose in quotes
1727 * Return = ptr to quoted string
1731 * Returned string should be freed with XtFree().
1733 ******************************<->***********************************/
1736 _DtWmParseMakeQuotedString (unsigned char *pchLine)
1738 unsigned char *pchRet;
1744 iLen0 = strlen ((char *)pchLine);
1745 iLen1 = iLen0 + 2; /* for starting, ending quotes */
1747 for (i=0; i < iLen0; i++)
1750 * Count special chars to get estimate of new length
1752 chlen = mblen ((char *) &pchLine[i], MB_CUR_MAX);
1754 ((pchLine[i] == '\\') ||
1755 (pchLine[i] == '"')))
1769 pchRet = (unsigned char *) XtMalloc (1+iLen1);
1773 pchRet[0] = '"'; /* starting quote */
1775 * Copy chars from old string to new one
1777 for (i=0, j=1; i < iLen0; i++, j++)
1779 chlen = mblen ((char *) &pchLine[i], MB_CUR_MAX);
1781 ((pchLine[i] == '\\') ||
1782 (pchLine[i] == '"')))
1784 /* quote next char */
1791 else while (chlen > 1)
1793 /* copy first bytes of multibyte char */
1794 pchRet[j++] = pchLine[i++];
1798 pchRet[j] = pchLine[i];
1800 pchRet[j++] = '"'; /* ending quote */
1801 pchRet[j] = '\0'; /* end of string */
1806 } /* END OF FUNCTION _DtWmParseMakeQuotedString */
1809 /*==================== END OF FILE WmParse.c ====================*/