exksh_tbls.c 35 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201
  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 librararies 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. /* $XConsortium: exksh_tbls.c /main/4 1995/11/01 15:54:33 rswiston $ */
  24. /* Copyright (c) 1991, 1992 UNIX System Laboratories, Inc. */
  25. /* All Rights Reserved */
  26. /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF */
  27. /* UNIX System Laboratories, Inc. */
  28. /* The copyright notice above does not evidence any */
  29. /* actual or intended publication of such source code. */
  30. #include "name.h"
  31. #include "shell.h"
  32. #include "stdio.h"
  33. #include <string.h>
  34. #include <sys/types.h>
  35. #include <ctype.h>
  36. #include "exksh.h"
  37. #include "exksh_tbls.h"
  38. #include "exksh_prpar.h"
  39. #include "docall.h"
  40. #include "msgs.h"
  41. int _Delim;
  42. static int strglen;
  43. static int struct_size;
  44. int Pr_tmpnonames = 0;
  45. static const char *Str_close_curly = "}";
  46. static const char *Str_open_curly = "{";
  47. #define MALMEMBERS (4) /* initial number of members of malloc'ed array to malloc */
  48. #define UPPER(C) (islower(C) ? toupper(C) : (C))
  49. #define isvarchar(C) (isalnum(C) || ((C) == '_'))
  50. /*
  51. * Some of our test programs use xk_parse() to parse cdata from command
  52. * lines. This has the drawback that anys or externals will get a malloc'ed
  53. * buffer for their char * on the send side, which would not normally be
  54. * freed, because xk_free() knows that such any's usually point into the
  55. * ubuf rather than being malloced. On the receive side, this would be
  56. * true even in our test program. So, on the send side, we keep a table
  57. * of any any or external char * that is malloc'ed, and xk_free checks
  58. * this table before free'ing the given item. After being freed, the
  59. * stack is decremented for efficiency.
  60. */
  61. #define ANYTBLINC (4)
  62. static char **Anytbl = NULL;
  63. static int Nanytbl = 0;
  64. static int Maxanytbl = 0;
  65. struct special {
  66. char *name;
  67. int (*free)();
  68. int (*parse)();
  69. int (*print)();
  70. };
  71. #define SPEC_FREE 0
  72. #define SPEC_PARSE 1
  73. #define SPEC_PRINT 2
  74. static struct special *Special = NULL;
  75. static int Nspecs = 0;
  76. static char **Dont = NULL;
  77. static int Ndont, Sdont;
  78. int
  79. (*find_special(
  80. int type,
  81. char *name ))()
  82. {
  83. int i;
  84. if (!Special)
  85. return(NULL);
  86. for (i = 0; i < Nspecs; i++) {
  87. if (strcmp(Special[i].name, name) == 0) {
  88. switch(type) {
  89. case SPEC_PRINT:
  90. return(Special[i].print);
  91. case SPEC_FREE:
  92. return(Special[i].free);
  93. case SPEC_PARSE:
  94. return(Special[i].parse);
  95. }
  96. }
  97. }
  98. return(NULL);
  99. }
  100. int
  101. set_special(
  102. char *name,
  103. int (*free)(),
  104. int (*parse)(),
  105. int (*print)() )
  106. {
  107. int i;
  108. for (i = 0; i < Nspecs; i++)
  109. if (strcmp(Special[i].name, name) == 0)
  110. break;
  111. if (i == Nspecs) {
  112. if (!Special) {
  113. Special = (struct special *) malloc(sizeof(struct special));
  114. Special[0].name = strdup(name);
  115. Nspecs = 1;
  116. }
  117. else {
  118. Special = (struct special *) realloc(Special, (Nspecs + 1) * sizeof(struct special));
  119. Special[i].name = strdup(name);
  120. Nspecs++;
  121. }
  122. }
  123. if (!Special)
  124. return(FAIL);
  125. Special[i].free = free;
  126. Special[i].parse = parse;
  127. Special[i].print = print;
  128. return(SUCCESS);
  129. }
  130. /*
  131. * xk_parse: Takes a pointer to a structure member table, a pointer
  132. * to a buffer containing an ascii representation of the structure
  133. * represented by the table pointer, and the number of pointers saved
  134. * from previous recursive calls to this routine, and parses the
  135. * buf into p.
  136. *
  137. * Increments buf to the last point at which it read a character,
  138. * and returns SUCCESS or FAIL.
  139. */
  140. int
  141. xk_parse(
  142. memtbl_t *tbl,
  143. char **buf,
  144. char *p,
  145. int nptr,
  146. int sub,
  147. void *pass,
  148. memtbl_t *(*tbl_find)() )
  149. {
  150. memtbl_t *ntbl;
  151. register int i = 0;
  152. int skind, delim_type;
  153. long val = 0; /* used for choice selection */
  154. char *np;
  155. int delim = _Delim;
  156. int nmal; /* number of members malloc'ed arrays */
  157. char *pp;
  158. int (*spec_parse)();
  159. char * errmsg;
  160. if (tbl == NULL) {
  161. if (_Prdebug)
  162. {
  163. errmsg=strdup(GETMESSAGE(8,1,
  164. "xk_parse: A NULL 'type' table was specified\n"));
  165. fprintf(stderr, errmsg);
  166. free(errmsg);
  167. }
  168. return(FAIL);
  169. }
  170. xk_skipwhite(buf);
  171. /*
  172. * If this is supposed to be a pointer, and we have a string that
  173. * starts with "P" and a number then we should take the pointer
  174. * itself. This is done by stripping off the 'p' and parsing it as a
  175. * unsigned long.
  176. *
  177. * Further, if it starts with an '&', then we want the address of
  178. * a variable, use fsym() to find it.
  179. */
  180. if (((tbl->flags & F_TYPE_IS_PTR) || ((tbl->ptr + nptr) > 0)) &&
  181. (((UPPER((*buf)[0]) == 'P') && isdigit((*buf)[1])) || ((*buf)[0] == '&'))) {
  182. if ((*buf)[0] == '&') {
  183. char *start;
  184. (*buf)++;
  185. for (start = *buf; isvarchar(*buf[0]); (*buf)++)
  186. ;
  187. if ((((unsigned long *) p)[0] = fsym(start, -1)) == NULL)
  188. return(FAIL);
  189. }
  190. else {
  191. (*buf)++;
  192. RIF(xk_par_int(buf, (long *)p, pass));
  193. }
  194. if (Ndont == Sdont) {
  195. if (Dont)
  196. Dont = (char **) realloc(Dont, (Sdont + 20) * sizeof(char *));
  197. else
  198. Dont = (char **) malloc((Sdont + 20) * sizeof(char *));
  199. if (!Dont) {
  200. errmsg = strdup(GetSharedMsg(DT_ALLOC_FAILURE));
  201. ALTPUTS(errmsg);
  202. free(errmsg);
  203. exit(1);
  204. }
  205. Sdont += 20;
  206. }
  207. Dont[Ndont++] = ((char **) p)[0];
  208. return(SUCCESS);
  209. }
  210. if (tbl->tname && (spec_parse = find_special(SPEC_PARSE, tbl->tname)))
  211. return(spec_parse(tbl, buf, p, nptr, sub, pass, tbl_find));
  212. if (tbl->name && (spec_parse = find_special(SPEC_PARSE, tbl->name)))
  213. return(spec_parse(tbl, buf, p, nptr, sub, pass, tbl_find));
  214. nptr += tbl->ptr;
  215. if (sub > 0 && tbl->subscr > 0) {
  216. if (_Prdebug)
  217. {
  218. errmsg=strdup(GETMESSAGE(8,2,
  219. "xk_parse: Multiple array subscripts are not handled in '%s'\n"));
  220. fprintf(stderr, errmsg, tbl->name);
  221. free(errmsg);
  222. }
  223. return(FAIL);
  224. }
  225. /*
  226. * If there is exactly one pointer associated with this
  227. * member, and no length delimiters, and no subscripts,
  228. * or there are multiple pointers,
  229. * then malloc space for the structure and call ourself
  230. * recursively.
  231. */
  232. if ((nptr > 1 && tbl->delim != 0) || (nptr == 1 && tbl->delim == 0 && tbl->subscr == 0)) {
  233. if (PARPEEK(buf, ",") || PARPEEK(buf, Str_close_curly)) {
  234. ((char **)p)[0] = NULL;
  235. if (_Prdebug)
  236. {
  237. errmsg=strdup(GetSharedMsg(DT_XK_PARSE_SET_NULL));
  238. fprintf(stderr, errmsg, tbl->name);
  239. free(errmsg);
  240. }
  241. return(SUCCESS);
  242. }
  243. if (xk_parpeek(buf, "NULL")) {
  244. RIF(xk_parexpect(buf, "NULL"));
  245. ((char **)p)[0] = NULL;
  246. if (_Prdebug)
  247. {
  248. errmsg=strdup(GetSharedMsg(
  249. DT_XK_PARSE_SET_NULL));
  250. fprintf(stderr, errmsg, tbl->name);
  251. free(errmsg);
  252. }
  253. return(SUCCESS);
  254. }
  255. if ((((char **)p)[0] = malloc(tbl->size)) == NULL) {
  256. return(FAIL);
  257. }
  258. if (_Prdebug)
  259. {
  260. errmsg=strdup(GETMESSAGE(8,3,
  261. "xk_parse: Setting '%s' to malloc'ed address 0x%x, of size %d\n"));
  262. fprintf(stderr,errmsg,tbl->name, ((char **)p)[0], tbl->size);
  263. free(errmsg);
  264. }
  265. return(xk_parse(tbl, buf, ((char **)p)[0], nptr-1-tbl->ptr, sub, pass, tbl_find));
  266. }
  267. /*
  268. * If there is exactly one pointer level, or one subscripting level,
  269. * and there is a delimiter,
  270. * and no subscript, then we are a length delimited malloced array.
  271. */
  272. xk_skipwhite(buf);
  273. if (tbl->delim != 0 && ((nptr == 1 && tbl->subscr == 0) ||
  274. (nptr == 0 && tbl->subscr != 0 && tbl->kind != K_STRING))) {
  275. if (tbl->subscr == 0) {
  276. if (PARPEEK(buf, ",") || PARPEEK(buf, Str_close_curly)) {
  277. ((char **)p)[0] = NULL;
  278. if (_Prdebug)
  279. {
  280. errmsg=strdup(GETMESSAGE(8,4,
  281. "xk_parse: Setting malloc'ed array '%s' to NULL\n"));
  282. fprintf(stderr, errmsg, tbl->name);
  283. free(errmsg);
  284. }
  285. return(SUCCESS);
  286. }
  287. if (xk_parpeek(buf, "NULL")) {
  288. RIF(xk_parexpect(buf, "NULL"));
  289. ((char **)p)[0] = NULL;
  290. if (_Prdebug)
  291. {
  292. errmsg=strdup(GetSharedMsg(
  293. DT_XK_PARSE_SET_NULL));
  294. fprintf(stderr, errmsg, tbl->name);
  295. free(errmsg);
  296. }
  297. return(SUCCESS);
  298. }
  299. nmal = MALMEMBERS;
  300. if ((np = malloc(nmal*tbl->size)) == NULL) {
  301. return(FAIL);
  302. }
  303. ((char **)p)[0] = np;
  304. if (_Prdebug)
  305. {
  306. errmsg=strdup(GETMESSAGE(8,5,
  307. "xk_parse: Setting member '%s' to malloc'ed pointer 0x%x, of size %d\n"));
  308. fprintf(stderr, errmsg, tbl->name, np, 4*tbl->size);
  309. free(errmsg);
  310. }
  311. } else {
  312. np = p;
  313. }
  314. xk_skipwhite(buf);
  315. RIF(PAREXPECT(buf, Str_open_curly));
  316. *buf += 1;
  317. i = 0;
  318. xk_skipwhite(buf);
  319. while (PARPEEK(buf, Str_close_curly) == FALSE) {
  320. if (tbl->subscr == 0 && i >= nmal) {
  321. nmal += MALMEMBERS;
  322. if((np = realloc(np, nmal*tbl->size)) == NULL) {
  323. return(FAIL);
  324. }
  325. ((char **)p)[0] = np;
  326. if (_Prdebug) {
  327. errmsg=strdup(GetSharedMsg(
  328. DT_XK_PARSE_ARRAY_OVERFLOW));
  329. fprintf(stderr, errmsg, tbl->name, nmal, nmal*tbl->size);
  330. free(errmsg);
  331. }
  332. } else if (tbl->subscr > 0 && i > tbl->subscr) {
  333. if (_Prdebug)
  334. {
  335. errmsg=strdup(GETMESSAGE(8,6,
  336. "xk_parse: The array '%s' overflowed at element number %d\n"));
  337. fprintf(stderr, errmsg, tbl->name, i);
  338. free(errmsg);
  339. }
  340. }
  341. if (_Prdebug)
  342. {
  343. errmsg=strdup(GETMESSAGE(8,7,
  344. "xk_parse: Parsing array element [%d] of '%s' into address 0x%x\n"));
  345. fprintf(stderr, errmsg, i, tbl->name, &np[i*tbl->size]);
  346. free(errmsg);
  347. }
  348. if (i) {
  349. xk_skipwhite(buf);
  350. if (PARPEEK(buf, ",") == FALSE) {
  351. if (PARPEEK(buf, Str_close_curly) == FALSE) {
  352. RIF(PAREXPECT(buf, ","));
  353. *buf += 1;
  354. }
  355. }
  356. else {
  357. RIF(PAREXPECT(buf, ","));
  358. *buf += 1;
  359. }
  360. }
  361. RIF(xk_parse(tbl, buf, &np[i*tbl->size], nptr ? -1 : 0,
  362. 0, (void *)-1, tbl_find));
  363. i++;
  364. struct_size = i;
  365. xk_skipwhite(buf);
  366. }
  367. RIF(PAREXPECT(buf, Str_close_curly));
  368. *buf += 1;
  369. return(SUCCESS);
  370. }
  371. /*
  372. * If there is no delimiter, and there are two levels of pointer,
  373. * then we are a NULL terminated array of pointers
  374. */
  375. if (tbl->delim == 0 &&
  376. ((nptr == 2 && sub == 0) || (sub == 1 && nptr == 1))) {
  377. /*
  378. * malloc a few members, realloc as needed
  379. */
  380. nmal = MALMEMBERS;
  381. if ((((char **)p)[0] = malloc(nmal*tbl->size)) == NULL) {
  382. return(FAIL);
  383. }
  384. xk_skipwhite(buf);
  385. RIF(PAREXPECT(buf, Str_open_curly));
  386. *buf += 1;
  387. xk_skipwhite(buf);
  388. while (PARPEEK(buf, Str_close_curly) == FALSE) {
  389. if (i >= nmal) {
  390. nmal += MALMEMBERS;
  391. if ((((char **)p)[0] = realloc(((char **)p)[0], nmal*tbl->size)) == NULL) {
  392. return(FAIL);
  393. }
  394. if (_Prdebug) {
  395. errmsg=strdup(GetSharedMsg(
  396. DT_XK_PARSE_ARRAY_OVERFLOW));
  397. fprintf(stderr, errmsg, tbl->name, nmal, nmal*tbl->size);
  398. free(errmsg);
  399. }
  400. }
  401. if (_Prdebug)
  402. {
  403. errmsg=strdup(GETMESSAGE(8,8,
  404. "xk_parse: Parsing array element [%d] of '%s'\n"));
  405. fprintf(stderr, errmsg, i, tbl->name);
  406. free(errmsg);
  407. }
  408. if (i) {
  409. RIF(PAREXPECT(buf, ","));
  410. *buf += 1;
  411. }
  412. RIF(xk_parse(tbl, buf, &p[i*tbl->size],
  413. nptr == 2 ? -2 : -1, 0, (void *)-1,
  414. tbl_find));
  415. xk_skipwhite(buf);
  416. }
  417. RIF(PAREXPECT(buf, Str_close_curly));
  418. *buf++;
  419. ((char **)p)[i*tbl->size] = NULL;
  420. return(SUCCESS);
  421. }
  422. switch(tbl->kind) {
  423. case K_CHAR:
  424. RIF(xk_par_int(buf, &val, pass));
  425. ((unsigned char *)p)[0] = val;
  426. break;
  427. case K_SHORT:
  428. RIF(xk_par_int(buf, &val, pass));
  429. ((ushort *)p)[0] = val;
  430. break;
  431. case K_INT:
  432. RIF(xk_par_int(buf, &val, pass));
  433. ((int *)p)[0] = val;
  434. break;
  435. case K_LONG:
  436. RIF(xk_par_int(buf, (long *)p, pass));
  437. break;
  438. case K_STRING:
  439. if (tbl->subscr) {
  440. val = tbl->subscr;
  441. RIF(xk_par_chararr(buf, (char *)p, (int *)&val));
  442. if (tbl->delim <= 0 && val > -1) {
  443. p[val] = '\0';
  444. }
  445. } else {
  446. val = 0;
  447. RIF(xk_par_charstr(buf, (char **)p, (int *)&val));
  448. /* If this is not a delimited char string,
  449. * then it must be null terminated
  450. */
  451. if (tbl->delim <= 0 && val > -1) {
  452. ((char **) p)[0][val] = '\0';
  453. }
  454. strglen = val;
  455. }
  456. break;
  457. case K_TYPEDEF:
  458. ntbl = tbl_find(tbl->tname, tbl->tbl, tbl->id);
  459. RIF(xk_parse(ntbl, buf, p, nptr, 0, pass, tbl_find));
  460. return(SUCCESS);
  461. case K_STRUCT:
  462. xk_skipwhite(buf);
  463. RIF(PAREXPECT(buf, Str_open_curly));
  464. *buf += 1;
  465. ntbl = tbl_find(tbl->tname, tbl->tbl, tbl->id);
  466. pp = NULL;
  467. for (i = 0; ntbl[i].name != NULL; i++) {
  468. _Delim = xk_get_pardelim(&ntbl[i], p);
  469. if (ntbl[i].kind >= K_DSHORT) {
  470. skind = ntbl[i].kind;
  471. pp = p + ntbl[i].offset;
  472. struct_size = 0;
  473. }
  474. if (ntbl[i].delim) {
  475. delim_type = ntbl[i].kind;
  476. }
  477. if (i && ntbl[i-1].kind < K_DSHORT) {
  478. xk_skipwhite(buf);
  479. if (PARPEEK(buf, ",") == FALSE) {
  480. if (PARPEEK(buf, Str_close_curly) == FALSE) {
  481. RIF(PAREXPECT(buf, ","));
  482. *buf += 1;
  483. }
  484. }
  485. else {
  486. RIF(PAREXPECT(buf, ","));
  487. *buf += 1;
  488. }
  489. }
  490. if (_Prdebug)
  491. {
  492. errmsg=strdup(GETMESSAGE(8,9,
  493. "xk_parse: Parsing member '%s' into location 0x%x\n"));
  494. fprintf(stderr, errmsg, ntbl[i].name, p + ntbl[i].offset);
  495. free(errmsg);
  496. }
  497. if (xk_parse(&ntbl[i], buf, p+ntbl[i].offset, nptr, sub, pass, tbl_find) == FAIL) {
  498. if (_Prdebug)
  499. {
  500. errmsg=strdup(GetSharedMsg(
  501. DT_XK_PARSE_ERROR));
  502. fprintf(stderr, errmsg, ntbl[i].name);
  503. free(errmsg);
  504. }
  505. return(FAIL);
  506. }
  507. }
  508. if (pp != NULL) {
  509. switch(skind) {
  510. case K_DSHORT:
  511. if (delim_type == K_STRING)
  512. ((short *)pp)[0] = strglen;
  513. else
  514. ((short *)pp)[0] = struct_size;
  515. break;
  516. case K_DINT:
  517. if (delim_type == K_STRING)
  518. ((int *)pp)[0] = strglen;
  519. else
  520. ((int *)pp)[0] = struct_size;
  521. break;
  522. case K_DLONG:
  523. if (delim_type == K_STRING)
  524. ((long *)pp)[0] = strglen;
  525. else
  526. ((long *)pp)[0] = struct_size;
  527. break;
  528. default:
  529. break;
  530. }
  531. }
  532. xk_skipwhite(buf);
  533. RIF(PAREXPECT(buf, Str_close_curly));
  534. *buf += 1;
  535. break;
  536. case K_UNION:
  537. if (strncmp(tbl[-1].name, "ch_", 3) != 0) {
  538. if (_Prdebug)
  539. {
  540. errmsg=strdup(GETMESSAGE(8,10,
  541. "xk_parse: Cannot determine the choice in '%s'\n"));
  542. fprintf(stderr, errmsg, tbl->name);
  543. free(errmsg);
  544. }
  545. return(FAIL);
  546. }
  547. ntbl = tbl_find(tbl->tname, tbl->tbl, tbl->id);
  548. xk_skipwhite(buf);
  549. RIF(PAREXPECT(buf, Str_open_curly));
  550. *buf += 1;
  551. for (i = 0; ntbl[i].name != NULL; i++) {
  552. if (xk_parpeek(buf, ntbl[i].name) == TRUE) {
  553. RIF(xk_parexpect(buf, ntbl[i].name));
  554. ((long *)(p - sizeof(long)))[0] = ntbl[i].choice;
  555. if (_Prdebug)
  556. {
  557. errmsg=strdup(GETMESSAGE(8,11,
  558. "xk_parse: Parsing union member '%s' into location 0x%x\n"));
  559. fprintf(stderr, errmsg, ntbl[i].name, p + ntbl[i].offset);
  560. free(errmsg);
  561. }
  562. if (xk_parse(&ntbl[i], buf, p, nptr, sub, pass, tbl_find) == FAIL) {
  563. if (_Prdebug)
  564. {
  565. errmsg=strdup(GetSharedMsg(
  566. DT_XK_PARSE_ERROR));
  567. fprintf(stderr, errmsg, ntbl[i].name);
  568. free(errmsg);
  569. }
  570. return(FAIL);
  571. }
  572. break;
  573. }
  574. }
  575. xk_skipwhite(buf);
  576. RIF(PAREXPECT(buf, Str_close_curly));
  577. *buf += 1;
  578. break;
  579. case K_DSHORT:
  580. case K_DINT:
  581. case K_DLONG:
  582. break;
  583. default:
  584. return(FAIL);
  585. }
  586. return(SUCCESS);
  587. }
  588. int
  589. xk_get_delim(
  590. memtbl_t *tbl,
  591. char *p )
  592. {
  593. memtbl_t *dtbl = &tbl[tbl->delim];
  594. char * errmsg;
  595. if (tbl->delim == 0) {
  596. return(-1);
  597. }
  598. if (_Prdebug)
  599. {
  600. errmsg=strdup(GETMESSAGE(8,12,
  601. "xk_get_delim: The delimiter for field '%s' is field '%s'\n"));
  602. fprintf(stderr, errmsg, tbl->name, dtbl->name);
  603. free(errmsg);
  604. }
  605. p += dtbl->offset;
  606. switch (dtbl->kind) {
  607. case K_DLONG:
  608. case K_LONG:
  609. return(((long *)p)[0]);
  610. case K_CHAR:
  611. return(((char *)p)[0]);
  612. case K_DSHORT:
  613. case K_SHORT:
  614. return(((short *)p)[0]);
  615. case K_DINT:
  616. case K_INT:
  617. return(((int *)p)[0]);
  618. default:
  619. if (_Prdebug)
  620. {
  621. errmsg=strdup(GETMESSAGE(8,13,
  622. "xk_get_delim: Cannot find a delimiter value in '%s'\n"));
  623. fprintf(stderr, errmsg, tbl->name);
  624. free(errmsg);
  625. }
  626. return(0);
  627. }
  628. }
  629. int
  630. xk_get_pardelim(
  631. memtbl_t *tbl,
  632. char *p )
  633. {
  634. memtbl_t *dtbl = &tbl[tbl->delim];
  635. char * errmsg;
  636. if (tbl->delim == 0) {
  637. return(-1);
  638. }
  639. if (_Prdebug)
  640. {
  641. errmsg=strdup(GETMESSAGE(8,14,
  642. "xk_get_pardelim: The delimiter for field '%s' is field '%s'\n"));
  643. fprintf(stderr, errmsg, tbl->name, dtbl->name);
  644. free(errmsg);
  645. }
  646. p += dtbl->offset;
  647. switch (dtbl->kind) {
  648. case K_DLONG:
  649. return(-1);
  650. case K_LONG:
  651. return(((long *)p)[0]);
  652. case K_DSHORT:
  653. return(-1);
  654. case K_CHAR:
  655. return(((char *)p)[0]);
  656. case K_SHORT:
  657. return(((short *)p)[0]);
  658. case K_DINT:
  659. return(-1);
  660. case K_INT:
  661. return(((int *)p)[0]);
  662. default:
  663. if (_Prdebug)
  664. {
  665. errmsg=strdup(GETMESSAGE(8,15,
  666. "xk_get_pardelim: Cannot find a delimiter value in '%s'\n"));
  667. fprintf(stderr, errmsg, tbl->name);
  668. free(errmsg);
  669. }
  670. return(0);
  671. }
  672. }
  673. /*
  674. * xk_print: Takes a pointer to a structure member table, a pointer
  675. * to a buffer big enough to hold an ascii representation of the structure
  676. * represented by the table pointer, and a pointer to a structure to
  677. * be filled in, and the number of pointers saved
  678. * from previous recursive calls to this routine, and prints the
  679. * buf into p.
  680. *
  681. * Increments buf to the last point at which it wrote a character,
  682. * and returns SUCCESS or FAIL.
  683. */
  684. int
  685. xk_print(
  686. memtbl_t *tbl,
  687. char **buf,
  688. char *p,
  689. int nptr,
  690. int sub,
  691. void *pass,
  692. memtbl_t *(*tbl_find)() )
  693. {
  694. memtbl_t *ntbl;
  695. register int i;
  696. long val; /* used for choice selection */
  697. char *np;
  698. int delim = _Delim;
  699. int (*spec_print)();
  700. char * errmsg;
  701. if (p == NULL) {
  702. *buf += lsprintf(*buf, "NULL");
  703. return(SUCCESS);
  704. }
  705. if (tbl == NULL) {
  706. if (_Prdebug)
  707. {
  708. errmsg=strdup(GETMESSAGE(8,16,
  709. "xk_print: A NULL 'type' table was specified\n"));
  710. fprintf(stderr, errmsg);
  711. free(errmsg);
  712. }
  713. return(FAIL);
  714. }
  715. if (tbl->tname && (spec_print = find_special(SPEC_PRINT, tbl->tname)))
  716. return(spec_print(tbl, buf, p, nptr, sub, pass, tbl_find));
  717. if (tbl->name && (spec_print = find_special(SPEC_PRINT, tbl->name)))
  718. return(spec_print(tbl, buf, p, nptr, sub, pass, tbl_find));
  719. nptr += tbl->ptr;
  720. if (sub > 0 && tbl->subscr > 0) {
  721. if (_Prdebug)
  722. {
  723. errmsg=strdup(GETMESSAGE(8,17,
  724. "xk_print: Multiple array subscripts are not handled in '%s'\n"));
  725. fprintf(stderr, errmsg, tbl->name);
  726. free(errmsg);
  727. }
  728. return(FAIL);
  729. }
  730. /*
  731. * If there is exactly one pointer associated with this
  732. * member, and no length delimiters, and no subscripts,
  733. * or there are multiple pointers,
  734. * then dereference the structure and call ourself
  735. * recursively.
  736. */
  737. if ((nptr > 1 && tbl->delim != 0) || (nptr == 1 && tbl->delim == 0 && tbl->subscr == 0)) {
  738. if (_Prdebug)
  739. {
  740. errmsg=strdup(GETMESSAGE(8,18,
  741. "xk_print: Dereferencing '%s' to address 0x%x\n"));
  742. fprintf(stderr, errmsg, tbl->name, ((char **)p)[0]);
  743. free(errmsg);
  744. }
  745. return(xk_print(tbl, buf, ((char **)p)[0], nptr-1-tbl->ptr, sub, pass, tbl_find));
  746. }
  747. /*
  748. * If there is exactly one pointer level, or one subscripting level,
  749. * and there is a delimiter,
  750. * and no subscript, then we are a length delimited array.
  751. */
  752. if (tbl->delim != 0 && ((nptr == 1 && tbl->subscr == 0) ||
  753. nptr == 0 && tbl->subscr != 0 && tbl->kind != K_STRING)) {
  754. if (_Prdebug)
  755. {
  756. errmsg=strdup(GETMESSAGE(8,19,
  757. "xk_print: The delimiter for '%s' is %d\n"));
  758. fprintf(stderr, errmsg, tbl->name, delim);
  759. free(errmsg);
  760. }
  761. if (tbl->subscr == 0) {
  762. np = ((char **)p)[0];
  763. if (_Prdebug)
  764. {
  765. errmsg=strdup(GETMESSAGE(8,20,
  766. "xk_print: Using the pointer 0x%x as an array\n"));
  767. fprintf(stderr, errmsg, np);
  768. free(errmsg);
  769. }
  770. } else {
  771. np = p;
  772. }
  773. if (np == NULL) {
  774. *buf += lsprintf(*buf, "NULL");
  775. return(SUCCESS);
  776. }
  777. *buf += lsprintf(*buf, Str_open_curly);
  778. for (i = 0; i < delim; i++) {
  779. if (_Prdebug)
  780. {
  781. errmsg=strdup(GETMESSAGE(8,21,
  782. "xk_print: Printing array level %d of member '%s' at location 0x%x\n"));
  783. fprintf(stderr, errmsg, i, tbl->name, &np[i*tbl->size]);
  784. free(errmsg);
  785. }
  786. if (i)
  787. *buf += lsprintf(*buf, ", ");
  788. RIF(xk_print(tbl, buf, &np[i*tbl->size], nptr ? -1 : 0,
  789. 0, (void *)-1, tbl_find));
  790. }
  791. *buf += lsprintf(*buf, Str_close_curly);
  792. return(SUCCESS);
  793. }
  794. /*
  795. * If there is no delimiter, and there are two levels of pointer,
  796. * then we are a NULL terminated array.
  797. */
  798. if (tbl->delim == 0 &&
  799. ((nptr == 2 && sub == 0) || (sub == 1 && nptr == 1))) {
  800. *buf += lsprintf(*buf, Str_open_curly);
  801. for (i = 0; ((char **)p)[i*tbl->size] != NULL; i++) {
  802. if (i)
  803. *buf += lsprintf(*buf, ", ");
  804. if (_Prdebug)
  805. {
  806. errmsg=strdup(GETMESSAGE(8,22,
  807. "xk_print: Printing array level %d of member '%s'\n"));
  808. fprintf(stderr, errmsg, i, tbl->name);
  809. free(errmsg);
  810. }
  811. RIF(xk_print(tbl, buf, ((char **)p)[i*tbl->size],
  812. nptr-(!sub), 0, (void *)-1, tbl_find));
  813. }
  814. *buf += lsprintf(*buf, Str_close_curly);
  815. return(SUCCESS);
  816. }
  817. if (!Pr_tmpnonames && (Pr_format & PRNAMES)) {
  818. switch(tbl->kind) {
  819. case K_CHAR:
  820. case K_SHORT:
  821. case K_INT:
  822. case K_LONG:
  823. case K_STRING:
  824. *buf += lsprintf(*buf, "%s=", tbl->name);
  825. }
  826. }
  827. switch(tbl->kind) {
  828. case K_CHAR:
  829. case K_SHORT:
  830. case K_INT:
  831. case K_LONG:
  832. RIF(xk_prin_int(tbl, buf, (unsigned long *)p));
  833. break;
  834. case K_STRING:
  835. if (delim > 0) {
  836. if (tbl->subscr) {
  837. RIF(xk_prin_hexstr(buf, (char *)p, delim));
  838. } else {
  839. RIF(xk_prin_hexstr(buf, ((char **)p)[0], delim));
  840. }
  841. } else {
  842. if (tbl->subscr) {
  843. RIF(xk_prin_nts(buf, (char *)p));
  844. } else {
  845. RIF(xk_prin_nts(buf, ((char **)p)[0]));
  846. }
  847. }
  848. break;
  849. case K_TYPEDEF:
  850. ntbl = tbl_find(tbl->tname, tbl->tbl, tbl->id);
  851. return(xk_print(ntbl, buf, p, nptr, 0, pass, tbl_find));
  852. case K_STRUCT:
  853. *buf += lsprintf(*buf, Str_open_curly);
  854. ntbl = tbl_find(tbl->tname, tbl->tbl, tbl->id);
  855. for (i = 0; ntbl[i].name != NULL; i++) {
  856. _Delim = xk_get_delim(&ntbl[i], p);
  857. if (_Prdebug)
  858. {
  859. errmsg=strdup(GETMESSAGE(8,23,
  860. "xk_print: Printing member '%s' at location 0x%x\n"));
  861. fprintf(stderr, errmsg, ntbl[i].name, p+ntbl[i].offset);
  862. free(errmsg);
  863. }
  864. RIF(xk_print(&ntbl[i], buf, p+ntbl[i].offset, nptr, sub, pass, tbl_find));
  865. if (ntbl[i].kind < K_DSHORT && ntbl[i+1].name != NULL)
  866. *buf += lsprintf(*buf, ", ");
  867. }
  868. *buf += lsprintf(*buf, Str_close_curly);
  869. break;
  870. case K_UNION:
  871. if (strncmp(tbl[-1].name, "ch_", 3) != 0) {
  872. if (_Prdebug)
  873. {
  874. errmsg=strdup(GETMESSAGE(8,24,
  875. "xk_print: Cannot determine the choice in '%s'\n"));
  876. fprintf(stderr, errmsg, tbl->name);
  877. free(errmsg);
  878. }
  879. return(FAIL);
  880. }
  881. val = *((long *)(p - sizeof(long)));
  882. ntbl = tbl_find(tbl->tname, tbl->tbl, tbl->id);
  883. *buf += lsprintf(*buf, Str_open_curly);
  884. for (i = 0; ntbl[i].name != NULL; i++) {
  885. if (ntbl[i].choice == val) {
  886. *buf += lsprintf(*buf, "%s ", ntbl[i].name);
  887. if (_Prdebug)
  888. {
  889. errmsg=strdup(GETMESSAGE(8,25,
  890. "xk_print: Printing union member '%s' into location 0x%x\n"));
  891. fprintf(stderr, errmsg, ntbl[i].name, p + ntbl[i].offset);
  892. free(errmsg);
  893. }
  894. RIF(xk_print(&ntbl[i], buf, p, nptr, sub, pass, tbl_find));
  895. break;
  896. }
  897. }
  898. *buf += lsprintf(*buf, Str_close_curly);
  899. break;
  900. case K_DSHORT:
  901. case K_DINT:
  902. case K_DLONG:
  903. break;
  904. default:
  905. return(FAIL);
  906. }
  907. return(SUCCESS);
  908. }
  909. /*
  910. * xk_free: Takes a pointer to a structure member table, and
  911. * free any malloc'ec elements in it at all levels.
  912. * Returns SUCCESS or FAIL.
  913. *
  914. * Contains an optimization that if a structure or union contains a
  915. * type that is a simple type and nptr is zero, does not do a recursive call.
  916. */
  917. int
  918. xk_free(
  919. memtbl_t *tbl,
  920. char *p,
  921. int nptr,
  922. int sub,
  923. memtbl_t *(*tbl_find)() )
  924. {
  925. memtbl_t *ntbl;
  926. register int i;
  927. long val; /* used for choice selection */
  928. char *np;
  929. int delim = _Delim;
  930. int (*spec_free)();
  931. char * errmsg;
  932. if (tbl == NULL) {
  933. if (_Prdebug)
  934. {
  935. errmsg=strdup(GETMESSAGE(8,26,
  936. "xk_free: A NULL 'type' table was specified\n"));
  937. fprintf(stderr, errmsg);
  938. free(errmsg);
  939. }
  940. return(FAIL);
  941. }
  942. if (tbl->tname && (spec_free = find_special(SPEC_FREE, tbl->tname)))
  943. return(spec_free(tbl, p, nptr, sub, tbl_find));
  944. if (tbl->name && (spec_free = find_special(SPEC_FREE, tbl->name)))
  945. return(spec_free(tbl, p, nptr, sub, tbl_find));
  946. nptr += tbl->ptr;
  947. if ((tbl->flags & F_TYPE_IS_PTR) || (nptr > 0)) {
  948. for (i = Ndont - 1; i >= 0; i--) {
  949. if (Dont[i] == ((char **) p)[0]) {
  950. for ( ; i < Ndont - 1; i++)
  951. Dont[i] = Dont[i + 1];
  952. Ndont--;
  953. return(SUCCESS);
  954. }
  955. }
  956. }
  957. if (sub > 0 && tbl->subscr > 0) {
  958. if (_Prdebug)
  959. {
  960. errmsg=strdup(GETMESSAGE(8,27,
  961. "xk_free: Multiple array subscripts are not handled in '%s'\n"));
  962. fprintf(stderr, errmsg, tbl->name);
  963. free(errmsg);
  964. }
  965. return(FAIL);
  966. }
  967. /*
  968. * If there is exactly one pointer associated with this
  969. * member, and no length delimiters, and no subscripts,
  970. * or there are multiple pointers,
  971. * then recursively call ourselves on the structure, then
  972. * free the structure itself.
  973. */
  974. if ((nptr > 1 && tbl->delim != 0) || (nptr == 1 && tbl->delim == 0 && tbl->subscr == 0)) {
  975. if (((char **)p)[0] != NULL) {
  976. RIF(xk_free(tbl, ((char **)p)[0], nptr-1-tbl->ptr, sub, tbl_find));
  977. free(((char **)p)[0]);
  978. if (_Prdebug)
  979. {
  980. errmsg=strdup(GETMESSAGE(8,28,
  981. "xk_free: The member '%s' at location 0x%x was freed and set to NULL\n"));
  982. fprintf(stderr, errmsg, tbl->name, ((char **)p)[0]);
  983. free(errmsg);
  984. }
  985. ((char **)p)[0] = NULL;
  986. } else {
  987. if (_Prdebug)
  988. {
  989. errmsg=strdup(GETMESSAGE(8,29,
  990. "xk_free: The member '%s' is NULL; no free occurred\n"));
  991. fprintf(stderr, errmsg, tbl->name);
  992. free(errmsg);
  993. }
  994. }
  995. return(SUCCESS);
  996. }
  997. /*
  998. * If there is exactly one pointer level, or one subscripting level,
  999. * and there is a delimiter,
  1000. * and no subscript, then we are a length delimited malloced array.
  1001. * Free each element, then free the whole array.
  1002. */
  1003. if (tbl->delim != 0 && ((nptr == 1 && tbl->subscr == 0) ||
  1004. nptr == 0 && tbl->subscr != 0 && tbl->kind != K_STRING)) {
  1005. if (_Prdebug)
  1006. {
  1007. errmsg=strdup(GETMESSAGE(8,30,
  1008. "xk_free: The delimiter for '%s' is %d\n"));
  1009. fprintf(stderr, errmsg, tbl->name, delim);
  1010. free(errmsg);
  1011. }
  1012. if (tbl->subscr == 0)
  1013. np = ((char **)p)[0];
  1014. else
  1015. np = p;
  1016. for (i = 0; i < delim; i++) {
  1017. if (_Prdebug)
  1018. {
  1019. errmsg=strdup(GETMESSAGE(8,31,
  1020. "xk_free: Freeing array element [%d] of '%s' at address 0x%x\n"));
  1021. fprintf(stderr, errmsg, i, tbl->name, &np[i*tbl->size]);
  1022. free(errmsg);
  1023. }
  1024. RIF(xk_free(tbl, &np[i*tbl->size], nptr ? -1 : 0, 0, tbl_find));
  1025. }
  1026. if (tbl->subscr == 0) {
  1027. if (np != NULL) {
  1028. if (_Prdebug)
  1029. {
  1030. errmsg=strdup(GETMESSAGE(8,32,
  1031. "xk_free: Freeing pointer to array of '%s' at location 0x%x and setting to NULL\n"));
  1032. fprintf(stderr, errmsg, tbl->name, np);
  1033. free(errmsg);
  1034. }
  1035. free(np);
  1036. if (tbl->subscr == 0)
  1037. ((char **)p)[0] = NULL;
  1038. } else if (_Prdebug) {
  1039. errmsg=strdup(GETMESSAGE(8,33,
  1040. "xk_free: The pointer to array of '%s'is NULL; no free occurred\n"));
  1041. fprintf(stderr, errmsg, tbl->name);
  1042. free(errmsg);
  1043. }
  1044. }
  1045. return(SUCCESS);
  1046. }
  1047. switch(tbl->kind) {
  1048. case K_DSHORT:
  1049. case K_SHORT:
  1050. case K_DINT:
  1051. case K_INT:
  1052. case K_DLONG:
  1053. case K_LONG:
  1054. break;
  1055. case K_STRING:
  1056. if (!tbl->subscr) {
  1057. if (((char **)p)[0] != NULL) {
  1058. if (_Prdebug)
  1059. {
  1060. errmsg=strdup(GETMESSAGE(8,34,
  1061. "xk_free: Freeing string '%s' at location 0x%x, and setting to NULL\n"));
  1062. fprintf(stderr, errmsg, tbl->name, p);
  1063. free(errmsg);
  1064. }
  1065. free(((char **)p)[0]);
  1066. ((char **)p)[0] = NULL;
  1067. } else if (_Prdebug) {
  1068. errmsg=strdup(GETMESSAGE(8,35,
  1069. "xk_free: The string '%s' is NULL; no free occurred\n"));
  1070. fprintf(stderr, errmsg, tbl->name, p);
  1071. free(errmsg);
  1072. }
  1073. }
  1074. break;
  1075. case K_TYPEDEF:
  1076. ntbl = tbl_find(tbl->tname, tbl->tbl, tbl->id);
  1077. return(xk_free(ntbl, p, nptr, 0, tbl_find));
  1078. case K_STRUCT:
  1079. ntbl = tbl_find(tbl->tname, tbl->tbl, tbl->id);
  1080. for (i = 0; ntbl[i].name != NULL; i++) {
  1081. if ((ntbl[i].flags & F_SIMPLE) && nptr+ntbl[i].ptr == 0) {
  1082. if (_Prdebug)
  1083. {
  1084. errmsg=strdup(GetSharedMsg(
  1085. DT_XK_FREE_NO_MEMBER));
  1086. fprintf(stderr, errmsg, ntbl[i].name, p + ntbl[i].offset);
  1087. free(errmsg);
  1088. }
  1089. continue;
  1090. }
  1091. _Delim = xk_get_delim(&ntbl[i], p);
  1092. if (_Prdebug)
  1093. {
  1094. errmsg=strdup(GETMESSAGE(8,36,
  1095. "xk_free: Freeing member '%s' at location 0x%x\n"));
  1096. fprintf(stderr, errmsg, ntbl[i].name, p + ntbl[i].offset);
  1097. free(errmsg);
  1098. }
  1099. if (xk_free(&ntbl[i], p+ntbl[i].offset, nptr, sub, tbl_find) == FAIL) {
  1100. if (_Prdebug)
  1101. {
  1102. errmsg=strdup(GETMESSAGE(8,37,
  1103. "xk_free: A failure occurred while freeing the '%s' member\n"));
  1104. fprintf(stderr, errmsg, ntbl[i].name);
  1105. free(errmsg);
  1106. }
  1107. return(FAIL);
  1108. }
  1109. }
  1110. break;
  1111. case K_UNION:
  1112. if (strncmp(tbl[-1].name, "ch_", 3) != 0) {
  1113. if (_Prdebug)
  1114. {
  1115. errmsg=strdup(GETMESSAGE(8,38,
  1116. "xk_free: Cannot determine the choice in '%s'\n"));
  1117. fprintf(stderr, errmsg, tbl->name);
  1118. free(errmsg);
  1119. }
  1120. return(FAIL);
  1121. }
  1122. val = *((long *)(p - sizeof(long)));
  1123. ntbl = tbl_find(tbl->tname, tbl->tbl, tbl->id);
  1124. for (i = 0; ntbl[i].name != NULL; i++) {
  1125. if (ntbl[i].choice == val) {
  1126. if ((ntbl[i].flags & F_SIMPLE) && nptr+ntbl[i].ptr == 0) {
  1127. if (_Prdebug)
  1128. {
  1129. errmsg=strdup(GetSharedMsg(
  1130. DT_XK_FREE_NO_MEMBER));
  1131. fprintf(stderr, errmsg, ntbl[i].name, p + ntbl[i].offset);
  1132. free(errmsg);
  1133. }
  1134. continue;
  1135. }
  1136. if (_Prdebug)
  1137. {
  1138. errmsg=strdup(GETMESSAGE(8,39,
  1139. "xk_free: Freeing union member '%s' at location 0x%x\n"));
  1140. fprintf(stderr, errmsg, ntbl[i].name, p + ntbl[i].offset);
  1141. free(errmsg);
  1142. }
  1143. RIF(xk_free(&ntbl[i], p, nptr, sub, tbl_find));
  1144. break;
  1145. }
  1146. }
  1147. if (ntbl[i].name == NULL && _Prdebug)
  1148. if (_Prdebug)
  1149. {
  1150. errmsg=strdup(GETMESSAGE(8,40,
  1151. "xk_free: There is no legal union choice for '%s' (value is 0x%x); no free occurred\n"));
  1152. fprintf(stderr, errmsg, tbl->name, val);
  1153. free(errmsg);
  1154. }
  1155. break;
  1156. default:
  1157. return(FAIL);
  1158. }
  1159. return(SUCCESS);
  1160. }