Mercurial > hg > dmlib
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, §Start, §End, §Len)) | 451 if (!dmParseSection(optArg, §Start, §End, §Name, 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 } |