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

Last change on this file since 9133 was 9133, checked in by bird, 23 years ago

Bugfixing on initerm issues.

File size: 27.8 KB
Line 
1/* $Id: kFileDef.cpp,v 1.11 2002-08-25 23:24:57 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;
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 /* if phys/virt device skip second word too */
508 if (fVirtualDevice || fPhysicalDevice)
509 {
510 pszStart = strpbrk(ltrim(pszStart), " \t");
511 if (pszStart == NULL)
512 return TRUE;
513 }
514
515 pszStart = ltrim(pszStart);
516 pszEnd = strpbrk(pszStart, " \t");
517 if (pszEnd == NULL)
518 pszEnd = pszStart + strlen(pszStart);
519 pszModName = new char[pszEnd - pszStart + 1];
520 memcpy(pszModName, pszStart, pszEnd - pszStart);
521 pszModName[pszEnd - pszStart] = '\0';
522 }
523 else
524 return !StringCase(pszType, "LIBRARY");
525 return TRUE;
526}
527
528
529/**
530 * Query for the module name.
531 * @returns Success indicator. TRUE / FALSE.
532 * @param pszBuffer Pointer to buffer which to put the name into.
533 * @param cchBuffer Size of the buffer (defaults to 260 chars).
534 */
535KBOOL kFileDef::moduleGetName(char *pszBuffer, int cchSize/* = 260*/)
536{
537 int cch;
538 if (pszModName == NULL)
539 return FALSE;
540
541 cch = strlen(pszModName) + 1;
542 if (cch > cchSize)
543 return FALSE;
544 memcpy(pszBuffer, pszModName, cch);
545
546 return TRUE;
547}
548
549
550/**
551 * Finds the first exports.
552 * @returns Success indicator. TRUE / FALSE.
553 * @param pExport Pointer to export structure.
554 */
555KBOOL kFileDef::exportFindFirst(kExportEntry *pExport)
556{
557 if (pExports != NULL && pExport != NULL)
558 {
559 pExport->ulOrdinal = pExports->ulOrdinal;
560 pExport->achName[0] = '\0';
561 if (pExports->pszName != NULL)
562 strcpy(&pExport->achName[0], pExports->pszName);
563
564 pExport->achIntName[0] = '\0';
565 if (pExports->pszIntName)
566 strcpy(&pExport->achIntName[0], pExports->pszIntName);
567
568 pExport->ulAddress = pExport->iObject = pExport->ulOffset = ~0UL;
569 pExport->pv = (void*)pExports->pNext;
570 }
571 else
572 return FALSE;
573 return TRUE;
574}
575
576
577/**
578 * Finds the next export.
579 * @returns Success indicator. TRUE / FALSE.
580 * @param pExport Pointer to export structure.
581 */
582KBOOL kFileDef::exportFindNext(kExportEntry *pExport)
583{
584 if (pExport != NULL && pExport->pv != NULL)
585 {
586 PDEFEXPORT pExp = (PDEFEXPORT)pExport->pv;
587
588 pExport->ulOrdinal = pExp->ulOrdinal;
589 pExport->achName[0] = '\0';
590 if (pExp->pszName != NULL)
591 strcpy(&pExport->achName[0], pExp->pszName);
592 pExport->achIntName[0] = '\0';
593 if (pExp->pszIntName)
594 strcpy(&pExport->achIntName[0], pExp->pszIntName);
595 pExport->ulAddress = pExport->iObject = pExport->ulOffset = ~0UL;
596 pExport->pv = (void*)pExp->pNext;
597 }
598 else
599 return FALSE;
600 return TRUE;
601}
602
603
604/**
605 * Frees resources associated with the communicatin area.
606 * It's not necessary to call this when exportFindNext has return FALSE.
607 * (We don't allocate anything so it's not a problem ;-)
608 * @param pExport Communication area which has been successfully
609 * processed by findFirstExport.
610 */
611void kFileDef::exportFindClose(kExportEntry *pExport)
612{
613 pExport = pExport;
614 return;
615}
616
617
618/**
619 * Lookup information on a spesific export given by ordinal number.
620 * @returns Success indicator.
621 * @param pExport Communication area containing export information
622 * on successful return.
623 * @remark stub
624 */
625KBOOL kFileDef::exportLookup(unsigned long ulOrdinal, kExportEntry *pExport)
626{
627 kASSERT(!"not implemented.");
628 ulOrdinal = ulOrdinal;
629 pExport = pExport;
630 return FALSE;
631}
632
633/**
634 * Lookup information on a spesific export given by name.
635 * @returns Success indicator.
636 * @param pExport Communication area containing export information
637 * on successful return.
638 * @remark stub
639 */
640KBOOL kFileDef::exportLookup(const char * pszName, kExportEntry *pExport)
641{
642 kASSERT(!"not implemented.");
643 pszName = pszName;
644 pExport = pExport;
645 return FALSE;
646}
647
648
649/**
650 * Make a Watcom Linker parameter file addtition of this definition file.
651 * @returns Success indicator.
652 * @param pFile File which we're to write to (append).
653 * Appends at current posistion.
654 * @param enmOS The target OS of the link operation.
655 * @sketch
656 * @status
657 * @author knut st. osmundsen (knut.stange.osmundsen@mynd.no)
658 * @remark
659 */
660KBOOL kFileDef::makeWatcomLinkFileAddtion(kFile *pOut, int enmOS)
661{
662 PDEFSEGMENT pSeg;
663 PDEFIMPORT pImp;
664 PDEFEXPORT pExp;
665 pOut->setThrowOnErrors();
666
667 /*
668 * Write a little remark first to tell that converted stuff starts here.
669 */
670 pOut->printf("#\n# Directives generated from .DEF-file.\n#\n");
671
672 /* Format - Module type */
673 switch (enmOS)
674 {
675 case kFileDef::os2:
676 pOut->printf("FORMAT OS2 LX %s %s %s\n",
677 fLibrary ? "DLL" :
678 (fProgram ? (chAppType == pm ? "PM"
679 : (chAppType == fullscreen ? "FULLSCREEN"
680 : "PMCOMPATIBLE"))
681 : (fVirtualDevice ? "VIRTDEVICE"
682 : "PHYSDEVICE" )),
683 fLibrary ? (fInitGlobal || (!fInitInstance && !fTermInstance)
684 ? "INITGLOBAL"
685 : "INITINSTANCE")
686 : "",
687 fLibrary ? (fTermGlobal || (!fTermInstance && !fInitInstance)
688 ? "TERMGLOBAL"
689 : "TERMINSTANCE")
690 : "");
691 break;
692
693 case kFileDef::os2v1:
694 pOut->printf("FORMAT OS2 %s %s %s\n",
695 fLibrary ? "DLL" :
696 (fProgram ? (chAppType == pm ? "PM"
697 : (chAppType == fullscreen ? "FULLSCREEN"
698 : "PMCOMPATIBLE"))
699 : (fVirtualDevice ? "VIRTDEVICE"
700 : "PHYSDEVICE" )),
701 fLibrary ? (fInitGlobal || fTermGlobal ? "INITGLOBAL" /* Not sure how correct these things are! */
702 : "")
703 : "",
704 /*fLibrary ? (fTermGlobal || fInitGlobal ? "TERMGLOBAL"
705 : "")
706 :*/ "");
707 break;
708
709 case kFileDef::win32:
710 if (fLibrary)
711 pOut->printf("FORMAT Window NT DLL %s %s\n"
712 "Runtime Windows\n",
713 fLibrary ? (fInitGlobal ? "INITGLOBAL" : "INITINSTANCE") : "",
714 fLibrary ? (fTermGlobal ? "TERMGLOBAL" : "TERMINSTANCE") : "");
715 else
716 pOut->printf("FORMAT Window NT\n"
717 "Runtime %s\n",
718 fProgram ? chAppType == pm ? "Windows" : "Console" : "Native");
719 break;
720 default:
721 return FALSE;
722 }
723
724
725 /* Module name */
726 if (pszModName)
727 pOut->printf("OPTION MODNAME=%s\n", pszModName);
728
729 /* Description */
730 if (pszDescription)
731 pOut->printf("OPTION DESCRIPTION '%s'\n", pszDescription);
732
733 /* Base */
734 if (pszBase)
735 pOut->printf("OPTION OFFSET=%s\n", pszBase);
736
737 /* Stub */
738 if (pszStub)
739 pOut->printf("OPTION STUB='%s'\n", pszStub);
740
741 /* Old */
742 if (pszOld)
743 pOut->printf("OPTION OLDLIBRARY=%s\n", pszOld);
744
745 /* Protected mode */
746 if (pszProtmode && (enmOS == kFileDef::os2))
747 pOut->printf("OPTION PROTMODE\n", pszProtmode);
748
749 /* Stacksize */
750 if (pszStackSize)
751 pOut->printf("OPTION STACK=%s\n", pszStackSize);
752
753 /* HeapSize */
754 if (pszHeapSize)
755 pOut->printf("OPTION HEAPSIZE=%s\n", pszHeapSize);
756
757 /* Code - not supported */
758
759 /* Data - not supported */
760
761 /*
762 * Segments.
763 */
764 pSeg = pSegments;
765 while (pSeg != NULL)
766 {
767 pOut->printf("SEGMENT %s\n", pSeg->psz);
768 pSeg = pSeg->pNext;
769 }
770
771 /*
772 * Imports.
773 */
774 pImp = pImports;
775 while (pImp != NULL)
776 {
777 if (pImp->pszName == NULL)
778 pOut->printf("IMPORT '%s' '%s'.%d\n", pImp->pszIntName, pImp->pszDll, pImp->ulOrdinal);
779 else
780 pOut->printf("IMPORT '%s' '%s'.'%s'\n", pImp->pszIntName, pImp->pszDll, pImp->pszName);
781 pImp = pImp->pNext;
782 }
783
784 /*
785 * Exports.
786 */
787 pExp = pExports;
788 while (pExp != NULL)
789 {
790 pOut->printf("EXPORT '%s'", pExp->pszName);
791 if (pExp->ulOrdinal != ~0UL)
792 pOut->printf(".%d", pExp->ulOrdinal);
793 if (pExp->pszIntName)
794 pOut->printf("='%s'", pExp->pszIntName);
795 if (pExp->fResident && (enmOS == kFileDef::os2 || enmOS == kFileDef::win16))
796 pOut->printf(" RESIDENT");
797 if (pExp->cParam != ~0UL)
798 pOut->printf(" %d", pExp->cParam * 2); /* .DEFs this is number of words. Watcom should have bytes. */
799 pOut->printf("\n");
800 pExp = pExp->pNext;
801 }
802
803 return TRUE;
804}
805
806
807
808
809/**
810 * Removes '"' and ''' at start and end of the string.
811 * @returns pszStr!
812 * @param pszStr String that is to have "s and 's removed.
813 */
814static char *removeFnutts(char *pszStr)
815{
816 if (pszStr != NULL)
817 {
818 int cch = strlen(pszStr);
819 if (cch > 0 && (pszStr[cch-1] == '"' || pszStr[cch-1] == '\''))
820 pszStr[cch-1] = '\0';
821
822 if (*pszStr == '"' || *pszStr == '\'')
823 memmove(pszStr, pszStr+1, cch-1);
824 }
825 return pszStr;
826}
827
828
829/**
830 * Upcases a char.
831 * @returns Upper case of the char given in ch.
832 * @param ch Char to capitalize.
833 */
834inline char upcase(char ch)
835{
836 return ch >= 'a' && ch <= 'z' ? (char)(ch - ('a' - 'A')) : ch;
837}
838
839
840/**
841 * Searches for a substring in a string.
842 * @returns Pointer to start of substring when found, NULL when not found.
843 * @param pszStr String to be searched.
844 * @param pszSubStr String to be searched.
845 * @remark Depends on the upcase function.
846 */
847static char *stristr(const char *pszStr, const char *pszSubStr)
848{
849 int cchSubStr = strlen(pszSubStr);
850 int i = 0;
851
852 while (*pszStr != '\0' && i < cchSubStr)
853 {
854 i = 0;
855 while (i < cchSubStr && pszStr[i] != '\0' &&
856 (upcase(pszStr[i]) == upcase(pszSubStr[i])))
857 i++;
858 pszStr++;
859 }
860
861 return (char*)(*pszStr != '\0' ? pszStr - 1 : NULL);
862}
863
Note: See TracBrowser for help on using the repository browser.