source: trunk/tools/common/kFileDef.cpp@ 2759

Last change on this file since 2759 was 2759, checked in by bird, 26 years ago

Odin32 DB.

File size: 15.8 KB
Line 
1/*
2 * kFileDef - Definition files.
3 *
4 * Copyright (c) 1999 knut st. osmundsen
5 *
6 */
7
8/*******************************************************************************
9* Defined Constants *
10*******************************************************************************/
11#define StringCase(psz, pszMatch) (strnicmp(psz, pszMatch, sizeof(pszMatch)-1) == 0)
12
13/*******************************************************************************
14* Header Files *
15*******************************************************************************/
16#include <os2.h>
17#include <stdio.h>
18#include <string.h>
19#include <stdlib.h>
20
21#include "kFileFormatBase.h"
22#include "kFileDef.h"
23
24
25/*******************************************************************************
26* Internal Functions *
27*******************************************************************************/
28static char *dupeString(const char *psz);
29static char *trim(char *psz);
30static char *removeFnutts(char *pszStr);
31
32/**
33 * Duplicates a string.
34 * @returns Pointer to stringcopy. Remeber to delete this!
35 * @param psz Pointer to string to duplicate.
36 */
37static char *dupeString(const char *psz)
38{
39 char *pszDupe;
40 if (psz == NULL)
41 return NULL;
42 pszDupe = new char[strlen(psz)+1];
43 return strcpy(pszDupe, psz);
44}
45
46
47/**
48 * Trims a string, that is removing blank spaces at start and end.
49 * @returns Pointer to first non-blank char.
50 * @param psz Pointer to string.
51 * @result Blank at end of string is removed. ('\0' is moved to the left.)
52 */
53static char *trim(char *psz)
54{
55 int i;
56 if (psz == NULL)
57 return NULL;
58 while (*psz == ' ')
59 psz++;
60 i = strlen(psz) - 1;
61 while (i >= 0 && psz[i] == ' ')
62 i--;
63 psz[i+1] = '\0';
64 return psz;
65}
66
67
68kFileDef::kFileDef(FILE *phFile) throw(int)
69 :pszType(NULL), pszBase(NULL), pszCode(NULL), pszData(NULL), pszDescription(NULL),
70 pszExeType(NULL), pszHeapSize(NULL), pszOld(NULL), pszProtmode(NULL), pszStackSize(NULL),
71 pszStub(NULL), pSegments(NULL), pImports(NULL), pExports(NULL)
72{
73 /* determin file size */
74 if (!fseek(phFile, 0, SEEK_SET))
75 {
76 this->read(phFile);
77 }
78 else
79 throw (0x001);
80}
81
82
83/**
84 * Destructor. Frees used memory.
85 */
86kFileDef::~kFileDef()
87{
88 if (pszType != NULL) delete pszType;
89 if (pszBase != NULL) delete pszBase;
90 if (pszCode != NULL) delete pszCode;
91 if (pszData != NULL) delete pszData;
92 if (pszDescription != NULL) delete pszDescription;
93 if (pszExeType != NULL) delete pszExeType;
94 if (pszHeapSize != NULL) delete pszHeapSize;
95 if (pszOld != NULL) delete pszOld;
96 if (pszProtmode != NULL) delete pszProtmode;
97 if (pszStackSize != NULL) delete pszStackSize;
98 if (pszStub != NULL) delete pszStub;
99 while (pSegments != NULL)
100 {
101 PDEFSEGMENT p = pSegments;
102 pSegments = pSegments->pNext;
103 if (p->psz != NULL) delete p->psz;
104 delete p;
105 }
106 while (pImports != NULL)
107 {
108 PDEFIMPORT p = pImports;
109 pImports = pImports->pNext;
110 if (p->pszName != NULL) delete p->pszName;
111 if (p->pszDll != NULL) delete p->pszDll;
112 if (p->pszIntName != NULL) delete p->pszIntName;
113 delete p;
114 }
115 while (pExports != NULL)
116 {
117 PDEFEXPORT p = pExports;
118 pExports = p->pNext;
119 if (p->pszName != NULL) delete p->pszName;
120 if (p->pszIntName != NULL) delete p->pszIntName;
121 delete p;
122 }
123}
124
125
126/**
127 * Read/parse the Definition file.
128 * @param phFile Handle to file.
129 * @remark throws errorcode on error (TODO: errorhandling)
130 */
131void kFileDef::read(FILE *phFile) throw (int)
132{
133 char *pszTmp;
134 char *psz;
135 char szBuffer[256];
136
137 /* readloop */
138 psz = readln(phFile, &szBuffer[0], sizeof(szBuffer));
139 while (psz != NULL)
140 {
141 BOOL fNext = TRUE;
142
143 /* if-switch */
144 if (StringCase(psz, "LIBRARY"))
145 {
146 if (pszType != NULL) throw (0x101);
147 pszType = dupeString(psz);
148 }
149 else if (StringCase(psz, "NAME"))
150 {
151 if (pszType != NULL) throw (0x101);
152 pszType = dupeString(psz);
153 }
154 else if (StringCase(psz, "PHYSICAL DEVICE")) //gap is fixed to one space, this may be fixed in readln.
155 {
156 if (pszType != NULL) throw (0x101);
157 pszType = dupeString(psz);
158 }
159 else if (StringCase(psz, "VIRTUAL DEVICE")) //gap is fixed to one space, this may be fixed in readln.
160 {
161 if (pszType != NULL) throw (0x101);
162 pszType = dupeString(psz);
163 }
164 else if (StringCase(psz, "BASE"))
165 pszBase = dupeString(psz);
166 else if (StringCase(psz, "CODE"))
167 pszCode = dupeString(psz);
168 else if (StringCase(psz, "DATA"))
169 pszData = dupeString(psz);
170 else if (StringCase(psz, "DESCRIPTION"))
171 pszDescription = dupeString(psz);
172 else if (StringCase(psz, "EXETYPE"))
173 pszExeType = dupeString(psz);
174 else if (StringCase(psz, "HEAPSIZE"))
175 pszHeapSize = dupeString(psz);
176 else if (StringCase(psz, "OLD"))
177 pszOld = dupeString(psz);
178 else if (StringCase(psz, "PROTMODE"))
179 pszProtmode = dupeString(psz);
180 else if (StringCase(psz, "STACKSIZE"))
181 pszStackSize = dupeString(psz);
182 else if (StringCase(psz, "STUB"))
183 pszStub = dupeString(psz);
184 else if (StringCase(psz, "SEGMENTS"))
185 {
186 PDEFSEGMENT *pps = &pSegments;
187 while (!isKeyword(psz = readln(phFile, &szBuffer[0], sizeof(szBuffer))) && psz != NULL)
188 {
189 *pps = new DEFSEGMENT; memset(*pps, 0, sizeof(**pps));
190 (**pps).psz = dupeString(psz);
191 pps = &(**pps).pNext;
192 }
193 fNext = FALSE;
194 }
195 else if (StringCase(psz, "IMPORTS"))
196 {
197 PDEFIMPORT *ppi = &pImports;
198 while (!isKeyword(psz = readln(phFile, &szBuffer[0], sizeof(szBuffer))) && psz != NULL)
199 {
200 //DOSCALL1.154 or DosQueryHeaderInfo = DOSCALL1.154
201 *ppi = new DEFIMPORT; memset(*ppi, 0, sizeof(**ppi));
202 (**ppi).ulOrdinal = 0xffffffffUL;
203
204 if ((pszTmp = strchr(psz, '=')) != NULL)
205 {
206 *pszTmp = '\0';
207 (**ppi).pszIntName = dupeString(trim(psz));
208 psz = pszTmp + 1;
209 }
210 if ((pszTmp = strchr(psz, '.')) != NULL)
211 {
212 *pszTmp = '\0';
213 (**ppi).pszDll = dupeString(trim(psz));
214 psz = pszTmp + 1;
215 }
216 psz = trim(psz);
217 if (*psz >= '0' && *psz <= '9')
218 {
219 (**ppi).ulOrdinal = strtol(psz, &pszTmp, 0);
220 if (psz ==pszTmp) throw(0x102);
221 }
222 else
223 (**ppi).pszName = dupeString(psz);
224 ppi = &(**ppi).pNext;
225 }
226 fNext = FALSE;
227 }
228 else if (StringCase(psz, "EXPORTS"))
229 {
230 PDEFEXPORT *ppe = &pExports;
231 while (!isKeyword(psz = readln(phFile, &szBuffer[0], sizeof(szBuffer))) && psz != NULL)
232 {
233 /* CloseHandle = CloseHandle@4 @1234 RESIDENTNAME 2 */
234 *ppe = new DEFEXPORT; memset(*ppe, 0, sizeof(**ppe));
235 (**ppe).ulOrdinal = 0xffffffffUL;
236 (**ppe).cParam = 0xffffffffUL;
237
238 /* look for '=' */
239 pszTmp = strchr(psz, '=');
240 if (pszTmp != NULL)
241 { /* CloseHandle = CloseHandle@4 */
242 *pszTmp ='\0';
243 (**ppe).pszName = dupeString(trim(psz));
244 psz = trim(pszTmp + 1);
245
246 pszTmp = strchr(psz, ' ');
247 if (pszTmp != NULL)
248 *pszTmp = '\0';
249 (**ppe).pszIntName = dupeString(trim(psz));
250 if (pszTmp != NULL)
251 psz = pszTmp + 1;
252 else
253 psz = NULL;
254 }
255 else
256 { /* CloseHandle (no '= CloseHandle@4')*/
257 pszTmp = strchr(psz, ' ');
258 if (pszTmp != NULL)
259 *pszTmp = '\0';
260 (**ppe).pszName = dupeString(trim(psz));
261 if (pszTmp != NULL)
262 psz = pszTmp + 1;
263 else
264 psz = NULL;
265 }
266
267 if (psz != NULL)
268 { /* @1234 RESIDENTNAME 2 */
269 pszTmp = strchr(psz, '@');
270 if (pszTmp)
271 { /* @1234 RESIDENTNAME 2 */
272 psz = pszTmp + 1;
273 (**ppe).ulOrdinal = strtol(psz, &pszTmp, 0);
274 if (pszTmp == psz) throw (0x103);
275 psz = trim(pszTmp);
276
277 if (*psz != '\0')
278 { /* RESIDENTNAME 2 */
279 if (StringCase(psz, "RESIDENTNAME"))
280 {
281 (**ppe).fResident = TRUE;
282 psz = trim(psz + sizeof("RESIDENTNAME") - 1);
283 }
284 else if (StringCase(psz, "NONAME"))
285 {
286 (**ppe).fResident = FALSE;
287 psz = trim(psz + sizeof("NONAME") - 1);
288 }
289 }
290 else
291 {
292 (**ppe).fResident = (**ppe).ulOrdinal == 0xffffffffUL;
293 }
294 }
295
296 if (*psz != '\0')
297 { /* 2 */
298 (**ppe).cParam = strtol(psz, &pszTmp, 0);
299 if (pszTmp == psz) throw (0x104);
300 }
301 }
302
303 removeFnutts((**ppe).pszIntName);
304 removeFnutts((**ppe).pszName);
305 ppe = &(**ppe).pNext;
306 }
307 fNext = FALSE;
308 }
309 else
310 throw(0x105);
311
312 /* next ? */
313 if (fNext)
314 psz = readln(phFile, &szBuffer[0], sizeof(szBuffer));
315 }
316
317 /* sanity check */
318 if (pszType == NULL)
319 throw (0x106);
320}
321
322
323/**
324 * Reads first meaning full line from a file into a buffer.
325 * @returns Pointer to buffer on success; NULL on error.
326 * @param phFile Filea handle.
327 * @param pszBuffer Pointer to buffer.
328 * @param cbBuffer Size of buffer.
329 * @remark tabs are expanded. string is trimmed. comments removed.
330 */
331char *kFileDef::readln(FILE *phFile, char *pszBuffer, int cbBuffer) throw (int)
332{
333 int i;
334 int cch;
335
336 do
337 {
338 /* read line */
339 if (!fgets(pszBuffer, cbBuffer, phFile))
340 {
341 if (feof(phFile))
342 return FALSE;
343 else
344 throw (0x201);
345 }
346
347 /* check for and remove comments, and get string length. */
348 cch = 0;
349 while (pszBuffer[cch] != '\0' && pszBuffer[cch] != ';')
350 cch++;
351 pszBuffer[cch] = '\0';
352
353 if (cch > 0)
354 {
355 /* remove '\t' - tab is trouble some! */
356 for (i = 0; i < cch; i++)
357 if (pszBuffer[i] == '\t')
358 pszBuffer[i] = ' ';
359
360 /* trim line - right */
361 i = cch - 1;
362 while (i >= 0 &&
363 (
364 pszBuffer[i] == '\n' ||
365 pszBuffer[i] == '\r' ||
366 pszBuffer[i] == ' '
367 ))
368 i--;
369 pszBuffer[++i] = '\0';
370 cch = i;
371
372 /* trim line - left */
373 i = 0;
374 while (i < cch && pszBuffer[i] == ' ')
375 i++;
376 cch -= i;
377 if (i > 0)
378 memmove(pszBuffer, &pszBuffer[i], cch + 1);
379 }
380 } while ((*pszBuffer == ';' || cch == 0) && !feof(phFile));
381
382 return !(*pszBuffer == ';' || cch == 0) ? pszBuffer : NULL;
383}
384
385
386/**
387 * Checks for keyword.
388 * @returns TRUE - keyword; FALSE - not keyword;
389 * @param psz Pointer to word/string to check.
390 * @remark TODO - we are going to check WORDS.
391 */
392BOOL kFileDef::isKeyword(const char *psz)
393{
394 return psz != NULL
395 &&
396 (
397 StringCase(psz, "LIBRARY") ||
398 StringCase(psz, "NAME") ||
399 StringCase(psz, "PHYSICAL DEVICE") || //gap is fixed to one space, this may be fixed in readln.
400 StringCase(psz, "VIRTUAL DEVICE") || //gap is fixed to one space, this may be fixed in readln.
401 StringCase(psz, "BASE") ||
402 StringCase(psz, "CODE") ||
403 StringCase(psz, "DATA") ||
404 StringCase(psz, "DESCRIPTION") ||
405 StringCase(psz, "EXETYPE") ||
406 StringCase(psz, "HEAPSIZE") ||
407 StringCase(psz, "OLD") ||
408 StringCase(psz, "STACKSIZE") ||
409 StringCase(psz, "STUB") ||
410 StringCase(psz, "SEGMENTS") ||
411 StringCase(psz, "IMPORTS") ||
412 StringCase(psz, "EXPORTS")
413 );
414}
415
416
417/**
418 * Queries the module name.
419 * @returns Success indicator.
420 * @param pszBuffer Pointer to string buffer which is to hold the module name upon return.
421 * @remark Assumes that pszBuffer is large enough.
422 */
423BOOL kFileDef::queryModuleName(char *pszBuffer)
424{
425 char *psz;
426
427 if (pszType != NULL && StringCase(pszType, "LIBRARY"))
428 {
429 psz = pszType + sizeof("LIBRARY") - 1;
430 while (*psz == ' ')
431 psz++;
432 while (*psz != '\0' && *psz != ' ')
433 *pszBuffer++ = *psz++;
434 *pszBuffer = '\0';
435 }
436 else
437 return FALSE;
438 return TRUE;
439}
440
441
442/**
443 * Finds the first exports.
444 * @returns Success indicator. TRUE / FALSE.
445 * @param pExport Pointer to export structure.
446 * @remark
447 */
448BOOL kFileDef::findFirstExport(PEXPORTENTRY pExport)
449{
450 if (pExports != NULL && pExport != NULL)
451 {
452 pExport->ulOrdinal = pExports->ulOrdinal;
453 if (pExports->pszName != NULL)
454 strcpy(&pExport->achName[0], pExports->pszName);
455 else
456 pExport->achName[0] = '\0';
457 if (pExports->pszIntName)
458 strcpy(&pExport->achIntName[0], pExports->pszIntName);
459 else
460 pExport->achIntName[0] = '\0';
461 pExport->pv = (void*)pExports->pNext;
462 }
463 else
464 return FALSE;
465 return TRUE;
466}
467
468
469/**
470 * Finds the next export.
471 * @returns Success indicator. TRUE / FALSE.
472 * @param pExport Pointer to export structure.
473 * @remark
474 */
475BOOL kFileDef::findNextExport(PEXPORTENTRY pExport)
476{
477 if (pExport != NULL && pExport->pv != NULL)
478 {
479 PDEFEXPORT pExp = (PDEFEXPORT)pExport->pv;
480
481 pExport->ulOrdinal = pExp->ulOrdinal;
482 if (pExp->pszName != NULL)
483 strcpy(&pExport->achName[0], pExp->pszName);
484 else
485 pExport->achName[0] = '\0';
486 if (pExp->pszIntName)
487 strcpy(&pExport->achIntName[0], pExp->pszIntName);
488 else
489 pExport->achIntName[0] = '\0';
490 pExport->pv = (void*)pExp->pNext;
491 }
492 else
493 return FALSE;
494 return TRUE;
495}
496
497
498/**
499 * Removes '"' and ''' at start and end of the string.
500 * @returns pszStr!
501 * @param pszStr String that is to have "s and 's removed.
502 */
503static char *removeFnutts(char *pszStr)
504{
505 if (pszStr != NULL)
506 {
507 int cch = strlen(pszStr);
508 if (cch > 0 && (pszStr[cch-1] == '"' || pszStr[cch-1] == '\''))
509 pszStr[cch-1] = '\0';
510
511 if (*pszStr == '"' || *pszStr == '\'')
512 memmove(pszStr, pszStr+1, cch-1);
513 }
514 return pszStr;
515}
Note: See TracBrowser for help on using the repository browser.