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

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

Second iteration of the kFile* classes and interfaces.

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