source: trunk/src/helpers/map_vac.c@ 319

Last change on this file since 319 was 229, checked in by umoeller, 23 years ago

Sources as of 1.0.0.

  • Property svn:eol-style set to CRLF
  • Property svn:keywords set to Author Date Id Revision
File size: 20.2 KB
Line 
1/*
2 *@@sourcefile map_vac.c:
3 * map file parser for the VAC 3.08 format.
4 *
5 * Usage: All OS/2 programs.
6 *
7 * Note: Version numbering in this file relates to XWorkplace version
8 * numbering.
9 *
10 *@@added V1.0.0 (2002-09-13) [umoeller]
11 *
12 *@@header "helpers\mapfile.h"
13 */
14
15/*
16 * This file Copyright (C) 2002 Ulrich M”ller.
17 * This file is part of the "XWorkplace helpers" source package.
18 * This is free software; you can redistribute it and/or modify
19 * it under the terms of the GNU General Public License as published
20 * by the Free Software Foundation, in version 2 as it comes in the
21 * "COPYING" file of the XWorkplace main distribution.
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
26 */
27
28#define OS2EMX_PLAIN_CHAR
29 // this is needed for "os2emx.h"; if this is defined,
30 // emx will define PSZ as _signed_ char, otherwise
31 // as unsigned char
32
33#define INCL_DOSPROCESS
34#define INCL_DOSMODULEMGR
35#define INCL_DOSMISC
36#define INCL_DOSERRORS
37#include <os2.h>
38
39#include <stdlib.h>
40#include <stdio.h>
41#include <string.h>
42
43#define DONT_REPLACE_MALLOC
44#include "setup.h" // code generation and debugging options
45
46#include "helpers\linklist.h"
47#include "helpers\mapfile.h"
48#include "helpers\stringh.h"
49#include "helpers\standards.h"
50
51#pragma hdrstop
52
53/*
54 *@@category: Helpers\Control program helpers\Map file parsing (VAC 3.08)
55 * See map_vac.c.
56 */
57
58/*
59 *@@ MAPSTATE:
60 *
61 */
62
63typedef enum _MAPSTATE
64{
65 MAP_START,
66 // until we find " Start Length Name Class"
67
68 MAP_SEGMENTS,
69 // each segment is introduced by
70 // " 0001:00000000 000001630H FREQ_CODE1 CODE 32-bit"
71 // then for each source file
72 // " at offset 00000000 003A4H bytes from T:\_build\xwp\xfdataf.obj (xfdataf.c)"
73
74 // until we find " Origin Group"
75
76 MAP_GROUPS,
77 // whatever this is for, ignoring for now
78 // until we find " Address Export Alias"
79
80 MAP_EXPORTS,
81 // for each export
82 // " 0003:00096AE8 apmhClose apmhClose"
83
84 // until we find
85 // " Address Publics by Name"
86
87 MAP_PUBLICS_BY_NAME,
88 // for each public
89 // " 0003:000A800A anmBlowUpBitmap"
90 // or, for imports,
91 // " 0000:00000000 Imp DevCloseDC (PMGPI.604)"
92
93 // until we find
94 // " Address Publics by Value"
95
96 MAP_PUBLICS_BY_VALUE,
97 // same thing as previous section, we can ignore that
98
99 // until we find
100 // "Line numbers for T:\_build\xwp\xcenter.obj(xcenter.c)"
101
102 MAP_LINENUMBERS_FILEINTRO,
103
104 // starts with:
105 // " Record Number of Start of Source: 0"
106 // " Number of Primary Source Records: 0"
107 // " Source & Listing Files: 67"
108
109 // then
110 // " File 1) xcenter.c" etc.
111
112 // until we find
113 // "Line numbers for T:\_build\xwp\xcenter.obj(xcenter.c) segment CODE32 (@0x00000000)"
114
115 MAP_LINENUMBERS_FILEDATA,
116
117 // starts with:
118 // " Source Src File Seg:Offset
119 // " Line Num Index (0X)
120 // " -------- -------- -------------
121
122 // then for each line
123 // " 1630 1 0003:00000000"
124
125 // until we find again
126 // "Line numbers for T:\_build\xwp\xcenter.obj(xcenter.c)"
127
128 // or
129 // "Program entry point at 0003:00023228"
130
131} MAPSTATE;
132
133/*
134 *@@ mapvRead:
135 *
136 */
137
138APIRET mapvRead(PCSZ pcszMapFilename,
139 PMAPFILE *ppMapFile,
140 PSZ pszLineBuf,
141 ULONG cbLineBuf,
142 PULONG pulLineError) // out: line no. where we choked
143{
144 APIRET arc = NO_ERROR;
145 ULONG ulLine = 2;
146
147 MAPSTATE State = MAP_START;
148
149 PMAPFILE pMapFile = NULL;
150 PSEGMENT pCurrentSegment = NULL;
151
152 FILE *MapFile;
153
154 if (!(MapFile = fopen(pcszMapFilename, "r")))
155 return _doserrno;
156
157 while (!arc)
158 {
159 if (!(fgets(pszLineBuf, cbLineBuf, MapFile)))
160 {
161 if (!(feof(MapFile)))
162 arc = _doserrno;
163
164 break;
165 }
166
167 // printf("Running line \"%s\"", pszLineBuf);
168
169 ulLine++;
170
171 if ( (pszLineBuf[0] == '\n')
172 || (pszLineBuf[0] == '\r')
173 )
174 // empty line:
175 continue;
176
177 #define STRNCMP(p1, p2) memcmp(p1, p2, sizeof(p2) - 1)
178
179 switch (State)
180 {
181 case MAP_START:
182 if (!STRNCMP(pszLineBuf,
183 " Start Length Name Class"))
184 {
185 if (!pMapFile)
186 arc = MAPERROR_NO_MODULE_NAME;
187 else
188 State = MAP_SEGMENTS;
189 }
190 else
191 {
192 PSZ p = pszLineBuf;
193 while (*p == ' ')
194 p++;
195 if (*p)
196 {
197 if (!(pMapFile = NEW(MAPFILE)))
198 arc = ERROR_NOT_ENOUGH_MEMORY;
199 else
200 {
201 ZERO(pMapFile);
202 strncpy(pMapFile->szModule,
203 p,
204 strchr(p, '\n') - p);
205
206 lstInit(&pMapFile->llSegments, TRUE);
207 lstInit(&pMapFile->llExports, TRUE);
208 lstInit(&pMapFile->llPublics, TRUE);
209 }
210 }
211 else
212 return MAPERROR_NO_MODULE_NAME;
213 }
214 break;
215
216 case MAP_SEGMENTS:
217 if (!STRNCMP(pszLineBuf,
218 " Origin Group"))
219 {
220 pCurrentSegment = NULL;
221
222 State = MAP_GROUPS;
223 }
224 else if (!STRNCMP(pszLineBuf,
225 "\tat offset "))
226 {
227
228 }
229 // " 0001:00000000 000001630H FREQ_CODE1 CODE 32-bit"
230 else if ( (pszLineBuf[0] == ' ')
231 && (pszLineBuf[5] == ':')
232 )
233 {
234 if (!(pCurrentSegment = NEW(SEGMENT)))
235 arc = ERROR_NOT_ENOUGH_MEMORY;
236 else
237 {
238 ZERO(pCurrentSegment);
239
240 if (3 != sscanf(pszLineBuf,
241 " %04lX:%08lX %08lXH ",
242 &pCurrentSegment->ulObjNo,
243 &pCurrentSegment->ulObjOfs,
244 &pCurrentSegment->cbSeg))
245 {
246 arc = MAPERROR_SYNTAX_SEGMENTS_START;
247 }
248 else
249 {
250 PSZ pStartOfSegName = pszLineBuf + sizeof(" 0001:00000000 000001630H ") - 1;
251 PSZ pSpaceAfterSegName;
252
253 if (!(pSpaceAfterSegName = strchr(pStartOfSegName, ' ')))
254 arc = MAPERROR_SYNTAX_SEGMENTS_NOSEGNAME;
255 else
256 {
257 PSZ pStartOfSegType;
258 memcpy(pCurrentSegment->szSegName,
259 pStartOfSegName,
260 pSpaceAfterSegName - pStartOfSegName);
261
262 pStartOfSegType = pszLineBuf + sizeof(" 0006:00000000 00001E288H CONST32_RO ") - 1;
263 if (!STRNCMP(pStartOfSegType,
264 "CODE 32-bit"))
265 pCurrentSegment->ulType = SEGTYPE_CODE32;
266 else if (!STRNCMP(pStartOfSegType,
267 "CODE 16-bit"))
268 pCurrentSegment->ulType = SEGTYPE_CODE16;
269 else if (!STRNCMP(pStartOfSegType,
270 "CONST 32-bit"))
271 pCurrentSegment->ulType = SEGTYPE_CONST32;
272 else if (!STRNCMP(pStartOfSegType,
273 "DATA16 16-bit"))
274 pCurrentSegment->ulType = SEGTYPE_DATA16;
275 else if (!STRNCMP(pStartOfSegType,
276 "DATA 32-bit"))
277 pCurrentSegment->ulType = SEGTYPE_DATA32;
278 else if (!STRNCMP(pStartOfSegType,
279 "EDC_CLASS 32-bit"))
280 pCurrentSegment->ulType = SEGTYPE_EDC_CLASS32;
281 else if (!STRNCMP(pStartOfSegType,
282 "BSS 32-bit"))
283 pCurrentSegment->ulType = SEGTYPE_BSS32;
284 else if (!STRNCMP(pStartOfSegType,
285 "STACK 32-bit"))
286 pCurrentSegment->ulType = SEGTYPE_STACK32;
287 else
288 {
289 printf(" MAP_SEGMENTS: Cannot handle segment type \"%s\"",
290 pStartOfSegType);
291 arc = MAPERROR_SYNTAX_SEGMENTS_SEGTYPE;
292 }
293 }
294
295 if (!arc)
296 lstAppendItem(&pMapFile->llSegments,
297 pCurrentSegment);
298 else
299 FREE(pCurrentSegment);
300 }
301 }
302 }
303 else
304 arc = MAPERROR_SYNTAX_SEGMENTS_OTHER;
305 break;
306
307 case MAP_GROUPS:
308 if (!STRNCMP(pszLineBuf,
309 " Address Export Alias"))
310 {
311 State = MAP_EXPORTS;
312 }
313 // executables usually have no exports, so we
314 // might run into the publics as well
315 else if (!STRNCMP(pszLineBuf,
316 " Address Publics by Name"))
317 {
318 State = MAP_PUBLICS_BY_NAME;
319 }
320 break;
321
322 case MAP_EXPORTS:
323 if (!STRNCMP(pszLineBuf,
324 " Address Publics by Name"))
325 {
326 State = MAP_PUBLICS_BY_NAME;
327 }
328 // " 0003:00096AE8 apmhClose apmhClose"
329 else if ( (pszLineBuf[0] == ' ')
330 && (pszLineBuf[5] == ':')
331 )
332 {
333 EXPORT expTemp;
334
335 if (2 != sscanf(pszLineBuf,
336 " %04lX:%08lX ",
337 &expTemp.ulObjNo,
338 &expTemp.ulObjOfs))
339 arc = MAPERROR_SYNTAX_EXPORTS_OBJOFS;
340 else
341 {
342 PSZ pStartOfName1 = pszLineBuf + sizeof(" 0003:00096AE8 ") - 1,
343 pEndOfName1;
344 if (!(pEndOfName1 = strchr(pStartOfName1, ' ')))
345 arc = MAPERROR_SYNTAX_EXPORTS_NAME1;
346 else
347 {
348 PSZ pStartOfName2 = pEndOfName1,
349 pEndOfName2;
350
351 PEXPORT pExport;
352
353 while (*pStartOfName2 == ' ')
354 pStartOfName2++;
355 pEndOfName2 = strhFindEOL(pStartOfName2, NULL);
356
357 expTemp.ulName1Len = pEndOfName1 - pStartOfName1;
358 expTemp.ulName2Len = pEndOfName2 - pStartOfName2;
359
360 if (!(pExport = malloc( sizeof(EXPORT)
361 + expTemp.ulName1Len
362 + expTemp.ulName2Len
363 + 1
364 )))
365 arc = ERROR_NOT_ENOUGH_MEMORY;
366 else
367 {
368 PSZ pszName2;
369 memcpy(pExport,
370 &expTemp,
371 sizeof(expTemp));
372 memcpy(pExport->szNames,
373 pStartOfName1,
374 expTemp.ulName1Len);
375 pExport->szNames[expTemp.ulName1Len] = '\0';
376
377 pszName2 = pExport->szNames +expTemp.ulName1Len + 1;
378 memcpy(pszName2,
379 pStartOfName2,
380 expTemp.ulName2Len);
381 pszName2[expTemp.ulName2Len] = '\0';
382
383 lstAppendItem(&pMapFile->llExports, pExport);
384 }
385 }
386 }
387 }
388 else
389 arc = MAPERROR_SYNTAX_EXPORTS_OTHER;
390 break;
391
392 case MAP_PUBLICS_BY_NAME:
393 if (!STRNCMP(pszLineBuf,
394 " Address Publics by Value"))
395 {
396 State = MAP_PUBLICS_BY_VALUE;
397 }
398 // " 0003:00096AE8 apmhClose apmhClose"
399 else if ( (pszLineBuf[0] == ' ')
400 && (pszLineBuf[5] == ':')
401 )
402 {
403 PUBLIC pubTemp;
404
405 if (2 != sscanf(pszLineBuf,
406 " %04lX:%08lX ",
407 &pubTemp.ulObjNo,
408 &pubTemp.ulObjOfs))
409 arc = MAPERROR_SYNTAX_PUBLICS_OBJOFS;
410 else
411 {
412 PSZ p2 = pszLineBuf + sizeof(" 0000:00000000 ") - 1,
413 p3;
414 PPUBLIC pPublic;
415 PCSZ pcszImportLib = NULL;
416
417 BOOL fImport = !STRNCMP(p2, "Imp");
418
419 p2 += 5;
420
421 pubTemp.ulImportLen = 0;
422 pubTemp.ulImportIndex = 0;
423
424 if (fImport)
425 {
426 p3 = strchr(p2, ' ');
427 pubTemp.ulNameLen = p3 - p2;
428 if (p3 = strchr(p3, '('))
429 {
430 PSZ p4;
431 pcszImportLib = p3 + 1;
432 p4 = strchr(pcszImportLib, '.');
433 // "(DOSCALLS.303)"
434 pubTemp.ulImportLen = p4 - pcszImportLib;
435 pubTemp.ulImportIndex = atoi(p4 + 1);
436 }
437 }
438 else
439 // no import:
440 p3 = strhFindEOL(p2, &pubTemp.ulNameLen);
441
442 if (!(pPublic = malloc( sizeof(PUBLIC)
443 + pubTemp.ulNameLen
444 + pubTemp.ulImportLen
445 + 1)))
446 arc = ERROR_NOT_ENOUGH_MEMORY;
447 else
448 {
449 memcpy(pPublic, &pubTemp, sizeof(PUBLIC));
450 memcpy(pPublic->szName,
451 p2,
452 pubTemp.ulNameLen);
453 pPublic->szName[pubTemp.ulNameLen] = '\0';
454
455 if (pubTemp.ulImportLen)
456 {
457 PSZ pszImport = pPublic->szName + pubTemp.ulNameLen + 1;
458 memcpy(pszImport,
459 pcszImportLib,
460 pubTemp.ulImportLen);
461 pszImport[pubTemp.ulImportLen] = '\0';
462 }
463
464
465 lstAppendItem(&pMapFile->llPublics, pPublic);
466 }
467 }
468 }
469 else
470 arc = MAPERROR_SYNTAX_PUBLICS_OTHER;
471 break;
472
473 case MAP_PUBLICS_BY_VALUE:
474 if (!STRNCMP(pszLineBuf,
475 "Line numbers for "))
476 {
477 // "Line numbers for T:\_build\xwp\xcenter.obj(xcenter.c)"
478 PSZ pObjStart,
479 pSourceStart,
480 pSourceEnd;
481
482 StartLineNumersIntro:
483
484 pObjStart = pszLineBuf + sizeof("Line numbers for ") - 1;
485 if (pSourceStart = strchr(pObjStart, '('))
486 {
487 *pSourceStart++ = '\0';
488 if (pSourceEnd = strchr(pSourceStart, ')'))
489 *pSourceEnd = '\0';
490 }
491
492 // starts with:
493 // " Record Number of Start of Source: 0"
494 // " Number of Primary Source Records: 0"
495 // " Source & Listing Files: 67"
496
497
498 State = MAP_LINENUMBERS_FILEINTRO;
499 }
500 break;
501
502 case MAP_LINENUMBERS_FILEINTRO:
503 if (!STRNCMP(pszLineBuf,
504 "Line numbers for "))
505 {
506 State = MAP_LINENUMBERS_FILEDATA;
507 }
508 break;
509
510 case MAP_LINENUMBERS_FILEDATA:
511 if (!STRNCMP(pszLineBuf,
512 "Program entry point at "))
513 {
514 break;
515 }
516 else if (!STRNCMP(pszLineBuf,
517 "Line numbers for "))
518 {
519 goto StartLineNumersIntro;
520 }
521 break;
522
523 default:
524 printf("Internal error, unknown parsing state.\n");
525 break;
526 }
527 }
528
529 if (arc)
530 {
531 mapvClose(&pMapFile);
532 *pulLineError = ulLine;
533 }
534 else
535 *ppMapFile = pMapFile;
536
537 fclose(MapFile);
538
539 return arc;
540}
541
542/*
543 *@@ mapvClose:
544 *
545 */
546
547APIRET mapvClose(PMAPFILE *ppMapFile)
548{
549 PMAPFILE pMapFile;
550
551 if ( (!ppMapFile)
552 || (!(pMapFile = *ppMapFile))
553 )
554 return ERROR_INVALID_PARAMETER;
555
556 // these three are auto-free
557 lstClear(&pMapFile->llSegments);
558 lstClear(&pMapFile->llExports);
559 lstClear(&pMapFile->llPublics);
560
561 free(pMapFile);
562 *ppMapFile = NULL;
563}
Note: See TracBrowser for help on using the repository browser.