new.c 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. /*
  2. * File: - new.c
  3. *
  4. * new() 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 <em_abs.h>
  32. #include <pc_err.h>
  33. #define assert(x) /* nothing */
  34. #define UNDEF 0x8000
  35. #define NALLOC (1024) /* request this many units from OS */
  36. /*
  37. * use a singly linked list of free blocks.
  38. */
  39. struct adm {
  40. struct adm *next;
  41. int size;
  42. };
  43. extern struct adm *freep;
  44. extern void _trp(int); /* called on error */
  45. extern void _dis(int, struct adm **);
  46. /*
  47. * Helper function to request 'nu' units of memory from the OS.
  48. * A storage unit is sizeof(struct adm). Typically 8 bytes
  49. * on a 32-bit machine like i386 etc.
  50. */
  51. static struct adm *
  52. morecore(unsigned nu)
  53. {
  54. char *cp, *sbrk(int);
  55. struct adm *up;
  56. if (nu < NALLOC)
  57. nu = NALLOC;
  58. cp = sbrk(nu * sizeof(struct adm));
  59. if (cp == (char *) -1) /* no space at all */
  60. return 0;
  61. up = (struct adm*) cp;
  62. up->size = nu;
  63. up = up + 1;
  64. _dis((nu - 1) * sizeof(struct adm), &up);
  65. return freep;
  66. } /* morecore */
  67. /*
  68. * Dispose
  69. * Called with two arguments:
  70. * n the size of the block to be freed, in bytes,
  71. * pp address of pointer to data.
  72. */
  73. void
  74. _new(int n, struct adm **pp)
  75. {
  76. int nunits; /* the unit of storage is sizeof(struct adm) */
  77. struct adm *p,*q;
  78. /* round up size of request */
  79. nunits = (n + sizeof(struct adm) - 1) / sizeof(struct adm) + 1;
  80. q = 0;
  81. for (p = freep; ; p = p->next) {
  82. if (p == 0) {
  83. p = morecore(nunits);
  84. if (p == 0)
  85. _trp(EHEAP);
  86. q = 0;
  87. }
  88. if (p->size >= nunits) {
  89. if (p->size == nunits) { /* exact fit */
  90. if (q == 0) { /* first element on free list. */
  91. freep = p->next;
  92. } else {
  93. q->next = p->next;
  94. }
  95. } else { /* allocate tail end */
  96. q = p;
  97. q->size = q->size - nunits;
  98. p = q + q->size;
  99. p->next = 0;
  100. p->size = nunits;
  101. }
  102. break;
  103. }
  104. q = p;
  105. }
  106. *pp = p + 1;
  107. } /* _new */