source: trunk/kLdr/kLdrHlp.c@ 2898

Last change on this file since 2898 was 2898, checked in by bird, 19 years ago

Made it build on windows.

  • Property svn:keywords set to Id
File size: 21.4 KB
Line 
1/* $Id: kLdrHlp.c 2898 2006-12-24 03:10:53Z bird $ */
2/** @file
3 *
4 * kLdr - The Dynamic Loader, Helper Functions.
5 *
6 * Copyright (c) 2006 knut st. osmundsen <bird-kbuild-src@anduin.net>
7 *
8 *
9 * This file is part of kLdr.
10 *
11 * kLdr is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * kLdr is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with kLdr; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 *
25 */
26
27
28/*******************************************************************************
29* Header Files *
30*******************************************************************************/
31#ifdef __OS2__
32# define INCL_BASE
33# define INCL_ERRORS
34# include <os2.h>
35#elif defined(__WIN__)
36# include <Windows.h>
37#else
38# error "port me"
39#endif
40
41#include <kLdr.h>
42#include "kLdrHlp.h"
43
44
45/*******************************************************************************
46* Global Variables *
47*******************************************************************************/
48#ifdef __OS2__
49/** The loader sempahore. */
50static HMTX g_hmtx;
51/** The base of the stub object.
52 * The OS/2 exe stub consists of a single data object. When allocating memory
53 * for an executable, we'll have to reuse this. */
54static void *g_pvStub = NULL;
55/** The size of the stub object - 0 if no stub. */
56static size_t g_cbStub = 0;
57
58#elif defined(__WIN__)
59/** The loader sempahore. */
60static CRITICAL_SECTION g_CritSect;
61/** The system info. */
62static SYSTEM_INFO g_SystemInfo;
63#else
64# error "port me"
65#endif
66
67
68/**
69 * Initializes the loader semaphore.
70 *
71 * @returns 0 on success, non-zero OS status code on failure.
72 */
73int kldrHlpSemInit(void)
74{
75#ifdef __OS2__
76 APIRET rc;
77 g_hmtx = NULLHANDLE;
78 rc = DosCreateMutexSem(NULL, &g_hmtx, 0, FALSE);
79 if (rc)
80 return rc;
81
82#elif defined(__WIN__)
83 InitializeCriticalSection(&g_CritSect);
84
85#else
86# error "port me"
87#endif
88 return 0;
89}
90
91
92/**
93 * Terminates the loader semaphore.
94 */
95void kldrHlpSemTerm(void)
96{
97#ifdef __OS2__
98 HMTX hmtx = g_hmtx;
99 g_hmtx = NULLHANDLE;
100 DosCloseMutexSem(hmtx);
101
102#elif defined(__WIN__)
103 DeleteCriticalSection(&g_CritSect);
104
105#else
106# error "port me"
107#endif
108}
109
110
111/**
112 * Requests the loader sempahore ownership.
113 * This can be done recursivly.
114 *
115 * @returns 0 on success, non-zero OS status code on failure.
116 */
117int kldrHlpSemRequest(void)
118{
119#ifdef __OS2__
120 APIRET rc = DosRequestMutexSem(g_hmtx, 5000);
121 if (rc == ERROR_TIMEOUT || rc == ERROR_SEM_TIMEOUT || rc == ERROR_INTERRUPT)
122 {
123 unsigned i = 0;
124 do
125 {
126 /** @todo check for deadlocks etc. */
127 rc = DosRequestMutexSem(g_hmtx, 1000);
128 } while ( ( rc == ERROR_TIMEOUT
129 || rc == ERROR_SEM_TIMEOUT
130 || rc == ERROR_INTERRUPT)
131 && i++ < 120);
132 }
133 return rc;
134
135#elif defined(__WIN__)
136 EnterCriticalSection(&g_CritSect);
137 return 0;
138
139#else
140# error "port me"
141#endif
142}
143
144
145/**
146 * Releases the loader semaphore ownership.
147 * The caller is responsible for making sure it's the semaphore owner!
148 */
149void kldrHlpSemRelease(void)
150{
151#ifdef __OS2__
152 APIRET rc = DosReleaseMutexSem(g_hmtx);
153 kldrHlpAssert(!rc); (void)rc;
154
155#elif defined(__WIN__)
156 LeaveCriticalSection(&g_CritSect);
157
158#else
159# error "port me"
160#endif
161
162}
163
164#ifdef __OS2__
165static ULONG kldrHlpPageProtToNative(KLDRPROT enmProt)
166{
167 switch (enmProt)
168 {
169 case KLDRPROT_NOACCESS: return PAG_EXECUTE | PAG_READ | PAG_WRITE;
170 case KLDRPROT_READONLY: return PAG_COMMIT | PAG_READ;
171 case KLDRPROT_READWRITE: return PAG_COMMIT | PAG_READ | PAG_WRITE;
172 case KLDRPROT_EXECUTE: return PAG_COMMIT | PAG_EXECUTE;
173 case KLDRPROT_EXECUTE_READ: return PAG_COMMIT | PAG_EXECUTE | PAG_READ;
174 case KLDRPROT_EXECUTE_READWRITE: return PAG_COMMIT | PAG_EXECUTE | PAG_READ | PAG_WRITE;
175 default:
176 kldrHlpAssert(0);
177 return ~0U;
178 }
179}
180#elif defined(__WIN__)
181static DWORD kldrHlpPageProtToNative(KLDRPROT enmProt)
182{
183 switch (enmProt)
184 {
185 case KLDRPROT_NOACCESS: return PAGE_NOACCESS;
186 case KLDRPROT_READONLY: return PAGE_READONLY;
187 case KLDRPROT_READWRITE: return PAGE_READWRITE;
188 case KLDRPROT_EXECUTE: return PAGE_EXECUTE;
189 case KLDRPROT_EXECUTE_READ: return PAGE_EXECUTE_READ;
190 case KLDRPROT_EXECUTE_READWRITE: return PAGE_EXECUTE_READWRITE;
191 default:
192 kldrHlpAssert(0);
193 return ~0U;
194 }
195}
196#endif
197
198
199/**
200 * Allocate a chunk of memory with page granularity.
201 *
202 * @returns 0 on success, non-zero OS status code on failure.
203 * @param ppv Where to store the address of the allocated memory.
204 * If fFixed is set, *ppv will on entry contain the desired address (page aligned).
205 * @param cb Number of bytes. Page aligned.
206 * @param enmProt The new protection. Copy-on-write is invalid.
207 */
208int kldrHlpPageAlloc(void **ppv, size_t cb, KLDRPROT enmProt, unsigned fFixed)
209{
210#ifdef __OS2__
211 APIRET rc;
212 ULONG fFlags = kldrHlpPageProtToNative(enmProt);;
213
214 if (!fFixed)
215 {
216 /* simple */
217 rc = DosAllocMem(ppv, cb, fFlags | OBJ_ANY);
218 if (rc == ERROR_INVALID_PARAMETER)
219 rc = DosAllocMem(ppv, cb, fFlags);
220 }
221 else
222 {
223 /* not so simple. */
224 /** @todo I've got code for this in libc somewhere. */
225 rc = -1;
226 }
227 if (!rc)
228 return 0;
229 kldrHlpAssert(0);
230 return rc;
231
232#elif defined(__WIN__)
233 /* (We don't have to care about the stub here, because the stub will be unmapped before we get here.) */
234 int rc;
235 DWORD fProt = kldrHlpPageProtToNative(enmProt);
236
237 if (!g_SystemInfo.dwPageSize)
238 GetSystemInfo(&g_SystemInfo);
239
240 *ppv = VirtualAlloc(fFixed ? *ppv : NULL, cb, MEM_COMMIT, fProt);
241 if (*ppv != NULL)
242 return 0;
243 rc = GetLastError();
244 kldrHlpAssert(0);
245 return rc;
246
247#else
248# error "port me"
249#endif
250}
251
252
253/**
254 * Change the protection of one or more pages in an allocation.
255 *
256 * (This will of course only work correctly on memory allocated by kldrHlpPageAlloc().)
257 *
258 * @returns 0 on success, non-zero OS status code on failure.
259 * @param pv First page. Page aligned.
260 * @param cb Number of bytes. Page aligned.
261 * @param enmProt The new protection. Copy-on-write is invalid.
262 */
263int kldrHlpPageProtect(void *pv, size_t cb, KLDRPROT enmProt)
264{
265#ifdef __OS2__
266 APIRET rc;
267 ULONG fFlags = kldrHlpPageProtToNative(enmProt);;
268
269 /*
270 * The non-stub pages.
271 */
272 rc = DosSetMem(pv, cb, fFlags);
273 if (rc && fFlags != PAG_DECOMMIT)
274 rc = DosSetMem(pv, cb, fFlags | PAG_COMMIT);
275 if (rc)
276 {
277 /* Try page by page. */
278 while (cb > 0)
279 {
280 rc = DosSetMem(pv, 0x1000, fFlags);
281 if (rc && fFlags != PAG_DECOMMIT)
282 rc = DosSetMem(pv, 0x1000, fFlags | PAG_COMMIT);
283 if (rc)
284 return rc;
285 pv = (void *)((uintptr_t)pv + 0x1000);
286 cb -= 0x1000;
287 }
288 }
289 kldrHlpAssert(!rc);
290 return rc;
291
292#elif defined(__WIN__)
293 DWORD fOldProt = 0;
294 DWORD fProt = kldrHlpPageProtToNative(enmProt);
295 int rc = 0;
296
297 if (!VirtualProtect(pv, cb, fProt, &fOldProt))
298 {
299 rc = GetLastError();
300 kldrHlpAssert(0);
301 }
302 return rc;
303#else
304# error "port me"
305#endif
306}
307
308
309/**
310 * Free memory allocated by kldrHlpPageAlloc().
311 *
312 * @returns 0 on success, non-zero OS status code on failure.
313 * @param pv The address returned by kldrHlpPageAlloc().
314 * @param cb The byte count requested from kldrHlpPageAlloc().
315 */
316int kldrHlpPageFree(void *pv, size_t cb)
317{
318#ifdef __OS2__
319 APIRET rc;
320
321 /*
322 * Deal with any portion overlapping with the stub.
323 */
324 uintptr_t offStub = (uintptr_t)pv - (uintptr_t)g_pvStub;
325 if (offStub < g_cbStub)
326 {
327 /* decommit the pages in the stub. */
328 size_t cbStub = KLDR_MIN(g_cbStub - offStub, cb);
329 rc = DosSetMem(pv, cbStub, PAG_DECOMMIT);
330 if (rc)
331 {
332 /* Page by page, ignoring errors after the first success. */
333 while (cbStub > 0)
334 {
335 if (!DosSetMem(pv, 0x1000, PAG_DECOMMIT))
336 rc = 0;
337 pv = (void *)((uintptr_t)pv + 0x1000);
338 cbStub -= 0x1000;
339 cb -= 0x1000;
340 }
341 if (rc)
342 {
343 kldrHlpAssert(!rc);
344 return rc;
345 }
346 }
347 else
348 {
349 cb -= cbStub;
350 if (!cb)
351 return 0;
352 pv = (void *)((uintptr_t)pv + cbStub);
353 }
354 }
355
356 /*
357 * Free the object.
358 */
359 rc = DosFreeMem(pv);
360 kldrHlpAssert(!rc);
361 return rc;
362
363#elif defined(__WIN__)
364 /*
365 * Free the object.
366 */
367 int rc = 0;
368 if (!VirtualFree(pv, 0 /*cb*/, MEM_RELEASE))
369 {
370 rc = GetLastError();
371 kldrHlpAssert(0);
372 }
373 return rc;
374
375#else
376# error "port me"
377#endif
378}
379
380
381/**
382 * Get an environment variable.
383 *
384 * @returns 0 on success.
385 * @returns KLDR_ERR_BUFFER_OVERFLOW on if the buffer is too small.
386 * @returns KLDR_ERR_SYMBOL_NOT_FOUND if not found. (Yeah, abusing the status code, but it's only internally...)
387 * @returns OS specfic status code on other error.
388 * @param pszVar The variable name.
389 * @param pszVal Where to store the value.
390 * @param cchVal The size of the buffer pointed to by pszVal.
391 */
392int kldrHlpGetEnv(const char *pszVar, char *pszVal, size_t cchVal)
393{
394#ifdef __OS2__
395 PSZ pszValue = NULL;
396 int rc;
397
398 *pszVal = '\0';
399 rc = DosScanEnv((PCSZ)pszVar, &pszValue);
400 if (!rc)
401 {
402 size_t cch = kLdrHlpStrLen((const char *)pszValue);
403 if (cchVal > cch)
404 kLdrHlpMemCopy(pszVal, pszValue, cch + 1);
405 else
406 rc = KLDR_ERR_BUFFER_OVERFLOW;
407 }
408 else
409 rc = KLDR_ERR_SYMBOL_NOT_FOUND;
410 return rc;
411
412#elif defined(__WIN__)
413 DWORD cch;
414
415 SetLastError(0);
416 cch = GetEnvironmentVariable(pszVar, pszVal, cchVal);
417 if (cch > 0 && cch < cchVal)
418 return 0;
419
420 *pszVal = '\0';
421 if (cch >= cchVal)
422 return KLDR_ERR_BUFFER_OVERFLOW;
423 if (GetLastError() == ERROR_ENVVAR_NOT_FOUND)
424 return KLDR_ERR_SYMBOL_NOT_FOUND;
425 return GetLastError();
426
427#else
428# error "Port me"
429#endif
430}
431
432
433/**
434 * Gets an environment variable and converts it to a size_t.
435 *
436 * @returns 0 and *pcb on success.
437 * @returns On failure see kldrHlpGetEnv.
438 * @param pszVar The name of the variable.
439 * @param pcb Where to put the value.
440 */
441int kldrHlpGetEnvUZ(const char *pszVar, size_t *pcb)
442{
443 size_t cb;
444 unsigned uBase;
445 char szVal[64];
446 size_t cchVal = sizeof(szVal);
447 const char *psz;
448 int rc;
449
450 *pcb = 0;
451 rc = kldrHlpGetEnv(pszVar, szVal, cchVal);
452 if (rc)
453 return rc;
454
455 /* figure out the base. */
456 uBase = 10;
457 psz = szVal;
458 if ( *psz == '0'
459 && (psz[1] == 'x' || psz[1] == 'X'))
460 {
461 uBase = 16;
462 psz += 2;
463 }
464
465 /* convert it up to the first unknown char. */
466 cb = 0;
467 for(;;)
468 {
469 const char ch = *psz;
470 unsigned uDigit;
471 if (!ch)
472 break;
473 else if (ch >= '0' && ch <= '9')
474 uDigit = ch - '0';
475 else if (ch >= 'a' && ch <= 'z')
476 uDigit = ch - 'a' + 10;
477 else if (ch >= 'A' && ch <= 'Z')
478 uDigit = ch - 'A' + 10;
479 else
480 break;
481 if (uDigit >= uBase)
482 break;
483
484 /* add the digit */
485 cb *= uBase;
486 cb += uDigit;
487
488 psz++;
489 }
490
491 /* check for unit */
492 if (*psz == 'm' || *psz == 'M')
493 cb *= 1024*1024;
494 else if (*psz == 'k' ||*psz == 'K')
495 cb *= 1024;
496 else if (*psz == 'g' || *psz == 'G')
497 cb *= 1024*1024*1024;
498
499 *pcb = cb;
500 return 0;
501}
502
503
504/**
505 * Get the pointer to the filename part of the name.
506 *
507 * @returns Pointer to where the filename starts within the string pointed to by pszFilename.
508 * @returns Pointer to the terminator char if no filename.
509 * @param pszFilename The filename to parse.
510 */
511char *kldrHlpGetFilename(const char *pszFilename)
512{
513 const char *pszLast = NULL;
514 for (;;)
515 {
516 char ch = *pszFilename;
517#if defined(__OS2__) || defined(__WIN__)
518 if (ch == '/' || ch == '\\' || ch == ':')
519 {
520 while ((ch = *++pszFilename) == '/' || ch == '\\' || ch == ':')
521 /* nothing */;
522 pszLast = pszFilename;
523 }
524#else
525 if (ch == '/')
526 {
527 while ((ch = *++pszFilename) == '/')
528 /* betsuni */;
529 pszLast = pszFilename;
530 }
531#endif
532 if (!ch)
533 return (char *)(pszLast ? pszLast : pszFilename);
534 pszFilename++;
535 }
536}
537
538
539/**
540 * Gets the filename suffix.
541 *
542 * @returns Pointer to where the suffix starts within the string pointed to by pszFilename.
543 * @returns Pointer to the terminator char if no suffix.
544 * @param pszFilename The filename to parse.
545 */
546char *kldrHlpGetSuff(const char *pszFilename)
547{
548 const char *pszDot = NULL;
549 pszFilename = kldrHlpGetFilename(pszFilename);
550 for (;;)
551 {
552 char ch = *pszFilename;
553 if (ch == '.')
554 {
555 while ((ch = *++pszFilename) == '.')
556 /* nothing */;
557 if (ch)
558 pszDot = pszFilename - 1;
559 }
560 if (!ch)
561 return (char *)(pszDot ? pszDot : pszFilename);
562 pszFilename++;
563 }
564}
565
566
567/**
568 * Gets the filename extention.
569 *
570 * @returns Pointer to where the extension starts within the string pointed to by pszFilename.
571 * @returns Pointer to the terminator char if no extension.
572 * @param pszFilename The filename to parse.
573 */
574char *kldrHlpGetExt(const char *pszFilename)
575{
576 char *psz = kldrHlpGetSuff(pszFilename);
577 return *psz ? psz + 1 : psz;
578}
579
580
581/**
582 * Checks if this is only a filename or if it contains any kind
583 * of drive, directory, or server specs.
584 *
585 * @returns 1 if this is a filename only.
586 * @returns 0 of it's isn't only a filename.
587 * @param pszFilename The filename to parse.
588 */
589int kldrHlpIsFilenameOnly(const char *pszFilename)
590{
591 for (;;)
592 {
593 const char ch = *pszFilename++;
594#if defined(__OS2__) || defined(__WIN__)
595 if (ch == '/' || ch == '\\' || ch == ':')
596#else
597 if (ch == '/')
598#endif
599 return 0;
600 if (!ch)
601 return 1;
602 }
603}
604
605
606/**
607 * Terminate the process.
608 *
609 * @param rc The exit status.
610 */
611void kldrHlpExit(int rc)
612{
613 for (;;)
614 {
615#ifdef __OS2__
616 DosExit(EXIT_PROCESS, rc);
617
618#elif defined(__WIN__)
619 TerminateProcess(GetCurrentProcess(), rc);
620
621#else
622# error "Port me"
623#endif
624 kldrHlpAssert(!"Impossible");
625 }
626}
627
628
629/**
630 * Sleep for a number of milliseconds.
631 * @param cMillies Number of milliseconds to sleep.
632 */
633void kldrHlpSleep(unsigned cMillies)
634{
635#ifdef __OS2__
636 DosSleep(cMillies);
637#elif defined(__WIN__)
638 Sleep(cMillies);
639#else
640 usleep(cMillies * 1000);
641#endif
642}
643
644
645/**
646 * Converts an signed integer to an ascii string.
647 *
648 * @returns psz.
649 * @param psz Pointer to the output buffer.
650 * @param cch The size of the output buffer.
651 * @param lVal The value.
652 * @param iBase The base to format it. (2,8,10 or 16)
653 */
654char *kldrHlpInt2Ascii(char *psz, size_t cch, long lVal, unsigned iBase)
655{
656 static const char s_szDigits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
657 char *pszRet = psz;
658
659 if (cch >= (lVal < 0 ? 3U : 2U) && psz)
660 {
661 /* prefix */
662 if (lVal < 0)
663 {
664 *psz++ = '-';
665 cch--;
666 lVal = -lVal;
667 }
668
669 /* the digits */
670 do
671 {
672 *psz++ = s_szDigits[lVal % iBase];
673 cch--;
674 lVal /= iBase;
675 } while (lVal && cch > 1);
676
677 /* overflow indicator */
678 if (lVal)
679 psz[-1] = '+';
680 }
681 else if (!pszRet)
682 return pszRet;
683 else if (cch < 1 || !pszRet)
684 return pszRet;
685 else
686 *psz++ = '+';
687 *psz = '\0';
688
689 return pszRet;
690}
691
692
693/**
694 * Writes a assert string with unix lineendings.
695 *
696 * @param pszMsg The string.
697 */
698static void kldrHlpAssertWrite(const char *pszMsg)
699{
700#if defined(__OS2__) || defined(__WIN__)
701 /*
702 * Line by line.
703 */
704 ULONG cbWritten;
705 const char *pszNl = kLdrHlpStrChr(pszMsg, '\n');
706 while (pszNl)
707 {
708 cbWritten = pszNl - pszMsg;
709
710#ifdef __OS2__
711 if (cbWritten)
712 DosWrite((HFILE)2, pszMsg, cbWritten, &cbWritten);
713 DosWrite((HFILE)2, "\r\n", 2, &cbWritten);
714#else /* __WIN32__ */
715 if (cbWritten)
716 WriteFile((HANDLE)STD_ERROR_HANDLE, pszMsg, cbWritten, &cbWritten, NULL);
717 WriteFile((HANDLE)STD_ERROR_HANDLE, "\r\n", 2, &cbWritten, NULL);
718#endif
719
720 /* next */
721 pszMsg = pszNl + 1;
722 pszNl = kLdrHlpStrChr(pszMsg, '\n');
723 }
724
725 /*
726 * Remaining incomplete line.
727 */
728 if (*pszMsg)
729 {
730 cbWritten = kLdrHlpStrLen(pszMsg);
731#ifdef __OS2__
732 DosWrite((HFILE)2, pszMsg, cbWritten, &cbWritten);
733#else /* __WIN32__ */
734 WriteFile((HANDLE)STD_ERROR_HANDLE, pszMsg, cbWritten, &cbWritten, NULL);
735#endif
736 }
737
738#else
739# error "port me"
740#endif
741}
742
743
744/**
745 * Internal worker for the kLdrHlpAssert() macro.
746 *
747 * @param pszExpr The assert expression.
748 * @param pszFile The filename.
749 * @param iLine The line number.
750 * @param pszFunction The function name.
751 */
752void kldrHlpAssertMsg(const char *pszExpr, const char *pszFile, unsigned iLine, const char *pszFunction)
753{
754 char szLine[16];
755
756 kldrHlpAssertWrite("\n!!!kLdr Assertion Failed!!!\nExpression: ");
757 kldrHlpAssertWrite(pszExpr);
758 kldrHlpAssertWrite("\nAt: ");
759 kldrHlpAssertWrite(pszFile);
760 kldrHlpAssertWrite("(");
761 kldrHlpAssertWrite(kldrHlpInt2Ascii(szLine, sizeof(szLine), iLine, 10));
762 kldrHlpAssertWrite(") ");
763 kldrHlpAssertWrite(pszFunction);
764 kldrHlpAssertWrite("\n");
765}
766
767
768#ifdef kLdrHlpStrChr_needed
769char *kLdrHlpStrChr(const char *psz, int ch)
770{
771 while (*psz)
772 {
773 if (*psz == ch)
774 return (char *)psz;
775 psz++;
776 }
777 return NULL;
778}
779#endif
780
781
782#ifdef kLdrHlpMemChr_needed
783void *kLdrHlpMemChr(const void *pv, int ch, size_t cb)
784{
785 const uint8_t *pb = (const uint8_t *)pv;
786 const uint8_t b = (uint8_t)ch;
787 while (cb-- > 0)
788 {
789 if (*pb == b)
790 return (void *)pb;
791 pb++;
792 }
793 return NULL;
794}
795#endif
796
797
798#ifdef kLdrHlpMemMove_needed
799void *kLdrHlpMemMove(void *pv1, const void *pv2, size_t cb)
800{
801 uint8_t *pbDst = (uint8_t *)pv1;
802 const uint8_t *pbSrc = (const uint8_t *)pv2;
803 while (cb-- > 0)
804 {
805 const uint8_t b = *pbSrc++;
806 *pbDst++ = b;
807 }
808 return pv1;
809}
810#endif
811
812
813int kLdrHlpMemIComp(const void *pv1, const void *pv2, size_t cb)
814{
815 const uint8_t *pb1 = (const uint8_t *)pv1;
816 const uint8_t *pb2 = (const uint8_t *)pv2;
817 while (cb-- > 0)
818 {
819 if (*pb1 != *pb2)
820 {
821 const uint8_t u1 = *pb1 >= 'a' && *pb1 <= 'z' ? *pb1 - 'a' : *pb1;
822 const uint8_t u2 = *pb2 >= 'a' && *pb2 <= 'z' ? *pb2 - 'a' : *pb2;
823 if (u1 != u2)
824 return (int)*pb1 - (int)*pb2;
825 }
826 pb1++;
827 pb2++;
828 }
829 return 0;
830}
831
832
833int kLdrHlpStrIComp(const char *pv1, const char *pv2)
834{
835 const uint8_t *pb1 = (const uint8_t *)pv1;
836 const uint8_t *pb2 = (const uint8_t *)pv2;
837 for (;;)
838 {
839 if (*pb1 != *pb2)
840 {
841 const uint8_t u1 = *pb1 >= 'a' && *pb1 <= 'z' ? *pb1 - 'a' : *pb1;
842 const uint8_t u2 = *pb2 >= 'a' && *pb2 <= 'z' ? *pb2 - 'a' : *pb2;
843 if (u1 != u2)
844 return (int)*pb1 - (int)*pb2;
845 }
846 if (!*pb1)
847 break;
848 pb1++;
849 pb2++;
850 }
851 return 0;
852}
853
854
855#ifdef kLdrHlpStrNComp_needed
856int kLdrHlpStrNComp(const char *psz1, const char *psz2, size_t cch)
857{
858 while (cch-- > 0)
859 {
860 if (*psz1 != *psz2)
861 return (int)*psz1 - (int)*psz2;
862 if (!*psz1)
863 break;
864 psz1++;
865 psz2++;
866 }
867 return 0;
868}
869#endif
870
Note: See TracBrowser for help on using the repository browser.