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

Last change on this file since 8003 was 8003, checked in by bird, 24 years ago

New kFile* classes; now in sync with os2tools.

File size: 25.2 KB
Line 
1/* $Id: kFileDef.cpp,v 1.8 2002-02-24 02:47:25 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) :
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()
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)
185{
186 char *pszTmp;
187 char *psz;
188 char szBuffer[256];
189
190 /* readloop */
191 psz = readln(pFile, &szBuffer[0], sizeof(szBuffer));
192 while (psz != NULL)
193 {
194 KBOOL fNext = TRUE;
195
196 /* if-switch */
197 if (StringCase(psz, "LIBRARY"))
198 {
199 if (pszType != NULL) throw (kError(kError::DEF_MULIPLE_MODULE_STATEMENT));
200 pszType = dupeString(psz);
201 fLibrary = TRUE;
202 if (!setModuleName())
203 throw (kError(kError::DEF_BAD_LIBRARY_STATEMENT));
204 fInitInstance = stristr(pszType, "INITINSTANCE") != NULL;
205 fInitGlobal = stristr(pszType, "INITGLOBAL") != NULL || !fInitInstance;
206 fTermInstance = stristr(pszType, "TERMINSTANCE") != NULL;
207 fTermGlobal = stristr(pszType, "TERMGLOBAL") != NULL || !fTermInstance;
208 }
209 else if (StringCase(psz, "NAME"))
210 {
211 if (pszType != NULL) throw (kError(kError::DEF_MULIPLE_MODULE_STATEMENT));
212 pszType = dupeString(psz);
213 fProgram = TRUE;
214 setModuleName();
215 if (stristr(pszType, "WINDOWAPI"))
216 chAppType = kFileDef::pm;
217 else if (stristr(pszType, "NOTWINDOWCOMPAT"))
218 chAppType = kFileDef::fullscreen;
219 else if (stristr(pszType, "WINDOWCOMPAT"))
220 chAppType = kFileDef::pmvio;
221 else
222 chAppType = kFileDef::unknown;
223 }
224 else if (StringCase(psz, "PHYSICAL DEVICE")) //gap is fixed to one space, this may be fixed in readln.
225 {
226 if (pszType != NULL) throw (kError(kError::DEF_MULIPLE_MODULE_STATEMENT));
227 pszType = dupeString(psz);
228 fPhysicalDevice = TRUE;
229 setModuleName();
230 }
231 else if (StringCase(psz, "VIRTUAL DEVICE")) //gap is fixed to one space, this may be fixed in readln.
232 {
233 if (pszType != NULL) throw (kError(kError::DEF_MULIPLE_MODULE_STATEMENT));
234 pszType = dupeString(psz);
235 fVirtualDevice = TRUE;
236 setModuleName();
237 }
238 else if (StringCase(psz, "BASE"))
239 pszBase = dupeString(psz, TRUE);
240 else if (StringCase(psz, "CODE"))
241 pszCode = dupeString(psz, TRUE);
242 else if (StringCase(psz, "DATA"))
243 pszData = dupeString(psz, TRUE);
244 else if (StringCase(psz, "DESCRIPTION"))
245 pszDescription = dupeString(psz, TRUE);
246 else if (StringCase(psz, "EXETYPE"))
247 pszExeType = dupeString(psz, TRUE);
248 else if (StringCase(psz, "HEAPSIZE"))
249 pszHeapSize = dupeString(psz, TRUE);
250 else if (StringCase(psz, "OLD"))
251 pszOld = dupeString(psz, TRUE);
252 else if (StringCase(psz, "PROTMODE"))
253 pszProtmode = dupeString(psz, TRUE);
254 else if (StringCase(psz, "STACKSIZE"))
255 pszStackSize = dupeString(psz, TRUE);
256 else if (StringCase(psz, "STUB"))
257 pszStub = dupeString(psz, TRUE);
258 else if (StringCase(psz, "SEGMENTS"))
259 {
260 PDEFSEGMENT *pps = &pSegments;
261 while (!isKeyword(psz = readln(pFile, &szBuffer[0], sizeof(szBuffer))) && psz != NULL)
262 {
263 *pps = new DEFSEGMENT; memset(*pps, 0, sizeof(**pps));
264 (**pps).psz = dupeString(psz);
265 pps = &(**pps).pNext;
266 }
267 fNext = FALSE;
268 }
269 else if (StringCase(psz, "IMPORTS"))
270 {
271 PDEFIMPORT *ppi = &pImports;
272 while (!isKeyword(psz = readln(pFile, &szBuffer[0], sizeof(szBuffer))) && psz != NULL)
273 {
274 //DOSCALL1.154 or DosQueryHeaderInfo = DOSCALL1.154
275 *ppi = new DEFIMPORT; memset(*ppi, 0, sizeof(**ppi));
276 (**ppi).ulOrdinal = 0xffffffffUL;
277
278 if ((pszTmp = strchr(psz, '=')) != NULL)
279 {
280 *pszTmp = '\0';
281 (**ppi).pszIntName = dupeString(trim(psz));
282 psz = pszTmp + 1;
283 }
284 if ((pszTmp = strchr(psz, '.')) != NULL)
285 {
286 *pszTmp = '\0';
287 (**ppi).pszDll = dupeString(trim(psz));
288 psz = pszTmp + 1;
289 }
290 psz = trim(psz);
291 if (*psz >= '0' && *psz <= '9')
292 {
293 (**ppi).ulOrdinal = strtol(psz, &pszTmp, 0);
294 if (psz ==pszTmp) throw (kError(kError::DEF_BAD_IMPORT));
295 }
296 else
297 (**ppi).pszName = dupeString(psz);
298 ppi = &(**ppi).pNext;
299 }
300 fNext = FALSE;
301 }
302 else if (StringCase(psz, "EXPORTS"))
303 {
304 PDEFEXPORT *ppe = &pExports;
305 while (!isKeyword(psz = readln(pFile, &szBuffer[0], sizeof(szBuffer))) && psz != NULL)
306 {
307 /* CloseHandle = CloseHandle@4 @1234 RESIDENTNAME 2 */
308 *ppe = new DEFEXPORT; memset(*ppe, 0, sizeof(**ppe));
309 (**ppe).ulOrdinal = 0xffffffffUL;
310 (**ppe).cParam = 0xffffffffUL;
311
312 /* look for '=' */
313 pszTmp = strchr(psz, '=');
314 if (pszTmp != NULL)
315 { /* CloseHandle = CloseHandle@4 */
316 *pszTmp ='\0';
317 (**ppe).pszName = dupeString(trim(psz));
318 psz = trim(pszTmp + 1);
319
320 pszTmp = strchr(psz, ' ');
321 if (pszTmp != NULL)
322 *pszTmp = '\0';
323 (**ppe).pszIntName = dupeString(trim(psz));
324 if (pszTmp != NULL)
325 psz = pszTmp + 1;
326 else
327 psz = NULL;
328 }
329 else
330 { /* CloseHandle (no '= CloseHandle@4')*/
331 pszTmp = strchr(psz, ' ');
332 if (pszTmp != NULL)
333 *pszTmp = '\0';
334 (**ppe).pszName = dupeString(trim(psz));
335 if (pszTmp != NULL)
336 psz = pszTmp + 1;
337 else
338 psz = NULL;
339 }
340
341 if (psz != NULL)
342 { /* @1234 RESIDENTNAME 2 */
343 pszTmp = strchr(psz, '@');
344 if (pszTmp)
345 { /* @1234 RESIDENTNAME 2 */
346 psz = pszTmp + 1;
347 (**ppe).ulOrdinal = strtol(psz, &pszTmp, 0);
348 if (pszTmp == psz) throw (kError(kError::DEF_BAD_EXPORT));
349 psz = trim(pszTmp);
350
351 if (*psz != '\0')
352 { /* RESIDENTNAME 2 */
353 if (StringCase(psz, "RESIDENTNAME"))
354 {
355 (**ppe).fResident = TRUE;
356 psz = trim(psz + sizeof("RESIDENTNAME") - 1);
357 }
358 else if (StringCase(psz, "NONAME"))
359 {
360 (**ppe).fResident = FALSE;
361 psz = trim(psz + sizeof("NONAME") - 1);
362 }
363 }
364 else
365 {
366 (**ppe).fResident = (**ppe).ulOrdinal == 0xffffffffUL;
367 }
368 }
369
370 if (*psz != '\0')
371 { /* 2 */
372 (**ppe).cParam = strtol(psz, &pszTmp, 0);
373 if (pszTmp == psz) throw (kError(kError::DEF_BAD_EXPORT));
374 }
375 }
376
377 removeFnutts((**ppe).pszIntName);
378 removeFnutts((**ppe).pszName);
379 ppe = &(**ppe).pNext;
380 }
381 fNext = FALSE;
382 }
383 else
384 throw (kError(kError::DEF_UNKOWN_VERB));
385
386 /* next ? */
387 if (fNext)
388 psz = readln(pFile, &szBuffer[0], sizeof(szBuffer));
389 }
390
391 /* sanity check */
392 if (pszType == NULL)
393 throw (kError(kError::DEF_NO_MODULE_STATEMENT));
394}
395
396
397/**
398 * Reads first meaning full line from a file into a buffer.
399 * @returns Pointer to buffer on success; NULL on error.
400 * @param pFile Pointer to fileobject to read line from.
401 * @param pszBuffer Pointer to buffer.
402 * @param cbBuffer Size of buffer.
403 * @remark tabs are expanded. string is trimmed. comments removed.
404 */
405char *kFileDef::readln(kFile *pFile, char *pszBuffer, int cbBuffer)
406{
407 int i;
408 int cch;
409
410 do
411 {
412 /* read line */
413 if (pFile->readln(pszBuffer, cbBuffer))
414 {
415 if (!pFile->isEOF())
416 throw (kError(pFile->getLastError()));
417 return NULL;
418 }
419
420 /* check for and remove comments, and get string length. */
421 cch = 0;
422 while (pszBuffer[cch] != '\0' && pszBuffer[cch] != ';')
423 cch++;
424 pszBuffer[cch] = '\0';
425
426 if (cch > 0)
427 {
428 /* remove '\t' - tab is trouble some! */
429 for (i = 0; i < cch; i++)
430 if (pszBuffer[i] == '\t')
431 pszBuffer[i] = ' ';
432
433 /* trim line - right */
434 i = cch - 1;
435 while (i >= 0 &&
436 (
437 pszBuffer[i] == '\n' ||
438 pszBuffer[i] == '\r' ||
439 pszBuffer[i] == ' '
440 ))
441 i--;
442 pszBuffer[++i] = '\0';
443 cch = i;
444
445 /* trim line - left */
446 i = 0;
447 while (i < cch && pszBuffer[i] == ' ')
448 i++;
449 cch -= i;
450 if (i > 0)
451 memmove(pszBuffer, &pszBuffer[i], cch + 1);
452 }
453 } while ((*pszBuffer == ';' || cch == 0) && !pFile->isEOF());
454
455 return !(*pszBuffer == ';' || cch == 0) ? pszBuffer : NULL;
456}
457
458
459/**
460 * Checks for keyword.
461 * @returns TRUE - keyword; FALSE - not keyword;
462 * @param psz Pointer to word/string to check.
463 * @remark TODO - we are going to check WORDS.
464 */
465KBOOL kFileDef::isKeyword(const char *psz)
466{
467 return psz != NULL
468 &&
469 (
470 StringCase(psz, "LIBRARY") ||
471 StringCase(psz, "NAME") ||
472 StringCase(psz, "PHYSICAL DEVICE") || //gap is fixed to one space, this may be fixed in readln.
473 StringCase(psz, "VIRTUAL DEVICE") || //gap is fixed to one space, this may be fixed in readln.
474 StringCase(psz, "BASE") ||
475 StringCase(psz, "CODE") ||
476 StringCase(psz, "DATA") ||
477 StringCase(psz, "DESCRIPTION") ||
478 StringCase(psz, "EXETYPE") ||
479 StringCase(psz, "HEAPSIZE") ||
480 StringCase(psz, "OLD") ||
481 StringCase(psz, "STACKSIZE") ||
482 StringCase(psz, "STUB") ||
483 StringCase(psz, "SEGMENTS") ||
484 StringCase(psz, "IMPORTS") ||
485 StringCase(psz, "EXPORTS")
486 );
487}
488
489
490/**
491 * Extracts the module name from the pszType string.
492 * @returns Success indicator.
493 * @param pszBuffer Pointer to string buffer which is to hold the module name upon return.
494 * @remark Assumes that pszBuffer is large enough.
495 */
496KBOOL kFileDef::setModuleName(void)
497{
498 char *pszEnd;
499 char *pszStart;
500
501 kASSERT(pszType);
502
503 /* skip the first word */
504 pszStart = strpbrk(pszType, " \t");
505 if (pszStart != NULL)
506 {
507 pszStart = ltrim(pszStart);
508 pszEnd = strpbrk(pszStart, " \t");
509 if (pszEnd == NULL)
510 pszEnd = pszStart + strlen(pszStart);
511 pszModName = new char[pszEnd - pszStart + 1];
512 memcpy(pszModName, pszStart, pszEnd - pszStart);
513 pszModName[pszEnd - pszStart] = '\0';
514 }
515 else
516 return !StringCase(pszType, "LIBRARY");
517 return TRUE;
518}
519
520
521/**
522 * Query for the module name.
523 * @returns Success indicator. TRUE / FALSE.
524 * @param pszBuffer Pointer to buffer which to put the name into.
525 * @param cchBuffer Size of the buffer (defaults to 260 chars).
526 */
527KBOOL kFileDef::moduleGetName(char *pszBuffer, int cchSize/* = 260*/)
528{
529 int cch;
530 if (pszModName == NULL)
531 return FALSE;
532
533 cch = strlen(pszModName) + 1;
534 if (cch > cchSize)
535 return FALSE;
536 memcpy(pszBuffer, pszModName, cch);
537
538 return TRUE;
539}
540
541
542/**
543 * Finds the first exports.
544 * @returns Success indicator. TRUE / FALSE.
545 * @param pExport Pointer to export structure.
546 */
547KBOOL kFileDef::exportFindFirst(kExportEntry *pExport)
548{
549 if (pExports != NULL && pExport != NULL)
550 {
551 pExport->ulOrdinal = pExports->ulOrdinal;
552 pExport->achName[0] = '\0';
553 if (pExports->pszName != NULL)
554 strcpy(&pExport->achName[0], pExports->pszName);
555
556 pExport->achIntName[0] = '\0';
557 if (pExports->pszIntName)
558 strcpy(&pExport->achIntName[0], pExports->pszIntName);
559
560 pExport->ulAddress = pExport->iObject = pExport->ulOffset = ~0UL;
561 pExport->pv = (void*)pExports->pNext;
562 }
563 else
564 return FALSE;
565 return TRUE;
566}
567
568
569/**
570 * Finds the next export.
571 * @returns Success indicator. TRUE / FALSE.
572 * @param pExport Pointer to export structure.
573 */
574KBOOL kFileDef::exportFindNext(kExportEntry *pExport)
575{
576 if (pExport != NULL && pExport->pv != NULL)
577 {
578 PDEFEXPORT pExp = (PDEFEXPORT)pExport->pv;
579
580 pExport->ulOrdinal = pExp->ulOrdinal;
581 pExport->achName[0] = '\0';
582 if (pExp->pszName != NULL)
583 strcpy(&pExport->achName[0], pExp->pszName);
584 pExport->achIntName[0] = '\0';
585 if (pExp->pszIntName)
586 strcpy(&pExport->achIntName[0], pExp->pszIntName);
587 pExport->ulAddress = pExport->iObject = pExport->ulOffset = ~0UL;
588 pExport->pv = (void*)pExp->pNext;
589 }
590 else
591 return FALSE;
592 return TRUE;
593}
594
595
596/**
597 * Frees resources associated with the communicatin area.
598 * It's not necessary to call this when exportFindNext has return FALSE.
599 * (We don't allocate anything so it's not a problem ;-)
600 * @param pExport Communication area which has been successfully
601 * processed by findFirstExport.
602 */
603void kFileDef::exportFindClose(kExportEntry *pExport)
604{
605 pExport = pExport;
606 return;
607}
608
609
610/**
611 * Lookup information on a spesific export given by ordinal number.
612 * @returns Success indicator.
613 * @param pExport Communication area containing export information
614 * on successful return.
615 * @remark stub
616 */
617KBOOL kFileDef::exportLookup(unsigned long ulOrdinal, kExportEntry *pExport)
618{
619 kASSERT(!"not implemented.");
620 ulOrdinal = ulOrdinal;
621 pExport = pExport;
622 return FALSE;
623}
624
625/**
626 * Lookup information on a spesific export given by name.
627 * @returns Success indicator.
628 * @param pExport Communication area containing export information
629 * on successful return.
630 * @remark stub
631 */
632KBOOL kFileDef::exportLookup(const char * pszName, kExportEntry *pExport)
633{
634 kASSERT(!"not implemented.");
635 pszName = pszName;
636 pExport = pExport;
637 return FALSE;
638}
639
640
641/**
642 * Make a Watcom Linker parameter file addtition of this definition file.
643 * @returns Success indicator.
644 * @param pFile File which we're to write to (append).
645 * Appends at current posistion.
646 * @sketch
647 * @status
648 * @author knut st. osmundsen (knut.stange.osmundsen@mynd.no)
649 * @remark
650 */
651KBOOL kFileDef::makeWatcomLinkFileAddtion(kFile *pOut)
652{
653 PDEFSEGMENT pSeg;
654 PDEFIMPORT pImp;
655 PDEFEXPORT pExp;
656 pOut->setThrowOnErrors();
657
658 /*
659 * Write a little remark first to tell that converted stuff starts here.
660 */
661 pOut->printf("#\n# Directives generated from .DEF-file.\n#\n");
662
663 /* Format - Module type */
664 pOut->printf("FORMAT OS2 LX %s %s %s\n",
665 fLibrary ? "DLL" :
666 (fProgram ? (chAppType == pm ? "PM"
667 : (chAppType == fullscreen ? "FULLSCREEN"
668 : "PMCOMPATIBLE"))
669 : (fVirtualDevice ? "VIRTDEVICE"
670 : "PHYSDEVICE" )),
671 fLibrary ? (fInitGlobal ? "INITGLOBAL" : "INITINSTANCE") : "",
672 fLibrary ? (fTermGlobal ? "TERMGLOBAL" : "TERMINSTANCE") : "");
673
674
675 /* Module name */
676 if (pszModName)
677 pOut->printf("OPTION MODNAME=%s\n", pszModName);
678
679 /* Description */
680 if (pszDescription)
681 pOut->printf("OPTION DESCRIPTION '%s'\n", pszDescription);
682
683 /* Base */
684 if (pszBase)
685 pOut->printf("OPTION OFFSET=%s\n", pszBase);
686
687 /* Stub */
688 if (pszStub)
689 pOut->printf("OPTION STUB='%s'\n", pszStub);
690
691 /* Old */
692 if (pszOld)
693 pOut->printf("OPTION OLDLIBRARY=%s\n", pszOld);
694
695 /* Protected mode */
696 if (pszProtmode)
697 pOut->printf("OPTION PROTMODE\n", pszProtmode);
698
699 /* Stacksize */
700 if (pszStackSize)
701 pOut->printf("OPTION STACK=%s\n", pszStackSize);
702
703 /* HeapSize */
704 if (pszHeapSize)
705 pOut->printf("OPTION HEAPSIZE=%s\n", pszHeapSize);
706
707 /* Code - not supported */
708
709 /* Data - not supported */
710
711 /*
712 * Segments.
713 */
714 pSeg = pSegments;
715 while (pSeg != NULL)
716 {
717 pOut->printf("SEGMENT %s\n", pSeg->psz);
718 pSeg = pSeg->pNext;
719 }
720
721 /*
722 * Imports.
723 */
724 pImp = pImports;
725 while (pImp != NULL)
726 {
727 if (pImp->pszName == NULL)
728 pOut->printf("IMPORT '%s' '%s'.%d\n", pImp->pszIntName, pImp->pszDll, pImp->ulOrdinal);
729 else
730 pOut->printf("IMPORT '%s' '%s'.'%s'\n", pImp->pszIntName, pImp->pszDll, pImp->pszName);
731 pImp = pImp->pNext;
732 }
733
734 /*
735 * Exports.
736 */
737 pExp = pExports;
738 while (pExp != NULL)
739 {
740 pOut->printf("EXPORT '%s'", pExp->pszName);
741 if (pExp->ulOrdinal != ~0UL)
742 pOut->printf(".%d", pExp->ulOrdinal);
743 if (pExp->pszIntName)
744 pOut->printf("='%s'", pExp->pszIntName);
745 if (pExp->fResident)
746 pOut->printf(" RESIDENT");
747 if (pExp->cParam != ~0UL)
748 pOut->printf(" %d", pExp->cParam * 2); /* .DEFs this is number of words. Watcom should have bytes. */
749 pOut->printf("\n");
750 pExp = pExp->pNext;
751 }
752
753 return TRUE;
754}
755
756
757
758
759/**
760 * Removes '"' and ''' at start and end of the string.
761 * @returns pszStr!
762 * @param pszStr String that is to have "s and 's removed.
763 */
764static char *removeFnutts(char *pszStr)
765{
766 if (pszStr != NULL)
767 {
768 int cch = strlen(pszStr);
769 if (cch > 0 && (pszStr[cch-1] == '"' || pszStr[cch-1] == '\''))
770 pszStr[cch-1] = '\0';
771
772 if (*pszStr == '"' || *pszStr == '\'')
773 memmove(pszStr, pszStr+1, cch-1);
774 }
775 return pszStr;
776}
777
778
779/**
780 * Upcases a char.
781 * @returns Upper case of the char given in ch.
782 * @param ch Char to capitalize.
783 */
784inline char upcase(char ch)
785{
786 return ch >= 'a' && ch <= 'z' ? (char)(ch - ('a' - 'A')) : ch;
787}
788
789
790/**
791 * Searches for a substring in a string.
792 * @returns Pointer to start of substring when found, NULL when not found.
793 * @param pszStr String to be searched.
794 * @param pszSubStr String to be searched.
795 * @remark Depends on the upcase function.
796 */
797static char *stristr(const char *pszStr, const char *pszSubStr)
798{
799 int cchSubStr = strlen(pszSubStr);
800 int i = 0;
801
802 while (*pszStr != '\0' && i < cchSubStr)
803 {
804 i = 0;
805 while (i < cchSubStr && pszStr[i] != '\0' &&
806 (upcase(pszStr[i]) == upcase(pszSubStr[i])))
807 i++;
808 pszStr++;
809 }
810
811 return (char*)(*pszStr != '\0' ? pszStr - 1 : NULL);
812}
813
Note: See TracBrowser for help on using the repository browser.