WmParse.c 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809
  1. /*
  2. * CDE - Common Desktop Environment
  3. *
  4. * Copyright (c) 1993-2012, The Open Group. All rights reserved.
  5. *
  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)
  10. * any later version.
  11. *
  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
  16. * details.
  17. *
  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
  22. */
  23. /******************************<+>*************************************
  24. **********************************************************************
  25. **
  26. ** File: WmParse.c
  27. **
  28. ** Project: HP/Motif Workspace Manager (dtwm)
  29. **
  30. ** Description:
  31. ** -----------
  32. ** This file contains the generic parsing routines
  33. **
  34. **
  35. *********************************************************************
  36. **
  37. ** (c) Copyright 1987, 1988, 1989, 1990, 1991 HEWLETT-PACKARD COMPANY
  38. ** ALL RIGHTS RESERVED
  39. **
  40. **********************************************************************
  41. **********************************************************************
  42. **
  43. **
  44. **********************************************************************
  45. ******************************<+>*************************************/
  46. /* ANSI C definitions, This should be the first thing in WmGlobal.h */
  47. #ifdef __STDC__
  48. #define Const const
  49. #else
  50. #define Const /**/
  51. #endif
  52. /*
  53. * Included Files:
  54. */
  55. #include <stdio.h>
  56. #include <X11/Intrinsic.h>
  57. #include "WmGlobal.h"
  58. #include "WmParse.h"
  59. #include "WmParseP.h"
  60. #include <stdlib.h>
  61. #include <ctype.h>
  62. /*
  63. * Internal routines
  64. */
  65. static DtWmpParseBuf * _DtWmpIncBuf (
  66. DtWmpParseBuf *pWmPB);
  67. #ifndef MAXLINE
  68. #define MAXLINE (MAXWMPATH+1)
  69. #endif
  70. #define MAX_QUOTE_DEPTH 10
  71. /*
  72. * This flags non-OSF code in those sections that were lifted
  73. * from mwm.
  74. */
  75. #define PARSE_LIB
  76. /*
  77. * Defines used to maintain code similarity between OSF/mwm source
  78. * routines and these routines.
  79. */
  80. #define cfileP ((pWmPB)->pFile)
  81. #define linec ((pWmPB)->lineNumber)
  82. #define line ((pWmPB)->pchLine)
  83. #define parseP ((pWmPB)->pchNext)
  84. #define ScanWhitespace(s) (_DtWmParseSkipWhitespaceC(s))
  85. #define PeekAhead(s,l) (_DtWmParsePeekAhead(s,l))
  86. /*************************************<->*************************************
  87. *
  88. * _DtWmParseSkipWhitespace(pWmPB)
  89. *
  90. *
  91. * Description:
  92. * -----------
  93. * Scan the current string, skipping over all white space characters.
  94. *
  95. *
  96. * Inputs:
  97. * ------
  98. * pWmPB = ptr to parse buffer
  99. *
  100. *
  101. * Outputs:
  102. * -------
  103. * pWmPB = parse buffer modified; current line ptr may be moved.
  104. *
  105. *
  106. * Comments:
  107. * --------
  108. * Assumes there's a current line in the parse buffer
  109. *
  110. *************************************<->***********************************/
  111. void _DtWmParseSkipWhitespace(DtWmpParseBuf *pWmPB)
  112. {
  113. _DtWmParseSkipWhitespaceC (&(pWmPB->pchNext));
  114. } /* END OF FUNCTION _DtWmParseSkipWhitespace */
  115. /*************************************<->*************************************
  116. *
  117. * _DtWmParseNextToken (pWmPB)
  118. *
  119. *
  120. * Description:
  121. * -----------
  122. * Returns the next quoted or whitespace-terminated nonquoted string in the
  123. * current line buffer.
  124. *
  125. *
  126. * Inputs:
  127. * ------
  128. * pWmPB = ptr to parse buffer
  129. *
  130. *
  131. * Outputs:
  132. * -------
  133. * Return = ptr to null terminated string.
  134. * pWmPB = current line modified internally.
  135. *
  136. *
  137. * Comments:
  138. * --------
  139. * May alter the line buffer contents.
  140. * Handles quoted strings and characters, removing trailing whitespace from
  141. * quoted strings.
  142. * Returns NULL string if the line is empty or is a comment.
  143. * Does not use session manager style algorithm for dealing with
  144. * quoted strings.
  145. *
  146. *************************************<->***********************************/
  147. unsigned char *
  148. _DtWmParseNextToken (
  149. DtWmpParseBuf *pWmPB
  150. )
  151. {
  152. return (_DtWmParseNextTokenC (&(pWmPB->pchNext), False));
  153. }
  154. /*************************************<->*************************************
  155. *
  156. * _DtWmParseNextTokenExpand (pWmPB)
  157. *
  158. *
  159. * Description:
  160. * -----------
  161. * Returns the next quoted or whitespace-terminated nonquoted string in the
  162. * current line buffer. Environment variables found in the are expanded.
  163. * Characters quoted by '\' are passed through unaffected with the
  164. * quoting '\' removed.
  165. *
  166. *
  167. * Inputs:
  168. * ------
  169. * pWmPB = ptr to parse buffer
  170. *
  171. *
  172. * Outputs:
  173. * -------
  174. * Return = ptr to null terminated string.
  175. * Free this string with XtFree().
  176. * pWmPB = current line modified internally.
  177. *
  178. *
  179. * Comments:
  180. * --------
  181. * May alter the line buffer contents.
  182. * Handles quoted strings and characters, removing trailing whitespace from
  183. * quoted strings.
  184. * Returns NULL string if the line is empty or is a comment.
  185. *
  186. *************************************<->***********************************/
  187. unsigned char *
  188. _DtWmParseNextTokenExpand (
  189. DtWmpParseBuf *pWmPB
  190. )
  191. {
  192. unsigned char *pch;
  193. unsigned char *pchReturn = NULL;
  194. /* isolate the next token */
  195. pch = _DtWmParseNextTokenC (&(pWmPB->pchNext), False);
  196. /* expand environment variables, a copy of the string is returned */
  197. pchReturn = _DtWmParseExpandEnvironmentVariables (pch, NULL);
  198. /*
  199. * If a token was found, but no copy returned, there were no
  200. * environment variables. This routine needs to return a copy,
  201. * so make one now.
  202. */
  203. if (pch && !pchReturn)
  204. pchReturn = (unsigned char *) XtNewString ((String) pch);
  205. return (pchReturn);
  206. }
  207. /*************************************<->*************************************
  208. *
  209. * _DtWmParseBackUp (pWmPB, pchTok)
  210. *
  211. *
  212. * Description:
  213. * -----------
  214. * Backs up to the previous token (the one before pchTok)
  215. *
  216. *
  217. * Inputs:
  218. * ------
  219. * pWmPB = ptr to parse buffer
  220. * pchTok = ptr to a token in the parse buffer
  221. *
  222. *
  223. * Outputs:
  224. * -------
  225. * Returns = ptr to prev token
  226. *
  227. *
  228. * Comments:
  229. * --------
  230. * Operates on the line buffer in the pWmPB structure. Backs up
  231. * the next pointer and writes a space over the interpolated
  232. * NULL (if any).
  233. *
  234. *************************************<->***********************************/
  235. unsigned char *
  236. _DtWmParseBackUp (
  237. DtWmpParseBuf *pWmPB,
  238. unsigned char *pchTok
  239. )
  240. {
  241. if ((pchTok > pWmPB->pchLine) &&
  242. (pchTok < (pWmPB->pchLine + pWmPB->cLineSize)))
  243. {
  244. unsigned char *pch;
  245. unsigned char *pchLast;
  246. int chlen;
  247. pch = pchLast = pWmPB->pchLine;
  248. /*
  249. * Search from beginning (because of multibyte chars) to
  250. * find the token before the string we're interested in.
  251. */
  252. while ((pch < pchTok))
  253. {
  254. chlen = mblen ((char *)pch, MB_CUR_MAX);
  255. if (*pch == '\0')
  256. {
  257. pch++;
  258. if (pch == pchTok)
  259. {
  260. /*
  261. * Found the NULL preceding the string passed in!
  262. * Replace it with a blank and return the previous
  263. * token (pointed to by pchLast).
  264. */
  265. *(pch - 1) = DTWM_CHAR_SPACE;
  266. break;
  267. }
  268. else
  269. {
  270. /*
  271. * Remember the beginning of this token.
  272. */
  273. pchLast = pch;
  274. }
  275. }
  276. else if (chlen < 1)
  277. {
  278. break;
  279. }
  280. else
  281. {
  282. pch += chlen;
  283. }
  284. }
  285. pWmPB->pchNext = pchLast;
  286. }
  287. return (pWmPB->pchNext);
  288. }
  289. /*************************************<->*************************************
  290. *
  291. * _DtWmParseSkipWhitespaceC(linePP)
  292. *
  293. *
  294. * Description:
  295. * -----------
  296. * Scan the string, skipping over all white space characters.
  297. *
  298. *
  299. * Inputs:
  300. * ------
  301. * linePP = nonNULL pointer to current line buffer pointer
  302. *
  303. *
  304. * Outputs:
  305. * -------
  306. * linePP = nonNULL pointer to revised line buffer pointer
  307. *
  308. *
  309. * Comments:
  310. * --------
  311. * Assumes linePP is nonNULL
  312. *
  313. *************************************<->***********************************/
  314. void _DtWmParseSkipWhitespaceC(unsigned char **linePP)
  315. {
  316. while (*linePP &&
  317. (mblen ((char *)*linePP, MB_CUR_MAX) == 1) &&
  318. isspace (**linePP))
  319. {
  320. (*linePP)++;
  321. }
  322. } /* END OF FUNCTION _DtWmParseSkipWhitespaceC */
  323. /*************************************<->*************************************
  324. *
  325. * _DtWmParseNextTokenC (linePP, SmBehavior)
  326. *
  327. *
  328. * Description:
  329. * -----------
  330. * Returns the next quoted or whitespace-terminated nonquoted string in the
  331. * line buffer.
  332. * Additional functionality added to GetString in that anything in a
  333. * quoted string is considered sacred and nothing will be stripped from
  334. * the middle of a quoted string.
  335. *
  336. *
  337. * Inputs:
  338. * ------
  339. * linePP = pointer to current line buffer pointer.
  340. * SmBehavior = flag that enables parsing session manager hints if True.
  341. * If False, this behaves as the normal OSF mwm GetString
  342. * routine.
  343. *
  344. *
  345. * Outputs:
  346. * -------
  347. * linePP = pointer to revised line buffer pointer.
  348. * Return = string
  349. *
  350. *
  351. * Comments:
  352. * --------
  353. * May alter the line buffer contents.
  354. * Handles quoted strings and characters, removing trailing whitespace from
  355. * quoted strings.
  356. * Returns NULL string if the line is empty or is a comment.
  357. * Code stolen from dtmwm.
  358. *
  359. *************************************<->***********************************/
  360. unsigned char *
  361. _DtWmParseNextTokenC (
  362. unsigned char **linePP,
  363. Boolean SmBehavior
  364. )
  365. {
  366. /***********************************************************************
  367. *
  368. * The following code is duplicated from WmResParse.c (GetStringC)
  369. * GetStringC is the HP DT version of GetString.
  370. *
  371. * It works here through the magic of #defines.
  372. *
  373. ***********************************************************************/
  374. unsigned char *lineP = *linePP;
  375. unsigned char *endP;
  376. unsigned char *curP;
  377. unsigned char *lnwsP;
  378. unsigned int level = 0, checkLev, i, quoteLevel[MAX_QUOTE_DEPTH];
  379. int chlen;
  380. /* get rid of leading white space */
  381. ScanWhitespace (&lineP);
  382. /*
  383. * Return NULL if line is empty, whitespace, or begins with a comment.
  384. */
  385. if (
  386. *lineP == '\0' ||
  387. ((chlen = mblen ((char *)lineP, MB_CUR_MAX)) < 1) ||
  388. ((chlen == 1) && ((*lineP == '!') ||
  389. ((!SmBehavior) && (*lineP == '#'))))
  390. )
  391. {
  392. *linePP = lineP;
  393. return (NULL);
  394. }
  395. if ((chlen == 1) && (*lineP == '"'))
  396. /* Quoted string */
  397. {
  398. quoteLevel[level] = 1;
  399. /*
  400. * Start beyond double quote and find the end of the quoted string.
  401. * '\' quotes the next character.
  402. * Otherwise, matching double quote or NULL terminates the string.
  403. *
  404. * We use lnwsP to point to the last non-whitespace character in the
  405. * quoted string. When we have found the end of the quoted string,
  406. * increment lnwsP and if lnwsP < endP, write NULL into *lnwsP.
  407. * This removes any trailing whitespace without overwriting the
  408. * matching quote, needed later. If the quoted string was all
  409. * whitespace, then this will write a NULL at the beginning of the
  410. * string that will be returned -- OK.
  411. */
  412. lnwsP = lineP++; /* lnwsP points to first '"' */
  413. curP = endP = lineP; /* other pointers point beyond */
  414. while ((*endP = *curP) &&
  415. ((chlen = mblen ((char *)curP, MB_CUR_MAX)) > 0) &&
  416. ((chlen > 1) || (*curP != '"')))
  417. /* Haven't found matching quote yet.
  418. * First byte of next character has been copied to endP.
  419. */
  420. {
  421. curP++;
  422. if ((chlen == 1) && (*endP == '\\') &&
  423. ((chlen = mblen ((char *)curP, MB_CUR_MAX)) > 0))
  424. /* character quote:
  425. * copy first byte of quoted nonNULL character down.
  426. * point curP to next byte
  427. */
  428. {
  429. if (SmBehavior)
  430. {
  431. /*
  432. * Check to see if this is a quoted quote - if it is
  433. * strip off a level - if not - it's sacred leave it alone
  434. */
  435. checkLev = PeekAhead((curP - 1), quoteLevel[level]);
  436. if(checkLev > 0)
  437. {
  438. if(quoteLevel[level] >= checkLev)
  439. {
  440. if (level > 0) level--;
  441. }
  442. else if (level < MAX_QUOTE_DEPTH)
  443. {
  444. level++;
  445. quoteLevel[level] = checkLev;
  446. }
  447. for(i = 0;i < (checkLev - 2);i++)
  448. {
  449. *endP++ = *curP++;curP++;
  450. }
  451. *endP = *curP++;
  452. }
  453. }
  454. else
  455. {
  456. *endP = *curP++;
  457. }
  458. }
  459. if (chlen == 1)
  460. /* Singlebyte character: character copy finished. */
  461. {
  462. if (isspace (*endP))
  463. /* whitespace character: leave lnwsP unchanged. */
  464. {
  465. endP++;
  466. }
  467. else
  468. /* non-whitespace character: point lnwsP to it. */
  469. {
  470. lnwsP = endP++;
  471. }
  472. }
  473. else if (chlen > 1)
  474. /* Multibyte (nonwhitespace) character: point lnwsP to it.
  475. * Finish character byte copy.
  476. */
  477. {
  478. lnwsP = endP++;
  479. while (--chlen)
  480. {
  481. *endP++ = *curP++;
  482. lnwsP++;
  483. }
  484. }
  485. }
  486. /*
  487. * Found matching quote or NULL.
  488. * NULL out any trailing whitespace.
  489. */
  490. lnwsP++;
  491. if (lnwsP < endP)
  492. {
  493. *lnwsP = '\0';
  494. }
  495. }
  496. else
  497. /* Unquoted string */
  498. {
  499. /*
  500. * Find the end of the nonquoted string.
  501. * '\' quotes the next character.
  502. * Otherwise, whitespace, NULL, or '#' terminates the string.
  503. */
  504. curP = endP = lineP;
  505. while ((*endP = *curP) &&
  506. ((chlen = mblen ((char *)curP, MB_CUR_MAX)) > 0) &&
  507. ((chlen > 1) || (!isspace (*curP) &&
  508. (SmBehavior || (*curP != '#')))))
  509. /* Haven't found whitespace or '#' yet.
  510. * First byte of next character has been copied to endP.
  511. */
  512. {
  513. curP++;
  514. if ((chlen == 1) && (*endP == '\\') &&
  515. ((chlen = mblen ((char *)curP, MB_CUR_MAX)) > 0))
  516. /* character quote:
  517. * copy first byte of quoted nonNULL character down.
  518. * point curP to next byte
  519. */
  520. {
  521. *endP = *curP++;
  522. }
  523. endP++;
  524. if (chlen > 1)
  525. /* Multibyte character: finish character copy. */
  526. {
  527. while (--chlen)
  528. {
  529. *endP++ = *curP++;
  530. }
  531. }
  532. }
  533. }
  534. /*
  535. * Three cases for *endP:
  536. * '#' --> write NULL over # and point to NULL
  537. * whitespace or
  538. * matching quote -> write NULL over char and point beyond
  539. * NULL -> point to NULL
  540. */
  541. if (!SmBehavior && (*endP == '#'))
  542. {
  543. *endP = '\0'; /* write NULL over '#' */
  544. *linePP = endP; /* point to NULL */
  545. }
  546. else if (*endP != '\0')
  547. {
  548. *endP = '\0'; /* write NULL over terminator */
  549. *linePP = ++curP; /* point beyond terminator */
  550. }
  551. else
  552. {
  553. *linePP = endP;
  554. }
  555. return ((unsigned char *)lineP);
  556. } /* END OF FUNCTION _DtWmParseNextTokenC */
  557. /*************************************<->*************************************
  558. *
  559. * (DtWmParseBuf *) _DtWmParseNewBuf (void)
  560. *
  561. *
  562. * Description:
  563. * -----------
  564. * Allocates a new parse record for parsing.
  565. *
  566. * Inputs:
  567. * ------
  568. * none
  569. *
  570. *
  571. * Outputs:
  572. * -------
  573. * Return = ptr to parse buffer record, NULL if memory allocation
  574. * error.
  575. *
  576. *
  577. * Comments:
  578. * --------
  579. * Call this first before using the other DtWmp routines that require
  580. * a parse buffer. Treat this as an opaque type; use the provided
  581. * routines to create, access, and destroy this structure.
  582. *
  583. *************************************<->***********************************/
  584. DtWmpParseBuf *
  585. _DtWmParseNewBuf ( void )
  586. {
  587. DtWmpParseBuf *pWmPB;
  588. pWmPB = (DtWmpParseBuf *) XtMalloc (sizeof (DtWmpParseBuf));
  589. if (pWmPB)
  590. {
  591. pWmPB->pchLine = (unsigned char *) XtMalloc (MAXLINE+1);
  592. if (!pWmPB->pchLine)
  593. {
  594. XtFree ((char *)pWmPB);
  595. pWmPB = NULL;
  596. }
  597. }
  598. if (pWmPB)
  599. {
  600. pWmPB->lineNumber = 0;
  601. pWmPB->pchNext = pWmPB->pchLine;
  602. pWmPB->cLineSize = MAXLINE+1;
  603. pWmPB->pFile = NULL;
  604. *(pWmPB->pchLine) = '\0';
  605. }
  606. return (pWmPB);
  607. } /* END OF FUNCTION _DtWmParseNewBuf */
  608. /*************************************<->*************************************
  609. *
  610. * (DtWmParseBuf *) _DtWmpIncBuf (pWmPB)
  611. *
  612. *
  613. * Description:
  614. * -----------
  615. * Increases the size of the line buffer in the parse buffer
  616. *
  617. * Inputs:
  618. * ------
  619. * pWmPB = pointer to a parse buffer
  620. *
  621. *
  622. * Outputs:
  623. * -------
  624. * Return = ptr to parse buffer record, NULL if memory allocation
  625. * error.
  626. *
  627. *
  628. * Comments:
  629. * --------
  630. *
  631. *************************************<->***********************************/
  632. static DtWmpParseBuf *
  633. _DtWmpIncBuf (
  634. DtWmpParseBuf *pWmPB)
  635. {
  636. if (pWmPB)
  637. {
  638. int ix;
  639. if (pWmPB->pFile)
  640. {
  641. /* save index into old string */
  642. ix = pWmPB->pchNext - pWmPB->pchLine;
  643. }
  644. pWmPB->pchLine = (unsigned char *)
  645. XtRealloc ((char *)pWmPB->pchLine, (pWmPB->cLineSize + MAXLINE));
  646. if (pWmPB->pchLine)
  647. {
  648. pWmPB->cLineSize += MAXLINE;
  649. if (pWmPB->pFile)
  650. {
  651. /* restore index into new string */
  652. pWmPB->pchNext = pWmPB->pchLine + ix;
  653. }
  654. }
  655. }
  656. return (pWmPB);
  657. } /* END OF FUNCTION _DtWmpIncBuf */
  658. /*************************************<->*************************************
  659. *
  660. * _DtWmParseDestroyBuf (pWmPB)
  661. *
  662. *
  663. * Description:
  664. * -----------
  665. * Destroys a parse buffer record, freeing any allocated memory.
  666. *
  667. *
  668. * Inputs:
  669. * ------
  670. * pWmPB = ptr to previously allocated parse buffer
  671. *
  672. *
  673. * Outputs:
  674. * -------
  675. * none
  676. *
  677. *
  678. * Comments:
  679. * --------
  680. * Destroys parse buffers allocated by _DtWmParseNewBuf.
  681. *
  682. *************************************<->***********************************/
  683. void
  684. _DtWmParseDestroyBuf (
  685. DtWmpParseBuf *pWmPB
  686. )
  687. {
  688. if (pWmPB)
  689. {
  690. if (pWmPB->pchLine)
  691. {
  692. XtFree ((char *) pWmPB->pchLine);
  693. }
  694. XtFree ((char *) pWmPB);
  695. }
  696. } /* END OF FUNCTION _DtWmParseDestroyBuf */
  697. /*************************************<->*************************************
  698. *
  699. * (unsigned char *) _DtWmParseSetLine (pWmPB, pch)
  700. *
  701. *
  702. * Description:
  703. * -----------
  704. * Sets a line into the parse buffer structure. This is used in cases
  705. * where parsing of an embedded string, usually a default, is done
  706. * instead of parsing out of a file.
  707. *
  708. *
  709. * Inputs:
  710. * ------
  711. * pWmPB = previously allocated parse buffer
  712. * pch = ptr to unsigned char string (zero terminated)
  713. *
  714. * Outputs:
  715. * -------
  716. * Return = pch
  717. *
  718. *
  719. * Comments:
  720. * --------
  721. * This resets any previous setting of the file pointer. EOF wil be
  722. * returned when the string pointed to by pch is exhausted.
  723. *
  724. * Resets line number count.
  725. *
  726. *************************************<->***********************************/
  727. void
  728. _DtWmParseSetLine (
  729. DtWmpParseBuf *pWmPB,
  730. unsigned char *pch
  731. )
  732. {
  733. if (pWmPB)
  734. {
  735. pWmPB->pchLine = pch;
  736. pWmPB->pchNext = pWmPB->pchLine;
  737. pWmPB->pFile = NULL;
  738. pWmPB->lineNumber = 0;
  739. }
  740. } /* END OF FUNCTION _DtWmParseSetLine */
  741. /*************************************<->*************************************
  742. *
  743. * (FILE *) _DtWmParseSetFile (pWmPB, pFile)
  744. *
  745. *
  746. * Description:
  747. * -----------
  748. * Sets the file pointer in a parse buffer. This is used when parsing
  749. * from a file is required.
  750. *
  751. *
  752. * Inputs:
  753. * ------
  754. * pWmPB = pointer to a parse buffer
  755. * pFile = pointer to an opened FILE
  756. *
  757. * Outputs:
  758. * -------
  759. * Return = pFile
  760. *
  761. *
  762. * Comments:
  763. * --------
  764. * You fopen the file first, then pass in the FILE * returned to this
  765. * routine.
  766. *
  767. * Resets line number count.
  768. *
  769. *************************************<->***********************************/
  770. void
  771. _DtWmParseSetFile (
  772. DtWmpParseBuf *pWmPB,
  773. FILE *pFile
  774. )
  775. {
  776. if (pWmPB)
  777. {
  778. pWmPB->pchLine[0] = '\0';
  779. pWmPB->pchNext = NULL;
  780. pWmPB->pFile = pFile;
  781. pWmPB->lineNumber = 0;
  782. }
  783. } /* END OF FUNCTION _DtWmParseSetFile */
  784. /*************************************<->*************************************
  785. *
  786. * (unsigned char *) _DtWmParseNextLine ( pWmPB )
  787. *
  788. *
  789. * Description:
  790. * -----------
  791. * Returns a pointer to the next line to parse.
  792. *
  793. *
  794. * Inputs:
  795. * ------
  796. * pWmPB = pointer to a parse buffer
  797. *
  798. *
  799. * Outputs:
  800. * -------
  801. * Return = pointer to next line to parse or NULL on EOF.
  802. *
  803. *
  804. * Comments:
  805. * --------
  806. *
  807. *
  808. *************************************<->***********************************/
  809. unsigned char *
  810. _DtWmParseNextLine (
  811. DtWmpParseBuf *pWmPB
  812. )
  813. {
  814. /***********************************************************************
  815. *
  816. * The following code is duplicated from WmResParse.c (GetNextLine)
  817. * It works here through the magic of #defines.
  818. *
  819. ***********************************************************************/
  820. unsigned char *string;
  821. int len;
  822. int chlen;
  823. wchar_t last;
  824. wchar_t wdelim;
  825. char delim;
  826. int lastlen;
  827. if (cfileP != NULL)
  828. /* read fopened file */
  829. {
  830. if ((string = (unsigned char *)
  831. fgets ((char *)line, MAXLINE, cfileP)) != NULL)
  832. {
  833. #ifdef PARSE_LIB
  834. if (strlen((char *)string) > (size_t)pWmPB->cLineSize)
  835. {
  836. /*
  837. * Bump size of destination buffer
  838. */
  839. pWmPB->cLineSize = 1 + strlen((char *)string);
  840. pWmPB->pchLine = (unsigned char *)
  841. XtRealloc ((char *)pWmPB->pchLine,
  842. (pWmPB->cLineSize));
  843. }
  844. #endif /* PARSE_LIB */
  845. lastlen = 0;
  846. while (*string &&
  847. ((len = mblen((char *)string, MB_CUR_MAX)) > 0))
  848. {
  849. mbtowc(&last, (char *)string, MB_CUR_MAX);
  850. lastlen = len;
  851. string += len;
  852. }
  853. delim = '\\';
  854. mbtowc(&wdelim, &delim, MB_CUR_MAX);
  855. if (lastlen == 1 && last == wdelim)
  856. {
  857. do
  858. {
  859. if (!fgets((char *)string, MAXLINE - (string - line), cfileP))
  860. break;
  861. lastlen = 0;
  862. while (*string &&
  863. ((len = mblen((char *)string, MB_CUR_MAX)) > 0))
  864. {
  865. mbtowc(&last, (char *)string, MB_CUR_MAX);
  866. lastlen = len;
  867. string += len;
  868. }
  869. linec++;
  870. }
  871. while (lastlen == 1 && last == wdelim);
  872. }
  873. string = line;
  874. }
  875. }
  876. else if ((parseP != NULL) && (*parseP != '\0'))
  877. /* read parse string */
  878. {
  879. #ifdef PARSE_LIB
  880. if (strlen((char *)parseP) > (size_t)pWmPB->cLineSize)
  881. {
  882. /*
  883. * Bump size of destination buffer
  884. */
  885. pWmPB->cLineSize = 1 + strlen((char *)parseP);
  886. pWmPB->pchLine = (unsigned char *)
  887. XtRealloc ((char *)pWmPB->pchLine,
  888. (pWmPB->cLineSize));
  889. }
  890. #endif /* PARSE_LIB */
  891. string = line;
  892. while ((*parseP != '\0') &&
  893. ((chlen = mblen ((char *)parseP, MB_CUR_MAX)) != 0) &&
  894. (*parseP != '\n'))
  895. /* copy all but end-of-line and newlines to line buffer */
  896. {
  897. if (chlen == -1)
  898. parseP++;
  899. else
  900. {
  901. while (chlen--)
  902. {
  903. *(string++) = *(parseP++);
  904. }
  905. }
  906. }
  907. *string = '\0';
  908. if (*parseP == '\n')
  909. {
  910. parseP++;
  911. }
  912. }
  913. else
  914. {
  915. string = NULL;
  916. }
  917. linec++;
  918. #ifdef PARSE_LIB
  919. if (cfileP)
  920. {
  921. /* update pchNext to get next line */
  922. pWmPB->pchNext = string;
  923. }
  924. #endif /* PARSE_LIB */
  925. return (string);
  926. } /* END OF FUNCTION _DtWmParseNextLine */
  927. /*************************************<->*************************************
  928. *
  929. * (unsigned char *) _DtWmParseCurrentChar (pWmPB)
  930. *
  931. *
  932. * Description:
  933. * -----------
  934. * Returns a pointer to the rest of the current line.
  935. *
  936. *
  937. * Inputs:
  938. * ------
  939. * pWmPB = pointer to a parse buffer
  940. *
  941. *
  942. * Outputs:
  943. * -------
  944. * Return = pointer to the rest of the current line
  945. *
  946. *
  947. * Comments:
  948. * --------
  949. * Useful in cases where you want to look at a char before getting the
  950. * next token or if you want to treat the rest of the line as a
  951. * single token.
  952. *
  953. *************************************<->***********************************/
  954. unsigned char *
  955. _DtWmParseCurrentChar (
  956. DtWmpParseBuf *pWmPB
  957. )
  958. {
  959. return (pWmPB ? pWmPB->pchNext : (unsigned char *)NULL);
  960. } /* END OF FUNCTION _DtWmParseCurrentChar */
  961. /*************************************<->*************************************
  962. *
  963. * (unsigned char *) _DtWmParseNextChar (pWmPB)
  964. *
  965. *
  966. * Description:
  967. * -----------
  968. * Advances the pointer to the next char and returns a pointer
  969. * to the new current char.
  970. *
  971. *
  972. * Inputs:
  973. * ------
  974. * pWmPB = pointer to a parse buffer
  975. *
  976. *
  977. * Outputs:
  978. * -------
  979. * Return = pointer to the rest of the current line
  980. *
  981. *
  982. * Comments:
  983. * --------
  984. *
  985. *************************************<->***********************************/
  986. unsigned char *
  987. _DtWmParseNextChar (
  988. DtWmpParseBuf *pWmPB
  989. )
  990. {
  991. unsigned char *pch = NULL;
  992. int chlen;
  993. if (pWmPB &&
  994. pWmPB->pchNext &&
  995. (chlen = mblen((char *)pWmPB->pchNext, MB_CUR_MAX) > 0))
  996. {
  997. pch = (pWmPB->pchNext += chlen);
  998. }
  999. return (pch);
  1000. }
  1001. /*************************************<->*************************************
  1002. *
  1003. * (int) _DtWmParseLineNumber (pWmPB)
  1004. *
  1005. *
  1006. * Description:
  1007. * -----------
  1008. * Returns the number of the current line of what's being parsed.
  1009. *
  1010. *
  1011. * Inputs:
  1012. * ------
  1013. * pWmPB = ptr to parse buffer
  1014. *
  1015. *
  1016. * Outputs:
  1017. * -------
  1018. * Return = number of current line
  1019. *
  1020. *
  1021. * Comments:
  1022. * --------
  1023. * Used for error reporting.
  1024. *
  1025. * The line number is computed by counting '\n' characters.
  1026. *
  1027. *************************************<->***********************************/
  1028. int
  1029. _DtWmParseLineNumber (
  1030. DtWmpParseBuf *pWmPB
  1031. )
  1032. {
  1033. return (pWmPB ? pWmPB->lineNumber : 0);
  1034. } /* END OF FUNCTION _DtWmParseLineNumber */
  1035. /*************************************<->*************************************
  1036. *
  1037. * _DtWmParseToLower (string)
  1038. *
  1039. *
  1040. * Description:
  1041. * -----------
  1042. * Lower all characters in a string.
  1043. *
  1044. *
  1045. * Inputs:
  1046. * ------
  1047. * string = NULL-terminated character string or NULL
  1048. *
  1049. *
  1050. * Outputs:
  1051. * -------
  1052. * string = NULL-terminated lower case character string or NULL
  1053. *
  1054. *
  1055. * Comments:
  1056. * --------
  1057. * Can handle multi-byte characters
  1058. *
  1059. *************************************<->***********************************/
  1060. void _DtWmParseToLower (char *string)
  1061. {
  1062. char *pch = string;
  1063. int chlen;
  1064. while ((chlen = mblen (pch, MB_CUR_MAX)) > 0)
  1065. {
  1066. if ((chlen == 1) && (isupper (*pch)))
  1067. {
  1068. *pch = tolower(*pch);
  1069. }
  1070. pch += chlen;
  1071. }
  1072. } /* END OF FUNCTION _DtWmParseToLower */
  1073. /*************************************<->*************************************
  1074. *
  1075. * _DtWmParsePeekAhead (currentChar, currentLev)
  1076. *
  1077. *
  1078. * Description:
  1079. * -----------
  1080. * Returns a new level value if this is a new nesting level of quoted string
  1081. * Otherwise it returns a zero
  1082. *
  1083. *
  1084. * Inputs:
  1085. * ------
  1086. * currentChar = current position in the string
  1087. * currentLev = current level of nesting
  1088. *
  1089. *
  1090. * Outputs:
  1091. * -------
  1092. * Returns either a new level of nesting or zero if the character is copied in
  1093. *
  1094. *
  1095. * Comments:
  1096. * --------
  1097. *
  1098. *************************************<->***********************************/
  1099. unsigned int _DtWmParsePeekAhead(unsigned char *currentChar,
  1100. unsigned int currentLev)
  1101. {
  1102. Boolean done = False;
  1103. unsigned int tmpLev = 1;
  1104. unsigned int chlen;
  1105. while (((chlen = mblen ((char *)currentChar, MB_CUR_MAX)) > 0) &&
  1106. (chlen == 1) && ((*currentChar == '"') || (*currentChar == '\\'))
  1107. && (done == False))
  1108. {
  1109. currentChar++;
  1110. if(((chlen = mblen ((char *)currentChar, MB_CUR_MAX)) > 0) &&
  1111. (chlen == 1) &&
  1112. ((*currentChar == '"') || (*currentChar == '\\')))
  1113. {
  1114. tmpLev++;
  1115. if(*currentChar == '"')
  1116. {
  1117. done = True;
  1118. }
  1119. else
  1120. {
  1121. currentChar++;
  1122. }
  1123. }
  1124. }
  1125. /*
  1126. * Figure out if this is truly a new level of nesting - else ignore it
  1127. * This section probably could do some error checking and return -1
  1128. * If so, change type of routine from unsigned int to int
  1129. */
  1130. if(done == True)
  1131. {
  1132. return(tmpLev);
  1133. }
  1134. else
  1135. {
  1136. return(0);
  1137. }
  1138. } /* END OF FUNCTION _DtWmParsePeekAhead */
  1139. /*************************************<->*************************************
  1140. *
  1141. * (unsigned char *) _DtWmParseFilenameExpand (pchFilename)
  1142. *
  1143. *
  1144. * Description:
  1145. * -----------
  1146. * Returns a copy of a file name with environment variables
  1147. * expanded.
  1148. *
  1149. *
  1150. * Inputs:
  1151. * ------
  1152. * pchFilename = ptr to a zero terminated character string (filename)
  1153. *
  1154. *
  1155. * Outputs:
  1156. * -------
  1157. * Return = ptr to a new file name with environment variables
  1158. * expanded.
  1159. *
  1160. *
  1161. * Comments:
  1162. * --------
  1163. * The passed in string is temporarily modified inside here.
  1164. *
  1165. * Free the returned string with XtFree().
  1166. *
  1167. * Returns NULL on a memory allocation error.
  1168. *
  1169. * Environment variables that can't be expanded are removed from
  1170. * the returned copy.
  1171. *
  1172. * If no environment variables, you get a copy of the string back.
  1173. *
  1174. *************************************<->***********************************/
  1175. unsigned char *
  1176. _DtWmParseFilenameExpand (
  1177. unsigned char *pchFilename
  1178. )
  1179. {
  1180. unsigned char *pchN, *pchNew, *pchO;
  1181. unsigned char *pchEnv, *pchEnv0, *pchEnv1;
  1182. unsigned char chSave;
  1183. int len, n, nx, ix;
  1184. unsigned char pchBrk[] = { DTWM_CHAR_ENVIRONMENT,
  1185. DTWM_CHAR_DIRECTORY,
  1186. '\0'
  1187. };
  1188. len = strlen ((char *)pchFilename);
  1189. pchNew = (unsigned char *) XtMalloc (1+len);
  1190. pchO = pchFilename;
  1191. chSave = '\0';
  1192. ix = 0;
  1193. while (pchNew && pchO && *pchO)
  1194. {
  1195. /* find next environment variable */
  1196. pchEnv0 = (unsigned char *)
  1197. strchr ((char *)pchO, (int) DTWM_CHAR_ENVIRONMENT);
  1198. if (pchEnv0)
  1199. {
  1200. /* length to this point */
  1201. n = pchEnv0 - pchO;
  1202. /* copy up to environment character */
  1203. if (n)
  1204. {
  1205. memcpy (&pchNew[ix], pchO, n);
  1206. ix += n;
  1207. }
  1208. /* skip environment character */
  1209. pchEnv0++;
  1210. /* end of variable is at one of:
  1211. * start of next variable,
  1212. * start of next directory,
  1213. * end of string
  1214. */
  1215. pchEnv1 = (unsigned char *)
  1216. strpbrk ((char *)pchEnv0, (char *)pchBrk);
  1217. if (pchEnv1)
  1218. {
  1219. /* next string starts after this one */
  1220. pchO = pchEnv1;
  1221. n = pchEnv1 - pchEnv0 + 1;
  1222. /* replace this char with NULL for now */
  1223. chSave = *pchEnv1;
  1224. *pchEnv1 = '\0';
  1225. }
  1226. else
  1227. {
  1228. /* This environment variable is the last thing on
  1229. * the line. Signal all done.
  1230. */
  1231. n = strlen ((char *) pchO);
  1232. pchO += n;
  1233. }
  1234. pchEnv = (unsigned char *) getenv ((char *)pchEnv0);
  1235. if (pchEnv)
  1236. {
  1237. nx = strlen ((char *) pchEnv);
  1238. if (nx > n)
  1239. {
  1240. len += nx - n;
  1241. pchNew = (unsigned char *)
  1242. XtRealloc ((char *)pchNew, 1+len);
  1243. }
  1244. if (pchNew)
  1245. {
  1246. memcpy (&pchNew[ix], pchEnv, nx);
  1247. ix += nx;
  1248. }
  1249. else
  1250. {
  1251. continue;
  1252. }
  1253. }
  1254. if (chSave)
  1255. {
  1256. *pchO = chSave;
  1257. chSave = '\0';
  1258. }
  1259. /* keep a kosher string */
  1260. pchNew[ix] = '\0';
  1261. }
  1262. else
  1263. {
  1264. /* copy the rest of the string */
  1265. n = strlen ((char *) pchO);
  1266. memcpy (&pchNew[ix], pchO, n);
  1267. pchO += n;
  1268. /* remember the NULL! (a famous battle cry) */
  1269. pchNew[ix + n] = '\0';
  1270. }
  1271. }
  1272. return (pchNew);
  1273. } /* END OF FUNCTION _DtWmParseFilenameExpand */
  1274. /*************************************<->*************************************
  1275. *
  1276. * unsigned char * _DtWmParseExpandEnvironmentVariables (pch, pchBrk)
  1277. *
  1278. *
  1279. * Description:
  1280. * -----------
  1281. * Expands environment variables in a string.
  1282. *
  1283. *
  1284. * Inputs:
  1285. * ------
  1286. * pch = ptr to a zero terminated character string
  1287. * pchBrk = array of "break" characters (see strpbrk()).
  1288. * defaults are used if this is NULL.
  1289. *
  1290. * Outputs:
  1291. * -------
  1292. * Return = string with expanded environment variables. (free with XtFree)
  1293. * NULL string if no environment variables or backslashes
  1294. * found in the string passed in.
  1295. *
  1296. *
  1297. * Comments:
  1298. * --------
  1299. * Free returned string with XtFree()
  1300. *
  1301. * Environment variables that can't be expanded are removed from
  1302. * the returned copy.
  1303. *
  1304. * Default delimiter set is [Space], [Tab], '$', [Newline], '\', '/'.
  1305. *
  1306. * Variables of form $(..) and ${..} supported.
  1307. *
  1308. * A backslash '\' in front of any character quotes it. The backslash
  1309. * is removed in the returned string. A literal backslash needs to be
  1310. * quoted with a backslash.
  1311. *
  1312. *************************************<->***********************************/
  1313. unsigned char *
  1314. _DtWmParseExpandEnvironmentVariables (
  1315. unsigned char *pch,
  1316. unsigned char *pchBrk
  1317. )
  1318. {
  1319. int chlen;
  1320. unsigned char *pchStart;
  1321. unsigned char chSave;
  1322. unsigned char *pchEnvStart;
  1323. unsigned char *pchEnvValue;
  1324. unsigned char *pchReturn = NULL;
  1325. unsigned char *pchNext;
  1326. unsigned char *pchBreak;
  1327. Boolean bEatBreak;
  1328. Boolean bAlreadyAdvanced;
  1329. int lenOriginal;
  1330. int lenNonEnv;
  1331. int lenEnvVar;
  1332. int lenEnvValue;
  1333. int lenReturn = 0;
  1334. int lenSave;
  1335. static unsigned char pchDefaultBrk[] = {
  1336. DTWM_CHAR_ENVIRONMENT,
  1337. DTWM_CHAR_SPACE,
  1338. DTWM_CHAR_TAB,
  1339. DTWM_CHAR_NEW_LINE,
  1340. DTWM_CHAR_BACKSLASH,
  1341. DTWM_CHAR_DIRECTORY,
  1342. '\0' };
  1343. unsigned char pchParenBrk[] = {
  1344. DTWM_CHAR_R_PAREN,
  1345. '\0' };
  1346. unsigned char pchBraceBrk[] = {
  1347. DTWM_CHAR_R_BRACE,
  1348. '\0' };
  1349. /* There needs to be something to look at */
  1350. if (!pch)
  1351. return (NULL);
  1352. pchStart = pch;
  1353. lenOriginal = strlen ((char *)pch);
  1354. chlen = mblen ((char *)pch, MB_CUR_MAX);
  1355. chSave = '\0';
  1356. while (*pch && (chlen > 0))
  1357. {
  1358. if (chlen == 1)
  1359. {
  1360. bAlreadyAdvanced = False;
  1361. switch (*pch)
  1362. {
  1363. case DTWM_CHAR_BACKSLASH:
  1364. /*
  1365. * Copy up to start of quoted char
  1366. */
  1367. if (!pchReturn)
  1368. {
  1369. lenReturn = lenOriginal + 1;
  1370. pchReturn = (unsigned char *)
  1371. XtMalloc (lenReturn * sizeof (unsigned char));
  1372. pchReturn[0] = '\0';
  1373. }
  1374. chSave = *pch;
  1375. *pch = '\0';
  1376. strcat ((char *) pchReturn, (char *)pchStart);
  1377. *pch = chSave;
  1378. chSave = '\0';
  1379. /*
  1380. * The next character is "escaped", skip over it.
  1381. */
  1382. pchStart = pch += chlen;
  1383. chlen = mblen ((char *)pch, MB_CUR_MAX);
  1384. break;
  1385. case DTWM_CHAR_ENVIRONMENT:
  1386. /* save start of environment variable */
  1387. pchEnvStart = pch;
  1388. pch += chlen;
  1389. chlen = mblen ((char *)pch, MB_CUR_MAX);
  1390. /*
  1391. * Copy up to start of environment variable
  1392. */
  1393. if (!pchReturn)
  1394. {
  1395. lenReturn = lenOriginal + 1;
  1396. pchReturn = (unsigned char *)
  1397. XtMalloc (lenReturn * sizeof (unsigned char));
  1398. pchReturn[0] = '\0';
  1399. lenSave = 0;
  1400. }
  1401. else
  1402. {
  1403. lenSave = strlen ((char *)pchReturn);
  1404. }
  1405. lenNonEnv = pchEnvStart - pchStart;
  1406. memcpy (&pchReturn[lenSave], pchStart, lenNonEnv);
  1407. pchReturn[lenSave+lenNonEnv] = '\0';
  1408. /*
  1409. * Determine how we find the end of this
  1410. * environment variable.
  1411. */
  1412. bEatBreak = False;
  1413. if ((chlen == 1) &&
  1414. (*pch == DTWM_CHAR_L_PAREN))
  1415. {
  1416. pch += chlen;
  1417. chlen = mblen ((char *)pch, MB_CUR_MAX);
  1418. pchBreak = pchParenBrk;
  1419. bEatBreak = True;
  1420. }
  1421. else if ((chlen == 1) &&
  1422. (*pch == DTWM_CHAR_L_BRACE))
  1423. {
  1424. pch += chlen;
  1425. chlen = mblen ((char *)pch, MB_CUR_MAX);
  1426. pchBreak = pchBraceBrk;
  1427. bEatBreak = True;
  1428. }
  1429. else if (pchBrk && *pchBrk)
  1430. {
  1431. pchBreak = pchBrk;
  1432. }
  1433. else
  1434. {
  1435. pchBreak = pchDefaultBrk;
  1436. }
  1437. /*
  1438. * Look for end of environment variable
  1439. */
  1440. pchNext = (unsigned char *)
  1441. strpbrk ((char *)pch, (char *)pchBreak);
  1442. if (!pchNext)
  1443. {
  1444. /* it's the rest of the string */
  1445. chSave = '\0';
  1446. bEatBreak = False;
  1447. pchNext = pch + strlen ((char *) pch);
  1448. }
  1449. else
  1450. {
  1451. /* temporarily put a string terminator here */
  1452. chSave = *pchNext;
  1453. *pchNext = '\0';
  1454. }
  1455. /*
  1456. * Lookup environment variable
  1457. */
  1458. lenEnvVar = strlen ((char *)pch);
  1459. pchEnvValue = (unsigned char *) getenv ((char *)pch);
  1460. if (pchEnvValue)
  1461. {
  1462. /*
  1463. * Insure there's enough room in the return string
  1464. */
  1465. lenEnvValue = strlen ((char *)pchEnvValue);
  1466. if (!pchReturn)
  1467. {
  1468. lenReturn = lenOriginal + 1 - lenEnvVar +
  1469. lenEnvValue;
  1470. pchReturn = (unsigned char *)
  1471. XtMalloc (lenReturn * sizeof (unsigned char));
  1472. pchReturn[0] = '\0';
  1473. }
  1474. else
  1475. {
  1476. lenReturn = lenReturn + 1 - lenEnvVar +
  1477. lenEnvValue;
  1478. pchReturn = (unsigned char *)
  1479. XtRealloc ((char *)pchReturn,
  1480. lenReturn * sizeof (unsigned char));
  1481. }
  1482. /*
  1483. * Tack it onto the return string
  1484. */
  1485. strcat ((char *)pchReturn, (char *)pchEnvValue);
  1486. }
  1487. /*
  1488. * Advance the pointer for the next pass
  1489. */
  1490. if (chSave)
  1491. {
  1492. /* restore saved character */
  1493. *pchNext = chSave;
  1494. chSave = '\0';
  1495. /*
  1496. * If this was a closing paren, then skip it
  1497. */
  1498. if (bEatBreak)
  1499. {
  1500. chlen = mblen ((char *)pchNext, MB_CUR_MAX);
  1501. pchNext += chlen;
  1502. }
  1503. }
  1504. pchStart = pch = pchNext;
  1505. chlen = mblen ((char *)pch, MB_CUR_MAX);
  1506. /*
  1507. * We're already pointing at the next character
  1508. * to process, don't advance again!
  1509. */
  1510. bAlreadyAdvanced = True;
  1511. break;
  1512. default:
  1513. /* this character is not interesting */
  1514. break;
  1515. }
  1516. /*
  1517. * Move to the next character if we're not already
  1518. * there.
  1519. */
  1520. if (!bAlreadyAdvanced)
  1521. {
  1522. pch += chlen;
  1523. chlen = mblen ((char *)pch, MB_CUR_MAX);
  1524. }
  1525. }
  1526. else
  1527. {
  1528. pch += chlen;
  1529. chlen = mblen ((char *)pch, MB_CUR_MAX);
  1530. }
  1531. }
  1532. if (pchReturn && *pchStart)
  1533. {
  1534. /*
  1535. * Copy remaining parts of the string
  1536. */
  1537. strcat ((char *)pchReturn, (char *)pchStart);
  1538. }
  1539. return (pchReturn);
  1540. } /* END OF FUNCTION _DtWmParseExpandEnvironmentVariables */
  1541. /******************************<->*************************************
  1542. *
  1543. * _DtWmParseMakeQuotedString (pchLine)
  1544. *
  1545. *
  1546. * Description:
  1547. * -----------
  1548. * Encapsulates the passed in "line" into a string argument quoted
  1549. * by double quotes. Special characters are "escaped" as needed.
  1550. *
  1551. * Inputs:
  1552. * ------
  1553. * pchLine = ptr to string to enclose in quotes
  1554. *
  1555. * Outputs:
  1556. * -------
  1557. * Return = ptr to quoted string
  1558. *
  1559. * Comment:
  1560. * -------
  1561. * Returned string should be freed with XtFree().
  1562. *
  1563. ******************************<->***********************************/
  1564. unsigned char *
  1565. _DtWmParseMakeQuotedString (unsigned char *pchLine)
  1566. {
  1567. unsigned char *pchRet;
  1568. int iLen0, iLen1;
  1569. int cSpecial;
  1570. int i,j;
  1571. int chlen;
  1572. iLen0 = strlen ((char *)pchLine);
  1573. iLen1 = iLen0 + 2; /* for starting, ending quotes */
  1574. for (i=0; i < iLen0; i++)
  1575. {
  1576. /*
  1577. * Count special chars to get estimate of new length
  1578. */
  1579. chlen = mblen ((char *) &pchLine[i], MB_CUR_MAX);
  1580. if ((chlen == 1) &&
  1581. ((pchLine[i] == '\\') ||
  1582. (pchLine[i] == '"')))
  1583. {
  1584. iLen1++;
  1585. }
  1586. else if (chlen < 1)
  1587. {
  1588. break;
  1589. }
  1590. else
  1591. {
  1592. i += chlen-1;
  1593. }
  1594. }
  1595. pchRet = (unsigned char *) XtMalloc (1+iLen1);
  1596. if (pchRet)
  1597. {
  1598. pchRet[0] = '"'; /* starting quote */
  1599. /*
  1600. * Copy chars from old string to new one
  1601. */
  1602. for (i=0, j=1; i < iLen0; i++, j++)
  1603. {
  1604. chlen = mblen ((char *) &pchLine[i], MB_CUR_MAX);
  1605. if ((chlen == 1) &&
  1606. ((pchLine[i] == '\\') ||
  1607. (pchLine[i] == '"')))
  1608. {
  1609. /* quote next char */
  1610. pchRet[j++] = '\\';
  1611. }
  1612. else if (chlen < 1)
  1613. {
  1614. break;
  1615. }
  1616. else while (chlen > 1)
  1617. {
  1618. /* copy first bytes of multibyte char */
  1619. pchRet[j++] = pchLine[i++];
  1620. chlen--;
  1621. }
  1622. /* copy char */
  1623. pchRet[j] = pchLine[i];
  1624. }
  1625. pchRet[j++] = '"'; /* ending quote */
  1626. pchRet[j] = '\0'; /* end of string */
  1627. }
  1628. return (pchRet);
  1629. } /* END OF FUNCTION _DtWmParseMakeQuotedString */
  1630. /*==================== END OF FILE WmParse.c ====================*/