Link with C++ linker
[oweals/cde.git] / cde / programs / dtksh / struct.c
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: struct.c /main/4 1995/11/01 15:56:35 rswiston $ */
24 /*      Copyright (c) 1991, 1992 UNIX System Laboratories, Inc. */
25 /*      All Rights Reserved     */
26
27 /*      THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF */
28 /*      UNIX System Laboratories, Inc.                  */
29 /*      The copyright notice above does not evidence any       */
30 /*      actual or intended publication of such source code.    */
31
32 #undef printf
33
34
35 #include        "shell.h" 
36 #include <signal.h>
37 #include <fcntl.h>
38 #include <X11/X.h>
39 #include <X11/Intrinsic.h>
40 #include <X11/IntrinsicP.h>
41 #include <X11/CoreP.h>
42 #include <X11/StringDefs.h>
43 #include <Xm/XmStrDefs.h>
44 #include <Xm/List.h>
45 #include <setjmp.h>
46 #include <string.h>
47 #include <ctype.h>
48 #include <Xm/Xm.h>
49 #include <Xm/Protocols.h>
50 #include "hash.h"
51 #include "stdio.h"
52 #define NO_AST
53 #include "dtksh.h"
54 #undef NO_AST
55 #include "exksh.h"
56 #include "xmksh.h"
57 #include "dtkcmds.h"
58 #include "xmcvt.h"
59 #include "widget.h"
60 #include "extra.h"
61 #include "xmwidgets.h"
62 #include "struct.h"
63 #include "basetbl.h"
64 #include "docall.h"
65 #include "exksh_tbls.h"
66 #include "msgs.h"
67
68 const static char use[] = "0x%x";
69 const static char use2[] = "%s=0x%x";
70
71 static char structInited = 0;
72 static void *Hashnams = NULL;
73
74 static struct memtbl **Dynmem = NULL;
75 static int Ndynmem = 0;
76 static int Sdynmem = 0;
77
78 struct structlist {
79         char *prefix;
80         int id;
81         int size;
82         struct memtbl **mem;
83 };
84
85 struct structlist *Structlist = NULL;
86 int Nstructlist;
87
88
89
90 static int freemem( 
91                         struct memtbl *mem) ;
92 static growmem( void ) ;
93 static char * endtok( 
94                         char *start) ;
95 static int chg_structlist( 
96                         struct memtbl **memptr,
97                         int id) ;
98 static struct_init( void ) ;
99
100
101
102 memtbl_t *
103 ffind(
104         memtbl_t *tbl,
105         char *fld,
106         char **pptr )
107 {
108         static memtbl_t tbluse[2];
109         memtbl_t *tbl2;
110         char *p, *q, op;
111         unsigned int len, sub;
112
113         if (!fld || !(*fld))
114                 return(tbl);
115         tbl2 = tbluse;
116         tbluse[0] = *tbl;
117         tbluse[1] = Null_tbl;
118         q = fld;
119         while (tbl2 && q && *q) {
120                 p = q;
121                 if (*q == '[') {
122                         if (!tbl2->ptr)
123                                 return(NULL);
124                         q++;
125                         xk_par_int(&q, &sub, NULL);
126                         if (*q != ']')
127                                 return(NULL);
128                         *pptr = ((char **) (*pptr))[0];
129                         *pptr += sub * tbl2->size;
130                         q++;
131                         tbluse[0].ptr--;
132                         continue;
133                 }
134                 if ((len = strcspn(p, "[.")) < strlen(p)) {
135                         q = p + len;
136                         op = *q;
137                         *q = '\0';
138                 }
139                 else
140                         q = NULL;
141                 tbl2 = asl_find(NULL, tbluse, p, pptr);
142                 if (tbl2 && (tbl2 != tbluse)) {
143                         /* A field should not be a subfield of itself */
144
145                         tbluse[0] = *tbl2;
146                         tbl2 = tbluse;
147                         tbl2->name = ".";
148                         tbl2->offset = 0;
149                 }
150                 if (q) {
151                         if (op == '.')
152                                 *q++ = op;
153                         else
154                                 *q = op;
155                 }
156         }
157         return(tbl2);
158 }
159
160 static int
161 freemem(
162         struct memtbl *mem )
163 {
164         free(mem->name);
165         /*
166         int i;
167
168         ** Because structures and typedefs now inherit fields (i.e. copy
169         ** the memtbl entry) we must keep the fields of a structure
170         ** around permanently, (unless we implement a reference count).
171         ** Let's keep the code handy in case we do.
172                 if (mem->kind == K_STRUCT) {
173                         struct memtbl *fmem;
174
175                         fmem = Dynmem[mem->tbl];
176                         for (i = 0; fmem[i].name; i++) {
177                                 free(fmem[i].name);
178                                 if (fmem[i].tname)
179                                         free(fmem[i].tname);
180                         }
181                 }
182         */
183         free(mem);
184 }
185
186 static
187 growmem( void )
188 {
189         if (!(Dynmem = (struct memtbl **) realloc(Dynmem, (Sdynmem + 20) * sizeof(memtbl_t *))))
190                 return(SH_FAIL);
191         chg_structlist(Dynmem, DYNMEM_ID);
192         memset(((char *) Dynmem) + Sdynmem * sizeof(memtbl_t *), '\0', 20 * sizeof(memtbl_t *));
193         Sdynmem += 20;
194 }
195
196 int
197 do_struct(
198         int argc,
199         char **argv )
200 {
201         struct memtbl *mem, *fmem;
202         int i, j, argstart, redo;
203         char *name, *fname;
204         char *p;
205
206         if (!structInited)
207            struct_init();
208
209         if (argc > 1 && C_PAIR(argv[1], '-', 'R')) {
210                 redo = 0;
211                 argstart = 2;
212         }
213         else {
214                 argstart = 1;
215                 redo = 1;
216         }
217         if ((argstart + 1) >= argc)
218         {
219                 XK_USAGE(argv[0]);
220         }
221         name = argv[argstart++];
222         for (i = 0; i < Ndynmem; i++)
223                 if (!(Dynmem[i]->flags & F_FIELD) && (strcmp(name, Dynmem[i]->name) == 0))
224                         break;
225         if ((i < Ndynmem) && !redo) {
226                 if (!redo)
227                         return(SH_SUCC);
228                 if (Sdynmem - Ndynmem < 1)
229                         growmem();
230         }
231         else if (Sdynmem - Ndynmem < 2)
232                 growmem();
233         /*
234         ** Number of memtbls needed: two for structure table and one for
235         ** each field plus one for null termination.  The number of
236         ** fields is argc - 2.
237         */
238         if (!(mem = (struct memtbl *) malloc(2 * sizeof(struct memtbl))))
239                 return(SH_FAIL);
240         if (!(fmem = (struct memtbl *) malloc((argc - 1) * sizeof(struct memtbl))))
241                 return(SH_FAIL);
242         memset(mem, '\0', 2 * sizeof(struct memtbl));
243         memset(fmem, '\0', (argc - 1) * sizeof(struct memtbl));
244         if (i < Ndynmem) {
245                 mem->tbl = Ndynmem++;
246                 freemem(Dynmem[i]);
247                 xkhash_override(Hashnams, name, mem);
248         }
249         else {
250                 Ndynmem += 2;
251                 mem->tbl = i + 1;
252         }
253         Dynmem[i] = mem;
254         Dynmem[mem->tbl] = fmem;
255         mem->flags = F_TBL_IS_PTR;
256         mem->id = DYNMEM_ID;
257         mem->name = strdup(name);
258         mem->kind = K_STRUCT;
259         for (j = argstart; (j < argc) && argv[j]; j++) {
260                 if (p = strchr(argv[j], ':')) {
261                         fname = malloc(p - argv[j] + 1);
262                         strncpy(fname, argv[j], p - argv[j]);
263                         fname[p - argv[j]] = '\0';
264                         parse_decl(argv[0], fmem + j - argstart, p + 1, 0);
265                 }
266                 else {
267                         fname = strdup(argv[j]);
268                         fmem[j - argstart] = T_unsigned_long[0];
269                 }
270                 fmem[j - argstart].name = fname;
271                 fmem[j - argstart].flags |= F_FIELD;
272                 fmem[j - argstart].delim = 0;
273                 fmem[j - argstart].offset = mem->size;
274                 mem->size += (fmem[j - argstart].ptr) ? sizeof(void *) : fmem[j - argstart].size;
275         }
276         return(SH_SUCC);
277 }
278
279 int
280 do_typedef(
281         int argc,
282         char **argv )
283 {
284         struct memtbl *mem;
285         int i, redo;
286         char *name, *decl;
287
288         if (!structInited)
289            struct_init();
290
291         i = 1;
292         if (argc > 1 && C_PAIR(argv[i], '-', 'R')) 
293         {
294                 redo = 0;
295                 i++;
296         }
297         else 
298                 redo = 1;
299
300         if ((i + 1) >= argc)
301         {
302                 XK_USAGE(argv[0]);
303         }
304         decl = argv[i++];
305         name = argv[i++];
306
307         for (i = 0; i < Ndynmem; i++)
308                 if (!(Dynmem[i]->flags & F_FIELD) && (strcmp(name, Dynmem[i]->name) == 0))
309                         break;
310         if ((i < Ndynmem) && !redo) {
311                 if (!redo)
312                         return(SH_SUCC);
313         }
314         else if (Sdynmem - Ndynmem < 1)
315                 growmem();
316         if (!(mem = (struct memtbl *) malloc(2 * sizeof(struct memtbl))))
317                 return(SH_FAIL);
318         mem[1] = Null_tbl;
319         if (i < Ndynmem) {
320                 freemem(Dynmem[i]);
321                 xkhash_override(Hashnams, name, mem);
322         }
323         else
324                 Ndynmem++;
325         Dynmem[i] = mem;
326         parse_decl(argv[0], mem, decl, 0);
327         mem->name = strdup(name);
328         return(SH_SUCC);
329 }
330
331 static char *
332 endtok(
333         char *start )
334 {
335         while(*start && !isspace(*start))
336                 start++;
337         return(start);
338 }
339
340 int
341 parse_decl(
342         char * argv0,
343         struct memtbl *mem,
344         char *decl,
345         int tst )
346 {
347         struct memtbl *tbl;
348         char *p, *end;
349         char hold;
350         int flag = 0, done;
351         char * msg;
352         char * errbuf;
353         char * errmsg;
354
355         end = decl;
356         do {
357                 p = end;
358                 xk_skipwhite(&p);
359                 end = endtok(p);
360                 hold = *end;
361                 *end = '\0';
362                 done = ((strcmp(p, (const char *) "struct") != 0) &&
363                         (strcmp(p, (const char *) "const") != 0) &&
364                         (strcmp(p, (const char *) "unsigned") != 0) &&
365                         (strcmp(p, (const char *) "signed") != 0) &&
366                         (strcmp(p, (const char *) "union") != 0));
367                 *end = hold;
368         } while (!done && hold);
369         if (!p[0]) {
370                 if (tst) {
371                         return(FAIL);
372                 }
373                 errmsg = strdup(GetSharedMsg(DT_BAD_DECL));
374                 printerrf(argv0, errmsg,
375                            decl,NULL, NULL, NULL, NULL, NULL, NULL, NULL);
376                 free(errmsg);
377                 mem[0] = T_unsigned_long[0];
378                 return(SUCCESS);
379         }
380         hold = *end;
381         *end = '\0';
382         tbl = all_tbl_search(p, flag|NOHASH);
383         *end = hold;
384         if (!tbl) {
385                 if (tst) {
386                         return(FAIL);
387                 }
388                 errmsg = strdup(GetSharedMsg(DT_BAD_DECL));
389                 printerrf(argv0, errmsg,
390                           decl, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
391                 free(errmsg);
392                 mem[0] = T_unsigned_long[0];
393                 return(SUCCESS);
394         }
395         mem[0] = tbl[0];
396         for (p = end; *p; p++) {
397                 switch(*p) {
398                 case '[':
399                         {
400                                 char *q = strchr(p, ']');
401
402                                 if (!q) {
403                                         errmsg=strdup(GETMESSAGE(12,1, 
404                                            "Found a '[' character without a matching ']'"));
405                                         printerr(argv0, errmsg, NULL);
406                                         free(errmsg);
407                                         continue;
408                                 }
409                                 p++;
410                                 xk_par_int(&p, &(mem->subscr), NULL);
411                                 mem->flags &= ~(F_SIMPLE);
412                                 if (mem->subscr)
413                                         mem->size *= mem->subscr;
414                                 p = q;
415                                 break;
416                         }
417                 case '*':
418                         if ((mem->kind == K_CHAR) && !(mem->ptr)) {
419                                 char *name;
420
421                                 name = mem->name;
422                                 mem[0] = T_string_t[0];
423                                 mem->name = name;
424                         }
425                         else {
426                                 mem->ptr++;
427                                 mem->flags &= ~(F_SIMPLE);
428                         }
429                         break;
430                 }
431         }
432         return(SUCCESS);
433 }
434
435 int
436 do_structlist(
437         int argc,
438         char **argv )
439 {
440         int i, j, id = 0;
441         char *prefix = NULL;
442         struct memtbl **memptr = NULL;
443         char * errmsg;
444
445         for (i = 1; (i < argc) && argv[i]; i++) {
446                 if (argv[i][0] == '-') {
447                         for (j = 1; argv[i][j]; j++) {
448                                 switch(argv[i][j]) {
449                                 case 'i':
450                                    if (argv[i][j + 1])
451                                         fdef(argv[i] + j + 1, &id);
452                                    else
453                                         fdef(argv[++i], &id);
454                                    j = strlen(argv[i]) - 1;
455                                    break;
456                                 case 'p':
457                                    if (argv[i][j + 1])
458                                         prefix = argv[i] + j + 1;
459                                    else
460                                         prefix = argv[++i];
461                                    j = strlen(prefix) - 1;
462                                    break;
463                                 default:
464                                    errmsg = strdup(GetSharedMsg(
465                                                     DT_UNKNOWN_OPTION));
466                                    printerrf(argv[0], errmsg,
467                                             argv[i], NULL, NULL, NULL, NULL,
468                                             NULL, NULL, NULL);
469                                    free(errmsg);
470                                    xk_usage(argv[0]);
471                                    return(SH_FAIL);
472                                 }
473                         }
474                 }
475                 else {
476                         if ((memptr = (memtbl_t **) getaddr(argv[i])) == NULL) 
477                         {
478                            errmsg=strdup(GETMESSAGE(12,2, 
479                                 "Unable to locate the following symbol: %s"));
480                            printerrf(argv[0], errmsg, argv[i],
481                                           NULL, NULL, NULL, NULL, NULL, NULL,
482                                           NULL);
483                            free(errmsg);
484                            return(SH_FAIL);
485                         }
486                 }
487         }
488
489         if (memptr == NULL)
490         {
491            XK_USAGE(argv[0]);
492         }
493
494         for (i = 0; i < Nstructlist; i++)
495         {
496                 if ((Structlist[i].mem == memptr) && 
497                     (!prefix || (Structlist[i].prefix && 
498                         (strcmp(Structlist[i].prefix, prefix) == 0))) &&
499                     (!id || (Structlist[i].id == id)))
500                 {
501                         return(SH_SUCC);
502                 }
503         }
504
505         add_structlist(memptr, prefix, id);
506 }
507
508 static int
509 chg_structlist(
510         struct memtbl **memptr,
511         int id )
512 {
513         int i;
514
515         for (i = 0; i < Nstructlist; i++)
516                 if (Structlist[i].id == id) {
517                         Structlist[i].mem = memptr;
518                         return;
519                 }
520 }
521
522 int
523 add_structlist(
524         struct memtbl **memptr,
525         char *prefix,
526         int id )
527 {
528         int i;
529
530         if (!Structlist)
531                 Structlist = (struct structlist *) malloc((Nstructlist + 1) * sizeof(struct structlist));
532         else
533                 Structlist = (struct structlist *) realloc(Structlist, (Nstructlist + 1) * sizeof(struct structlist));
534         if (!Structlist)
535                 return(SH_FAIL);
536         Structlist[Nstructlist].mem = memptr;
537         Structlist[Nstructlist].id = id;
538         Structlist[Nstructlist].prefix = prefix ? strdup(prefix) : (char *)NULL;
539         if (memptr[0] && memptr[0][0].name) {
540                 for (i = 1; memptr[i] && memptr[i][0].name && memptr[i][0].name[0]; i++)
541                         if (strcmp(memptr[i][0].name, memptr[i - 1][0].name) < 0)
542                                 break;
543                 if (!(memptr[i] && memptr[i][0].name && memptr[i][0].name[0]))
544                         Structlist[Nstructlist].size = i - 1;
545                 else
546                         Structlist[Nstructlist].size = -1;
547         }
548         else
549                         Structlist[Nstructlist].size = 0;
550         Nstructlist++;
551         return(SH_SUCC);
552 }
553
554 int
555 strparse(
556         memtbl_t *tbl,
557         char **pbuf,
558         char *val )
559 {
560         char *p, *phold;
561         int ret;
562
563         if (!IS_SIMPLE(tbl) && !tbl->ptr && !(tbl->flags & F_TYPE_IS_PTR))
564                 tbl->ptr = 1;
565         phold = p = strdup(val);
566         ret = XK_PARSE(tbl, &p, (char *)pbuf, 0, 0, NULL, all_tbl_find);
567         free(phold);
568         return(ret != FAIL);
569 }
570
571 int
572 strfree(
573         char *buf,
574         char *type )
575 {
576         memtbl_t tbl;
577
578         if (parse_decl("strfree", &tbl, type, 1) == FAIL)
579                 return(SH_FAIL);
580         if (!IS_SIMPLE(&tbl) && !tbl.ptr && !(tbl.flags & F_TYPE_IS_PTR))
581                 tbl.ptr = 1;
582         if (XK_FREE(&tbl, (char *)&buf, 0, 0, all_tbl_find) == FAIL)
583                 return(SH_FAIL);
584         return(SH_SUCC);
585 }
586
587 int
588 do_sizeof(
589         int argc,
590         char **argv )
591 {
592         memtbl_t *tbl;
593         char * errmsg;
594
595         if (argc <= 1) {
596                 XK_USAGE(argv[0]);
597         }
598         if ((tbl = all_tbl_search(argv[1], 0)) == NULL) {
599                 errmsg=strdup(GETMESSAGE(12,3, 
600                   "The following is not a valid data type or structure name: %s"));
601                 printerrf(argv[0], errmsg, argv[1], NULL, NULL,
602                           NULL, NULL, NULL, NULL, NULL);
603                 free(errmsg);
604                 return(SH_FAIL);
605         }
606         if (argc >= 3) {
607                 char buf[50];
608
609                 sprintf(buf, use2, argv[2], tbl->ptr ? sizeof(void *) : tbl->size);
610                 env_set(buf);
611         }
612         else {
613                 sprintf(xk_ret_buffer, use, tbl->ptr ? sizeof(void *) : tbl->size);
614                 xk_ret_buf = xk_ret_buffer;
615         }
616         return(SH_SUCC);
617 }
618
619 memtbl_t *
620 all_tbl_find(
621         char *name,
622         int tbl,
623         long id )
624 {
625         int i;
626
627         if (tbl != -1) {
628                 for (i = 0; i < Nstructlist; i++)
629                         if (id == Structlist[i].id)
630                                 return(Structlist[i].mem[tbl]);
631                 return(NULL);
632         }
633         return(all_tbl_search(name, TYPEONLY));
634 }
635
636 memtbl_t *
637 all_tbl_search(
638         char *name,
639         int flag )
640 {
641         register int i;
642         void *found;
643
644         if (!structInited)
645            struct_init();
646
647         if (found = (void *) xkhash_find(Hashnams, name))
648                 return((memtbl_t *) found);
649         else {
650                 register int j;
651                 register memtbl_t **subtbl;
652
653                 for (i = 0; i < Nstructlist; i++) {
654                         if (subtbl = Structlist[i].mem)
655                                 for (j = 0; subtbl[j]; j++)
656                                         if (!(subtbl[j]->flags & F_FIELD) && (strcmp(name, subtbl[j]->name) == 0) && ((subtbl[j]->kind != K_TYPEDEF) || (subtbl[j]->tbl != -1))) {
657                                                 if (!(flag & NOHASH))
658                                                         xkhash_add(Hashnams, name, (char *)subtbl[j]);
659                                                 return(subtbl[j]);
660                                         }
661                 }
662         }
663         return(NULL);
664 }
665
666 memtbl_t *
667 asl_find(
668         memtbl_t *ptbl,
669         memtbl_t *tbls,
670         char *fld,
671         char **pptr )
672 {
673         int i;
674         memtbl_t *tbl;
675
676         if (!Structlist)
677                 return(NULL);
678         if (!pptr && (ptbl == tbls))
679                 return(NULL);
680         for (i = 0; tbls[i].name; i++) {
681                 if ((xk_Strncmp(tbls[i].name, fld, strlen(fld)) == 0) && (strlen(fld) == strlen(tbls[i].name))) {
682                         if (pptr && ptbl && ((ptbl->kind == K_STRUCT) || (ptbl->kind == K_ANY)))
683                                 *pptr += tbls[i].offset;
684                         return(tbls + i);
685                 }
686         }
687         for (i = 0; tbls[i].name; i++) {
688                 if ((tbls[i].kind == K_TYPEDEF) || (tbls[i].kind == K_STRUCT) || (tbls[i].kind == K_UNION) || (tbls[i].kind == K_ANY)) {
689                         char *hold;
690
691                         if (!pptr) {
692                                 if ((tbl = asl_find(tbls + i, all_tbl_find(tbls[i].tname, tbls[i].tbl, tbls[i].id), fld, pptr)) != NULL)
693                                         return(tbl);
694                                 continue;
695                         }
696                         hold = *pptr;
697                         if (tbls[i].ptr) {
698                                 int nptr;
699
700                                 nptr = tbls[i].ptr;
701                                 /* if you hit a NULL, stop the loop */
702                                 do {
703                                         *pptr = *((char **) *pptr);
704                                 } while (*pptr && --nptr);
705                         }
706                         if (*pptr) {
707                                 if (!tbls[i].ptr)
708                                         *pptr += tbls[i].offset;
709                                 if ((tbl = asl_find(tbls + i, all_tbl_find(tbls[i].tname, tbls[i].tbl, tbls[i].id), fld, pptr)) != NULL)
710                                         return(tbl);
711                                 *pptr = hold;
712                         }
713                 }
714         }
715         return(NULL);
716 }
717
718 static
719 struct_init( void )
720 {
721         char * errhdr;
722         char * errmsg;
723
724         structInited = 1;
725         Hashnams = (void *) xkhash_init(50);
726         if (!(Dynmem = (struct memtbl **) malloc(20 * sizeof(struct memtbl *))))
727         {
728                 errhdr = strdup(GetSharedMsg(DT_ERROR));
729                 errmsg = strdup(GetSharedMsg(DT_ALLOC_FAILURE));
730                 printerr(errhdr, errmsg, NULL);
731                 free(errhdr);
732                 free(errmsg);
733                 exit(1);
734         }
735         Dynmem[0] = NULL;
736         Sdynmem = 20;
737         Ndynmem = 0;
738         add_structlist(basemems, "base", BASE_ID);
739         add_structlist(Dynmem, "dynamic", DYNMEM_ID);
740 }
741