PVT ml_val_t ptrlist_to_MLlist(ml_state_t *msp) { ml_val_t lp = LIST_nil; ml_val_t v; ptrlist_t *p; #ifdef DEBUG_C_CALLS int i = 0; SayDebug("converting ptrlist (|ptrlist|=%d) to ML list ",ptrlist_len()); #endif p = ptrlist; while (p != NULL) { #ifdef DEBUG_C_CALLS i++; #endif ptrlist = p->next; v = MK_CADDR(msp,p->ptr); LIST_cons(msp, lp, v, lp); FREE(p); p = ptrlist; } #ifdef DEBUG_C_CALLS SayDebug("of length %d\n", i); #endif return lp; }
PVT void restore_ptrlist(ptrlist_t *save) { ptrlist = save; #ifdef DEBUG_C_CALLS SayDebug("restoring ptrlist, |ptrlist|=%d\n", ptrlist_len()); #endif }
PVT void save_ptrlist(ptrlist_t **save) { #ifdef DEBUG_C_CALLS SayDebug("saving ptrlist, |ptrlist|=%d\n", ptrlist_len()); #endif *save = ptrlist; ptrlist = NULL; }
PVT void keep_ptr(Word_t *p) { ptrlist_t *q = (ptrlist_t *) checked_alloc(sizeof(ptrlist_t)); #ifdef DEBUG_C_CALLS SayDebug("keeping ptr %x, |ptrlist|=%d\n", p, ptrlist_len()); #endif q->ptr = p; q->next = ptrlist; ptrlist = q; }
/* return the number of bytes the ptrlist will occupy in the ML heap */ PVT int ptrlist_space() { int n = 0; ptrlist_t *p; p = ptrlist; while (p != NULL) { p = p->next; n += CONS_SZB + CADDR_SZB; } #ifdef DEBUG_C_CALLS SayDebug("space for ptrlist is %d, |ptrlist|=%d\n",n,ptrlist_len()); #endif return n; }
PVT void free_ptrlist() { ptrlist_t *p; #ifdef DEBUG_C_CALLS SayDebug("freeing ptr list, |ptrlist|=%d\n",ptrlist_len()); #endif p = ptrlist; while (p != NULL) { ptrlist = ptrlist->next; FREE(p->ptr); /* the block */ FREE(p); /* the block's descriptor */ p = ptrlist; } }
int addconstellation(char* cname) { unsigned long nums, numc, i; char *string; struct sector *fs, *s; struct ptrlist work; double phi; unsigned long r; string = malloc(strlen(cname)+GREEK_LEN+2); if (!string) return -1; ptrlist_init(&work); /* Determine number of sectors in constellation */ nums = mtrandom_uint(GREEK_N); if (nums == 0) nums = 1; mprintf("addconstellation: will create %lu sectors (universe has %lu so far)\n", nums, ptrlist_len(&univ.sectors)); pthread_rwlock_wrlock(&univ.sectornames_lock); fs = NULL; for (numc = 0; numc < nums; numc++) { /* Create a new sector and put it in s */ s = malloc(sizeof(*s)); if (!s) goto err; sprintf(string, "%s %s", greek[numc], cname); if (sector_create(s, string)) goto err; ptrlist_push(&univ.sectors, s); st_add_string(&univ.sectornames, s->name, s); if (fs == NULL) { /* This was the first sector generated for this constellation We need to place this at a suitable point in the universe */ fs = s; if (ptrlist_len(&univ.sectors) == 1) { /* The first constellation always goes in (0, 0) */ if (sector_move(s, 0, 0)) bug("%s", "Error when placing first sector at (0,0)"); } else { /* All others are randomly distributed */ phi = mtrandom_uint(UINT_MAX) / (double)UINT_MAX*2*M_PI; r = 0; i = 2; while (i > 1) { r += mtrandom_ulong(CONSTELLATION_RANDOM_DISTANCE); phi += mtrandom_double(CONSTELLATION_PHI_RANDOM); if (!sector_move(s, POLTOX(phi, r), POLTOY(phi, r))) i = get_neighbouring_systems(NULL, s, CONSTELLATION_MIN_DISTANCE); } } ptrlist_push(&work, s); } else if (ptrlist_len(&work) == 0) { /* This isn't the first sector but no sectors are left in work Put this close to the first sector */ ptrlist_push(&work, s); makeneighbours(fs, s, 0, 0); } else { /* We have sectors in work, put this close to work[0] and add this one to work */ ptrlist_push(&work, s); makeneighbours(ptrlist_entry(&work, 0), s, 0, 0); /* Determine if work[0] has enough neighbours, if so remove it */ if (mtrandom_uint(UINT_MAX) < UINT_MAX/CONSTELLATION_NEIGHBOUR_CHANCE) ptrlist_pull(&work); } mprintf("Created %s (%p) at %ldx%ld\n", s->name, s, s->x, s->y); } pthread_rwlock_unlock(&univ.sectornames_lock); free(string); ptrlist_free(&work); return 0; err: pthread_rwlock_unlock(&univ.sectornames_lock); return -1; }