]> andersk Git - moira.git/blob - gdb/gdb_struct.c
4ebda470d0d02da668f1ab12577c4af8a5ca2294
[moira.git] / gdb / gdb_struct.c
1 /*
2  *      $Header$
3  */
4
5 #ifndef lint
6 static char *rcsid_gdb_struct_c = "$Header$";
7 #endif
8
9
10 /************************************************************************/
11 /*      
12 /*                         gdb_struct.c
13 /*      
14 /*            GDB - Structured Data Maintenance Routines
15 /*      
16 /*      Author: Noah Mendelsohn
17 /*      Copyright: 1986 MIT Project Athena 
18 /*              For copying and distribution information, please see
19 /*              the file <mit-copyright.h>.
20 /*      
21 /*      These routines implement the following layers of the 
22 /*      Client Library Specification of the GDB system:
23 /*      
24 /*              Layer           Function
25 /*              -----           --------
26 /*                2             Structured Data Management at a 
27 /*                              Single Site
28 /*                
29 /*                4             Memory Management
30 /*      
31 /*                5             String Management
32 /*      
33 /*      Some of the routines specified are actually implemented as
34 /*      macros defined in gdb.h.
35 /*      
36 /************************************************************************/
37
38 #include <mit-copyright.h>
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include "gdb.h"
43
44 \f
45 /************************************************************************/
46 /*      
47 /*                      MEMORY MANAGEMENT
48 /*      
49 /*      In anticipation of the day when we may want to do something 
50 /*      fancy with memory management, all of the gdb routines which
51 /*      require dynamic allocation of memory call the routines named
52 /*      db_alloc and db_free.  For the moment, these are implemented
53 /*      as calls to malloc and free.  
54 /*      
55 /************************************************************************/
56
57         /*----------------------------------------------------------*/
58         /*      
59         /*                      gdb_am
60         /*      
61         /*      Allocate memory for use by gdb.  Current implementation
62         /*      just does a malloc.
63         /*      
64         /*----------------------------------------------------------*/
65
66 char *
67 gdb_am(bytes)
68 int bytes;
69 {
70         return(malloc((unsigned)bytes));
71 }
72
73         /*----------------------------------------------------------*/
74         /*      
75         /*                      gdb_fm
76         /*      
77         /*      Return allocated memory.  Note: the current 
78         /*      implementation ignores the byte count supplied,
79         /*      but future implementations may require that it 
80         /*      be correct.
81         /*      
82         /*----------------------------------------------------------*/
83
84 /*ARGSUSED*/
85 int
86 gdb_fm(ptr, bytes)
87 char *ptr;
88 int bytes;
89 {
90         free(ptr);
91         return;
92 }
93 \f
94 /************************************************************************/
95 /*      
96 /*                      STRING MANAGEMENT
97 /*      
98 /*      To allow dynamic manipulation of strings in gdb without
99 /*      excessive memory re-allocation, we define a string as a
100 /*      counted byte space.  Though this space will frequently be used
101 /*      to store a standard null terminated string, that is not
102 /*      required.
103 /*      
104 /*      Current representation for a string is a pointer followed by
105 /*      an integer length.  A null pointer indicates a null string, in
106 /*      which case the length is arbitrary.  Any other pointer is to
107 /*      memory which was allocated by db_alloc in which must be free'd
108 /*      eventually with db_free.
109 /*      
110 /************************************************************************/
111
112         /*----------------------------------------------------------*/
113         /*      
114         /*              string_alloc (string_alloc)
115         /*      
116         /*      Fills in supplied string descriptor and returns 
117         /*      pointer to the newly allocated data.
118         /*      
119         /*----------------------------------------------------------*/
120
121 char *
122 string_alloc(stringp, bytes)
123 STRING *stringp;                                /* pointer to string */
124                                                 /* descriptor to be */
125                                                 /* filled in */
126 int     bytes;                                  /* number of bytes to alloc */
127 {
128         GDB_INIT_CHECK
129
130         MAX_STRING_SIZE(*stringp) = bytes;      /* put length in returned */
131                                                 /* string descriptor-- */
132                                                 /* will be irrelavent if */
133                                                 /* alloc fails */
134
135         STRING_DATA(*stringp) = db_alloc(bytes); /* try to get the data */
136         return (STRING_DATA(*stringp));         /* return ptr to new string */
137                                                 /* if any */
138 }
139
140         /*----------------------------------------------------------*/
141         /*      
142         /*                string_free (string_free)
143         /*      
144         /*      Releases the data space for a gdb string.  Must have
145         /*      been allocated with string_alloc.  Remember to pass
146         /*      in the address of the string descriptor, not the 
147         /*      descriptor itself!
148         /*      
149         /*----------------------------------------------------------*/
150 int
151 string_free(stringp)
152 STRING *stringp;
153 {
154         GDB_INIT_CHECK
155
156         if (stringp->ptr == NULL)
157                 return;  
158         db_free(stringp->ptr, stringp->length);
159         stringp->ptr = NULL;
160         stringp->length = 0;
161         return;
162 }
163 \f
164 /************************************************************************/
165 /*      
166 /*          STRUCTURED DATA MANAGEMENT AT A SINGLE SITE
167 /*      
168 /*      These routines provide the abstraction of typed, structured
169 /*      data at a single site.  Tuples are collections of typed fields,
170 /*      and they are each described by a tuple descriptor.  Relations
171 /*      are circularly linked lists of tuples.  For completeness, a
172 /*      relation also carries a tuple descriptor, which should match
173 /*      the descriptor for each of its constituent tuples.  This allows
174 /*      a null relation to be typed.
175 /*      
176 /*      Some of the facilities of structured data management are 
177 /*      defined as macros in gdb.h.  In many cases, the routines
178 /*      declared below are known by defines of more descriptive
179 /*      names, also in gdb.h.
180 /*      
181 /************************************************************************/
182 /************************************************************************/
183 /*      
184 /*                   TUPLE_DESCRIPTOR MANAGEMENT
185 /*      
186 /************************************************************************/
187
188
189         /*----------------------------------------------------------*/
190         /*      
191         /*          create_tuple_descriptor (create_tuple_descriptor)
192         /*      
193         /*      Allocates space for a tuple descriptor and fills
194         /*      it in.  Gives up if space is not available.  
195         /*      Should be passed a list of integer coded types
196         /*      and a list of string field names.  
197         /*      
198         /*      Tuple descriptors are reference counted, and they are
199         /*      not really deleted until the reference count goes
200         /*      to zero.   It is presumed that all callers use the
201         /*      create and delete routines, or otherwise maintain
202         /*      the reference count appropriately.
203         /*      
204         /*----------------------------------------------------------*/
205
206
207 TUPLE_DESCRIPTOR
208 create_tuple_descriptor(number_of_fields, name_list, type_list)
209 char *name_list[];
210 FIELD_TYPE type_list[];
211 int  number_of_fields;
212 {
213         register TUPLE_DESCRIPTOR tpd;          /* pointer to new descriptor */
214         register int i;
215         register int data_len;                  /* length of the actual */
216         int field_len;                          /* length of current field */
217         int align;                              /* code describing alignment */
218                                                 /* requirement for this field*/
219                                                 /* (4 for fullword, 1 for */
220                                                 /* char, etc.) */
221         int next_offset;                        /* byte offset to next field */
222         int descriptor_length;                  /* length of the part of */
223                                                 /* the allocated storage */
224                                                 /* actually used for the */
225                                                 /* descriptor.*/
226         int str_len;                            /* we also have to retain */
227                                                 /* the string names for the */
228                                                 /* fields.  These are stored */
229                                                 /* immediately off the end */
230                                                 /* of the descriptor, and */
231                                                 /* all are allocated */
232                                                 /* together.  This is the */
233                                                 /* length of the string data */
234         char *next_name;                        /* place to put the next */
235                                                 /* copied fieldname*/
236
237
238         GDB_INIT_CHECK
239
240        /*
241         * Calculate size and allocate descriptor
242         */
243
244         descriptor_length = sizeof(struct tupl_desc) +
245                             (number_of_fields-1) * sizeof(struct tupld_var);
246
247         str_len = 0;
248
249         for (i=0; i<number_of_fields; i++)
250                 str_len += strlen(name_list[i]) +1;
251
252         tpd = (TUPLE_DESCRIPTOR)db_alloc(descriptor_length+str_len);    
253                                                 /* try to allocate it */
254
255         if (tpd == NULL)
256                 GDB_GIVEUP("create_tuple_descriptor (gbd_ctd) could not get enough memory.\n") 
257
258          /*
259           * Fill in the descriptor fields:
260           * 
261           * Each field is aligned according to its own alignment code.
262           * Going in to the top of the for loop, next_offset is set to
263           * the offset of the first possible byte for storing the next field.
264           * During the loop, that number is rounded up, if necessary, to
265           * achieve the alignment actually required for the field.  Finally,
266           * the length of the new field is added, which yields the first
267           * possible byte of any field to follow.
268           */
269
270         tpd->id = GDB_DESC_ID;
271
272         tpd->ref_count = 1;                     /* whoever asked for creation*/
273                                                 /* is expected to delete*/
274
275         tpd->field_count = number_of_fields;
276         tpd->str_len = str_len;
277
278         data_len = sizeof(struct tuple_dat) - 1; /*  tuple_dat includes the */
279                                                  /*  first byte of data */
280         next_offset = 0;
281         next_name = ((char *)tpd) + descriptor_length;
282                                                 /* place to put first */
283                                                 /* field name*/
284         for (i=0; i<number_of_fields; i++) {
285                /*
286                 * Calculate lengths and alignments for the field data.
287                 */
288                 field_len = INT_PROPERTY(type_list[i],LENGTH_PROPERTY);
289                 align = INT_PROPERTY(type_list[i],ALIGNMENT_PROPERTY);
290                /*
291                 * Copy the string field name into the newly allocated
292                 * space just after the descriptor itself.
293                 */
294                 tpd->var[i].name = strcpy(next_name, name_list[i]);
295                 next_name += strlen(next_name) + 1;
296                /*
297                 * Put in the type and the length for the field data
298                 */
299                 tpd->var[i].type = type_list[i];
300                 tpd->var[i].length = field_len;
301                /*
302                 * Now store the actual offset of this field, and 
303                 * compute the first byte address we could conceivably
304                 * use for the next field.
305                 */
306                 next_offset = GDB_ROUNDUP(next_offset, align);
307                 tpd->var[i].offset = next_offset;
308                 next_offset += field_len;
309         }
310         
311         data_len += next_offset;
312         tpd->data_len = data_len;
313
314         return tpd;                             /* return the new descriptor */
315 }
316
317         /*----------------------------------------------------------*/
318         /*      
319         /*          delete_tuple_descriptor (delete_tuple_descriptor)
320         /*      
321         /*      Return the space for a tuple descriptor
322         /*      
323         /*----------------------------------------------------------*/
324
325 int
326 delete_tuple_descriptor(t)
327 TUPLE_DESCRIPTOR t;
328 {
329         int descriptor_length;
330         register int ref_count;                 /* buffer the reference */
331                                                 /* count here */
332
333         if (t == NULL)
334                 return ;
335         
336         GDB_CHECK_TPD(t, "delete_tuple_descriptor")
337
338
339        /*
340         * Decrement the reference count.  If it's not zero, then just 
341         * return.
342         */
343         if ((ref_count = --(t->ref_count)) >0) 
344                 return ;
345         if (ref_count <0)
346                 GDB_GIVEUP("Tuple descriptor reference count is less than zero")
347        /*
348         * Current representation is to allocate the space for the string
349         * right off the end of the descriptor itself.  We therefore have
350         * to add their length into the amount we free.
351         */
352         descriptor_length = gdb_descriptor_length(t->field_count);      
353         db_free((char *)t, descriptor_length+t->str_len);
354
355         return ;
356 }
357
358         /*----------------------------------------------------------*/
359         /*      
360         /*                 field_index (field_index)
361         /*      
362         /*----------------------------------------------------------*/
363
364 int
365 field_index(tuple_descriptor, field_name)
366 TUPLE_DESCRIPTOR tuple_descriptor;
367 char *field_name;
368 {
369         register int i;
370         register int n;
371         register TUPLE_DESCRIPTOR tpd = tuple_descriptor;
372
373        /*
374         * Make sure supplied descriptor is valid
375         */
376         if (tpd == NULL)
377                 GDB_GIVEUP("null tuple descriptor passed to field_index function")
378         GDB_CHECK_TPD(tpd, "field_index")
379
380         n = tpd -> field_count;
381
382        /*
383         * Loop through each field in descriptor, return index if match
384         */
385
386         for(i=0; i<n; i++) 
387                 if (strcmp(field_name, tpd->var[i].name) == 0)
388                         return i;
389        /*
390         * No match, return -1
391         */
392         return (-1);    
393 }
394
395 \f
396 /************************************************************************/
397 /*      
398 /*                      TUPLE MANAGEMENT
399 /*      
400 /************************************************************************/
401
402         /*----------------------------------------------------------*/
403         /*      
404         /*                create_tuple (create_tuple)
405         /*      
406         /*      Allocate space for a new tuple, given its 
407         /*      descriptor.  Giveup if out of memory.
408         /*      
409         /*----------------------------------------------------------*/
410
411 TUPLE
412 create_tuple(descriptor)
413 TUPLE_DESCRIPTOR descriptor;
414 {
415         register TUPLE t;
416
417         GDB_CHECK_TPD(descriptor, "create_tuple")
418
419         t = (TUPLE)db_alloc(descriptor -> data_len);
420
421         if (t == NULL)
422                 GDB_GIVEUP("create_tuple (create_tuple) could not allocate enough memory.\n")
423
424         t->id = GDB_TUP_ID;
425
426         t->desc = descriptor;                   /* fill in descriptor */
427                                                 /* pointer in new tuple */
428         REFERENCE_TUPLE_DESCRIPTOR(descriptor); /* bump the reference count */
429 #ifdef GDB_CHECK
430        /*
431         * Only for the sake of  keeping things clean, null out the pointers.
432         * Wastes time, but helps debugging.
433         */
434         t->next = t->prev = NULL;
435 #endif
436
437         return t;
438 }
439
440         /*----------------------------------------------------------*/
441         /*      
442         /*              delete_tuple (delete_tuple)
443         /*      
444         /*      Release the data space occupied by a tuple. 
445         /*      
446         /*----------------------------------------------------------*/
447
448 int
449 delete_tuple(t)
450 TUPLE t;
451 {
452         register TUPLE_DESCRIPTOR tpd;
453         if (t==NULL)
454                 GDB_GIVEUP("Delete_tuple called with null tuple")
455         GDB_CHECK_TUP(t, "delete_tuple")
456         tpd = t->desc;
457         db_free((char *)t, t->desc->data_len);
458         delete_tuple_descriptor(tpd);           /* does a reference counted */
459                                                 /* delete*/
460 }
461
462         /*----------------------------------------------------------*/
463         /*      
464         /*                   initialize_tuple (initialize_tuple)
465         /*      
466         /*      Set each field in tuple to its null value.
467         /*      
468         /*----------------------------------------------------------*/
469
470 int
471 initialize_tuple(t)
472 TUPLE t;
473 {
474         register char *field_data;              /* pointer to first byte */
475                                                 /* of field data in tuple*/
476         register TUPLE_DESCRIPTOR tpd;          /* pointer to descriptor */
477         register int i;                         /* counter of fields */
478         int num_fields;                         /* total number of fields */
479
480        /*
481         * Return if no tuple at all supplied--perhaps this should be
482         * an error.  If supplied, make sure it looks like a tuple.
483         */
484
485         if (t == NULL)
486                 return;
487
488         GDB_CHECK_TUP(t, "initialize_tuple")
489
490        /*
491         * Set up to loop through fields:  get tuple descriptor, field count
492         * and pointer to first data byte in the tuple.
493         */
494
495         tpd = t->desc;
496         num_fields = tpd->field_count;
497         field_data = t->data;                   /* address of first byte of */
498                                                 /* user data */
499
500
501        /*
502         * For each field in the tuple, loop calling its null value 
503         * initialization routine.
504         */
505
506         for (i=0; i<num_fields; i++) {
507                 FCN_PROPERTY(tpd->var[i].type, NULL_PROPERTY)
508                              (field_data+tpd->var[i].offset);
509         }
510 }
511
512
513         /*----------------------------------------------------------*/
514         /*      
515         /*            null_tuple_strings (null_tuple_strings)
516         /*      
517         /*      Reclaim the space for all fields in the tuple
518         /*      whose type is 'string.'
519         /*      
520         /*----------------------------------------------------------*/
521
522 int
523 null_tuple_strings(t)
524 TUPLE t;
525 {
526         register char *field_data;              /* pointer to first byte of */
527                                                 /* field data in tuple */
528         register TUPLE_DESCRIPTOR tpd;          /* pointer to descriptor */
529         register int i;                         /* counter of fields */
530         int num_fields;                         /* total number of fields */
531
532        /*
533         * Return if no tuple at all supplied--perhaps this should be
534         * an error
535         */
536
537         if (t == NULL)
538                 return;
539
540         GDB_CHECK_TUP(t, "null_tuple_strings")
541
542        /*
543         * Set up to loop through fields:  get tuple descriptor, field count
544         * and pointer to first data byte in the tuple.
545         */
546
547         tpd = t->desc;
548         num_fields = tpd->field_count;
549         field_data = t->data;                   /* address of first byte of */
550                                                 /* user data */
551
552        /*
553         * For each field in the tuple, loop calling its null value 
554         * initialization routine.
555         */
556
557         for (i=0; i<num_fields; i++) {
558                 if(FIELD_TYPE_IN_TUPLE(tpd,i) == STRING_T &&
559                    (*(char **)(field_data+FIELD_OFFSET_IN_TUPLE(tpd,i)))!=NULL)
560                         string_free((STRING *)(field_data+
561                                                FIELD_OFFSET_IN_TUPLE(tpd,i)));
562         }
563 }
564 \f
565 /************************************************************************/
566 /*      
567 /*                      RELATION MANAGEMENT
568 /*      
569 /************************************************************************/
570
571         /*----------------------------------------------------------*/
572         /*      
573         /*             create_relation (create_relation)
574         /*      
575         /*----------------------------------------------------------*/
576
577 RELATION
578 create_relation(desc)
579 TUPLE_DESCRIPTOR desc;
580 {
581         register RELATION r;
582
583         GDB_CHECK_TPD(desc, "create_relation")
584
585         r = (RELATION)db_alloc(sizeof(struct rel_dat));
586
587         if (r == NULL) 
588                 GDB_GIVEUP("create_relation (create_relation) could not get enough space.\n")
589
590        /*
591         * Fill in the empty relation.  Create a null circular list
592         * of tuples and also hang the description.
593         */
594
595         r->id = GDB_REL_ID;
596
597         r->first = (TUPLE)r;
598         r->last = (TUPLE)r;
599         r->desc = desc;
600         REFERENCE_TUPLE_DESCRIPTOR(desc);       /* bump the reference count */
601
602         return r;
603 }
604
605         /*----------------------------------------------------------*/
606         /*      
607         /*              delete_relation
608         /*      
609         /*      Deletes the tuples which comprise a relation.
610         /*      For each tuple, it does a null-tuple-strings 
611         /*      prior to deleting, but it does not yet handle
612         /*      any other non-contiguous data.
613         /*      
614         /*----------------------------------------------------------*/
615
616 int
617 delete_relation(rel)
618 RELATION rel;
619 {
620         register TUPLE t, next;
621         TUPLE_DESCRIPTOR desc;
622
623        /*
624         * Make sure a proper relation is supplied.
625         */
626
627         if (rel == NULL)
628                 GDB_GIVEUP("delete_relation called with null relation")
629         GDB_CHECK_REL(rel, "delete_relation")
630
631         t = FIRST_TUPLE_IN_RELATION(rel);
632
633         /*----------------------------------------------------------*/
634         /*      
635         /*      Free all the tuples
636         /*      
637         /*----------------------------------------------------------*/
638
639         while (t!=NULL) {
640                 null_tuple_strings(t);
641                 next = NEXT_TUPLE_IN_RELATION(rel, t);
642                 delete_tuple(t);
643                 t = next;
644         }
645
646         /*----------------------------------------------------------*/
647         /*      
648         /*      Give back the memory for the relation
649         /*      
650         /*----------------------------------------------------------*/
651
652         desc = DESCRIPTOR_FROM_RELATION(rel);
653         db_free((char *)rel, sizeof(struct rel_dat));
654         delete_tuple_descriptor(desc);          /* does a reference */
655                                                 /* counted delete */
656 }
657
658         /*----------------------------------------------------------*/
659         /*      
660         /*              tuples_in_relation
661         /*      
662         /*      Returns number of tuples in a relation.
663         /*      
664         /*      
665         /*----------------------------------------------------------*/
666
667 int
668 tuples_in_relation(rel)
669 RELATION rel;
670 {
671         register int count;
672         register RELATION r=rel;
673         register TUPLE t;
674
675         count = 0;
676
677         for (t=FIRST_TUPLE_IN_RELATION(r);
678              t != NULL;
679              t=NEXT_TUPLE_IN_RELATION(r,t)) {
680                   count++;
681         }
682         return count;
683 }
684         
685
686
This page took 0.826414 seconds and 3 git commands to generate.