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