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