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