I650: Avoid allocating large card decks on the stack.

Allocate them dynamically instead.
This commit is contained in:
Olaf Seibert 2022-07-07 19:22:40 +02:00
parent 3ffd20c1fa
commit b6ae88bd1c

View file

@ -705,25 +705,49 @@ int Shift_Digits(t_int64 * d, int nDigits)
*/ */
// load card file fn and add its cards to /*
// DeckImage array, up to a max of nMaxCards * Allocate space for a card deck of nCards cards.
// increment nCards with the number of added cards */
// uses cdr0 device/unit uint16 *deck_alloc(int nCards)
t_stat deck_load(CONST char *fn, uint16 * DeckImage, int * nCards) {
return malloc(nCards * 80 * sizeof(uint16));
}
/*
* Free a deck previously obtained from deck_alloc().
*/
void deck_free(uint16 *deck)
{
free(deck);
}
// Load card file fn and add its cards to
// DeckImage array, up to a max of MAX_CARDS_IN_DECK.
// If DeckImagePtr is NULL, allocates a deck (for now, fixed at
// MAX_CARDS_IN_DECK, but there is potential to make this flexible
// and reduce the size to actually used size).
// Uses cdr0 device/unit.
t_stat deck_load(CONST char *fn, uint16 ** DeckImagePtr, int * nCards)
{ {
UNIT * uptr = &cdr_unit[0]; UNIT * uptr = &cdr_unit[0];
uint16 image[80]; uint16 * DeckImage;
uint16 image[80];
t_stat r, r2; t_stat r, r2;
int i; int i;
uint16 c; uint16 c;
// set flags for read only // set flags for read only
uptr->flags |= UNIT_RO; uptr->flags |= UNIT_RO;
// attach file to cdr unit 0 // attach file to cdr unit 0
r = (cdr_dev.attach)(uptr, fn); r = (cdr_dev.attach)(uptr, fn);
if (r != SCPE_OK) return r; if (r != SCPE_OK) return r;
DeckImage = *DeckImagePtr;
if (!DeckImage) {
DeckImage = deck_alloc(MAX_CARDS_IN_DECK);
}
// read all cards from file // read all cards from file
while (1) { while (1) {
@ -745,10 +769,17 @@ t_stat deck_load(CONST char *fn, uint16 * DeckImage, int * nCards)
*nCards = *nCards + 1; *nCards = *nCards + 1;
} }
*DeckImagePtr = DeckImage;
// deattach file from cdr unit 0 // deattach file from cdr unit 0
r2 = (cdr_dev.detach)(uptr); r2 = (cdr_dev.detach)(uptr);
if (r == SCPE_OK) r = r2; if (r == SCPE_OK) r = r2;
if (r != SCPE_OK) return r; if (r != SCPE_OK) {
// Special case: allow caller to bail out without needing to free the deck.
deck_free(DeckImage);
*DeckImagePtr = NULL;
return r;
}
return SCPE_OK; return SCPE_OK;
} }
@ -840,7 +871,7 @@ static t_stat deck_split_cmd(CONST char *cptr)
int bSplit5CD = 0; int bSplit5CD = 0;
int bSplitPAT = 0; int bSplitPAT = 0;
uint16 DeckImage[80 * MAX_CARDS_IN_DECK]; uint16 *DeckImage = NULL;
int nCards, nCards1, tail; int nCards, nCards1, tail;
while (sim_isspace (*cptr)) cptr++; // trim leading spc while (sim_isspace (*cptr)) cptr++; // trim leading spc
@ -887,7 +918,7 @@ static t_stat deck_split_cmd(CONST char *cptr)
// read source deck // read source deck
nCards = 0; nCards = 0;
r = deck_load(fn0, DeckImage, &nCards); r = deck_load(fn0, &DeckImage, &nCards);
if (r != SCPE_OK) return sim_messagef (r, "Cannot read source deck (%s)\n", fn0); if (r != SCPE_OK) return sim_messagef (r, "Cannot read source deck (%s)\n", fn0);
// calc nCards1 = cards in first deck // calc nCards1 = cards in first deck
@ -907,8 +938,8 @@ static t_stat deck_split_cmd(CONST char *cptr)
if (bSplit5CD ) { if (bSplit5CD ) {
// separate 5cd deck // separate 5cd deck
uint16 DeckImage1[80 * MAX_CARDS_IN_DECK]; uint16 *DeckImage1 = deck_alloc(nCards);
uint16 DeckImage2[80 * MAX_CARDS_IN_DECK]; uint16 *DeckImage2 = deck_alloc(nCards);
int i, nc, nc1, nc2, bFound; int i, nc, nc1, nc2, bFound;
uint16 hol; uint16 hol;
@ -947,11 +978,20 @@ static t_stat deck_split_cmd(CONST char *cptr)
nc2++; nc2++;
} }
} }
// input deck is no longer needed
deck_free(DeckImage);
// save output decks // save output decks
r = deck_save(fn1, DeckImage1, 0, nc1); r = deck_save(fn1, DeckImage1, 0, nc1);
if (r != SCPE_OK) return sim_messagef (r, "Cannot write destination deck1 (%s)\n", fn0); deck_free(DeckImage1);
if (r != SCPE_OK) {
deck_free(DeckImage2);
return sim_messagef (r, "Cannot write destination deck1 (%s)\n", fn1);
}
r = deck_save(fn2, DeckImage2, 0, nc2); r = deck_save(fn2, DeckImage2, 0, nc2);
if (r != SCPE_OK) return sim_messagef (r, "Cannot write destination deck2 (%s)\n", fn0); deck_free(DeckImage2);
if (r != SCPE_OK) {
return sim_messagef (r, "Cannot write destination deck2 (%s)\n", fn2);
}
if (nc2 == 0) remove(fn2); // delete file2 if empty if (nc2 == 0) remove(fn2); // delete file2 if empty
if ((sim_switches & SWMASK ('Q')) == 0) { if ((sim_switches & SWMASK ('Q')) == 0) {
sim_messagef (SCPE_OK, "Deck with 5 words-per-card splitted %d/%d cards\n", nc1, nc2); sim_messagef (SCPE_OK, "Deck with 5 words-per-card splitted %d/%d cards\n", nc1, nc2);
@ -961,8 +1001,8 @@ static t_stat deck_split_cmd(CONST char *cptr)
if (bSplitPAT) { if (bSplitPAT) {
// separate pat deck // separate pat deck
uint16 DeckImage1[80 * MAX_CARDS_IN_DECK]; uint16 *DeckImage1 = deck_alloc(nCards);
uint16 DeckImage2[80 * MAX_CARDS_IN_DECK]; uint16 *DeckImage2 = deck_alloc(nCards);
int i, nc, nc1, nc2, bFound; int i, nc, nc1, nc2, bFound;
uint16 hol; uint16 hol;
@ -990,24 +1030,39 @@ static t_stat deck_split_cmd(CONST char *cptr)
nc2++; nc2++;
} }
} }
deck_free(DeckImage);
// save output decks // save output decks
r = deck_save(fn1, DeckImage1, 0, nc1); r = deck_save(fn1, DeckImage1, 0, nc1);
if (r != SCPE_OK) return sim_messagef (r, "Cannot write destination deck1 (%s)\n", fn0); deck_free(DeckImage1);
if (r != SCPE_OK) {
deck_free(DeckImage2);
return sim_messagef (r, "Cannot write destination deck1 (%s)\n", fn1);
}
r = deck_save(fn2, DeckImage2, 0, nc2); r = deck_save(fn2, DeckImage2, 0, nc2);
if (r != SCPE_OK) return sim_messagef (r, "Cannot write destination deck2 (%s)\n", fn0); deck_free(DeckImage2);
if (r != SCPE_OK) {
return sim_messagef (r, "Cannot write destination deck2 (%s)\n", fn2);
}
if (nc2 == 0) remove(fn2); // delete file2 if empty if (nc2 == 0) remove(fn2); // delete file2 if empty
if ((sim_switches & SWMASK ('Q')) == 0) { if ((sim_switches & SWMASK ('Q')) == 0) {
sim_messagef (SCPE_OK, "Deck with availability-card splitted %d/%d cards\n", nc1, nc2); sim_messagef (SCPE_OK, "Deck with availability-card splitted %d/%d cards\n", nc1, nc2);
} }
return SCPE_OK; return SCPE_OK;
} }
// split based on card count // split based on card count
r = deck_save(fn1, DeckImage, 0, nCards1); r = deck_save(fn1, DeckImage, 0, nCards1);
if (r != SCPE_OK) return sim_messagef (r, "Cannot write destination deck1 (%s)\n", fn0); if (r != SCPE_OK) {
deck_free(DeckImage);
return sim_messagef (r, "Cannot write destination deck1 (%s)\n", fn0);
}
r = deck_save(fn2, DeckImage, nCards1, nCards-nCards1); r = deck_save(fn2, DeckImage, nCards1, nCards-nCards1);
if (r != SCPE_OK) return sim_messagef (r, "Cannot write destination deck2 (%s)\n", fn0); deck_free(DeckImage);
if (r != SCPE_OK) {
return sim_messagef (r, "Cannot write destination deck2 (%s)\n", fn0);
}
if ((sim_switches & SWMASK ('Q')) == 0) { if ((sim_switches & SWMASK ('Q')) == 0) {
sim_messagef (SCPE_OK, "Deck splitted to %d/%d cards\n", nCards1, nCards-nCards1); sim_messagef (SCPE_OK, "Deck splitted to %d/%d cards\n", nCards1, nCards-nCards1);
@ -1026,7 +1081,7 @@ static t_stat deck_join_cmd(CONST char *cptr)
char gbuf[4*CBUFSIZE]; char gbuf[4*CBUFSIZE];
t_stat r; t_stat r;
uint16 DeckImage[80 * MAX_CARDS_IN_DECK]; uint16 *DeckImage = NULL;
int i,nDeck, nCards, nCards1; int i,nDeck, nCards, nCards1;
cptr0 = cptr; cptr0 = cptr;
@ -1047,7 +1102,6 @@ static t_stat deck_join_cmd(CONST char *cptr)
cptr = cptr0; // restore cptr to scan source filenames cptr = cptr0; // restore cptr to scan source filenames
nDeck = nCards = 0; nDeck = nCards = 0;
memset(DeckImage, 0, sizeof(DeckImage));
while (1) { while (1) {
while (sim_isspace (*cptr)) cptr++; // trim leading spc while (sim_isspace (*cptr)) cptr++; // trim leading spc
@ -1057,7 +1111,7 @@ static t_stat deck_join_cmd(CONST char *cptr)
// read source deck // read source deck
nCards1 = nCards; nCards1 = nCards;
r = deck_load(fnSrc, DeckImage, &nCards); r = deck_load(fnSrc, &DeckImage, &nCards);
if (r != SCPE_OK) return sim_messagef (r, "Cannot read source deck (%s)\n", fnSrc); if (r != SCPE_OK) return sim_messagef (r, "Cannot read source deck (%s)\n", fnSrc);
nDeck++; nDeck++;
@ -1066,6 +1120,7 @@ static t_stat deck_join_cmd(CONST char *cptr)
} }
} }
r = deck_save(fnDest, DeckImage, 0, nCards); r = deck_save(fnDest, DeckImage, 0, nCards);
deck_free(DeckImage);
if (r != SCPE_OK) return sim_messagef (r, "Cannot write destination deck (%s)\n", fnDest); if (r != SCPE_OK) return sim_messagef (r, "Cannot write destination deck (%s)\n", fnDest);
if ((sim_switches & SWMASK ('Q')) == 0) { if ((sim_switches & SWMASK ('Q')) == 0) {
@ -1081,7 +1136,7 @@ static t_stat deck_print_cmd(CONST char *cptr)
char fn[4*CBUFSIZE]; char fn[4*CBUFSIZE];
t_stat r; t_stat r;
uint16 DeckImage[80 * MAX_CARDS_IN_DECK]; uint16 *DeckImage = NULL;
int nCards; int nCards;
while (sim_isspace (*cptr)) cptr++; // trim leading spc while (sim_isspace (*cptr)) cptr++; // trim leading spc
@ -1091,7 +1146,7 @@ static t_stat deck_print_cmd(CONST char *cptr)
// read deck to be printed (-1 to convert to ascii value, not hol) // read deck to be printed (-1 to convert to ascii value, not hol)
nCards = 0; nCards = 0;
r = deck_load(fn, DeckImage, &nCards); r = deck_load(fn, &DeckImage, &nCards);
if (r != SCPE_OK) return sim_messagef (r, "Cannot read deck to print (%s)\n", fn); if (r != SCPE_OK) return sim_messagef (r, "Cannot read deck to print (%s)\n", fn);
deck_print_echo(DeckImage, nCards, 1,1); deck_print_echo(DeckImage, nCards, 1,1);
@ -1099,6 +1154,8 @@ static t_stat deck_print_cmd(CONST char *cptr)
if ((sim_switches & SWMASK ('Q')) == 0) { if ((sim_switches & SWMASK ('Q')) == 0) {
sim_messagef (SCPE_OK, "Printed Deck with %d cards (%s)\n", nCards, fn); sim_messagef (SCPE_OK, "Printed Deck with %d cards (%s)\n", nCards, fn);
} }
deck_free(DeckImage);
return SCPE_OK; return SCPE_OK;
} }
@ -1109,7 +1166,7 @@ static t_stat deck_echolast_cmd(CONST char *cptr)
char gbuf[4*CBUFSIZE]; char gbuf[4*CBUFSIZE];
t_stat r; t_stat r;
uint16 DeckImage[80 * MAX_CARDS_IN_DECK]; uint16 *DeckImage = NULL;
int i,nc,nCards, ic, nh, ncdr; int i,nc,nCards, ic, nh, ncdr;
while (sim_isspace (*cptr)) cptr++; // trim leading spc while (sim_isspace (*cptr)) cptr++; // trim leading spc
@ -1135,6 +1192,7 @@ static t_stat deck_echolast_cmd(CONST char *cptr)
// get nCards form read card take hopper buffer // get nCards form read card take hopper buffer
// that is, print last nCards read // that is, print last nCards read
DeckImage = deck_alloc(nCards);
// get last nCards cards, so // get last nCards cards, so
// first card to echo is count ones before last one // first card to echo is count ones before last one
@ -1149,6 +1207,7 @@ static t_stat deck_echolast_cmd(CONST char *cptr)
} }
deck_print_echo(DeckImage, nCards, 0,1); deck_print_echo(DeckImage, nCards, 0,1);
deck_free(DeckImage);
if ((sim_switches & SWMASK ('Q')) == 0) { if ((sim_switches & SWMASK ('Q')) == 0) {
sim_messagef (SCPE_OK, "Last %d cards from Read take Hopper\n", nCards); sim_messagef (SCPE_OK, "Last %d cards from Read take Hopper\n", nCards);