source: trunk/tools/common/kFileDef.cpp

Last change on this file was 21916, checked in by dmik, 14 years ago

Merge branch gcc-kmk to trunk.

File size: 29.6 KB
Line 
1/* $Id: kFileDef.cpp,v 1.13 2002-08-29 07:59:24 bird Exp $
2 *
3 * kFileDef - Definition files.
4 *
5 * Copyright (c) 1999-2001 knut st. osmundsen
6 *
7 */
8
9/*******************************************************************************
10* Defined Constants *
11*******************************************************************************/
12#define StringCase(psz, pszMatch) (strnicmp(psz, pszMatch, sizeof(pszMatch)-1) == 0 \
13 && ( psz[sizeof(pszMatch)-1] == '\0' \
14 || psz[sizeof(pszMatch)-1] == ' ' \
15 || psz[sizeof(pszMatch)-1] == '\n' \
16 || psz[sizeof(pszMatch)-1] == '\r' \
17 || psz[sizeof(pszMatch)-1] == '\t' \
18 ) \
19 )
20
21/*******************************************************************************
22* Header Files *
23*******************************************************************************/
24#include <stdio.h>
25#include <string.h>
26#include <stdlib.h>
27
28#include "kTypes.h"
29#include "kError.h"
30#include "kFile.h"
31#include "kFileFormatBase.h"
32#include "kFileInterfaces.h"
33#include "kFileDef.h"
34
35
36/*******************************************************************************
37* Global Variables *
38*******************************************************************************/
39#if 0
40static kFileDef tst((kFile*)NULL);
41#endif
42
43
44/*******************************************************************************
45* Internal Functions *
46*******************************************************************************/
47static char *dupeString(const char *psz, KBOOL fSkipFirstWord = FALSE);
48static char *trim(char *psz);
49static char *ltrim(const char *psz);
50static char *removeFnutts(char *pszStr);
51inline char upcase(char ch);
52static char *stristr(const char *pszStr, const char *pszSubStr);
53
54
55/**
56 * Duplicates a string.
57 * @returns Pointer to stringcopy. Remeber to delete this!
58 * @param psz Pointer to string to duplicate.
59 * @param fSkipFirstWord Skips the first word before duplicating the string.
60 */
61static char *dupeString(const char *psz, KBOOL fSkipFirstWord/* = FALSE*/)
62{
63 char *pszDupe;
64 if (psz == NULL)
65 return NULL;
66
67 if (fSkipFirstWord)
68 {
69 while (*psz != ' ' && *psz != '\t' && *psz != '\n' && *psz != '\r' && *psz != '\0')
70 psz++;
71 psz = ltrim(psz);
72 }
73
74 pszDupe = new char[strlen(psz)+1];
75 strcpy(pszDupe, psz);
76 if (fSkipFirstWord)
77 return removeFnutts(pszDupe);
78 return pszDupe;
79}
80
81
82/**
83 * Trims a string, that is removing blank spaces at start and end.
84 * @returns Pointer to first non-blank char.
85 * @param psz Pointer to string.
86 * @result Blank at end of string is removed. ('\0' is moved to the left.)
87 */
88static char *trim(char *psz)
89{
90 int i;
91 if (psz == NULL)
92 return NULL;
93 while (*psz == ' ' || *psz == '\t')
94 psz++;
95 i = strlen(psz) - 1;
96 while (i >= 0 && (psz[i] == ' ' || psz[i] == '\t'))
97 i--;
98 psz[i+1] = '\0';
99 return psz;
100}
101
102
103/**
104 * Trims a string, that is removing blank spaces at start and end.
105 * @returns Pointer to first non-blank char.
106 * @param psz Pointer to string.
107 * @result Blank at end of string is removed. ('\0' is moved to the left.)
108 */
109static char *ltrim(const char *psz)
110{
111 if (psz == NULL)
112 return NULL;
113
114 while (*psz == ' ' || *psz == '\t')
115 psz++;
116 return (char *)psz;
117}
118
119
120
121kFileDef::kFileDef(kFile *pFile) throw (kError) :
122 kFileFormatBase(pFile),
123 pszType(NULL), pszModName(NULL), pszBase(NULL), pszCode(NULL), pszData(NULL), pszDescription(NULL),
124 pszExeType(NULL), pszHeapSize(NULL), pszOld(NULL), pszProtmode(NULL), pszStackSize(NULL),
125 pszStub(NULL), pSegments(NULL), pImports(NULL), pExports(NULL),
126 fProgram(FALSE), fLibrary(FALSE), fPhysicalDevice(FALSE), fVirtualDevice(FALSE),
127 fInitInstance(FALSE), fTermInstance(FALSE), fInitGlobal(FALSE), fTermGlobal(FALSE),
128 chAppType(kFileDef::unknown)
129{
130 pFile->setThrowOnErrors();
131 pFile->start();
132 read(pFile);
133 }
134
135
136/**
137 * Destructor. Frees used memory.
138 */
139kFileDef::~kFileDef() throw (kError)
140{
141 if (pszType != NULL) delete pszType;
142 if (pszBase != NULL) delete pszBase;
143 if (pszCode != NULL) delete pszCode;
144 if (pszData != NULL) delete pszData;
145 if (pszDescription != NULL) delete pszDescription;
146 if (pszExeType != NULL) delete pszExeType;
147 if (pszHeapSize != NULL) delete pszHeapSize;
148 if (pszOld != NULL) delete pszOld;
149 if (pszProtmode != NULL) delete pszProtmode;
150 if (pszStackSize != NULL) delete pszStackSize;
151 if (pszStub != NULL) delete pszStub;
152 while (pSegments != NULL)
153 {
154 PDEFSEGMENT p = pSegments;
155 pSegments = pSegments->pNext;
156 if (p->psz != NULL) delete p->psz;
157 delete p;
158 }
159 while (pImports != NULL)
160 {
161 PDEFIMPORT p = pImports;
162 pImports = pImports->pNext;
163 if (p->pszName != NULL) delete p->pszName;
164 if (p->pszDll != NULL) delete p->pszDll;
165 if (p->pszIntName != NULL) delete p->pszIntName;
166 delete p;
167 }
168 while (pExports != NULL)
169 {
170 PDEFEXPORT p = pExports;
171 pExports = p->pNext;
172 if (p->pszName != NULL) delete p->pszName;
173 if (p->pszIntName != NULL) delete p->pszIntName;
174 delete p;
175 }
176}
177
178
179/**
180 * Read/parse the Definition file.
181 * @param pFile Pointer to fileobject.
182 * @remark throws errorcode on error (TODO: errorhandling)
183 */
184void kFileDef::read(kFile *pFile) throw (kError)
185{
186 char *pszTmp;
187 char *psz;
188 char szBuffer[256];
189 char ch;
190
191 /* readloop */
192 psz = readln(pFile, &szBuffer[0], sizeof(szBuffer));
193 while (psz != NULL)
194 {
195 KBOOL fNext = TRUE;
196
197 /* if-switch */
198 if (StringCase(psz, "LIBRARY"))
199 {
200 if (pszType != NULL) throw (kError(kError::DEF_MULIPLE_MODULE_STATEMENT));
201 pszType = dupeString(psz);
202 fLibrary = TRUE;
203 if (!setModuleName())
204 throw (kError(kError::DEF_BAD_LIBRARY_STATEMENT));
205 fInitInstance = stristr(pszType, "INITINSTANCE") != NULL;
206 fInitGlobal = stristr(pszType, "INITGLOBAL") != NULL;
207 fTermInstance = stristr(pszType, "TERMINSTANCE") != NULL;
208 fTermGlobal = stristr(pszType, "TERMGLOBAL") != NULL || !fTermInstance;
209 }
210 else if (StringCase(psz, "NAME"))
211 {
212 if (pszType != NULL) throw (kError(kError::DEF_MULIPLE_MODULE_STATEMENT));
213 pszType = dupeString(psz);
214 fProgram = TRUE;
215 setModuleName();
216 if (stristr(pszType, "WINDOWAPI"))
217 chAppType = kFileDef::pm;
218 else if (stristr(pszType, "NOTWINDOWCOMPAT"))
219 chAppType = kFileDef::fullscreen;
220 else if (stristr(pszType, "WINDOWCOMPAT"))
221 chAppType = kFileDef::pmvio;
222 else
223 chAppType = kFileDef::unknown;
224 }
225 else if (StringCase(psz, "PHYSICAL DEVICE")) //gap is fixed to one space, this may be fixed in readln.
226 {
227 if (pszType != NULL) throw (kError(kError::DEF_MULIPLE_MODULE_STATEMENT));
228 pszType = dupeString(psz);
229 fPhysicalDevice = TRUE;
230 setModuleName();
231 }
232 else if (StringCase(psz, "VIRTUAL DEVICE")) //gap is fixed to one space, this may be fixed in readln.
233 {
234 if (pszType != NULL) throw (kError(kError::DEF_MULIPLE_MODULE_STATEMENT));
235 pszType = dupeString(psz);
236 fVirtualDevice = TRUE;
237 setModuleName();
238 }
239 else if (StringCase(psz, "BASE"))
240 pszBase = dupeString(psz, TRUE);
241 else if (StringCase(psz, "CODE"))
242 pszCode = dupeString(psz, TRUE);
243 else if (StringCase(psz, "DATA"))
244 pszData = dupeString(psz, TRUE);
245 else if (StringCase(psz, "DESCRIPTION"))
246 pszDescription = dupeString(psz, TRUE);
247 else if (StringCase(psz, "EXETYPE"))
248 pszExeType = dupeString(psz, TRUE);
249 else if (StringCase(psz, "HEAPSIZE"))
250 pszHeapSize = dupeString(psz, TRUE);
251 else if (StringCase(psz, "OLD"))
252 pszOld = dupeString(psz, TRUE);
253 else if (StringCase(psz, "PROTMODE"))
254 pszProtmode = dupeString(psz, TRUE);
255 else if (StringCase(psz, "STACKSIZE"))
256 pszStackSize = dupeString(psz, TRUE);
257 else if (StringCase(psz, "STUB"))
258 pszStub = dupeString(psz, TRUE);
259 else if (StringCase(psz, "SEGMENTS"))
260 {
261 PDEFSEGMENT *pps = &pSegments;
262 while (!isKeyword(psz = readln(pFile, &szBuffer[0], sizeof(szBuffer))) && psz != NULL)
263 {
264 *pps = new DEFSEGMENT; memset(*pps, 0, sizeof(**pps));
265 (**pps).psz = dupeString(psz);
266
267 printf("debug: parsing: %s\n", psz);
268 /* seg name */
269 (**pps).pszName = ltrim((**pps).psz);
270 ch = *(**pps).pszName;
271 if (ch == '\'' || ch == '\"')
272 pszTmp = strchr(++(**pps).pszName, ch);
273 else
274 pszTmp = strpbrk((**pps).pszName, " \t");
275 if (pszTmp)
276 {
277 *pszTmp = '\0';
278
279 /* class ? */
280 pszTmp = ltrim(pszTmp + 1);
281 if (!strnicmp(pszTmp, "CLASS", 5))
282 {
283 (**pps).pszClass = ltrim(pszTmp + 5);
284 ch = *(**pps).pszClass;
285 if (ch == '\'' || ch == '\"')
286 pszTmp = strchr(++(**pps).pszClass, ch);
287 else
288 pszTmp = strpbrk((**pps).pszClass, " \t");
289 if (pszTmp)
290 {
291 *pszTmp++ = '\0';
292 }
293 }
294 if (pszTmp)
295 {
296 /* attribs */
297 (**pps).pszAttr = trim(pszTmp);
298 if (!*(**pps).pszAttr)
299 (**pps).pszAttr = NULL;
300 }
301 }
302
303 printf("debug: pszName=%s\n", (**pps).pszName);
304 printf("debug: pszClass=%s\n", (**pps).pszClass);
305 printf("debug: pszAttr=%s\n", (**pps).pszAttr);
306 /* next */
307 pps = &(**pps).pNext;
308 }
309 fNext = FALSE;
310 }
311 else if (StringCase(psz, "IMPORTS"))
312 {
313 PDEFIMPORT *ppi = &pImports;
314 while (!isKeyword(psz = readln(pFile, &szBuffer[0], sizeof(szBuffer))) && psz != NULL)
315 {
316 //DOSCALL1.154 or DosQueryHeaderInfo = DOSCALL1.154
317 *ppi = new DEFIMPORT; memset(*ppi, 0, sizeof(**ppi));
318 (**ppi).ulOrdinal = 0xffffffffUL;
319
320 if ((pszTmp = strchr(psz, '=')) != NULL)
321 {
322 *pszTmp = '\0';
323 (**ppi).pszIntName = dupeString(trim(psz));
324 psz = pszTmp + 1;
325 }
326 if ((pszTmp = strchr(psz, '.')) != NULL)
327 {
328 *pszTmp = '\0';
329 (**ppi).pszDll = dupeString(trim(psz));
330 psz = pszTmp + 1;
331 }
332 psz = trim(psz);
333 if (*psz >= '0' && *psz <= '9')
334 {
335 (**ppi).ulOrdinal = strtol(psz, &pszTmp, 0);
336 if (psz ==pszTmp) throw (kError(kError::DEF_BAD_IMPORT));
337 }
338 else
339 (**ppi).pszName = dupeString(psz);
340 ppi = &(**ppi).pNext;
341 }
342 fNext = FALSE;
343 }
344 else if (StringCase(psz, "EXPORTS"))
345 {
346 PDEFEXPORT *ppe = &pExports;
347 while (!isKeyword(psz = readln(pFile, &szBuffer[0], sizeof(szBuffer))) && psz != NULL)
348 {
349 /* CloseHandle = CloseHandle@4 @1234 RESIDENTNAME 2 */
350 *ppe = new DEFEXPORT; memset(*ppe, 0, sizeof(**ppe));
351 (**ppe).ulOrdinal = 0xffffffffUL;
352 (**ppe).cParam = 0xffffffffUL;
353
354 /* look for '=' */
355 pszTmp = strchr(psz, '=');
356 if (pszTmp != NULL)
357 { /* CloseHandle = CloseHandle@4 */
358 *pszTmp ='\0';
359 (**ppe).pszName = dupeString(trim(psz));
360 psz = trim(pszTmp + 1);
361
362 pszTmp = strchr(psz, ' ');
363 if (pszTmp != NULL)
364 *pszTmp = '\0';
365 (**ppe).pszIntName = dupeString(trim(psz));
366 if (pszTmp != NULL)
367 psz = pszTmp + 1;
368 else
369 psz = NULL;
370 }
371 else
372 { /* CloseHandle (no '= CloseHandle@4')*/
373 pszTmp = strchr(psz, ' ');
374 if (pszTmp != NULL)
375 *pszTmp = '\0';
376 (**ppe).pszName = dupeString(trim(psz));
377 if (pszTmp != NULL)
378 psz = pszTmp + 1;
379 else
380 psz = NULL;
381 }
382
383 if (psz != NULL)
384 { /* @1234 RESIDENTNAME 2 */
385 pszTmp = strchr(psz, '@');
386 if (pszTmp)
387 { /* @1234 RESIDENTNAME 2 */
388 psz = pszTmp + 1;
389 (**ppe).ulOrdinal = strtol(psz, &pszTmp, 0);
390 if (pszTmp == psz) throw (kError(kError::DEF_BAD_EXPORT));
391 psz = trim(pszTmp);
392
393 if (*psz != '\0')
394 { /* RESIDENTNAME 2 */
395 if (StringCase(psz, "RESIDENTNAME"))
396 {
397 (**ppe).fResident = TRUE;
398 psz = trim(psz + sizeof("RESIDENTNAME") - 1);
399 }
400 else if (StringCase(psz, "NONAME"))
401 {
402 (**ppe).fResident = FALSE;
403 psz = trim(psz + sizeof("NONAME") - 1);
404 }
405 }
406 else
407 {
408 (**ppe).fResident = (**ppe).ulOrdinal == 0xffffffffUL;
409 }
410 }
411
412 if (*psz != '\0')
413 { /* 2 */
414 (**ppe).cParam = strtol(psz, &pszTmp, 0);
415 if (pszTmp == psz) throw (kError(kError::DEF_BAD_EXPORT));
416 }
417 }
418
419 removeFnutts((**ppe).pszIntName);
420 removeFnutts((**ppe).pszName);
421 ppe = &(**ppe).pNext;
422 }
423 fNext = FALSE;
424 }
425 else
426 throw (kError(kError::DEF_UNKOWN_VERB));
427
428 /* next ? */
429 if (fNext)
430 psz = readln(pFile, &szBuffer[0], sizeof(szBuffer));
431 }
432
433 /* sanity check */
434 if (pszType == NULL)
435 throw (kError(kError::DEF_NO_MODULE_STATEMENT));
436}
437
438
439/**
440 * Reads first meaning full line from a file into a buffer.
441 * @returns Pointer to buffer on success; NULL on error.
442 * @param pFile Pointer to fileobject to read line from.
443 * @param pszBuffer Pointer to buffer.
444 * @param cbBuffer Size of buffer.
445 * @remark tabs are expanded. string is trimmed. comments removed.
446 */
447char *kFileDef::readln(kFile *pFile, char *pszBuffer, int cbBuffer) throw (kError)
448{
449 int i;
450 int cch;
451
452 do
453 {
454 /* read line */
455 if (pFile->readln(pszBuffer, cbBuffer))
456 {
457 if (!pFile->isEOF())
458 throw (kError(pFile->getLastError()));
459 return NULL;
460 }
461
462 /* check for and remove comments, and get string length. */
463 cch = 0;
464 while (pszBuffer[cch] != '\0' && pszBuffer[cch] != ';')
465 cch++;
466 pszBuffer[cch] = '\0';
467
468 if (cch > 0)
469 {
470 /* remove '\t' - tab is trouble some! */
471 for (i = 0; i < cch; i++)
472 if (pszBuffer[i] == '\t')
473 pszBuffer[i] = ' ';
474
475 /* trim line - right */
476 i = cch - 1;
477 while (i >= 0 &&
478 (
479 pszBuffer[i] == '\n' ||
480 pszBuffer[i] == '\r' ||
481 pszBuffer[i] == ' '
482 ))
483 i--;
484 pszBuffer[++i] = '\0';
485 cch = i;
486
487 /* trim line - left */
488 i = 0;
489 while (i < cch && pszBuffer[i] == ' ')
490 i++;
491 cch -= i;
492 if (i > 0)
493 memmove(pszBuffer, &pszBuffer[i], cch + 1);
494 }
495 } while ((*pszBuffer == ';' || cch == 0) && !pFile->isEOF());
496
497 return !(*pszBuffer == ';' || cch == 0) ? pszBuffer : NULL;
498}
499
500
501/**
502 * Checks for keyword.
503 * @returns TRUE - keyword; FALSE - not keyword;
504 * @param psz Pointer to word/string to check.
505 * @remark TODO - we are going to check WORDS.
506 */
507KBOOL kFileDef::isKeyword(const char *psz)
508{
509 return psz != NULL
510 &&
511 (
512 StringCase(psz, "LIBRARY") ||
513 StringCase(psz, "NAME") ||
514 StringCase(psz, "PHYSICAL DEVICE") || //gap is fixed to one space, this may be fixed in readln.
515 StringCase(psz, "VIRTUAL DEVICE") || //gap is fixed to one space, this may be fixed in readln.
516 StringCase(psz, "BASE") ||
517 StringCase(psz, "CODE") ||
518 StringCase(psz, "DATA") ||
519 StringCase(psz, "DESCRIPTION") ||
520 StringCase(psz, "EXETYPE") ||
521 StringCase(psz, "HEAPSIZE") ||
522 StringCase(psz, "OLD") ||
523 StringCase(psz, "STACKSIZE") ||
524 StringCase(psz, "STUB") ||
525 StringCase(psz, "SEGMENTS") ||
526 StringCase(psz, "IMPORTS") ||
527 StringCase(psz, "EXPORTS")
528 );
529}
530
531
532/**
533 * Extracts the module name from the pszType string.
534 * @returns Success indicator.
535 * @param pszBuffer Pointer to string buffer which is to hold the module name upon return.
536 * @remark Assumes that pszBuffer is large enough.
537 */
538KBOOL kFileDef::setModuleName(void)
539{
540 char *pszEnd;
541 char *pszStart;
542
543 kASSERT(pszType);
544
545 /* skip the first word */
546 pszStart = strpbrk(pszType, " \t");
547 if (pszStart != NULL)
548 {
549 /* if phys/virt device skip second word too */
550 if (fVirtualDevice || fPhysicalDevice)
551 {
552 pszStart = strpbrk(ltrim(pszStart), " \t");
553 if (pszStart == NULL)
554 return TRUE;
555 }
556
557 pszStart = ltrim(pszStart);
558 pszEnd = strpbrk(pszStart, " \t");
559 if (pszEnd == NULL)
560 pszEnd = pszStart + strlen(pszStart);
561 pszModName = new char[pszEnd - pszStart + 1];
562 memcpy(pszModName, pszStart, pszEnd - pszStart);
563 pszModName[pszEnd - pszStart] = '\0';
564 }
565 else
566 return !StringCase(pszType, "LIBRARY");
567 return TRUE;
568}
569
570
571/**
572 * Query for the module name.
573 * @returns Success indicator. TRUE / FALSE.
574 * @param pszBuffer Pointer to buffer which to put the name into.
575 * @param cchBuffer Size of the buffer (defaults to 260 chars).
576 */
577KBOOL kFileDef::moduleGetName(char *pszBuffer, int cchSize/* = 260*/)
578{
579 int cch;
580 if (pszModName == NULL)
581 return FALSE;
582
583 cch = strlen(pszModName) + 1;
584 if (cch > cchSize)
585 return FALSE;
586 memcpy(pszBuffer, pszModName, cch);
587
588 return TRUE;
589}
590
591
592/**
593 * Finds the first exports.
594 * @returns Success indicator. TRUE / FALSE.
595 * @param pExport Pointer to export structure.
596 */
597KBOOL kFileDef::exportFindFirst(kExportEntry *pExport)
598{
599 if (pExports != NULL && pExport != NULL)
600 {
601 pExport->ulOrdinal = pExports->ulOrdinal;
602 pExport->achName[0] = '\0';
603 if (pExports->pszName != NULL)
604 strcpy(&pExport->achName[0], pExports->pszName);
605
606 pExport->achIntName[0] = '\0';
607 if (pExports->pszIntName)
608 strcpy(&pExport->achIntName[0], pExports->pszIntName);
609
610 pExport->ulAddress = pExport->iObject = pExport->ulOffset = ~0UL;
611 pExport->pv = (void*)pExports->pNext;
612 }
613 else
614 return FALSE;
615 return TRUE;
616}
617
618
619/**
620 * Finds the next export.
621 * @returns Success indicator. TRUE / FALSE.
622 * @param pExport Pointer to export structure.
623 */
624KBOOL kFileDef::exportFindNext(kExportEntry *pExport)
625{
626 if (pExport != NULL && pExport->pv != NULL)
627 {
628 PDEFEXPORT pExp = (PDEFEXPORT)pExport->pv;
629
630 pExport->ulOrdinal = pExp->ulOrdinal;
631 pExport->achName[0] = '\0';
632 if (pExp->pszName != NULL)
633 strcpy(&pExport->achName[0], pExp->pszName);
634 pExport->achIntName[0] = '\0';
635 if (pExp->pszIntName)
636 strcpy(&pExport->achIntName[0], pExp->pszIntName);
637 pExport->ulAddress = pExport->iObject = pExport->ulOffset = ~0UL;
638 pExport->pv = (void*)pExp->pNext;
639 }
640 else
641 return FALSE;
642 return TRUE;
643}
644
645
646/**
647 * Frees resources associated with the communicatin area.
648 * It's not necessary to call this when exportFindNext has return FALSE.
649 * (We don't allocate anything so it's not a problem ;-)
650 * @param pExport Communication area which has been successfully
651 * processed by findFirstExport.
652 */
653void kFileDef::exportFindClose(kExportEntry *pExport)
654{
655 pExport = pExport;
656 return;
657}
658
659
660/**
661 * Lookup information on a spesific export given by ordinal number.
662 * @returns Success indicator.
663 * @param pExport Communication area containing export information
664 * on successful return.
665 * @remark stub
666 */
667KBOOL kFileDef::exportLookup(unsigned long ulOrdinal, kExportEntry *pExport)
668{
669 kASSERT(!"not implemented.");
670 ulOrdinal = ulOrdinal;
671 pExport = pExport;
672 return FALSE;
673}
674
675/**
676 * Lookup information on a spesific export given by name.
677 * @returns Success indicator.
678 * @param pExport Communication area containing export information
679 * on successful return.
680 * @remark stub
681 */
682KBOOL kFileDef::exportLookup(const char * pszName, kExportEntry *pExport)
683{
684 kASSERT(!"not implemented.");
685 pszName = pszName;
686 pExport = pExport;
687 return FALSE;
688}
689
690
691/**
692 * Make a Watcom Linker parameter file addtition of this definition file.
693 * @returns Success indicator.
694 * @param pFile File which we're to write to (append).
695 * Appends at current posistion.
696 * @param enmOS The target OS of the link operation.
697 * @sketch
698 * @status
699 * @author knut st. osmundsen (knut.stange.osmundsen@mynd.no)
700 * @remark
701 */
702KBOOL kFileDef::makeWatcomLinkFileAddtion(kFile *pOut, int enmOS) throw(kError)
703{
704 PDEFSEGMENT pSeg;
705 PDEFIMPORT pImp;
706 PDEFEXPORT pExp;
707 pOut->setThrowOnErrors();
708
709 /*
710 * Write a little remark first to tell that converted stuff starts here.
711 */
712 pOut->printf("#\n# Directives generated from .DEF-file.\n#\n");
713
714 /* Format - Module type */
715 switch (enmOS)
716 {
717 case kFileDef::os2:
718 pOut->printf("FORMAT OS2 LX %s %s %s\n",
719 fLibrary ? "DLL" :
720 (fProgram ? (chAppType == pm ? "PM"
721 : (chAppType == fullscreen ? "FULLSCREEN"
722 : "PMCOMPATIBLE"))
723 : (fVirtualDevice ? "VIRTDEVICE"
724 : "PHYSDEVICE" )),
725 fLibrary ? (fInitGlobal || (!fInitInstance && !fTermInstance)
726 ? "INITGLOBAL"
727 : "INITINSTANCE")
728 : "",
729 fLibrary ? (fTermGlobal || (!fTermInstance && !fInitInstance)
730 ? "TERMGLOBAL"
731 : "TERMINSTANCE")
732 : "");
733 break;
734
735 case kFileDef::os2v1:
736 pOut->printf("FORMAT OS2 %s %s %s\n",
737 fLibrary ? "DLL" :
738 (fProgram ? (chAppType == pm ? "PM"
739 : (chAppType == fullscreen ? "FULLSCREEN"
740 : "PMCOMPATIBLE"))
741 : (fVirtualDevice ? "VIRTDEVICE"
742 : "PHYSDEVICE" )),
743 fLibrary ? (fInitGlobal || fTermGlobal ? "INITGLOBAL" /* Not sure how correct these things are! */
744 : "")
745 : "",
746 /*fLibrary ? (fTermGlobal || fInitGlobal ? "TERMGLOBAL"
747 : "")
748 :*/ "");
749 break;
750
751 case kFileDef::win32:
752 if (fLibrary)
753 pOut->printf("FORMAT Window NT DLL %s %s\n"
754 "Runtime Windows\n",
755 fLibrary ? (fInitGlobal ? "INITGLOBAL" : "INITINSTANCE") : "",
756 fLibrary ? (fTermGlobal ? "TERMGLOBAL" : "TERMINSTANCE") : "");
757 else
758 pOut->printf("FORMAT Window NT\n"
759 "Runtime %s\n",
760 fProgram ? chAppType == pm ? "Windows" : "Console" : "Native");
761 break;
762 default:
763 return FALSE;
764 }
765
766
767 /* Module name */
768 if (pszModName)
769 pOut->printf("OPTION MODNAME=%s\n", pszModName);
770
771 /* Description */
772 if (pszDescription)
773 pOut->printf("OPTION DESCRIPTION '%s'\n", pszDescription);
774
775 /* Base */
776 if (pszBase)
777 pOut->printf("OPTION OFFSET=%s\n", pszBase);
778
779 /* Stub */
780 if (pszStub)
781 pOut->printf("OPTION STUB='%s'\n", pszStub);
782
783 /* Old */
784 if (pszOld)
785 pOut->printf("OPTION OLDLIBRARY=%s\n", pszOld);
786
787 /* Protected mode */
788 if (pszProtmode && (enmOS == kFileDef::os2))
789 pOut->printf("OPTION PROTMODE\n", pszProtmode);
790
791 /* Stacksize */
792 if (pszStackSize)
793 pOut->printf("OPTION STACK=%s\n", pszStackSize);
794
795 /* HeapSize */
796 if (pszHeapSize)
797 pOut->printf("OPTION HEAPSIZE=%s\n", pszHeapSize);
798
799 /* Code - not supported */
800
801 /* Data - not supported */
802
803 /*
804 * Segments.
805 */
806 pSeg = pSegments;
807 while (pSeg != NULL)
808 {
809 if (pSeg->pszName)
810 pOut->printf("SEGMENT '%s' %s\n", pSeg->pszName, pSeg->pszAttr ? pSeg->pszAttr : "");
811 if (pSeg->pszClass)
812 pOut->printf("SEGMENT CLASS '%s' %s\n", pSeg->pszClass, pSeg->pszAttr ? pSeg->pszAttr : "");
813 pSeg = pSeg->pNext;
814 }
815
816 /*
817 * Imports.
818 */
819 pImp = pImports;
820 while (pImp != NULL)
821 {
822 if (pImp->pszName == NULL)
823 pOut->printf("IMPORT '%s' '%s'.%d\n", pImp->pszIntName, pImp->pszDll, pImp->ulOrdinal);
824 else
825 pOut->printf("IMPORT '%s' '%s'.'%s'\n", pImp->pszIntName, pImp->pszDll, pImp->pszName);
826 pImp = pImp->pNext;
827 }
828
829 /*
830 * Exports.
831 */
832 pExp = pExports;
833 while (pExp != NULL)
834 {
835 pOut->printf("EXPORT '%s'", pExp->pszName);
836 if (pExp->ulOrdinal != ~0UL)
837 pOut->printf(".%d", pExp->ulOrdinal);
838 if (pExp->pszIntName)
839 pOut->printf("='%s'", pExp->pszIntName);
840 if (pExp->fResident && (enmOS == kFileDef::os2 || enmOS == kFileDef::win16))
841 pOut->printf(" RESIDENT");
842 if (pExp->cParam != ~0UL)
843 pOut->printf(" %d", pExp->cParam * 2); /* .DEFs this is number of words. Watcom should have bytes. */
844 pOut->printf("\n");
845 pExp = pExp->pNext;
846 }
847
848 return TRUE;
849}
850
851
852
853
854/**
855 * Removes '"' and ''' at start and end of the string.
856 * @returns pszStr!
857 * @param pszStr String that is to have "s and 's removed.
858 */
859static char *removeFnutts(char *pszStr)
860{
861 if (pszStr != NULL)
862 {
863 int cch = strlen(pszStr);
864 if (cch > 0 && (pszStr[cch-1] == '"' || pszStr[cch-1] == '\''))
865 pszStr[cch-1] = '\0';
866
867 if (*pszStr == '"' || *pszStr == '\'')
868 memmove(pszStr, pszStr+1, cch-1);
869 }
870 return pszStr;
871}
872
873
874/**
875 * Upcases a char.
876 * @returns Upper case of the char given in ch.
877 * @param ch Char to capitalize.
878 */
879inline char upcase(char ch)
880{
881 return ch >= 'a' && ch <= 'z' ? (char)(ch - ('a' - 'A')) : ch;
882}
883
884
885/**
886 * Searches for a substring in a string.
887 * @returns Pointer to start of substring when found, NULL when not found.
888 * @param pszStr String to be searched.
889 * @param pszSubStr String to be searched.
890 * @remark Depends on the upcase function.
891 */
892static char *stristr(const char *pszStr, const char *pszSubStr)
893{
894 int cchSubStr = strlen(pszSubStr);
895 int i = 0;
896
897 while (*pszStr != '\0' && i < cchSubStr)
898 {
899 i = 0;
900 while (i < cchSubStr && pszStr[i] != '\0' &&
901 (upcase(pszStr[i]) == upcase(pszSubStr[i])))
902 i++;
903 pszStr++;
904 }
905
906 return (char*)(*pszStr != '\0' ? pszStr - 1 : NULL);
907}
908
Note: See TracBrowser for help on using the repository browser.