]> andersk Git - moira.git/blame - gdb/gdb_struct.c
strings.h no longer exists on the sun, and string.h is POSIX anyway
[moira.git] / gdb / gdb_struct.c
CommitLineData
5580185e 1/*
5580185e 2 * $Header$
3 */
4
5#ifndef lint
6static char *rcsid_gdb_struct_c = "$Header$";
7#endif lint
8
5580185e 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
0a5ff702 18/* For copying and distribution information, please see
19/* the file <mit-copyright.h>.
5580185e 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
0a5ff702 38#include <mit-copyright.h>
5580185e 39#include <stdio.h>
f4c08abd 40#include <string.h>
5580185e 41#include "gdb.h"
42
43extern char *malloc();
24582af9 44#ifndef lint
6e546365 45extern void free();
24582af9 46#endif
5580185e 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
69char *
70gdb_am(bytes)
71int 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
24582af9 87/*ARGSUSED*/
5580185e 88int
89gdb_fm(ptr, bytes)
90char *ptr;
91int 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
124char *
125string_alloc(stringp, bytes)
126STRING *stringp; /* pointer to string */
127 /* descriptor to be */
128 /* filled in */
129int 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 /*----------------------------------------------------------*/
153int
154string_free(stringp)
155STRING *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
210TUPLE_DESCRIPTOR
211create_tuple_descriptor(number_of_fields, name_list, type_list)
212char *name_list[];
213FIELD_TYPE type_list[];
214int 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
328int
329delete_tuple_descriptor(t)
330TUPLE_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
367int
368field_index(tuple_descriptor, field_name)
369TUPLE_DESCRIPTOR tuple_descriptor;
370char *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
414TUPLE
415create_tuple(descriptor)
416TUPLE_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
451int
452delete_tuple(t)
453TUPLE 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
473int
474initialize_tuple(t)
475TUPLE 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
525int
526null_tuple_strings(t)
527TUPLE 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
580RELATION
581create_relation(desc)
582TUPLE_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
619int
620delete_relation(rel)
621RELATION 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
670int
671tuples_in_relation(rel)
672RELATION 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.163697 seconds and 5 git commands to generate.