comparison objlink.c @ 497:b02f1bfce53b

Improve and clean up section parsing support.
author Matti Hamalainen <ccr@tnsp.org>
date Sat, 17 Nov 2012 14:21:42 +0200
parents cb61c44f7846
children 270a2d695607
comparison
equal deleted inserted replaced
496:966617f0f6cd 497:b02f1bfce53b
20 typedef struct 20 typedef struct
21 { 21 {
22 ssize_t start, end; // Start and end address 22 ssize_t start, end; // Start and end address
23 int type; // Type 23 int type; // Type
24 char *name; // Name of the block 24 char *name; // Name of the block
25 ssize_t size;
26 int placement; 25 int placement;
27 } DMMemBlock; 26 } DMMemBlock;
28 27
29 typedef struct 28 typedef struct
30 { 29 {
78 77
79 /* Memory models 78 /* Memory models
80 */ 79 */
81 const DMMemModel memoryModels[] = { 80 const DMMemModel memoryModels[] = {
82 { "C64 unrestricted", "$01 = $34", (64*1024), 0, { 81 { "C64 unrestricted", "$01 = $34", (64*1024), 0, {
83 { 0, 0, 0, NULL, 0, 0 } 82 { 0, 0, 0, NULL, 0 }
84 }}, 83 }},
85 84
86 { "C64 normal (IO+Basic+Kernal)", "$01 = $37", (64*1024), 3, { 85 { "C64 normal (IO+Basic+Kernal)", "$01 = $37", (64*1024), 3, {
87 { 0xA000, 0xBFFF, MTYPE_ROM_WT, "Basic ROM", 0, PLACE_STATIC }, 86 { 0xA000, 0xBFFF, MTYPE_ROM_WT, "Basic ROM", PLACE_STATIC },
88 { 0xD000, 0xDFFF, MTYPE_IO, "I/O", 0, PLACE_STATIC }, 87 { 0xD000, 0xDFFF, MTYPE_IO, "I/O", PLACE_STATIC },
89 { 0xE000, 0xFFFF, MTYPE_ROM_WT, "Kernal ROM", 0, PLACE_STATIC }, 88 { 0xE000, 0xFFFF, MTYPE_ROM_WT, "Kernal ROM", PLACE_STATIC },
90 }}, 89 }},
91 90
92 { "C64 modified (IO+Kernal)", "$01 = $36", (64*1024), 2, { 91 { "C64 modified (IO+Kernal)", "$01 = $36", (64*1024), 2, {
93 { 0xD000, 0xDFFF, MTYPE_IO, "I/O", 0, PLACE_STATIC }, 92 { 0xD000, 0xDFFF, MTYPE_IO, "I/O", PLACE_STATIC },
94 { 0xE000, 0xFFFF, MTYPE_ROM_WT, "Kernal ROM", 0, PLACE_STATIC }, 93 { 0xE000, 0xFFFF, MTYPE_ROM_WT, "Kernal ROM", PLACE_STATIC },
95 }}, 94 }},
96 95
97 { "C64 modified (IO only)", "$01 = $35", (64*1024), 1, { 96 { "C64 modified (IO only)", "$01 = $35", (64*1024), 1, {
98 { 0xD000, 0xDFFF, MTYPE_IO, "I/O", 0, PLACE_STATIC }, 97 { 0xD000, 0xDFFF, MTYPE_IO, "I/O", PLACE_STATIC },
99 }}, 98 }},
100 99
101 { "C64 modified (Char+Kernal+Basic)", "$01 = $33", (64*1024), 3, { 100 { "C64 modified (Char+Kernal+Basic)", "$01 = $33", (64*1024), 3, {
102 { 0xA000, 0xBFFF, MTYPE_ROM_WT, "Basic ROM", 0, PLACE_STATIC }, 101 { 0xA000, 0xBFFF, MTYPE_ROM_WT, "Basic ROM", PLACE_STATIC },
103 { 0xD000, 0xDFFF, MTYPE_ROM, "Char ROM", 0, PLACE_STATIC }, 102 { 0xD000, 0xDFFF, MTYPE_ROM, "Char ROM", PLACE_STATIC },
104 { 0xE000, 0xFFFF, MTYPE_ROM_WT, "Kernal ROM", 0, PLACE_STATIC }, 103 { 0xE000, 0xFFFF, MTYPE_ROM_WT, "Kernal ROM", PLACE_STATIC },
105 }}, 104 }},
106 105
107 /* 106 /*
108 { "C64 normal", "$01 = $37", (64*1024), 0, { 107 { "C64 normal", "$01 = $37", (64*1024), 0, {
109 { 0x0000, 0x0000, MTYPE_RAM, "" }, 108 { 0x0000, 0x0000, MTYPE_RAM, "" },
144 */ 143 */
145 static DMOptArg optList[] = { 144 static DMOptArg optList[] = {
146 { 0, '?', "help", "Show this help", OPT_NONE }, 145 { 0, '?', "help", "Show this help", OPT_NONE },
147 { 1, 'r', "input-raw", "RAW input: -r <file>:<addr>", OPT_ARGREQ }, 146 { 1, 'r', "input-raw", "RAW input: -r <file>:<addr>", OPT_ARGREQ },
148 { 2, 'p', "input-prg", "PRG input: -p <file>[:<addr>]", OPT_ARGREQ }, 147 { 2, 'p', "input-prg", "PRG input: -p <file>[:<addr>]", OPT_ARGREQ },
149 { 12, 's', "section", "Reserved section: -s <start>-<end> or <start>:<len>", OPT_ARGREQ }, 148 { 12, 's', "section", "Reserved section: -s <start>-<end>[,name] or <start>:<len>[,name]", OPT_ARGREQ },
150 { 5, 'o', "output", "Specify output file, -o <file>", OPT_ARGREQ }, 149 { 5, 'o', "output", "Specify output file, -o <file>", OPT_ARGREQ },
151 { 6, 'O', "overlap", "Allow overlapping memory areas", OPT_NONE }, 150 { 6, 'O', "overlap", "Allow overlapping memory areas", OPT_NONE },
152 { 7, 'm', "model", "Set memory model", OPT_ARGREQ }, 151 { 7, 'm', "model", "Set memory model", OPT_ARGREQ },
153 { 8, 'l', "link-file", "Output addresses and labels into file", OPT_ARGREQ }, 152 { 8, 'l', "link-file", "Output addresses and labels into file", OPT_ARGREQ },
154 { 9, 'f', "format", "Format of link-file: (g)eneric, (p)lain, (d)ecimal", OPT_ARGREQ }, 153 { 9, 'f', "format", "Format of link-file: (g)eneric, (p)lain, (d)ecimal", OPT_ARGREQ },
205 } 204 }
206 205
207 if (nmemBlocks < MAX_FILENAMES) 206 if (nmemBlocks < MAX_FILENAMES)
208 { 207 {
209 memBlocks[nmemBlocks].start = startAddr; 208 memBlocks[nmemBlocks].start = startAddr;
210 memBlocks[nmemBlocks].end = endAddr; 209 memBlocks[nmemBlocks].end = endAddr;
211 memBlocks[nmemBlocks].size = (endAddr - startAddr + 1); 210 memBlocks[nmemBlocks].name = dm_strdup(blockName);
212 memBlocks[nmemBlocks].name = dm_strdup(blockName); 211 memBlocks[nmemBlocks].type = blockType;
213 memBlocks[nmemBlocks].type = blockType;
214 nmemBlocks++; 212 nmemBlocks++;
215 } 213 }
216 else 214 else
217 { 215 {
218 dmError("Maximum number of memBlock definitions (%d) exceeded!\n", 216 dmError("Maximum number of memBlock definitions (%d) exceeded!\n",
227 const DMMemBlock *a = cva, *b = cvb; 225 const DMMemBlock *a = cva, *b = cvb;
228 return a->start - b->start; 226 return a->start - b->start;
229 } 227 }
230 228
231 229
232 BOOL dmParseSection(const char *arg, ssize_t *sectStart, ssize_t *sectEnd, ssize_t *sectLen) 230 BOOL dmParseSection(const char *arg, ssize_t *sectStart, ssize_t *sectEnd, char **sectName, BOOL canHasName)
233 { 231 {
234 char sectMode, *sep, *str; 232 char sectMode, *sep, *str, *namesep;
235 ssize_t tmpi; 233 ssize_t tmpi;
236 234
237 // Define reserved section 235 // Define reserved section
238 // Create a copy of the argument 236 // Create a copy of the argument
239 if ((str = dm_strdup(arg)) == NULL) 237 if ((str = dm_strdup(arg)) == NULL)
254 252
255 // Get value 253 // Get value
256 if (!dmGetIntVal(str, sectStart)) 254 if (!dmGetIntVal(str, sectStart))
257 { 255 {
258 dmError("Section start address '%s' in '%s' invalid.\n", str, arg); 256 dmError("Section start address '%s' in '%s' invalid.\n", str, arg);
257 goto error;
258 }
259
260 // Check for name
261 namesep = strchr(sep + 1, ',');
262 if (canHasName && namesep != NULL)
263 {
264 *namesep = 0;
265 namesep++;
266 if (*namesep == 0)
267 {
268 dmError("Section definition '%s' name is empty. Either specify name or leave it out.\n",
269 arg);
270 goto error;
271 }
272 *sectName = dm_strdup(namesep);
273 }
274 else
275 if (namesep != NULL)
276 {
277 dmError("Section definition does not allow a name, syntax error in '%s' at '%s'.\n",
278 arg, namesep);
259 goto error; 279 goto error;
260 } 280 }
261 281
262 // Get end address or length 282 // Get end address or length
263 if (!dmGetIntVal(sep + 1, &tmpi)) 283 if (!dmGetIntVal(sep + 1, &tmpi))
268 goto error; 288 goto error;
269 } 289 }
270 290
271 if (sectMode == ':') 291 if (sectMode == ':')
272 { 292 {
273 *sectEnd = *sectStart + tmpi; 293 *sectEnd = *sectStart + tmpi - 1;
274 *sectLen = tmpi;
275 } 294 }
276 else 295 else
277 { 296 {
278 if (tmpi < *sectStart) 297 if (tmpi < *sectStart)
279 { 298 {
280 dmError("Section start address > end address in '%s'.\n", 299 dmError("Section start address > end address in '%s'.\n",
281 arg); 300 arg);
282 goto error; 301 goto error;
283 } 302 }
284 *sectLen = tmpi - *sectStart + 1;
285 *sectEnd = tmpi; 303 *sectEnd = tmpi;
286 } 304 }
287 305
288 dmFree(str); 306 dmFree(str);
289 return TRUE; 307 return TRUE;
426 optDescribe = TRUE; 444 optDescribe = TRUE;
427 break; 445 break;
428 446
429 case 12: 447 case 12:
430 { 448 {
449 char *sectName = "Clear";
431 ssize_t sectStart, sectEnd, sectLen; 450 ssize_t sectStart, sectEnd, sectLen;
432 if (!dmParseSection(optArg, &sectStart, &sectEnd, &sectLen)) 451 if (!dmParseSection(optArg, &sectStart, &sectEnd, &sectName, TRUE))
433 return FALSE; 452 return FALSE;
434 453
435 // Allocate memory block 454 // Allocate memory block
436 dmMsg(1, "Reserve $%.4x - $%.4x ($%x, %d bytes) as 'Clear'\n", 455 sectLen = sectEnd - sectStart + 1;
437 sectStart, sectEnd, sectLen, sectLen); 456 dmMsg(1, "Reserve $%.4x - $%.4x ($%x, %d bytes) as '%s'\n",
438 457 sectStart, sectEnd, sectLen, sectLen, sectName);
439 reserveMemBlock(sectStart, sectEnd, "Clear", MTYPE_RES); 458
459 reserveMemBlock(sectStart, sectEnd, sectName, MTYPE_RES);
440 } 460 }
441 break; 461 break;
442 462
443 case 13: 463 case 13:
444 { 464 {
445 ssize_t cropLen; 465 size_t cropLen;
446 if (!dmParseSection(optArg, &optCropStart, &optCropEnd, &cropLen)) 466 if (!dmParseSection(optArg, &optCropStart, &optCropEnd, NULL, FALSE))
447 return FALSE; 467 return FALSE;
448 468
469 cropLen = optCropEnd - optCropEnd + 1;
449 dmMsg(1, "Cutting output to $%.4x - $%.4x ($%x, %d bytes)\n", 470 dmMsg(1, "Cutting output to $%.4x - $%.4x ($%x, %d bytes)\n",
450 optCropStart, optCropEnd, cropLen, cropLen); 471 optCropStart, optCropEnd, cropLen, cropLen);
451 472
452 optCropOutput = TRUE; 473 optCropOutput = TRUE;
453 } 474 }