Annotation of 43BSD/contrib/emacs/src/alloc.c, revision 1.1

1.1     ! root        1: /* Storage allocation and gc for GNU Emacs Lisp interpreter.
        !             2:    Copyright (C) 1985 Richard M. Stallman.
        !             3: 
        !             4: This file is part of GNU Emacs.
        !             5: 
        !             6: GNU Emacs is distributed in the hope that it will be useful,
        !             7: but WITHOUT ANY WARRANTY.  No author or distributor
        !             8: accepts responsibility to anyone for the consequences of using it
        !             9: or for whether it serves any particular purpose or works at all,
        !            10: unless he says so in writing.  Refer to the GNU Emacs General Public
        !            11: License for full details.
        !            12: 
        !            13: Everyone is granted permission to copy, modify and redistribute
        !            14: GNU Emacs, but only under the conditions described in the
        !            15: GNU Emacs General Public License.   A copy of this license is
        !            16: supposed to have been given to you along with GNU Emacs so you
        !            17: can know your rights and responsibilities.  It should be in a
        !            18: file named COPYING.  Among other things, the copyright notice
        !            19: and this notice must be preserved on all copies.  */
        !            20: 
        !            21: 
        !            22: #include "config.h"
        !            23: #include "lisp.h"
        !            24: #ifndef standalone
        !            25: #include "buffer.h"
        !            26: #include "window.h"
        !            27: #endif
        !            28: 
        !            29: /* Number of bytes of consing done since the last gc */
        !            30: int consing_since_gc;
        !            31: 
        !            32: /* Number of bytes of consing since gc before another gc should be done. */
        !            33: int gc_cons_threshold;
        !            34: 
        !            35: /* Nonzero during gc */
        !            36: int gc_in_progress;
        !            37: 
        !            38: #ifndef VIRT_ADDR_VARIES
        !            39: /* Address below which pointers should not be traced */
        !            40: extern char edata[];
        !            41: #endif /* VIRT_ADDR_VARIES */
        !            42: 
        !            43: #ifndef VIRT_ADDR_VARIES
        !            44: extern
        !            45: #endif /* VIRT_ADDR_VARIES */
        !            46:  int malloc_sbrk_used;
        !            47: 
        !            48: #ifndef VIRT_ADDR_VARIES
        !            49: extern
        !            50: #endif /* VIRT_ADDR_VARIES */
        !            51:  int malloc_sbrk_unused;
        !            52: 
        !            53: /* Non-nil means defun should do purecopy on the function definition */
        !            54: Lisp_Object Vpurify_flag;
        !            55: 
        !            56: int pure[PURESIZE / sizeof (int)] = {0,};   /* Force it into data space! */
        !            57: 
        !            58: #define PUREBEG (char *) pure
        !            59: 
        !            60: /* Index in pure at which next pure object will be allocated. */
        !            61: int pureptr;
        !            62: 
        !            63: Lisp_Object
        !            64: malloc_warning_1 (str)
        !            65:      Lisp_Object str;
        !            66: {
        !            67:   return Fprinc (str, Vstandard_output);
        !            68: }
        !            69: 
        !            70: /* malloc calls this if it finds we are near exhausting storage */
        !            71: malloc_warning (str)
        !            72:      char *str;
        !            73: {
        !            74:   Lisp_Object val;
        !            75:   val = build_string (str);
        !            76:   internal_with_output_to_temp_buffer (" *Danger*", malloc_warning_1, val);
        !            77: }
        !            78: 
        !            79: /* Called if malloc returns zero */
        !            80: memory_full ()
        !            81: {
        !            82:   error ("Memory exhausted");
        !            83: }
        !            84: 
        !            85: /* like malloc and realloc but check for no memory left */
        !            86: 
        !            87: long *
        !            88: xmalloc (size)
        !            89:      int size;
        !            90: {
        !            91:   long *val = (long *) malloc (size);
        !            92:   if (!val) memory_full ();
        !            93:   return val;
        !            94: }
        !            95: 
        !            96: long *
        !            97: xrealloc (block, size)
        !            98:      long *block;
        !            99:      int size;
        !           100: {
        !           101:   long *val = (long *) realloc (block, size);
        !           102:   if (!val) memory_full ();
        !           103:   return val;
        !           104: }
        !           105: 
        !           106: /* Allocation of cons cells */
        !           107: /* We store cons cells inside of cons_blocks, allocating a new
        !           108:  cons_block with malloc whenever necessary.  Cons cells reclaimed by
        !           109:  GC are put on a free list to be reallocated before allocating
        !           110:  any new cons cells from the latest cons_block.
        !           111: 
        !           112:  Each cons_block is just under 1020 bytes long,
        !           113:  since malloc really allocates in units of powers of two
        !           114:  and uses 4 bytes for its own overhead. */
        !           115: 
        !           116: #define CONS_BLOCK_SIZE \
        !           117:   ((1020 - sizeof (struct cons_block *)) / sizeof (struct Lisp_Cons))
        !           118: 
        !           119: struct cons_block
        !           120:   {
        !           121:     struct cons_block *next;
        !           122:     struct Lisp_Cons conses[CONS_BLOCK_SIZE];
        !           123:   };
        !           124: 
        !           125: struct cons_block *cons_block;
        !           126: int cons_block_index;
        !           127: 
        !           128: struct Lisp_Cons *cons_free_list;
        !           129: 
        !           130: void
        !           131: init_cons ()
        !           132: {
        !           133:   cons_block = (struct cons_block *) malloc (sizeof (struct cons_block));
        !           134:   cons_block->next = 0;
        !           135:   bzero (cons_block->conses, sizeof cons_block->conses);
        !           136:   cons_block_index = 0;
        !           137:   cons_free_list = 0;
        !           138: }
        !           139: 
        !           140: /* Explicitly free a cons cell.  */
        !           141: free_cons (ptr)
        !           142:      struct Lisp_Cons *ptr;
        !           143: {
        !           144:   XSETCONS (ptr->car, cons_free_list);
        !           145:   cons_free_list = ptr;
        !           146: }
        !           147: 
        !           148: DEFUN ("cons", Fcons, Scons, 2, 2, 0,
        !           149:   "Create a new cons, give it CAR and CDR as components, and return it.")
        !           150:   (car, cdr)
        !           151:      Lisp_Object car, cdr;
        !           152: {
        !           153:   register Lisp_Object val;
        !           154: 
        !           155:   if (cons_free_list)
        !           156:     {
        !           157:       XSET (val, Lisp_Cons, cons_free_list);
        !           158:       cons_free_list = XCONS (cons_free_list->car);
        !           159:     }
        !           160:   else
        !           161:     {
        !           162:       if (cons_block_index == CONS_BLOCK_SIZE)
        !           163:        {
        !           164:          register struct cons_block *new = (struct cons_block *) malloc (sizeof (struct cons_block));
        !           165:          if (!new) memory_full ();
        !           166:          new->next = cons_block;
        !           167:          cons_block = new;
        !           168:          cons_block_index = 0;
        !           169:        }
        !           170:       XSET (val, Lisp_Cons, &cons_block->conses[cons_block_index++]);
        !           171:     }
        !           172:   XCONS (val)->car = car;
        !           173:   XCONS (val)->cdr = cdr;
        !           174:   consing_since_gc += sizeof (struct Lisp_Cons);
        !           175:   return val;
        !           176: }
        !           177: 
        !           178: DEFUN ("list", Flist, Slist, 0, MANY, 0,
        !           179:   "Return a newly created list whose elements are the arguments (any number).")
        !           180:   (nargs, args)
        !           181:      int nargs;
        !           182:      Lisp_Object *args;
        !           183: {
        !           184:   Lisp_Object len, val, val_tail;
        !           185: 
        !           186:   XFASTINT (len) = nargs;
        !           187:   val = Fmake_list (len, Qnil);
        !           188:   val_tail = val;
        !           189:   while (!NULL (val_tail))
        !           190:     {
        !           191:       XCONS (val_tail)->car = *args++;
        !           192:       val_tail = XCONS (val_tail)->cdr;
        !           193:     }
        !           194:   return val;
        !           195: }
        !           196: 
        !           197: DEFUN ("make-list", Fmake_list, Smake_list, 2, 2, 0,
        !           198:   "Return a newly created list of length LENGTH, with each element being INIT.")
        !           199:   (length, init)
        !           200:      Lisp_Object length, init;
        !           201: {
        !           202:   register Lisp_Object val;
        !           203:   register int size;
        !           204: 
        !           205:   if (XTYPE (length) != Lisp_Int || XINT (length) < 0)
        !           206:     length = wrong_type_argument (Qnatnump, length);
        !           207:   size = XINT (length);
        !           208: 
        !           209:   val = Qnil;
        !           210:   while (size-- > 0)
        !           211:     val = Fcons (init, val);
        !           212:   return val;
        !           213: }
        !           214: 
        !           215: /* Allocation of vectors */
        !           216: 
        !           217: struct Lisp_Vector *all_vectors;
        !           218: 
        !           219: DEFUN ("make-vector", Fmake_vector, Smake_vector, 2, 2, 0,
        !           220:   "Return a newly created vector of length LENGTH, with each element being INIT.")
        !           221:   (length, init)
        !           222:      Lisp_Object length, init;
        !           223: {
        !           224:   register int sizei, index;
        !           225:   register Lisp_Object vector;
        !           226: 
        !           227:   if (XTYPE (length) != Lisp_Int || XINT (length) < 0)
        !           228:     length = wrong_type_argument (Qnatnump, length);
        !           229:   sizei = XINT (length);
        !           230: 
        !           231:   XSET (vector, Lisp_Vector,
        !           232:        (struct Lisp_Vector *) malloc (sizeof (struct Lisp_Vector) + (sizei - 1) * sizeof (Lisp_Object)));
        !           233:   consing_since_gc += sizeof (struct Lisp_Vector) + (sizei - 1) * sizeof (Lisp_Object);
        !           234:   if (!XVECTOR (vector))
        !           235:     memory_full ();
        !           236: 
        !           237:   XVECTOR (vector)->size = sizei;
        !           238:   XVECTOR (vector)->next = all_vectors;
        !           239:   all_vectors = XVECTOR (vector);
        !           240: 
        !           241:   for (index = 0; index < sizei; index++)
        !           242:     XVECTOR (vector)->contents[index] = init;
        !           243: 
        !           244:   return vector;
        !           245: }
        !           246: 
        !           247: DEFUN ("vector", Fvector, Svector, 0, MANY, 0,
        !           248:   "Return a newly created vector with our arguments (any number) as its elements.")
        !           249:   (nargs, args)
        !           250:      int nargs;
        !           251:      Lisp_Object *args;
        !           252: {
        !           253:   register Lisp_Object len, val;
        !           254:   register int index;
        !           255:   register struct Lisp_Vector *p;
        !           256: 
        !           257:   XFASTINT (len) = nargs;
        !           258:   val = Fmake_vector (len, Qnil);
        !           259:   p = XVECTOR (val);
        !           260:   for (index = 0; index < nargs; index++)
        !           261:     p->contents[index] = args[index];
        !           262:   return val;
        !           263: }
        !           264: 
        !           265: /* Allocation of symbols.
        !           266:  Just like allocation of conses!
        !           267: 
        !           268:  Each symbol_block is just under 1020 bytes long,
        !           269:  since malloc really allocates in units of powers of two
        !           270:  and uses 4 bytes for its own overhead. */
        !           271: 
        !           272: #define SYMBOL_BLOCK_SIZE \
        !           273:   ((1020 - sizeof (struct symbol_block *)) / sizeof (struct Lisp_Symbol))
        !           274: 
        !           275: struct symbol_block
        !           276:   {
        !           277:     struct symbol_block *next;
        !           278:     struct Lisp_Symbol symbols[SYMBOL_BLOCK_SIZE];
        !           279:   };
        !           280: 
        !           281: struct symbol_block *symbol_block;
        !           282: int symbol_block_index;
        !           283: 
        !           284: struct Lisp_Symbol *symbol_free_list;
        !           285: 
        !           286: void
        !           287: init_symbol ()
        !           288: {
        !           289:   symbol_block = (struct symbol_block *) malloc (sizeof (struct symbol_block));
        !           290:   symbol_block->next = 0;
        !           291:   bzero (symbol_block->symbols, sizeof symbol_block->symbols);
        !           292:   symbol_block_index = 0;
        !           293:   symbol_free_list = 0;
        !           294: }
        !           295: 
        !           296: DEFUN ("make-symbol", Fmake_symbol, Smake_symbol, 1, 1, 0,
        !           297:   "Return a newly allocated uninterned symbol whose name is NAME.\n\
        !           298: Its value and function definition are void, and its property list is NIL.")
        !           299:   (str)
        !           300:      Lisp_Object str;
        !           301: {
        !           302:   register Lisp_Object val;
        !           303: 
        !           304:   CHECK_STRING (str, 0);
        !           305: 
        !           306:   if (symbol_free_list)
        !           307:     {
        !           308:       XSET (val, Lisp_Symbol, symbol_free_list);
        !           309:       symbol_free_list = XSYMBOL (symbol_free_list->value);
        !           310:     }
        !           311:   else
        !           312:     {
        !           313:       if (symbol_block_index == SYMBOL_BLOCK_SIZE)
        !           314:        {
        !           315:          struct symbol_block *new = (struct symbol_block *) malloc (sizeof (struct symbol_block));
        !           316:          if (!new) memory_full ();
        !           317:          new->next = symbol_block;
        !           318:          symbol_block = new;
        !           319:          symbol_block_index = 0;
        !           320:        }
        !           321:       XSET (val, Lisp_Symbol, &symbol_block->symbols[symbol_block_index++]);
        !           322:     }
        !           323:   XSYMBOL (val)->name = XSTRING (str);
        !           324:   XSYMBOL (val)->plist = Qnil;
        !           325:   XSYMBOL (val)->value = Qunbound;
        !           326:   XSYMBOL (val)->function = Qunbound;
        !           327:   XSYMBOL (val)->next = 0;
        !           328:   consing_since_gc += sizeof (struct Lisp_Symbol);
        !           329:   return val;
        !           330: }
        !           331: 
        !           332: /* Allocation of markers.
        !           333:  Works like allocation of conses. */
        !           334: 
        !           335: #define MARKER_BLOCK_SIZE \
        !           336:   ((1020 - sizeof (struct marker_block *)) / sizeof (struct Lisp_Marker))
        !           337: 
        !           338: struct marker_block
        !           339:   {
        !           340:     struct marker_block *next;
        !           341:     struct Lisp_Marker markers[MARKER_BLOCK_SIZE];
        !           342:   };
        !           343: 
        !           344: struct marker_block *marker_block;
        !           345: int marker_block_index;
        !           346: 
        !           347: struct Lisp_Marker *marker_free_list;
        !           348: 
        !           349: void
        !           350: init_marker ()
        !           351: {
        !           352:   marker_block = (struct marker_block *) malloc (sizeof (struct marker_block));
        !           353:   marker_block->next = 0;
        !           354:   bzero (marker_block->markers, sizeof marker_block->markers);
        !           355:   marker_block_index = 0;
        !           356:   marker_free_list = 0;
        !           357: }
        !           358: 
        !           359: DEFUN ("make-marker", Fmake_marker, Smake_marker, 0, 0, 0,
        !           360:   "Return a newly allocated marker which does not point at any place.")
        !           361:   ()
        !           362: {
        !           363:   register Lisp_Object val;
        !           364: 
        !           365:   if (marker_free_list)
        !           366:     {
        !           367:       XSET (val, Lisp_Marker, marker_free_list);
        !           368:       marker_free_list = XMARKER (marker_free_list->chain);
        !           369:     }
        !           370:   else
        !           371:     {
        !           372:       if (marker_block_index == MARKER_BLOCK_SIZE)
        !           373:        {
        !           374:          struct marker_block *new = (struct marker_block *) malloc (sizeof (struct marker_block));
        !           375:          if (!new) memory_full ();
        !           376:          new->next = marker_block;
        !           377:          marker_block = new;
        !           378:          marker_block_index = 0;
        !           379:        }
        !           380:       XSET (val, Lisp_Marker, &marker_block->markers[marker_block_index++]);
        !           381:     }
        !           382:   XMARKER (val)->buffer = 0;
        !           383:   XMARKER (val)->bufpos = 0;
        !           384:   XMARKER (val)->modified = 0;
        !           385:   XMARKER (val)->chain = Qnil;
        !           386:   consing_since_gc += sizeof (struct Lisp_Marker);
        !           387:   return val;
        !           388: }
        !           389: 
        !           390: /* Allocation of strings */
        !           391: 
        !           392: /* Strings reside inside of string_blocks.  The entire data of the string,
        !           393:  both the size and the contents, live in part of the `chars' component of a string_block.
        !           394:  The `pos' component is the index within `chars' of the first free byte */
        !           395: 
        !           396: /* String blocks contain this many bytes.
        !           397:   Power of 2, minus 4 for malloc overhead. */
        !           398: #define STRING_BLOCK_SIZE (8188 - sizeof (struct string_block_head))
        !           399: 
        !           400: /* A string bigger than this gets its own specially-made string block
        !           401:  if it doesn't fit in the current one. */
        !           402: #define STRING_BLOCK_OUTSIZE 1024
        !           403: 
        !           404: struct string_block_head
        !           405:   {
        !           406:     struct string_block *next;
        !           407:     int pos;
        !           408:   };
        !           409: 
        !           410: struct string_block
        !           411:   {
        !           412:     struct string_block *next;
        !           413:     int pos;
        !           414:     char chars[STRING_BLOCK_SIZE];
        !           415:   };
        !           416: 
        !           417: /* This points to the string block we are now allocating strings in
        !           418:  which is also the beginning of the chain of all string blocks ever made */
        !           419: 
        !           420: struct string_block *current_string_block;
        !           421: 
        !           422: void
        !           423: init_strings ()
        !           424: {
        !           425:   current_string_block = (struct string_block *) malloc (sizeof (struct string_block));
        !           426:   consing_since_gc += sizeof (struct string_block);
        !           427:   current_string_block->next = 0;
        !           428:   current_string_block->pos = 0;
        !           429: }
        !           430: 
        !           431: static Lisp_Object make_zero_string ();
        !           432: 
        !           433: DEFUN ("make-string", Fmake_string, Smake_string, 2, 2, 0,
        !           434:   "Return a newly created string of length LENGTH, with each element being INIT.\n\
        !           435: Both LENGTH and INIT must be numbers.")
        !           436:   (length, init)
        !           437:      Lisp_Object length, init;
        !           438: {
        !           439:   if (XTYPE (length) != Lisp_Int || XINT (length) < 0)
        !           440:     length = wrong_type_argument (Qnatnump, length);
        !           441:   CHECK_NUMBER (init, 1);
        !           442:   return make_zero_string (XINT (length), XINT (init));
        !           443: }
        !           444: 
        !           445: Lisp_Object
        !           446: make_string (contents, length)
        !           447:      char *contents;
        !           448:      int length;
        !           449: {
        !           450:   Lisp_Object val;
        !           451:   val = make_zero_string (length, 0);
        !           452:   bcopy (contents, XSTRING (val)->data, length);
        !           453:   return val;
        !           454: }
        !           455: 
        !           456: Lisp_Object
        !           457: build_string (str)
        !           458:      char *str;
        !           459: {
        !           460:   return make_string (str, strlen (str));
        !           461: }
        !           462: 
        !           463: static Lisp_Object
        !           464: make_zero_string (length, init)
        !           465:      int length;
        !           466:      register int init;
        !           467: {
        !           468:   register Lisp_Object val;
        !           469:   register int fullsize = length + sizeof (int);
        !           470:   register unsigned char *p, *end;
        !           471: 
        !           472:   if (length < 0) abort ();
        !           473: 
        !           474:   /* Round `fullsize' up to multiple of size of int; also add one for terminating zero */
        !           475:   fullsize += sizeof (int);
        !           476:   fullsize &= ~(sizeof (int) - 1);
        !           477: 
        !           478:   if (fullsize <= STRING_BLOCK_SIZE - current_string_block->pos)
        !           479:     /* This string can fit in the current string block */
        !           480:     {
        !           481:       XSET (val, Lisp_String,
        !           482:            (struct Lisp_String *) (current_string_block->chars + current_string_block->pos));
        !           483:       current_string_block->pos += fullsize;
        !           484:     }
        !           485:   else if (fullsize > STRING_BLOCK_OUTSIZE)
        !           486:     /* This string gets its own string block */
        !           487:     {
        !           488:       struct string_block *new = (struct string_block *) malloc (sizeof (struct string_block_head) + fullsize);
        !           489:       if (!new) memory_full ();
        !           490:       consing_since_gc += sizeof (struct string_block_head) + fullsize;
        !           491:       new->pos = fullsize;
        !           492:       new->next = current_string_block->next;
        !           493:       current_string_block->next = new;
        !           494:       XSET (val, Lisp_String,
        !           495:            (struct Lisp_String *) ((struct string_block_head *)new + 1));
        !           496:     }
        !           497:   else
        !           498:     /* Make a new current string block and start it off with this string */
        !           499:     {
        !           500:       struct string_block *new = (struct string_block *) malloc (sizeof (struct string_block));
        !           501:       if (!new) memory_full ();
        !           502:       consing_since_gc += sizeof (struct string_block);
        !           503:       new->next = current_string_block;
        !           504:       current_string_block = new;
        !           505:       new->pos = fullsize;
        !           506:       XSET (val, Lisp_String,
        !           507:            (struct Lisp_String *) current_string_block->chars);
        !           508:     }
        !           509:     
        !           510:   XSTRING (val)->size = length;
        !           511:   p = XSTRING (val)->data;
        !           512:   end = p + XSTRING (val)->size;
        !           513:   while (p != end)
        !           514:     *p++ = init;
        !           515:   *p = 0;
        !           516: 
        !           517:   return val;
        !           518: }
        !           519: 
        !           520: /* Must get an error if pure storage is full,
        !           521:  since if it cannot hold a large string
        !           522:  it may be able to hold conses that point to that string;
        !           523:  then the string is not protected from gc. */
        !           524: 
        !           525: Lisp_Object
        !           526: make_pure_string (data, length)
        !           527:      char *data;
        !           528:      int length;
        !           529: {
        !           530:   Lisp_Object new;
        !           531:   int size = sizeof (int) + length + 1;
        !           532: 
        !           533:   if (pureptr + size > PURESIZE)
        !           534:     error ("Pure Lisp storage exhausted");
        !           535:   XSET (new, Lisp_String, PUREBEG + pureptr);
        !           536:   XSTRING (new)->size = length;
        !           537:   bcopy (data, XSTRING (new)->data, length);
        !           538:   XSTRING (new)->data[length] = 0;
        !           539:   pureptr += (size + sizeof (int) - 1)
        !           540:             / sizeof (int) * sizeof (int);
        !           541:   return new;
        !           542: }
        !           543: 
        !           544: Lisp_Object
        !           545: pure_cons (car, cdr)
        !           546:      Lisp_Object car, cdr;
        !           547: {
        !           548:   Lisp_Object new;
        !           549: 
        !           550:   if (pureptr + sizeof (struct Lisp_Cons) > PURESIZE)
        !           551:     error ("Pure Lisp storage exhausted");
        !           552:   XSET (new, Lisp_Cons, PUREBEG + pureptr);
        !           553:   pureptr += sizeof (struct Lisp_Cons);
        !           554:   XCONS (new)->car = Fpurecopy (car);
        !           555:   XCONS (new)->cdr = Fpurecopy (cdr);
        !           556:   return new;
        !           557: }
        !           558: 
        !           559: Lisp_Object
        !           560: make_pure_vector (len)
        !           561:      int len;
        !           562: {
        !           563:   Lisp_Object new;
        !           564:   int size = sizeof (struct Lisp_Vector) + (len - 1) * sizeof (Lisp_Object);
        !           565: 
        !           566:   if (pureptr + size > PURESIZE)
        !           567:     error ("Pure Lisp storage exhausted");
        !           568: 
        !           569:   XSET (new, Lisp_Vector, PUREBEG + pureptr);
        !           570:   pureptr += size;
        !           571:   XVECTOR (new)->size = len;
        !           572:   return new;
        !           573: }
        !           574: 
        !           575: DEFUN ("purecopy", Fpurecopy, Spurecopy, 1, 1, 0,
        !           576:   "Make a copy of OBJECT in pure storage.\n\
        !           577: Recursively copies contents of vectors and cons cells.\n\
        !           578: Does not copy symbols.")
        !           579:   (obj)
        !           580:      Lisp_Object obj;
        !           581: {
        !           582:   Lisp_Object new, tem;
        !           583:   int i;
        !           584: 
        !           585: #ifndef VIRT_ADDR_VARIES
        !           586:   /* Need not trace pointers to pure storage */
        !           587:   if (XUINT (obj) < (unsigned int) edata && XUINT (obj) >= 0)
        !           588:     return obj;
        !           589: #else /* VIRT_ADDR_VARIES */
        !           590:   if (XUINT (obj) < (unsigned int) ((char *) pure + PURESIZE)
        !           591:       && XUINT (obj) >= (unsigned int) pure)
        !           592:     return obj;
        !           593: #endif /* VIRT_ADDR_VARIES */
        !           594: 
        !           595: #ifdef SWITCH_ENUM_BUG
        !           596:   switch ((int) XTYPE (obj))
        !           597: #else
        !           598:   switch (XTYPE (obj))
        !           599: #endif
        !           600:     {
        !           601:     case Lisp_Marker:
        !           602:       error ("Attempt to copy a marker to pure storage");
        !           603: 
        !           604:     case Lisp_Cons:
        !           605:       return pure_cons (XCONS (obj)->car, XCONS (obj)->cdr);
        !           606: 
        !           607:     case Lisp_String:
        !           608:       return make_pure_string (XSTRING (obj)->data, XSTRING (obj)->size);
        !           609: 
        !           610:     case Lisp_Vector:
        !           611:       new = make_pure_vector (XVECTOR (obj)->size);
        !           612:       for (i = 0; i < XVECTOR (obj)->size; i++)
        !           613:        {
        !           614:          tem = XVECTOR (obj)->contents[i];
        !           615:          XVECTOR (new)->contents[i] = Fpurecopy (tem);
        !           616:        }
        !           617:       return new;
        !           618: 
        !           619:     default:
        !           620:       return obj;
        !           621:     }
        !           622: }
        !           623: 
        !           624: /* Recording what needs to be marked for gc.  */
        !           625: 
        !           626: struct gcpro *gcprolist;
        !           627: 
        !           628: #define NSTATICS 100
        !           629: 
        !           630: char staticvec1[NSTATICS * sizeof (Lisp_Object *)] = {0};
        !           631: 
        !           632: int staticidx = 0;
        !           633: 
        !           634: #define staticvec ((Lisp_Object **) staticvec1)
        !           635: 
        !           636: /* Put an entry in staticvec, pointing at the variable whose address is given */
        !           637: 
        !           638: void
        !           639: staticpro (varaddress)
        !           640:      Lisp_Object *varaddress;
        !           641: {
        !           642:   staticvec[staticidx++] = varaddress;
        !           643:   if (staticidx >= NSTATICS)
        !           644:     abort ();
        !           645: }
        !           646: 
        !           647: struct catchtag
        !           648:   {
        !           649:     Lisp_Object tag;
        !           650:     Lisp_Object val;
        !           651:     struct catchtag *next;
        !           652: /*    jmp_buf jmp;  /* We don't need this for GC purposes */
        !           653:   };
        !           654: 
        !           655: extern struct catchtag *catchlist;
        !           656: 
        !           657: struct backtrace
        !           658:   {
        !           659:     struct backtrace *next;
        !           660:     Lisp_Object *function;
        !           661:     Lisp_Object *args; /* Points to vector of args. */
        !           662:     int nargs;         /* length of vector */
        !           663:               /* if nargs is UNEVALLED, args points to slot holding list of unevalled args */
        !           664:     char evalargs;
        !           665:   };
        !           666: 
        !           667: extern struct backtrace *backtrace_list;
        !           668: 
        !           669: /* On vector, means it has been marked.
        !           670:  On string, means it has been copied.  */
        !           671: static int most_negative_fixnum;
        !           672: 
        !           673: /* On string, means do not copy it.
        !           674:  This is set in all copies, and perhaps will be used
        !           675:  to indicate strings that there is no need to copy.  */
        !           676: static int dont_copy_flag;
        !           677: 
        !           678: int total_conses, total_markers, total_symbols, total_string_size, total_vector_size;
        !           679: int total_free_conses, total_free_markers, total_free_symbols;
        !           680: 
        !           681: /* Garbage collection: mark and sweep, except copy strings. */
        !           682: static Lisp_Object mark_object ();
        !           683: static void clear_marks (), gc_sweep ();
        !           684: 
        !           685: DEFUN ("garbage-collect", Fgarbage_collect, Sgarbage_collect, 0, 0, "",
        !           686:   "Reclaim storage for Lisp objects no longer needed.\n\
        !           687: Returns info on amount of space in use:\n\
        !           688:  ((USED-CONSES . FREE-CONSES) (USED-SYMS . FREE-SYMS)\n\
        !           689:   (USED-MARKERS . FREE-MARKERS) USED-STRING-CHARS USED-VECTOR-SLOTS)\n\
        !           690: Garbage collection happens automatically if you cons more than\n\
        !           691: gc-cons-threshold  bytes of Lisp data since previous garbage collection.")
        !           692:   ()
        !           693: {
        !           694:   struct string_block *old_string_block;
        !           695: 
        !           696:   register struct gcpro *tail;
        !           697:   register struct specbinding *bind;
        !           698:   struct catchtag *catch;
        !           699:   struct handler *handler;
        !           700:   register struct backtrace *backlist;
        !           701:   register Lisp_Object tem;
        !           702:   char *omessage = minibuf_message;
        !           703: 
        !           704:   register int i;
        !           705: 
        !           706:   if (!noninteractive)
        !           707:     message1 ("Garbage collecting...");
        !           708: 
        !           709:   /* Don't keep command history around forever */
        !           710:   tem = Fnthcdr (make_number (30), Vcommand_history);
        !           711:   if (LISTP (tem))
        !           712:     XCONS (tem)->cdr = Qnil;
        !           713: 
        !           714:   gc_in_progress = 1;
        !           715: 
        !           716:   clear_marks ();
        !           717:   old_string_block = current_string_block;
        !           718:   current_string_block = 0;
        !           719:   total_string_size = 0;
        !           720:   init_strings ();
        !           721: 
        !           722:   for (tail = gcprolist; tail; tail = tail->next)
        !           723:     {
        !           724:       for (i = 0; i < tail->nvars; i++)
        !           725:        {
        !           726:          tem = tail->var[i];
        !           727:          tail->var[i] = mark_object (tem);
        !           728:        }
        !           729:     }
        !           730:   for (i = 0; i < staticidx; i++)
        !           731:     {
        !           732:       tem = *staticvec[i];
        !           733:       *staticvec[i] = mark_object (tem);
        !           734:     }
        !           735:   for (bind = specpdl; bind != specpdl_ptr; bind++)
        !           736:     {
        !           737:       bind->symbol = mark_object (bind->symbol);
        !           738:       bind->old_value = mark_object (bind->old_value);
        !           739:     }
        !           740:   for (catch = catchlist; catch; catch = catch->next)
        !           741:     {
        !           742:       catch->tag = mark_object (catch->tag);
        !           743:       catch->val = mark_object (catch->val);
        !           744:     }  
        !           745:   for (handler = handlerlist; handler; handler = handler->next)
        !           746:     {
        !           747:       handler->handler = mark_object (handler->handler);
        !           748:       handler->var = mark_object (handler->var);
        !           749:     }  
        !           750:   for (backlist = backtrace_list; backlist; backlist = backlist->next)
        !           751:     {
        !           752:       tem = *backlist->function;
        !           753:       *backlist->function = mark_object (tem);
        !           754:       if (backlist->nargs == UNEVALLED || backlist->nargs == MANY)
        !           755:        {
        !           756:          tem = *backlist->args;
        !           757:          *backlist->args = mark_object (tem);
        !           758:        }
        !           759:       else
        !           760:        for (i = 0; i < backlist->nargs; i++)
        !           761:          {
        !           762:            tem = backlist->args[i];
        !           763:            backlist->args[i] = mark_object (tem);
        !           764:          }
        !           765:     }  
        !           766: 
        !           767:   gc_sweep (old_string_block);
        !           768: 
        !           769:   clear_marks ();
        !           770:   gc_in_progress = 0;
        !           771: 
        !           772:   consing_since_gc = 0;
        !           773:   if (gc_cons_threshold < 10000)
        !           774:     gc_cons_threshold = 10000;
        !           775: 
        !           776:   if (omessage)
        !           777:     message1 (omessage);
        !           778:   else if (!noninteractive)
        !           779:     message1 ("Garbage collecting...done");
        !           780:   
        !           781:   return Fcons (Fcons (make_number (total_conses),
        !           782:                       make_number (total_free_conses)),
        !           783:                Fcons (Fcons (make_number (total_symbols),
        !           784:                              make_number (total_free_symbols)),
        !           785:                       Fcons (Fcons (make_number (total_markers),
        !           786:                                     make_number (total_free_markers)),
        !           787:                              Fcons (make_number (total_string_size),
        !           788:                                     Fcons (make_number (total_vector_size),
        !           789:                                            Qnil)))));
        !           790: }
        !           791: 
        !           792: static void
        !           793: clear_marks ()
        !           794: {
        !           795:   /* Clear marks on all strings */
        !           796:   {
        !           797:     register struct string_block *csb;
        !           798:     register int pos;
        !           799: 
        !           800:     for (csb = current_string_block; csb; csb = csb->next)
        !           801:       {
        !           802:        pos = 0;
        !           803:        while (pos < csb->pos)
        !           804:          {
        !           805:            register struct Lisp_String *nextstr
        !           806:              = (struct Lisp_String *) &csb->chars[pos];
        !           807:            register int fullsize;
        !           808: 
        !           809:            nextstr->size &= ~dont_copy_flag;
        !           810:            fullsize = nextstr->size + sizeof (int);    
        !           811:            
        !           812:            fullsize += sizeof (int);
        !           813:            fullsize &= ~(sizeof (int) - 1);
        !           814:            pos += fullsize;
        !           815:          }
        !           816:       }
        !           817:   }
        !           818:   /* Clear marks on all conses */
        !           819:   {
        !           820:     register struct cons_block *cblk;
        !           821:     register int lim = cons_block_index;
        !           822:   
        !           823:     for (cblk = cons_block; cblk; cblk = cblk->next)
        !           824:       {
        !           825:        register int i;
        !           826:        for (i = 0; i < lim; i++)
        !           827:          XUNMARK (cblk->conses[i].car);
        !           828:        lim = CONS_BLOCK_SIZE;
        !           829:       }
        !           830:   }
        !           831:   /* Clear marks on all symbols */
        !           832:   {
        !           833:     register struct symbol_block *sblk;
        !           834:     register int lim = symbol_block_index;
        !           835:   
        !           836:     for (sblk = symbol_block; sblk; sblk = sblk->next)
        !           837:       {
        !           838:        register int i;
        !           839:        for (i = 0; i < lim; i++)
        !           840:          XUNMARK (sblk->symbols[i].plist);
        !           841:        lim = SYMBOL_BLOCK_SIZE;
        !           842:       }
        !           843:   }
        !           844:   /* Clear marks on all markers */
        !           845:   {
        !           846:     register struct marker_block *sblk;
        !           847:     register int lim = marker_block_index;
        !           848:   
        !           849:     for (sblk = marker_block; sblk; sblk = sblk->next)
        !           850:       {
        !           851:        register int i;
        !           852:        for (i = 0; i < lim; i++)
        !           853:          XUNMARK (sblk->markers[i].chain);
        !           854:        lim = MARKER_BLOCK_SIZE;
        !           855:       }
        !           856:   }
        !           857:   /* Clear mark bits on all buffers */
        !           858:   {
        !           859:     register struct buffer *nextb = all_buffers;
        !           860: 
        !           861:     while (nextb)
        !           862:       {
        !           863:        XUNMARK (nextb->name);
        !           864:        nextb = nextb->next;
        !           865:       }
        !           866:   }
        !           867: }
        !           868: 
        !           869: /* Mark one Lisp object, and recursively mark all the objects it points to
        !           870:  if this is the first time it is being marked.
        !           871:  If the object is a string, it is copied (once, only) and the copy is returned.
        !           872:  The original string's `size' is set to a value in which 1<<31 is set
        !           873:    and the rest of which is the string address shifted right by one.
        !           874:  If the object is not a string, it is returned unchanged. */
        !           875: 
        !           876: static Lisp_Object
        !           877: mark_object (obj)
        !           878:      Lisp_Object obj;
        !           879: {
        !           880:   Lisp_Object original;
        !           881: 
        !           882:   original = obj;
        !           883: 
        !           884:  loop:
        !           885: #ifndef VIRT_ADDR_VARIES
        !           886:   /* Need not trace pointers to pure storage */
        !           887:   if (XUINT (obj) < (unsigned int) edata && XUINT (obj) >= 0)
        !           888:     return original;
        !           889: #else /* VIRT_ADDR_VARIES */
        !           890:   if (XUINT (obj) < (unsigned int) ((char *) pure + PURESIZE)
        !           891:       && XUINT (obj) >= (unsigned int) pure)
        !           892:     return original;
        !           893: #endif /* VIRT_ADDR_VARIES */
        !           894: 
        !           895: #ifdef SWITCH_ENUM_BUG
        !           896:   switch ((int) XGCTYPE (obj))
        !           897: #else
        !           898:   switch (XGCTYPE (obj))
        !           899: #endif
        !           900:     {
        !           901:     case Lisp_String:
        !           902:       {
        !           903:        register struct Lisp_String *ptr = XSTRING (obj);
        !           904:        Lisp_Object tem;
        !           905: 
        !           906:        if (ptr->size & most_negative_fixnum)
        !           907:          {
        !           908:            XSETSTRING (obj, (struct Lisp_String *) (ptr->size & ~most_negative_fixnum));
        !           909:            return obj;
        !           910:          }
        !           911:        if (ptr->size & dont_copy_flag)
        !           912:          return obj;
        !           913:        total_string_size += ptr->size;
        !           914:        tem = make_string (ptr->data, ptr->size);
        !           915:        ptr->size = most_negative_fixnum | XINT (tem);
        !           916:        XSTRING (tem)->size |= dont_copy_flag;
        !           917:        return tem;
        !           918:       }
        !           919: 
        !           920:     case Lisp_Vector:
        !           921:     case Lisp_Window:
        !           922:     case Lisp_Process:
        !           923:       {
        !           924:        register struct Lisp_Vector *ptr = XVECTOR (obj);
        !           925:        register int size = ptr->size;
        !           926:        register int i;
        !           927:        Lisp_Object tem;
        !           928: 
        !           929:        if (size & most_negative_fixnum) break;   /* Already marked */
        !           930:        ptr->size |= most_negative_fixnum; /* Else mark it */
        !           931:        for (i = 0; i < size; i++)     /* and then mark its elements */
        !           932:          {
        !           933:            tem = ptr->contents[i];
        !           934:            ptr->contents[i] = mark_object (tem);
        !           935:          }
        !           936:       }
        !           937:       break;
        !           938: 
        !           939:     case Lisp_Temp_Vector:
        !           940:       {
        !           941:        register struct Lisp_Vector *ptr = XVECTOR (obj);
        !           942:        register int size = ptr->size;
        !           943:        register int i;
        !           944:        Lisp_Object tem;
        !           945: 
        !           946:        for (i = 0; i < size; i++)     /* and then mark its elements */
        !           947:          {
        !           948:            tem = ptr->contents[i];
        !           949:            ptr->contents[i] = mark_object (tem);
        !           950:          }
        !           951:       }
        !           952:       break;
        !           953: 
        !           954:     case Lisp_Symbol:
        !           955:       {
        !           956:        register struct Lisp_Symbol *ptr = XSYMBOL (obj);
        !           957:        struct Lisp_Symbol *ptrx;
        !           958:        Lisp_Object tem;
        !           959: 
        !           960:        if (XMARKBIT (ptr->plist)) break;
        !           961:        XMARK (ptr->plist);
        !           962:        XSET (tem, Lisp_String, ptr->name);
        !           963:        tem = mark_object (tem);
        !           964:        ptr->name = XSTRING (tem);
        !           965:        ptr->value = mark_object (ptr->value);
        !           966:        ptr->function = mark_object (ptr->function);
        !           967:        tem = ptr->plist;
        !           968:        XUNMARK (tem);
        !           969:        ptr->plist = mark_object (tem);
        !           970:        XMARK (ptr->plist);
        !           971:        ptr = ptr->next;
        !           972:        if (ptr)
        !           973:          {
        !           974:            ptrx = ptr;         /* Use pf ptrx avoids compiled bug on Sun */
        !           975:            XSETSYMBOL (obj, ptrx);
        !           976:            goto loop;
        !           977:          }
        !           978:       }
        !           979:       break;
        !           980: 
        !           981:     case Lisp_Marker:
        !           982:       XMARK (XMARKER (obj)->chain);
        !           983:       /* DO NOT mark thru the marker's chain.
        !           984:         The buffer's markers chain does not preserve markers from gc;
        !           985:         instead, markers are removed from the chain when they are freed by gc. */
        !           986:       break;
        !           987: 
        !           988:     case Lisp_Cons:
        !           989:     case Lisp_Buffer_Local_Value:
        !           990:     case Lisp_Some_Buffer_Local_Value:
        !           991:       {
        !           992:        Lisp_Object tem;
        !           993:        register struct Lisp_Cons *ptr = XCONS (obj);
        !           994:        if (XMARKBIT (ptr->car)) break;
        !           995:        tem = ptr->car;
        !           996:        XMARK (ptr->car);
        !           997:        ptr->car = mark_object (tem);
        !           998:        XMARK (ptr->car);
        !           999:        if (XGCTYPE (ptr->cdr) != Lisp_String)
        !          1000:          {
        !          1001:            obj = ptr->cdr;
        !          1002:            goto loop;
        !          1003:          }
        !          1004:        ptr->cdr = mark_object (ptr->cdr);
        !          1005:       }
        !          1006:       break;
        !          1007:     
        !          1008:     case Lisp_Objfwd:
        !          1009:       *XOBJFWD (obj) = mark_object (*XOBJFWD (obj));
        !          1010:       break;
        !          1011: 
        !          1012:     case Lisp_Buffer:
        !          1013:       if (!XMARKBIT (XBUFFER (obj)->name))
        !          1014:        mark_buffer (obj);
        !          1015:       break;
        !          1016: 
        !          1017:     /* Don't bother with Lisp_Buffer_Objfwd,
        !          1018:        since all markable slots in current buffer marked anyway.  */
        !          1019:     }
        !          1020:   return original;
        !          1021: }
        !          1022: 
        !          1023: /* Mark the pointers in a buffer structure.  */
        !          1024: 
        !          1025: mark_buffer (buf)
        !          1026:      Lisp_Object buf;
        !          1027: {
        !          1028:   Lisp_Object tem;
        !          1029:   register struct buffer *buffer = XBUFFER (buf);
        !          1030: 
        !          1031:   buffer->number = mark_object (buffer->number);
        !          1032:   buffer->name = mark_object (buffer->name);
        !          1033:   XMARK (buffer->name);
        !          1034:   buffer->filename = mark_object (buffer->filename);
        !          1035:   buffer->directory = mark_object (buffer->directory);
        !          1036:   buffer->save_length = mark_object (buffer->save_length);
        !          1037:   buffer->auto_save_file_name = mark_object (buffer->auto_save_file_name);
        !          1038:   buffer->read_only = mark_object (buffer->read_only);
        !          1039:   /* buffer->markers does not preserve from gc: scavenger removes marker from
        !          1040:      the markers chain if it is freed.  See gc_sweep */
        !          1041:   buffer->mark = mark_object (buffer->mark);
        !          1042:   buffer->major_mode = mark_object (buffer->major_mode);
        !          1043:   buffer->mode_name = mark_object (buffer->mode_name);
        !          1044:   buffer->mode_line_format = mark_object (buffer->mode_line_format);
        !          1045:   buffer->keymap = mark_object (buffer->keymap);
        !          1046:   XSET (tem, Lisp_Vector, buffer->syntax_table_v);
        !          1047:   if (buffer->syntax_table_v)
        !          1048:     mark_object (tem);
        !          1049:   buffer->abbrev_table = mark_object (buffer->abbrev_table);
        !          1050:   buffer->case_fold_search = mark_object (buffer->case_fold_search);
        !          1051:   buffer->tab_width = mark_object (buffer->tab_width);
        !          1052:   buffer->fill_column = mark_object (buffer->fill_column);
        !          1053:   buffer->left_margin = mark_object (buffer->left_margin);
        !          1054:   buffer->auto_fill_hook = mark_object (buffer->auto_fill_hook);
        !          1055:   buffer->local_var_alist = mark_object (buffer->local_var_alist);
        !          1056:   buffer->truncate_lines = mark_object (buffer->truncate_lines);
        !          1057:   buffer->ctl_arrow = mark_object (buffer->ctl_arrow);
        !          1058:   buffer->selective_display = mark_object (buffer->selective_display);
        !          1059:   buffer->minor_modes = mark_object (buffer->minor_modes);
        !          1060:   buffer->overwrite_mode = mark_object (buffer->overwrite_mode);
        !          1061:   buffer->abbrev_mode = mark_object (buffer->abbrev_mode);
        !          1062: 
        !          1063: }
        !          1064: 
        !          1065: /* Find all structures not marked, and free them. */
        !          1066: 
        !          1067: static void
        !          1068: gc_sweep (old_string_block)
        !          1069:      struct string_block *old_string_block;
        !          1070: {
        !          1071:   /* Put all unmarked conses on free list */
        !          1072:   {
        !          1073:     register struct cons_block *cblk;
        !          1074:     register int lim = cons_block_index;
        !          1075:     register int num_free = 0, num_used = 0;
        !          1076: 
        !          1077:     cons_free_list = 0;
        !          1078:   
        !          1079:     for (cblk = cons_block; cblk; cblk = cblk->next)
        !          1080:       {
        !          1081:        register int i;
        !          1082:        for (i = 0; i < lim; i++)
        !          1083:          if (!XMARKBIT (cblk->conses[i].car))
        !          1084:            {
        !          1085:              XSETCONS (cblk->conses[i].car, cons_free_list);
        !          1086:              num_free++;
        !          1087:              cons_free_list = &cblk->conses[i];
        !          1088:            }
        !          1089:          else num_used++;
        !          1090:        lim = CONS_BLOCK_SIZE;
        !          1091:       }
        !          1092:     total_conses = num_used;
        !          1093:     total_free_conses = num_free;
        !          1094:   }
        !          1095: 
        !          1096:   /* Put all unmarked symbols on free list */
        !          1097:   {
        !          1098:     register struct symbol_block *sblk;
        !          1099:     register int lim = symbol_block_index;
        !          1100:     register int num_free = 0, num_used = 0;
        !          1101: 
        !          1102:     symbol_free_list = 0;
        !          1103:   
        !          1104:     for (sblk = symbol_block; sblk; sblk = sblk->next)
        !          1105:       {
        !          1106:        register int i;
        !          1107:        for (i = 0; i < lim; i++)
        !          1108:          if (!XMARKBIT (sblk->symbols[i].plist))
        !          1109:            {
        !          1110:              XSETSYMBOL (sblk->symbols[i].value, symbol_free_list);
        !          1111:              symbol_free_list = &sblk->symbols[i];
        !          1112:              num_free++;
        !          1113:            }
        !          1114:          else num_used++;
        !          1115:        lim = SYMBOL_BLOCK_SIZE;
        !          1116:       }
        !          1117:     total_symbols = num_used;
        !          1118:     total_free_symbols = num_free;
        !          1119:   }
        !          1120: 
        !          1121: #ifndef standalone
        !          1122:   /* Put all unmarked markers on free list.
        !          1123:      Dechain each one first from the buffer it points into. */
        !          1124:   {
        !          1125:     register struct marker_block *mblk;
        !          1126:     struct Lisp_Marker *tem1;
        !          1127:     register int lim = marker_block_index;
        !          1128:     register int num_free = 0, num_used = 0;
        !          1129: 
        !          1130:     marker_free_list = 0;
        !          1131:   
        !          1132:     for (mblk = marker_block; mblk; mblk = mblk->next)
        !          1133:       {
        !          1134:        register int i;
        !          1135:        for (i = 0; i < lim; i++)
        !          1136:          if (!XMARKBIT (mblk->markers[i].chain))
        !          1137:            {
        !          1138:              Lisp_Object tem;
        !          1139:              tem1 = &mblk->markers[i];  /* tem1 avoids Sun compiler bug */
        !          1140:              XSET (tem, Lisp_Marker, tem1);
        !          1141:              unchain_marker (tem);
        !          1142:              XSETMARKER (mblk->markers[i].chain, marker_free_list);
        !          1143:              marker_free_list = &mblk->markers[i];
        !          1144:              num_free++;
        !          1145:            }
        !          1146:          else num_used++;
        !          1147:        lim = MARKER_BLOCK_SIZE;
        !          1148:       }
        !          1149: 
        !          1150:     total_markers = num_used;
        !          1151:     total_free_markers = num_free;
        !          1152:   }
        !          1153: 
        !          1154:   /* Free all unmarked buffers */
        !          1155:   {
        !          1156:     register struct buffer *buffer = all_buffers, *prev = 0, *next = 0;
        !          1157: 
        !          1158:     while (buffer)
        !          1159:       if (!XMARKBIT (buffer->name))
        !          1160:        {
        !          1161:          if (prev)
        !          1162:            prev->next = buffer->next;
        !          1163:          else
        !          1164:            all_buffers = buffer->next;
        !          1165:          next = buffer->next;
        !          1166:          free (buffer);
        !          1167:          buffer = next;
        !          1168:        }
        !          1169:       else
        !          1170:        {
        !          1171:          XUNMARK (buffer->name);
        !          1172:          prev = buffer, buffer = buffer->next;
        !          1173:        }
        !          1174:   }
        !          1175: 
        !          1176: #endif standalone
        !          1177: 
        !          1178:   /* Free all unmarked vectors */
        !          1179:   {
        !          1180:     register struct Lisp_Vector *vector = all_vectors, *prev = 0, *next = 0;
        !          1181:     total_vector_size = 0;
        !          1182: 
        !          1183:     while (vector)
        !          1184:       if (!(vector->size & most_negative_fixnum))
        !          1185:        {
        !          1186:          if (prev)
        !          1187:            prev->next = vector->next;
        !          1188:          else
        !          1189:            all_vectors = vector->next;
        !          1190:          next = vector->next;
        !          1191:          free (vector);
        !          1192:          vector = next;
        !          1193:        }
        !          1194:       else
        !          1195:        {
        !          1196:          vector->size &= ~most_negative_fixnum;
        !          1197:          total_vector_size += vector->size;
        !          1198:          prev = vector, vector = vector->next;
        !          1199:        }
        !          1200:   }
        !          1201: 
        !          1202:   /* Free all old string blocks, since all strings still used have been copied. */
        !          1203:   {
        !          1204:     register struct string_block *sblk = old_string_block;
        !          1205:     while (sblk)
        !          1206:       {
        !          1207:        struct string_block *next = sblk->next;
        !          1208:        free (sblk);
        !          1209:        sblk = next;
        !          1210:       }
        !          1211:   }
        !          1212: }
        !          1213: 
        !          1214: /* Initialization */
        !          1215: 
        !          1216: init_alloc_once ()
        !          1217: {
        !          1218:   register int i, x;
        !          1219:   /* Compute an int in which only the sign bit is set.  */
        !          1220:   for (i = 0, x = 1; (x <<= 1) & ~1; i++)
        !          1221:     /*empty loop*/;
        !          1222:   most_negative_fixnum = 1 << i;
        !          1223:   dont_copy_flag = 1 << (i - 1);
        !          1224: 
        !          1225:   Vpurify_flag = Qt;
        !          1226: 
        !          1227:   pureptr = 0;
        !          1228:   all_vectors = 0;
        !          1229:   init_strings ();
        !          1230:   init_cons ();
        !          1231:   init_symbol ();
        !          1232:   init_marker ();
        !          1233:   gcprolist = 0;
        !          1234:   staticidx = 0;
        !          1235:   consing_since_gc = 0;
        !          1236:   gc_cons_threshold = 100000;
        !          1237: #ifdef VIRT_ADDR_VARIES
        !          1238:   malloc_sbrk_unused = 1<<22;  /* A large number */
        !          1239:   malloc_sbrk_used = 100000;   /* as reasonable as any number */
        !          1240: #endif /* VIRT_ADDR_VARIES */
        !          1241: }
        !          1242: 
        !          1243: init_alloc ()
        !          1244: {
        !          1245:   gcprolist = 0;
        !          1246: }
        !          1247: 
        !          1248: void
        !          1249: syms_of_alloc ()
        !          1250: {
        !          1251:   DefIntVar ("gc-cons-threshold", &gc_cons_threshold,
        !          1252:     "*Number of bytes of consing between garbage collections.");
        !          1253: 
        !          1254:   DefIntVar ("pure-bytes-used", &pureptr,
        !          1255:     "Number of bytes of sharable Lisp data allocated so far.");
        !          1256: 
        !          1257:   DefIntVar ("data-bytes-used", &malloc_sbrk_used,
        !          1258:     "Number of bytes of unshared memory allocated in this session.");
        !          1259: 
        !          1260:   DefIntVar ("data-bytes-free", &malloc_sbrk_unused,
        !          1261:     "Number of bytes of unshared memory remaining available in this session.");
        !          1262: 
        !          1263:   DefLispVar ("purify-flag", &Vpurify_flag,
        !          1264:     "Non-nil means defun should purecopy the function definition.");
        !          1265: 
        !          1266:   defsubr (&Scons);
        !          1267:   defsubr (&Slist);
        !          1268:   defsubr (&Svector);
        !          1269:   defsubr (&Smake_list);
        !          1270:   defsubr (&Smake_vector);
        !          1271:   defsubr (&Smake_string);
        !          1272:   defsubr (&Smake_symbol);
        !          1273:   defsubr (&Smake_marker);
        !          1274:   defsubr (&Spurecopy);
        !          1275:   defsubr (&Sgarbage_collect);
        !          1276: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.