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