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

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

Support for os2-16 (NE executables).
Corrected bad modulename for PHYSICAL DEVICE and VIRTUAL DEVICE.

File size: 27.0 KB
Line 
1/* $Id: kFileDef.cpp,v 1.10 2002-08-25 22:35:46 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 /* 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 ? "INITGLOBAL" : "INITINSTANCE") : "",
684 fLibrary ? (fTermGlobal ? "TERMGLOBAL" : "TERMINSTANCE") : "");
685 break;
686
687 case kFileDef::os2v1:
688 pOut->printf("FORMAT OS2 %s %s %s\n",
689 fLibrary ? "DLL" :
690 (fProgram ? (chAppType == pm ? "PM"
691 : (chAppType == fullscreen ? "FULLSCREEN"
692 : "PMCOMPATIBLE"))
693 : (fVirtualDevice ? "VIRTDEVICE"
694 : "PHYSDEVICE" )),
695 fLibrary ? (fInitGlobal ? "INITGLOBAL" : "INITINSTANCE") : "",
696 fLibrary ? (fTermGlobal ? "TERMGLOBAL" : "TERMINSTANCE") : "");
697 break;
698
699 case kFileDef::win32:
700 if (fLibrary)
701 pOut->printf("FORMAT Window NT DLL %s %s\n"
702 "Runtime Windows\n",
703 fLibrary ? (fInitGlobal ? "INITGLOBAL" : "INITINSTANCE") : "",
704 fLibrary ? (fTermGlobal ? "TERMGLOBAL" : "TERMINSTANCE") : "");
705 else
706 pOut->printf("FORMAT Window NT\n"
707 "Runtime %s\n",
708 fProgram ? chAppType == pm ? "Windows" : "Console" : "Native");
709 break;
710 default:
711 return FALSE;
712 }
713
714
715 /* Module name */
716 if (pszModName)
717 pOut->printf("OPTION MODNAME=%s\n", pszModName);
718
719 /* Description */
720 if (pszDescription)
721 pOut->printf("OPTION DESCRIPTION '%s'\n", pszDescription);
722
723 /* Base */
724 if (pszBase)
725 pOut->printf("OPTION OFFSET=%s\n", pszBase);
726
727 /* Stub */
728 if (pszStub)
729 pOut->printf("OPTION STUB='%s'\n", pszStub);
730
731 /* Old */
732 if (pszOld)
733 pOut->printf("OPTION OLDLIBRARY=%s\n", pszOld);
734
735 /* Protected mode */
736 if (pszProtmode && (enmOS == kFileDef::os2))
737 pOut->printf("OPTION PROTMODE\n", pszProtmode);
738
739 /* Stacksize */
740 if (pszStackSize)
741 pOut->printf("OPTION STACK=%s\n", pszStackSize);
742
743 /* HeapSize */
744 if (pszHeapSize)
745 pOut->printf("OPTION HEAPSIZE=%s\n", pszHeapSize);
746
747 /* Code - not supported */
748
749 /* Data - not supported */
750
751 /*
752 * Segments.
753 */
754 pSeg = pSegments;
755 while (pSeg != NULL)
756 {
757 pOut->printf("SEGMENT %s\n", pSeg->psz);
758 pSeg = pSeg->pNext;
759 }
760
761 /*
762 * Imports.
763 */
764 pImp = pImports;
765 while (pImp != NULL)
766 {
767 if (pImp->pszName == NULL)
768 pOut->printf("IMPORT '%s' '%s'.%d\n", pImp->pszIntName, pImp->pszDll, pImp->ulOrdinal);
769 else
770 pOut->printf("IMPORT '%s' '%s'.'%s'\n", pImp->pszIntName, pImp->pszDll, pImp->pszName);
771 pImp = pImp->pNext;
772 }
773
774 /*
775 * Exports.
776 */
777 pExp = pExports;
778 while (pExp != NULL)
779 {
780 pOut->printf("EXPORT '%s'", pExp->pszName);
781 if (pExp->ulOrdinal != ~0UL)
782 pOut->printf(".%d", pExp->ulOrdinal);
783 if (pExp->pszIntName)
784 pOut->printf("='%s'", pExp->pszIntName);
785 if (pExp->fResident && (enmOS == kFileDef::os2 || enmOS == kFileDef::win16))
786 pOut->printf(" RESIDENT");
787 if (pExp->cParam != ~0UL)
788 pOut->printf(" %d", pExp->cParam * 2); /* .DEFs this is number of words. Watcom should have bytes. */
789 pOut->printf("\n");
790 pExp = pExp->pNext;
791 }
792
793 return TRUE;
794}
795
796
797
798
799/**
800 * Removes '"' and ''' at start and end of the string.
801 * @returns pszStr!
802 * @param pszStr String that is to have "s and 's removed.
803 */
804static char *removeFnutts(char *pszStr)
805{
806 if (pszStr != NULL)
807 {
808 int cch = strlen(pszStr);
809 if (cch > 0 && (pszStr[cch-1] == '"' || pszStr[cch-1] == '\''))
810 pszStr[cch-1] = '\0';
811
812 if (*pszStr == '"' || *pszStr == '\'')
813 memmove(pszStr, pszStr+1, cch-1);
814 }
815 return pszStr;
816}
817
818
819/**
820 * Upcases a char.
821 * @returns Upper case of the char given in ch.
822 * @param ch Char to capitalize.
823 */
824inline char upcase(char ch)
825{
826 return ch >= 'a' && ch <= 'z' ? (char)(ch - ('a' - 'A')) : ch;
827}
828
829
830/**
831 * Searches for a substring in a string.
832 * @returns Pointer to start of substring when found, NULL when not found.
833 * @param pszStr String to be searched.
834 * @param pszSubStr String to be searched.
835 * @remark Depends on the upcase function.
836 */
837static char *stristr(const char *pszStr, const char *pszSubStr)
838{
839 int cchSubStr = strlen(pszSubStr);
840 int i = 0;
841
842 while (*pszStr != '\0' && i < cchSubStr)
843 {
844 i = 0;
845 while (i < cchSubStr && pszStr[i] != '\0' &&
846 (upcase(pszStr[i]) == upcase(pszSubStr[i])))
847 i++;
848 pszStr++;
849 }
850
851 return (char*)(*pszStr != '\0' ? pszStr - 1 : NULL);
852}
853
Note: See TracBrowser for help on using the repository browser.