dis.c 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. /*
  2. * File: - dis.c
  3. *
  4. * dispose() built in standard procedure in Pascal (6.6.5.3)
  5. *
  6. * Re-implementation of storage allocator for Ack Pascal compiler
  7. * under Linux, and other UNIX-like systems.
  8. *
  9. * Written by Erik Backerud, 2010-10-01
  10. *
  11. * Original copyright and author info below:
  12. */
  13. /* $Id$ */
  14. /*
  15. * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
  16. *
  17. * This product is part of the Amsterdam Compiler Kit.
  18. *
  19. * Permission to use, sell, duplicate or disclose this software must be
  20. * obtained in writing. Requests for such permissions may be sent to
  21. *
  22. * Dr. Andrew S. Tanenbaum
  23. * Wiskundig Seminarium
  24. * Vrije Universiteit
  25. * Postbox 7161
  26. * 1007 MC Amsterdam
  27. * The Netherlands
  28. *
  29. */
  30. /* Author: J.W. Stevenson */
  31. #include <pc_err.h>
  32. #define assert() /* nothing */
  33. /*
  34. * use a singly linked list of free blocks.
  35. */
  36. struct adm {
  37. struct adm *next;
  38. int size;
  39. };
  40. struct adm *freep = 0; /* first element on free list */
  41. extern void _trp(int);
  42. /*
  43. * Dispose
  44. * Called with two arguments:
  45. * n the size of the block to be freed, in bytes,
  46. * pp address of pointer to data.
  47. */
  48. void
  49. _dis(int n, struct adm **pp)
  50. {
  51. struct adm *block; /* the block of data being freed (inc. header) */
  52. struct adm *p, *q;
  53. if (*pp == 0) {
  54. _trp(EFREE);
  55. }
  56. block = *pp - 1;
  57. if (freep == 0) {
  58. freep = block;
  59. block->next = 0;
  60. } else {
  61. q = 0; /* trail one behind */
  62. for (p = freep; p < block; p = p->next) {
  63. if (p == 0) { /* We reached the end of the free list. */
  64. break;
  65. }
  66. q = p;
  67. /* check if block is contained in the free block p */
  68. if (p+p->size > block) {
  69. _trp(EFREE);
  70. }
  71. }
  72. if (p == block) { /* this block already freed */
  73. _trp(EFREE);
  74. }
  75. if (q == 0) { /* block is first */
  76. freep = block;
  77. block->next = p;
  78. } else {
  79. q->next = block;
  80. }
  81. block->next = p;
  82. /* merge with successor on free list? */
  83. if (block + block->size == p) {
  84. block->size = block->size + p->size;
  85. block->next = p->next;
  86. }
  87. /* merge with preceding block on free list? */
  88. if (q != 0 && q+q->size == block) {
  89. q->size = q->size + block->size;
  90. q->next = block->next;
  91. }
  92. }
  93. } /* _dis */