1 #ifdef VERBOSE_REV_INFO
2 static char rcsid[] = "$XConsortium: WmParse.c /main/5 1996/10/30 11:36:06 drk $";
3 #endif /* VERBOSE_REV_INFO */
4 /******************************<+>*************************************
5 **********************************************************************
9 ** Project: HP/Motif Workspace Manager (dtwm)
13 ** This file contains the generic parsing routines
16 *********************************************************************
18 ** (c) Copyright 1987, 1988, 1989, 1990, 1991 HEWLETT-PACKARD COMPANY
19 ** ALL RIGHTS RESERVED
21 **********************************************************************
22 **********************************************************************
25 **********************************************************************
26 ******************************<+>*************************************/
28 /* ANSI C definitions, This should be the first thing in WmGlobal.h */
40 #include <X11/Intrinsic.h>
46 #endif /* MULTIBYTE */
52 static DtWmpParseBuf * _DtWmpIncBuf (
53 DtWmpParseBuf *pWmPB);
58 #define MAXLINE (MAXWMPATH+1)
60 #define MAX_QUOTE_DEPTH 10
63 * This flags non-OSF code in those sections that were lifted
70 * Defines used to maintain code similarity between OSF/mwm source
71 * routines and these routines.
73 #define cfileP ((pWmPB)->pFile)
74 #define linec ((pWmPB)->lineNumber)
75 #define line ((pWmPB)->pchLine)
76 #define parseP ((pWmPB)->pchNext)
77 #define ScanWhitespace(s) (_DtWmParseSkipWhitespaceC(s))
78 #define PeekAhead(s,l) (_DtWmParsePeekAhead(s,l))
81 /*************************************<->*************************************
83 * _DtWmParseSkipWhitespace(pWmPB)
88 * Scan the current string, skipping over all white space characters.
93 * pWmPB = ptr to parse buffer
98 * pWmPB = parse buffer modified; current line ptr may be moved.
103 * Assumes there's a current line in the parse buffer
105 *************************************<->***********************************/
107 void _DtWmParseSkipWhitespace(DtWmpParseBuf *pWmPB)
109 _DtWmParseSkipWhitespaceC (&(pWmPB->pchNext));
111 } /* END OF FUNCTION _DtWmParseSkipWhitespace */
114 /*************************************<->*************************************
116 * _DtWmParseNextToken (pWmPB)
121 * Returns the next quoted or whitespace-terminated nonquoted string in the
122 * current line buffer.
127 * pWmPB = ptr to parse buffer
132 * Return = ptr to null terminated string.
133 * pWmPB = current line modified internally.
138 * May alter the line buffer contents.
139 * Handles quoted strings and characters, removing trailing whitespace from
141 * Returns NULL string if the line is empty or is a comment.
142 * Does not use session manager style algorithm for dealing with
145 *************************************<->***********************************/
148 _DtWmParseNextToken (
152 return (_DtWmParseNextTokenC (&(pWmPB->pchNext), False));
156 /*************************************<->*************************************
158 * _DtWmParseNextTokenExpand (pWmPB)
163 * Returns the next quoted or whitespace-terminated nonquoted string in the
164 * current line buffer. Environment variables found in the are expanded.
165 * Characters quoted by '\' are passed through unaffected with the
166 * quoting '\' removed.
171 * pWmPB = ptr to parse buffer
176 * Return = ptr to null terminated string.
177 * Free this string with XtFree().
178 * pWmPB = current line modified internally.
183 * May alter the line buffer contents.
184 * Handles quoted strings and characters, removing trailing whitespace from
186 * Returns NULL string if the line is empty or is a comment.
188 *************************************<->***********************************/
191 _DtWmParseNextTokenExpand (
196 unsigned char *pchReturn = NULL;
198 /* isolate the next token */
199 pch = _DtWmParseNextTokenC (&(pWmPB->pchNext), False);
201 /* expand environment variables, a copy of the string is returned */
202 pchReturn = _DtWmParseExpandEnvironmentVariables (pch, NULL);
205 * If a token was found, but no copy returned, there were no
206 * environment variables. This routine needs to return a copy,
209 if (pch && !pchReturn)
210 pchReturn = (unsigned char *) XtNewString ((String) pch);
216 /*************************************<->*************************************
218 * _DtWmParseBackUp (pWmPB, pchTok)
223 * Backs up to the previous token (the one before pchTok)
228 * pWmPB = ptr to parse buffer
229 * pchTok = ptr to a token in the parse buffer
234 * Returns = ptr to prev token
239 * Operates on the line buffer in the pWmPB structure. Backs up
240 * the next pointer and writes a space over the interpolated
243 *************************************<->***********************************/
247 DtWmpParseBuf *pWmPB,
248 unsigned char *pchTok
251 if ((pchTok > pWmPB->pchLine) &&
252 (pchTok < (pWmPB->pchLine + pWmPB->cLineSize)))
256 unsigned char *pchLast;
259 pch = pchLast = pWmPB->pchLine;
262 * Search from beginning (because of multibyte chars) to
263 * find the token before the string we're interested in.
265 while ((pch < pchTok))
267 chlen = mblen ((char *)pch, MB_CUR_MAX);
274 * Found the NULL preceding the string passed in!
275 * Replace it with a blank and return the previous
276 * token (pointed to by pchLast).
278 *(pch - 1) = DTWM_CHAR_SPACE;
284 * Remember the beginning of this token.
299 pWmPB->pchNext = pchLast;
300 #else /* MULTIBYTE */
303 * Replace preceding NULL with a space.
309 *pchTok = DTWM_CHAR_SPACE;
313 * Back up to next NULL or beginning of line.
315 while ((pchTok >= pWmPB->pchLine) && *pchTok)
320 pWmPB->pchNext = pchTok + 1;
322 #endif /* MULTIBYTE */
324 return (pWmPB->pchNext);
329 /*************************************<->*************************************
331 * _DtWmParseSkipWhitespaceC(linePP)
336 * Scan the string, skipping over all white space characters.
341 * linePP = nonNULL pointer to current line buffer pointer
346 * linePP = nonNULL pointer to revised line buffer pointer
351 * Assumes linePP is nonNULL
353 *************************************<->***********************************/
355 void _DtWmParseSkipWhitespaceC(unsigned char **linePP)
359 (mblen ((char *)*linePP, MB_CUR_MAX) == 1) &&
362 while (*linePP && isspace (**linePP))
368 } /* END OF FUNCTION _DtWmParseSkipWhitespaceC */
372 /*************************************<->*************************************
374 * _DtWmParseNextTokenC (linePP, SmBehavior)
379 * Returns the next quoted or whitespace-terminated nonquoted string in the
381 * Additional functionality added to GetString in that anything in a
382 * quoted string is considered sacred and nothing will be stripped from
383 * the middle of a quoted string.
388 * linePP = pointer to current line buffer pointer.
389 * SmBehavior = flag that enables parsing session manager hints if True.
390 * If False, this behaves as the normal OSF mwm GetString
396 * linePP = pointer to revised line buffer pointer.
402 * May alter the line buffer contents.
403 * Handles quoted strings and characters, removing trailing whitespace from
405 * Returns NULL string if the line is empty or is a comment.
406 * Code stolen from dtmwm.
408 *************************************<->***********************************/
411 _DtWmParseNextTokenC (
412 unsigned char **linePP,
416 /***********************************************************************
418 * The following code is duplicated from WmResParse.c (GetStringC)
419 * GetStringC is the HP DT version of GetString.
421 * It works here through the magic of #defines.
423 ***********************************************************************/
424 unsigned char *lineP = *linePP;
427 unsigned char *lnwsP;
428 unsigned int level = 0, checkLev, i, quoteLevel[MAX_QUOTE_DEPTH];
432 /* get rid of leading white space */
433 ScanWhitespace (&lineP);
436 * Return NULL if line is empty, whitespace, or begins with a comment.
440 ((chlen = mblen ((char *)lineP, MB_CUR_MAX)) < 1) ||
441 ((chlen == 1) && ((*lineP == '!') ||
442 ((!SmBehavior) && (*lineP == '#'))))
449 if ((chlen == 1) && (*lineP == '"'))
452 quoteLevel[level] = 1;
454 * Start beyond double quote and find the end of the quoted string.
455 * '\' quotes the next character.
456 * Otherwise, matching double quote or NULL terminates the string.
458 * We use lnwsP to point to the last non-whitespace character in the
459 * quoted string. When we have found the end of the quoted string,
460 * increment lnwsP and if lnwsP < endP, write NULL into *lnwsP.
461 * This removes any trailing whitespace without overwriting the
462 * matching quote, needed later. If the quoted string was all
463 * whitespace, then this will write a NULL at the beginning of the
464 * string that will be returned -- OK.
466 lnwsP = lineP++; /* lnwsP points to first '"' */
467 curP = endP = lineP; /* other pointers point beyond */
469 while ((*endP = *curP) &&
470 ((chlen = mblen ((char *)curP, MB_CUR_MAX)) > 0) &&
471 ((chlen > 1) || (*curP != '"')))
472 /* Haven't found matching quote yet.
473 * First byte of next character has been copied to endP.
477 if ((chlen == 1) && (*endP == '\\') &&
478 ((chlen = mblen ((char *)curP, MB_CUR_MAX)) > 0))
480 * copy first byte of quoted nonNULL character down.
481 * point curP to next byte
487 * Check to see if this is a quoted quote - if it is
488 * strip off a level - if not - it's sacred leave it alone
490 checkLev = PeekAhead((curP - 1), quoteLevel[level]);
493 if(quoteLevel[level] >= checkLev)
495 if (level > 0) level--;
497 else if (level < MAX_QUOTE_DEPTH)
500 quoteLevel[level] = checkLev;
503 for(i = 0;i < (checkLev - 2);i++)
505 *endP++ = *curP++;curP++;
517 /* Singlebyte character: character copy finished. */
520 /* whitespace character: leave lnwsP unchanged. */
525 /* non-whitespace character: point lnwsP to it. */
531 /* Multibyte (nonwhitespace) character: point lnwsP to it.
532 * Finish character byte copy.
543 #else /* MULTIBYTE */
545 /* get rid of leading white space */
546 ScanWhitespace (&lineP);
548 /* Return NULL if line is empty, whitespace, or begins with a comment. */
549 if ((lineP == NULL || *lineP == '\0') ||
550 (!SmBehavior && (*lineP == '#')))
559 quoteLevel[level] = 1;
561 * Start beyond double quote and find the end of the quoted string.
562 * '\' quotes the next character.
563 * Otherwise, matching double quote or NULL terminates the string.
565 * We use lnwsP to point to the last non-whitespace character in the
566 * quoted string. When we have found the end of the quoted string,
567 * increment lnwsP and if lnwsP < endP, write NULL into *lnwsP.
568 * This removes any trailing whitespace without overwriting the
569 * matching quote, needed later. If the quoted string was all
570 * whitespace, then this will write a NULL at the beginning of the
571 * string that will be returned -- OK.
573 lnwsP = lineP++; /* lnwsP points to first '"' */
574 curP = endP = lineP; /* other pointers point beyond */
576 while ((*endP = *curP) && (*endP != '"'))
577 /* haven't found matching quote yet */
579 /* point curP to next character */
581 if ((*endP == '\\') && (*curP != NULL))
582 /* shift quoted nonNULL character down and curP ahead */
587 * Check to see if this is a quoted quote - if it is
588 * strip off a level - if not - it's sacred leave it alone
590 checkLev = PeekAhead((curP - 1), quoteLevel[level]);
593 if(quoteLevel[level] >= checkLev)
595 if (level > 0) level--;
597 else if (level < MAX_QUOTE_DEPTH)
600 quoteLevel[level] = checkLev;
603 for(i = 0;i < (checkLev - 2);i++)
605 *endP++ = *curP++;curP++;
616 /* whitespace character: leave lnwsP unchanged. */
621 /* non-whitespace character: point lnwsP to it. */
626 #endif /* MULTIBYTE */
629 * Found matching quote or NULL.
630 * NULL out any trailing whitespace.
641 /* Unquoted string */
644 * Find the end of the nonquoted string.
645 * '\' quotes the next character.
646 * Otherwise, whitespace, NULL, or '#' terminates the string.
651 while ((*endP = *curP) &&
652 ((chlen = mblen ((char *)curP, MB_CUR_MAX)) > 0) &&
653 ((chlen > 1) || (!isspace (*curP) &&
654 (SmBehavior || (*curP != '#')))))
655 /* Haven't found whitespace or '#' yet.
656 * First byte of next character has been copied to endP.
660 if ((chlen == 1) && (*endP == '\\') &&
661 ((chlen = mblen ((char *)curP, MB_CUR_MAX)) > 0))
663 * copy first byte of quoted nonNULL character down.
664 * point curP to next byte
671 /* Multibyte character: finish character copy. */
679 #else /* MULTIBYTE */
680 while ((*endP = *curP) && !isspace (*endP) &&
681 (SmBehavior || (*endP != '#')))
683 /* point curP to next character */
685 if ((*endP == '\\') && (*curP != '\0'))
686 /* shift quoted nonNULL character down and curP ahead */
692 #endif /* MULTIBYTE */
696 * Three cases for *endP:
697 * '#' --> write NULL over # and point to NULL
699 * matching quote -> write NULL over char and point beyond
700 * NULL -> point to NULL
703 if (!SmBehavior && (*endP == '#'))
705 *endP = '\0'; /* write NULL over '#' */
706 *linePP = endP; /* point to NULL */
708 else if (*endP != '\0')
710 *endP = '\0'; /* write NULL over terminator */
711 *linePP = ++curP; /* point beyond terminator */
717 return ((unsigned char *)lineP);
719 } /* END OF FUNCTION _DtWmParseNextTokenC */
723 /*************************************<->*************************************
725 * (DtWmParseBuf *) _DtWmParseNewBuf (void)
730 * Allocates a new parse record for parsing.
739 * Return = ptr to parse buffer record, NULL if memory allocation
745 * Call this first before using the other DtWmp routines that require
746 * a parse buffer. Treat this as an opaque type; use the provided
747 * routines to create, access, and destroy this structure.
749 *************************************<->***********************************/
752 _DtWmParseNewBuf ( void )
755 DtWmpParseBuf *pWmPB;
757 pWmPB = (DtWmpParseBuf *) XtMalloc (sizeof (DtWmpParseBuf));
760 pWmPB->pchLine = (unsigned char *) XtMalloc (MAXLINE+1);
763 XtFree ((char *)pWmPB);
770 pWmPB->lineNumber = 0;
771 pWmPB->pchNext = pWmPB->pchLine;
772 pWmPB->cLineSize = MAXLINE+1;
774 *(pWmPB->pchLine) = '\0';
779 } /* END OF FUNCTION _DtWmParseNewBuf */
782 /*************************************<->*************************************
784 * (DtWmParseBuf *) _DtWmpIncBuf (pWmPB)
789 * Increases the size of the line buffer in the parse buffer
793 * pWmPB = pointer to a parse buffer
798 * Return = ptr to parse buffer record, NULL if memory allocation
805 *************************************<->***********************************/
807 static DtWmpParseBuf *
809 DtWmpParseBuf *pWmPB)
818 /* save index into old string */
819 ix = pWmPB->pchNext - pWmPB->pchLine;
822 pWmPB->pchLine = (unsigned char *)
823 XtRealloc ((char *)pWmPB->pchLine, (pWmPB->cLineSize + MAXLINE));
826 pWmPB->cLineSize += MAXLINE;
830 /* restore index into new string */
831 pWmPB->pchNext = pWmPB->pchLine + ix;
838 } /* END OF FUNCTION _DtWmpIncBuf */
841 /*************************************<->*************************************
843 * _DtWmParseDestroyBuf (pWmPB)
848 * Destroys a parse buffer record, freeing any allocated memory.
853 * pWmPB = ptr to previously allocated parse buffer
863 * Destroys parse buffers allocated by _DtWmParseNewBuf.
865 *************************************<->***********************************/
868 _DtWmParseDestroyBuf (
877 XtFree ((char *) pWmPB->pchLine);
879 XtFree ((char *) pWmPB);
882 } /* END OF FUNCTION _DtWmParseDestroyBuf */
885 /*************************************<->*************************************
887 * (unsigned char *) _DtWmParseSetLine (pWmPB, pch)
892 * Sets a line into the parse buffer structure. This is used in cases
893 * where parsing of an embedded string, usually a default, is done
894 * instead of parsing out of a file.
899 * pWmPB = previously allocated parse buffer
900 * pch = ptr to unsigned char string (zero terminated)
909 * This resets any previous setting of the file pointer. EOF wil be
910 * returned when the string pointed to by pch is exhausted.
912 * Resets line number count.
914 *************************************<->***********************************/
918 DtWmpParseBuf *pWmPB,
925 pWmPB->pchLine = pch;
926 pWmPB->pchNext = pWmPB->pchLine;
928 pWmPB->lineNumber = 0;
931 } /* END OF FUNCTION _DtWmParseSetLine */
934 /*************************************<->*************************************
936 * (FILE *) _DtWmParseSetFile (pWmPB, pFile)
941 * Sets the file pointer in a parse buffer. This is used when parsing
942 * from a file is required.
947 * pWmPB = pointer to a parse buffer
948 * pFile = pointer to an opened FILE
957 * You fopen the file first, then pass in the FILE * returned to this
960 * Resets line number count.
962 *************************************<->***********************************/
966 DtWmpParseBuf *pWmPB,
973 pWmPB->pchLine[0] = '\0';
974 pWmPB->pchNext = NULL;
975 pWmPB->pFile = pFile;
976 pWmPB->lineNumber = 0;
979 } /* END OF FUNCTION _DtWmParseSetFile */
982 /*************************************<->*************************************
984 * (unsigned char *) _DtWmParseNextLine ( pWmPB )
989 * Returns a pointer to the next line to parse.
994 * pWmPB = pointer to a parse buffer
999 * Return = pointer to next line to parse or NULL on EOF.
1006 *************************************<->***********************************/
1009 _DtWmParseNextLine (
1010 DtWmpParseBuf *pWmPB
1014 /***********************************************************************
1016 * The following code is duplicated from WmResParse.c (GetNextLine)
1017 * It works here through the magic of #defines.
1019 ***********************************************************************/
1021 register unsigned char *string;
1033 /* read fopened file */
1035 if ((string = (unsigned char *)
1036 fgets ((char *)line, MAXLINE, cfileP)) != NULL)
1039 if (strlen((char *)string) > (size_t)pWmPB->cLineSize)
1042 * Bump size of destination buffer
1044 pWmPB->cLineSize = 1 + strlen((char *)string);
1045 pWmPB->pchLine = (unsigned char *)
1046 XtRealloc ((char *)pWmPB->pchLine,
1047 (pWmPB->cLineSize));
1049 #endif /* PARSE_LIB */
1050 #ifndef NO_MULTIBYTE
1054 ((len = mblen((char *)string, MB_CUR_MAX)) > 0))
1056 mbtowc(&last, (char *)string, MB_CUR_MAX);
1061 mbtowc(&wdelim, &delim, MB_CUR_MAX);
1062 if (lastlen == 1 && last == wdelim)
1066 if (!fgets((char *)string, MAXLINE - (string - line), cfileP))
1071 ((len = mblen((char *)string, MB_CUR_MAX)) > 0))
1073 mbtowc(&last, (char *)string, MB_CUR_MAX);
1079 while (lastlen == 1 && last == wdelim);
1083 len = strlen((char *)string) - 2;
1084 if ((len > 0) && string[len] == '\\')
1087 string = &string[len];
1088 if (fgets((char *)string,
1089 MAXLINE - (string-line), cfileP) == NULL)
1091 len = strlen((char *)string) - 2;
1093 } while ((len >= 0) && string[len] == '\\');
1099 else if ((parseP != NULL) && (*parseP != '\0'))
1100 /* read parse string */
1103 if (strlen((char *)parseP) > (size_t)pWmPB->cLineSize)
1106 * Bump size of destination buffer
1108 pWmPB->cLineSize = 1 + strlen((char *)parseP);
1109 pWmPB->pchLine = (unsigned char *)
1110 XtRealloc ((char *)pWmPB->pchLine,
1111 (pWmPB->cLineSize));
1113 #endif /* PARSE_LIB */
1116 while ((*parseP != '\0') &&
1117 ((chlen = mblen ((char *)parseP, MB_CUR_MAX)) != 0) &&
1119 /* copy all but end-of-line and newlines to line buffer */
1127 *(string++) = *(parseP++);
1132 while ((*parseP != '\0') && (*parseP != '\n'))
1133 /* copy all but end-of-line and newlines to line buffer */
1135 *(string++) = *(parseP++);
1139 if (*parseP == '\n')
1153 /* update pchNext to get next line */
1154 pWmPB->pchNext = string;
1156 #endif /* PARSE_LIB */
1160 } /* END OF FUNCTION _DtWmParseNextLine */
1163 /*************************************<->*************************************
1165 * (unsigned char *) _DtWmParseCurrentChar (pWmPB)
1170 * Returns a pointer to the rest of the current line.
1175 * pWmPB = pointer to a parse buffer
1180 * Return = pointer to the rest of the current line
1185 * Useful in cases where you want to look at a char before getting the
1186 * next token or if you want to treat the rest of the line as a
1189 *************************************<->***********************************/
1192 _DtWmParseCurrentChar (
1193 DtWmpParseBuf *pWmPB
1197 return (pWmPB ? pWmPB->pchNext : (unsigned char *)NULL);
1199 } /* END OF FUNCTION _DtWmParseCurrentChar */
1203 /*************************************<->*************************************
1205 * (unsigned char *) _DtWmParseNextChar (pWmPB)
1210 * Advances the pointer to the next char and returns a pointer
1211 * to the new current char.
1216 * pWmPB = pointer to a parse buffer
1221 * Return = pointer to the rest of the current line
1227 *************************************<->***********************************/
1230 _DtWmParseNextChar (
1231 DtWmpParseBuf *pWmPB
1235 unsigned char *pch = NULL;
1241 (chlen = mblen((char *)pWmPB->pchNext, MB_CUR_MAX) > 0))
1243 pch = (pWmPB->pchNext += chlen);
1245 #else /* MULTIBYTE */
1246 if (pWmPB && pWmPB->pchNext && *pWmPB->pchNext)
1248 pch = ++pWmPB->pchNext;
1250 #endif /* MULTIBYTE */
1256 /*************************************<->*************************************
1258 * (int) _DtWmParseLineNumber (pWmPB)
1263 * Returns the number of the current line of what's being parsed.
1268 * pWmPB = ptr to parse buffer
1273 * Return = number of current line
1278 * Used for error reporting.
1280 * The line number is computed by counting '\n' characters.
1282 *************************************<->***********************************/
1285 _DtWmParseLineNumber (
1286 DtWmpParseBuf *pWmPB
1290 return (pWmPB ? pWmPB->lineNumber : 0);
1292 } /* END OF FUNCTION _DtWmParseLineNumber */
1295 /*************************************<->*************************************
1297 * _DtWmParseToLower (string)
1302 * Lower all characters in a string.
1307 * string = NULL-terminated character string or NULL
1312 * string = NULL-terminated lower case character string or NULL
1317 * Can handle multi-byte characters
1319 *************************************<->***********************************/
1321 void _DtWmParseToLower (unsigned char *string)
1323 unsigned char *pch = string;
1327 while ((chlen = mblen ((char *)pch, MB_CUR_MAX)) > 0)
1329 if ((chlen == 1) && (isupper (*pch)))
1331 *pch = tolower(*pch);
1336 while (*pch != NULL)
1340 *pch = tolower(*pch);
1346 } /* END OF FUNCTION _DtWmParseToLower */
1350 /*************************************<->*************************************
1352 * _DtWmParsePeekAhead (currentChar, currentLev)
1357 * Returns a new level value if this is a new nesting level of quoted string
1358 * Otherwise it returns a zero
1363 * currentChar = current position in the string
1364 * currentLev = current level of nesting
1369 * Returns either a new level of nesting or zero if the character is copied in
1375 *************************************<->***********************************/
1376 unsigned int _DtWmParsePeekAhead(unsigned char *currentChar,
1377 unsigned int currentLev)
1381 Boolean done = False;
1382 unsigned int tmpLev = 1;
1386 while (((chlen = mblen ((char *)currentChar, MB_CUR_MAX)) > 0) &&
1387 (chlen == 1) && ((*currentChar == '"') || (*currentChar == '\\'))
1392 if(((chlen = mblen ((char *)currentChar, MB_CUR_MAX)) > 0) &&
1394 ((*currentChar == '"') || (*currentChar == '\\')))
1397 if(*currentChar == '"')
1408 while((*currentChar != NULL) && (done == False) &&
1409 ((*currentChar == '"') || (*currentChar == '\\')))
1412 if((*currentChar != NULL) &&
1413 ((*currentChar == '"') || (*currentChar == '\\')))
1416 if(*currentChar == '"')
1426 #endif /*MULTIBYTE*/
1429 * Figure out if this is truly a new level of nesting - else ignore it
1430 * This section probably could do some error checking and return -1
1431 * If so, change type of routine from unsigned int to int
1441 } /* END OF FUNCTION _DtWmParsePeekAhead */
1445 /*************************************<->*************************************
1447 * (unsigned char *) _DtWmParseFilenameExpand (pchFilename)
1452 * Returns a copy of a file name with environment variables
1458 * pchFilename = ptr to a zero terminated character string (filename)
1463 * Return = ptr to a new file name with environment variables
1469 * The passed in string is temporarily modified inside here.
1471 * Free the returned string with XtFree().
1473 * Returns NULL on a memory allocation error.
1475 * Environment variables that can't be expanded are removed from
1476 * the returned copy.
1478 * If no environment variables, you get a copy of the string back.
1480 *************************************<->***********************************/
1482 _DtWmParseFilenameExpand (
1483 unsigned char *pchFilename
1487 unsigned char *pchN, *pchNew, *pchO;
1488 unsigned char *pchEnv, *pchEnv0, *pchEnv1;
1489 unsigned char chSave;
1491 unsigned char pchBrk[] = { DTWM_CHAR_ENVIRONMENT,
1492 DTWM_CHAR_DIRECTORY,
1496 len = strlen ((char *)pchFilename);
1497 pchNew = (unsigned char *) XtMalloc (1+len);
1502 while (pchNew && pchO && *pchO)
1504 /* find next environment variable */
1505 pchEnv0 = (unsigned char *)
1506 strchr ((char *)pchO, (int) DTWM_CHAR_ENVIRONMENT);
1509 /* length to this point */
1512 /* copy up to environment character */
1515 memcpy (&pchNew[ix], pchO, n);
1519 /* skip environment character */
1522 /* end of variable is at one of:
1523 * start of next variable,
1524 * start of next directory,
1527 pchEnv1 = (unsigned char *)
1528 strpbrk ((char *)pchEnv0, (char *)pchBrk);
1532 /* next string starts after this one */
1534 n = pchEnv1 - pchEnv0 + 1;
1536 /* replace this char with NULL for now */
1542 /* This environment variable is the last thing on
1543 * the line. Signal all done.
1545 n = strlen ((char *) pchO);
1549 pchEnv = (unsigned char *) getenv ((char *)pchEnv0);
1552 nx = strlen ((char *) pchEnv);
1556 pchNew = (unsigned char *)
1557 XtRealloc ((char *)pchNew, 1+len);
1561 memcpy (&pchNew[ix], pchEnv, nx);
1575 /* keep a kosher string */
1580 /* copy the rest of the string */
1581 n = strlen ((char *) pchO);
1582 memcpy (&pchNew[ix], pchO, n);
1585 /* remember the NULL! (a famous battle cry) */
1586 pchNew[ix + n] = '\0';
1592 } /* END OF FUNCTION _DtWmParseFilenameExpand */
1595 /*************************************<->*************************************
1597 * unsigned char * _DtWmParseExpandEnvironmentVariables (pch, pchBrk)
1602 * Expands environment variables in a string.
1607 * pch = ptr to a zero terminated character string
1608 * pchBrk = array of "break" characters (see strpbrk()).
1609 * defaults are used if this is NULL.
1613 * Return = string with expanded environment variables. (free with XtFree)
1614 * NULL string if no environment variables or backslashes
1615 * found in the string passed in.
1620 * Free returned string with XtFree()
1622 * Environment variables that can't be expanded are removed from
1623 * the returned copy.
1625 * Default delimiter set is [Space], [Tab], '$', [Newline], '\', '/'.
1627 * Variables of form $(..) and ${..} supported.
1629 * A backslash '\' in front of any character quotes it. The backslash
1630 * is removed in the returned string. A literal backslash needs to be
1631 * quoted with a backslash.
1633 *************************************<->***********************************/
1635 _DtWmParseExpandEnvironmentVariables (
1637 unsigned char *pchBrk
1643 #else /* MULTIBYTE */
1644 int chlen = 1; /* length of character is always '1' */
1645 #endif /* MULTIBYTE */
1646 unsigned char *pchStart;
1647 unsigned char chSave;
1648 unsigned char *pchEnvStart;
1649 unsigned char *pchEnvValue;
1650 unsigned char *pchReturn = NULL;
1651 unsigned char *pchNext;
1652 unsigned char *pchBreak;
1654 Boolean bAlreadyAdvanced;
1661 static unsigned char pchDefaultBrk[] = {
1662 DTWM_CHAR_ENVIRONMENT,
1666 DTWM_CHAR_BACKSLASH,
1667 DTWM_CHAR_DIRECTORY,
1669 unsigned char pchParenBrk[] = {
1672 unsigned char pchBraceBrk[] = {
1676 /* There needs to be something to look at */
1681 lenOriginal = strlen ((char *)pch);
1683 chlen = mblen ((char *)pch, MB_CUR_MAX);
1684 #endif /* MULTIBYTE */
1687 while (*pch && (chlen > 0))
1691 bAlreadyAdvanced = False;
1694 case DTWM_CHAR_BACKSLASH:
1696 * Copy up to start of quoted char
1700 lenReturn = lenOriginal + 1;
1701 pchReturn = (unsigned char *)
1702 XtMalloc (lenReturn * sizeof (unsigned char));
1703 pchReturn[0] = '\0';
1707 strcat ((char *) pchReturn, (char *)pchStart);
1712 * The next character is "escaped", skip over it.
1714 pchStart = pch += chlen;
1716 chlen = mblen ((char *)pch, MB_CUR_MAX);
1717 #endif /* MULTIBYTE */
1720 case DTWM_CHAR_ENVIRONMENT:
1721 /* save start of environment variable */
1725 chlen = mblen ((char *)pch, MB_CUR_MAX);
1726 #endif /* MULTIBYTE */
1729 * Copy up to start of environment variable
1733 lenReturn = lenOriginal + 1;
1734 pchReturn = (unsigned char *)
1735 XtMalloc (lenReturn * sizeof (unsigned char));
1736 pchReturn[0] = '\0';
1741 lenSave = strlen ((char *)pchReturn);
1743 lenNonEnv = pchEnvStart - pchStart;
1744 memcpy (&pchReturn[lenSave], pchStart, lenNonEnv);
1745 pchReturn[lenSave+lenNonEnv] = '\0';
1748 * Determine how we find the end of this
1749 * environment variable.
1753 (*pch == DTWM_CHAR_L_PAREN))
1757 chlen = mblen ((char *)pch, MB_CUR_MAX);
1758 #endif /* MULTIBYTE */
1759 pchBreak = pchParenBrk;
1762 else if ((chlen == 1) &&
1763 (*pch == DTWM_CHAR_L_BRACE))
1767 chlen = mblen ((char *)pch, MB_CUR_MAX);
1768 #endif /* MULTIBYTE */
1769 pchBreak = pchBraceBrk;
1772 else if (pchBrk && *pchBrk)
1778 pchBreak = pchDefaultBrk;
1782 * Look for end of environment variable
1784 pchNext = (unsigned char *)
1785 strpbrk ((char *)pch, (char *)pchBreak);
1789 /* it's the rest of the string */
1792 pchNext = pch + strlen ((char *) pch);
1796 /* temporarily put a string terminator here */
1802 * Lookup environment variable
1804 lenEnvVar = strlen ((char *)pch);
1805 pchEnvValue = (unsigned char *) getenv ((char *)pch);
1810 * Insure there's enough room in the return string
1812 lenEnvValue = strlen ((char *)pchEnvValue);
1815 lenReturn = lenOriginal + 1 - lenEnvVar +
1817 pchReturn = (unsigned char *)
1818 XtMalloc (lenReturn * sizeof (unsigned char));
1819 pchReturn[0] = '\0';
1823 lenReturn = lenReturn + 1 - lenEnvVar +
1825 pchReturn = (unsigned char *)
1826 XtRealloc ((char *)pchReturn,
1827 lenReturn * sizeof (unsigned char));
1831 * Tack it onto the return string
1833 strcat ((char *)pchReturn, (char *)pchEnvValue);
1837 * Advance the pointer for the next pass
1841 /* restore saved character */
1846 * If this was a closing paren, then skip it
1851 chlen = mblen ((char *)pchNext, MB_CUR_MAX);
1852 #endif /* MULTIBYTE */
1856 pchStart = pch = pchNext;
1858 chlen = mblen ((char *)pch, MB_CUR_MAX);
1859 #endif /* MULTIBYTE */
1861 * We're already pointing at the next character
1862 * to process, don't advance again!
1864 bAlreadyAdvanced = True;
1869 /* this character is not interesting */
1874 * Move to the next character if we're not already
1877 if (!bAlreadyAdvanced)
1881 chlen = mblen ((char *)pch, MB_CUR_MAX);
1882 #endif /* MULTIBYTE */
1889 chlen = mblen ((char *)pch, MB_CUR_MAX);
1891 #endif /* MULTIBYTE */
1894 if (pchReturn && *pchStart)
1897 * Copy remaining parts of the string
1899 strcat ((char *)pchReturn, (char *)pchStart);
1904 } /* END OF FUNCTION _DtWmParseExpandEnvironmentVariables */
1908 /******************************<->*************************************
1910 * _DtWmParseMakeQuotedString (pchLine)
1915 * Encapsulates the passed in "line" into a string argument quoted
1916 * by double quotes. Special characters are "escaped" as needed.
1920 * pchLine = ptr to string to enclose in quotes
1924 * Return = ptr to quoted string
1928 * Returned string should be freed with XtFree().
1930 ******************************<->***********************************/
1933 _DtWmParseMakeQuotedString (unsigned char *pchLine)
1935 unsigned char *pchRet;
1943 iLen0 = strlen ((char *)pchLine);
1944 iLen1 = iLen0 + 2; /* for starting, ending quotes */
1946 for (i=0; i < iLen0; i++)
1949 * Count special chars to get estimate of new length
1952 chlen = mblen ((char *) &pchLine[i], MB_CUR_MAX);
1954 ((pchLine[i] == '\\') ||
1955 (pchLine[i] == '"')))
1967 #else /* MULTIBYTE */
1968 if ((pchLine[i] == '\\') ||
1969 (pchLine[i] == '"'))
1973 #endif /* MULTIBYTE */
1976 pchRet = (unsigned char *) XtMalloc (1+iLen1);
1980 pchRet[0] = '"'; /* starting quote */
1982 * Copy chars from old string to new one
1984 for (i=0, j=1; i < iLen0; i++, j++)
1987 chlen = mblen ((char *) &pchLine[i], MB_CUR_MAX);
1989 ((pchLine[i] == '\\') ||
1990 (pchLine[i] == '"')))
1992 /* quote next char */
1999 else while (chlen > 1)
2001 /* copy first bytes of multibyte char */
2002 pchRet[j++] = pchLine[i++];
2005 #else /* MULTIBYTE */
2006 if ((pchLine[i] == '\\') ||
2007 (pchLine[i] == '"'))
2009 /* quote next char */
2012 #endif /* MULTIBYTE */
2014 pchRet[j] = pchLine[i];
2016 pchRet[j++] = '"'; /* ending quote */
2017 pchRet[j] = '\0'; /* end of string */
2022 } /* END OF FUNCTION _DtWmParseMakeQuotedString */
2025 /*==================== END OF FILE WmParse.c ====================*/