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

Last change on this file since 4804 was 4804, checked in by bird, 25 years ago

Prepared for build level info.

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