]> andersk Git - moira.git/blame - gdb/gdb_struct.c
added copyright message
[moira.git] / gdb / gdb_struct.c
CommitLineData
5580185e 1/*
2 * $Source$
3 * $Header$
4 */
5
6#ifndef lint
7static 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
0a5ff702 38/* For copying and distribution information, please see
39/* the file <mit-copyright.h>.
5580185e 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
0a5ff702 58#include <mit-copyright.h>
5580185e 59#include <stdio.h>
60#include <strings.h>
61#include "gdb.h"
62
63extern char *malloc();
64extern int 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
87char *
88gdb_am(bytes)
89int 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
105int
106gdb_fm(ptr, bytes)
107char *ptr;
108int 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
141char *
142string_alloc(stringp, bytes)
143STRING *stringp; /* pointer to string */
144 /* descriptor to be */
145 /* filled in */
146int 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 /*----------------------------------------------------------*/
170int
171string_free(stringp)
172STRING *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
227TUPLE_DESCRIPTOR
228create_tuple_descriptor(number_of_fields, name_list, type_list)
229char *name_list[];
230FIELD_TYPE type_list[];
231int 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
345int
346delete_tuple_descriptor(t)
347TUPLE_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
384int
385field_index(tuple_descriptor, field_name)
386TUPLE_DESCRIPTOR tuple_descriptor;
387char *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
431TUPLE
432create_tuple(descriptor)
433TUPLE_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
468int
469delete_tuple(t)
470TUPLE 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
490int
491initialize_tuple(t)
492TUPLE 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
542int
543null_tuple_strings(t)
544TUPLE 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
597RELATION
598create_relation(desc)
599TUPLE_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
636int
637delete_relation(rel)
638RELATION 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
687int
688tuples_in_relation(rel)
689RELATION 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.254562 seconds and 5 git commands to generate.