source: trunk/kLdr/kLdrHlp.c@ 2883

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

cleanup.

  • Property svn:keywords set to Id
File size: 21.1 KB
Line 
1/* $Id: kLdrHlp.c 2883 2006-11-18 11:21:33Z 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 }
226 if (!rc)
227 return 0;
228 kldrHlpAssert(0);
229 return rc;
230
231#elif defined(__WIN__)
232 /* (We don't have to care about the stub here, because the stub will be unmapped before we get here.) */
233 int rc;
234 DWORD fProt = kldrHlpPageProtToNative(enmProt);
235
236 if (!g_SystemInfo.dwPageSize)
237 GetSystemInfo(&g_SystemInfo);
238
239 *ppv = VirtualAlloc(fFixed ? *ppv : NULL, cb, MEM_COMMIT, fProt);
240 if (*ppv != NULL)
241 return 0;
242 rc = GetLastError();
243 kldrHlpAssert(0);
244 return rc;
245
246#else
247# error "port me"
248#endif
249}
250
251
252/**
253 * Change the protection of one or more pages in an allocation.
254 *
255 * (This will of course only work correctly on memory allocated by kldrHlpPageAlloc().)
256 *
257 * @returns 0 on success, non-zero OS status code on failure.
258 * @param pv First page. Page aligned.
259 * @param cb Number of bytes. Page aligned.
260 * @param enmProt The new protection. Copy-on-write is invalid.
261 */
262int kldrHlpPageProtect(void *pv, size_t cb, KLDRPROT enmProt)
263{
264#ifdef __OS2__
265 APIRET rc;
266 ULONG fFlags = kldrHlpPageProtToNative(enmProt);;
267
268 /*
269 * The non-stub pages.
270 */
271 rc = DosSetMem(pv, cb, fFlags);
272 if (rc && fFlags != PAG_DECOMMIT)
273 rc = DosSetMem(pv, cb, fFlags | PAG_COMMIT);
274 if (rc)
275 {
276 /* Try page by page. */
277 while (cb > 0)
278 {
279 rc = DosSetMem(pv, 0x1000, fFlags);
280 if (rc && fFlags != PAG_DECOMMIT)
281 rc = DosSetMem(pv, 0x1000, fFlags | PAG_COMMIT);
282 if (rc)
283 return rc;
284 pv = (void *)((uintptr_t)pv + 0x1000);
285 cb -= 0x1000;
286 }
287 }
288 kldrHlpAssert(!rc);
289 return rc;
290
291#elif defined(__WIN__)
292 DWORD fOldProt = 0;
293 DWORD fProt = kldrHlpPageProtToNative(enmProt);
294 int rc = 0;
295
296 if (!VirtualProtect(pv, cb, fProt, &fOldProt))
297 {
298 rc = GetLastError();
299 kldrHlpAssert(0);
300 }
301 return rc;
302#else
303# error "port me"
304#endif
305}
306
307
308/**
309 * Free memory allocated by kldrHlpPageAlloc().
310 *
311 * @returns 0 on success, non-zero OS status code on failure.
312 * @param pv The address returned by kldrHlpPageAlloc().
313 * @param cb The byte count requested from kldrHlpPageAlloc().
314 */
315int kldrHlpPageFree(void *pv, size_t cb)
316{
317#ifdef __OS2__
318 APIRET rc;
319
320 /*
321 * Deal with any portion overlapping with the stub.
322 */
323 uintptr_t offStub = (uintptr_t)pv - (uintptr_t)g_pvStub;
324 if (offStub < g_cbStub)
325 {
326 /* decommit the pages in the stub. */
327 size_t cbStub = KLDR_MIN(g_cbStub - offStub, cb);
328 rc = DosSetMem(pv, cbStub, PAG_DECOMMIT);
329 if (rc)
330 {
331 /* Page by page, ignoring errors after the first success. */
332 while (cbStub > 0)
333 {
334 if (!DosSetMem(pv, 0x1000, PAG_DECOMMIT))
335 rc = 0;
336 pv = (void *)((uintptr_t)pv + 0x1000);
337 cbStub -= 0x1000;
338 cb -= 0x1000;
339 }
340 if (rc)
341 {
342 kldrHlpAssert(!rc);
343 return rc;
344 }
345 }
346 else
347 {
348 cb -= cbStub;
349 if (!cb)
350 return 0;
351 pv = (void *)((uintptr_t)pv + cbStub);
352 }
353 }
354
355 /*
356 * Free the object.
357 */
358 rc = DosFreeMem(pv);
359 kldrHlpAssert(!rc);
360 return rc;
361
362#elif defined(__WIN__)
363 /*
364 * Free the object.
365 */
366 int rc = 0;
367 if (!VirtualFree(pv, 0 /*cb*/, MEM_RELEASE))
368 {
369 rc = GetLastError();
370 kldrHlpAssert(0);
371 }
372 return rc;
373
374#else
375# error "port me"
376#endif
377}
378
379
380/**
381 * Get an environment variable.
382 *
383 * @returns 0 on success.
384 * @returns KLDR_ERR_BUFFER_OVERFLOW on if the buffer is too small.
385 * @returns KLDR_ERR_SYMBOL_NOT_FOUND if not found. (Yeah, abusing the status code, but it's only internally...)
386 * @returns OS specfic status code on other error.
387 * @param pszVar The variable name.
388 * @param pszVal Where to store the value.
389 * @param cchVal The size of the buffer pointed to by pszVal.
390 */
391int kldrHlpGetEnv(const char *pszVar, char *pszVal, size_t cchVal)
392{
393#ifdef __OS2__
394 PSZ pszValue = NULL;
395 int rc;
396
397 *pszVal = '\0';
398 rc = DosScanEnv((PCSZ)pszVar, &pszValue);
399 if (!rc)
400 {
401 size_t cch = kLdrHlpStrLen((const char *)pszValue);
402 if (cchVal > cch)
403 kLdrHlpMemCopy(pszVal, pszValue, cch + 1);
404 else
405 rc = KLDR_ERR_BUFFER_OVERFLOW;
406 }
407 else
408 rc = KLDR_ERR_SYMBOL_NOT_FOUND;
409 return rc;
410
411#elif defined(__WIN__)
412 DWORD cch;
413
414 SetLastError(0);
415 cch = GetEnvironmentVariable(pszVar, pszVal, cchVal);
416 if (cch > 0 && cch < cchVal)
417 return 0;
418
419 *pszVal = '\0';
420 if (cch >= cchVal)
421 return KLDR_ERR_BUFFER_OVERFLOW;
422 if (GetLastError() == ERROR_ENVVAR_NOT_FOUND)
423 return KLDR_ERR_SYMBOL_NOT_FOUND;
424 return GetLastError();
425
426#else
427# error "Port me"
428#endif
429}
430
431
432/**
433 * Gets an environment variable and converts it to a size_t.
434 *
435 * @returns 0 and *pcb on success.
436 * @returns On failure see kldrHlpGetEnv.
437 * @param pszVar The name of the variable.
438 * @param pcb Where to put the value.
439 */
440int kldrHlpGetEnvUZ(const char *pszVar, size_t *pcb)
441{
442 size_t cb;
443 unsigned uBase;
444 char szVal[64];
445 size_t cchVal = sizeof(szVal);
446 const char *psz;
447 int rc;
448
449 *pcb = 0;
450 rc = kldrHlpGetEnv(pszVar, szVal, cchVal);
451 if (rc)
452 return rc;
453
454 /* figure out the base. */
455 uBase = 10;
456 psz = szVal;
457 if ( *psz == '0'
458 && (psz[1] == 'x' || psz[1] == 'X'))
459 {
460 uBase = 16;
461 psz += 2;
462 }
463
464 /* convert it up to the first unknown char. */
465 cb = 0;
466 for(;;)
467 {
468 const char ch = *psz;
469 unsigned uDigit;
470 if (!ch)
471 break;
472 else if (ch >= '0' && ch <= '9')
473 uDigit = ch - '0';
474 else if (ch >= 'a' && ch <= 'z')
475 uDigit = ch - 'a' + 10;
476 else if (ch >= 'A' && ch <= 'Z')
477 uDigit = ch - 'A' + 10;
478 else
479 break;
480 if (uDigit >= uBase)
481 break;
482
483 /* add the digit */
484 cb *= uBase;
485 cb += uDigit;
486
487 psz++;
488 }
489
490 /* check for unit */
491 if (*psz == 'm' || *psz == 'M')
492 cb *= 1024*1024;
493 else if (*psz == 'k' ||*psz == 'K')
494 cb *= 1024;
495 else if (*psz == 'g' || *psz == 'G')
496 cb *= 1024*1024*1024;
497
498 *pcb = cb;
499 return 0;
500}
501
502
503/**
504 * Get the pointer to the filename part of the name.
505 *
506 * @returns Pointer to where the filename starts within the string pointed to by pszFilename.
507 * @returns Pointer to the terminator char if no filename.
508 * @param pszFilename The filename to parse.
509 */
510char *kldrHlpGetFilename(const char *pszFilename)
511{
512 const char *pszLast = NULL;
513 for (;;)
514 {
515 char ch = *pszFilename;
516#if defined(__OS2__) || defined(__WIN__)
517 if (ch == '/' || ch == '\\' || ch == ':')
518 {
519 while ((ch = *++pszFilename) == '/' || ch == '\\' || ch == ':')
520 /* nothing */;
521 pszLast = pszFilename;
522 }
523#else
524 if (ch == '/')
525 {
526 while ((ch = *++pszFilename) == '/')
527 /* betsuni */;
528 pszLast = pszFilename;
529 }
530#endif
531 if (!ch)
532 return (char *)(pszLast ? pszLast : pszFilename);
533 pszFilename++;
534 }
535}
536
537
538/**
539 * Gets the filename suffix.
540 *
541 * @returns Pointer to where the suffix starts within the string pointed to by pszFilename.
542 * @returns Pointer to the terminator char if no suffix.
543 * @param pszFilename The filename to parse.
544 */
545char *kldrHlpGetSuff(const char *pszFilename)
546{
547 const char *pszDot = NULL;
548 pszFilename = kldrHlpGetFilename(pszFilename);
549 for (;;)
550 {
551 char ch = *pszFilename;
552 if (ch == '.')
553 {
554 while ((ch = *++pszFilename) == '.')
555 /* nothing */;
556 if (ch)
557 pszDot = pszFilename - 1;
558 }
559 if (!ch)
560 return (char *)(pszDot ? pszDot : pszFilename);
561 pszFilename++;
562 }
563}
564
565
566/**
567 * Gets the filename extention.
568 *
569 * @returns Pointer to where the extension starts within the string pointed to by pszFilename.
570 * @returns Pointer to the terminator char if no extension.
571 * @param pszFilename The filename to parse.
572 */
573char *kldrHlpGetExt(const char *pszFilename)
574{
575 char *psz = kldrHlpGetSuff(pszFilename);
576 return *psz ? psz + 1 : psz;
577}
578
579
580/**
581 * Checks if this is only a filename or if it contains any kind
582 * of drive, directory, or server specs.
583 *
584 * @returns 1 if this is a filename only.
585 * @returns 0 of it's isn't only a filename.
586 * @param pszFilename The filename to parse.
587 */
588int kldrHlpIsFilenameOnly(const char *pszFilename)
589{
590 for (;;)
591 {
592 const char ch = *pszFilename++;
593#if defined(__OS2__) || defined(__WIN__)
594 if (ch == '/' || ch == '\\' || ch == ':')
595#else
596 if (ch == '/')
597#endif
598 return 0;
599 if (!ch)
600 return 1;
601 }
602}
603
604
605/**
606 * Terminate the process.
607 *
608 * @param rc The exit status.
609 */
610void kldrHlpExit(int rc)
611{
612 for (;;)
613 {
614#ifdef __OS2__
615 DosExit(EXIT_PROCESS, rc);
616
617#elif defined(__WIN__)
618 TerminateProcess(GetCurrentProcess(), rc);
619
620#else
621# error "Port me"
622#endif
623 kldrHlpAssert(!"Impossible");
624 }
625}
626
627
628/**
629 * Sleep for a number of milliseconds.
630 * @param cMillies Number of milliseconds to sleep.
631 */
632void kldrHlpSleep(unsigned cMillies)
633{
634#ifdef __OS2__
635 DosSleep(cMillies);
636#elif defined(__WIN__)
637 Sleep(cMillies);
638#else
639 usleep(cMillies * 1000);
640#endif
641}
642
643
644/**
645 * Converts an signed integer to an ascii string.
646 *
647 * @returns psz.
648 * @param psz Pointer to the output buffer.
649 * @param cch The size of the output buffer.
650 * @param lVal The value.
651 * @param iBase The base to format it. (2,8,10 or 16)
652 */
653char *kldrHlpInt2Ascii(char *psz, size_t cch, long lVal, unsigned iBase)
654{
655 static const char s_szDigits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
656 char *pszRet = psz;
657
658 if (cch >= (lVal < 0 ? 3U : 2U) && psz)
659 {
660 /* prefix */
661 if (lVal < 0)
662 {
663 *psz++ = '-';
664 cch--;
665 lVal = -lVal;
666 }
667
668 /* the digits */
669 do
670 {
671 *psz++ = s_szDigits[lVal % iBase];
672 cch--;
673 lVal /= iBase;
674 } while (lVal && cch > 1);
675
676 /* overflow indicator */
677 if (lVal)
678 psz[-1] = '+';
679 }
680 else if (!pszRet)
681 return pszRet;
682 else if (cch < 1 || !pszRet)
683 return pszRet;
684 else
685 *psz++ = '+';
686 *psz = '\0';
687
688 return pszRet;
689}
690
691
692/**
693 * Writes a assert string with unix lineendings.
694 *
695 * @param pszMsg The string.
696 */
697static void kldrHlpAssertWrite(const char *pszMsg)
698{
699#if defined(__OS2__) || defined(__WIN__)
700 /*
701 * Line by line.
702 */
703 ULONG cbWritten;
704 const char *pszNl = kLdrHlpStrChr(pszMsg, '\n');
705 while (pszNl)
706 {
707 cbWritten = pszNl - pszMsg;
708
709#ifdef __OS2__
710 if (cbWritten)
711 DosWrite((HFILE)2, pszMsg, cbWritten, &cbWritten);
712 DosWrite((HFILE)2, "\r\n", 2, &cbWritten);
713#else /* __WIN32__ */
714 if (cbWritten)
715 WriteFile((HANDLE)STD_ERROR_HANDLE, pszMsg, cbWritten, &cbWritten, NULL);
716 WriteFile((HANDLE)STD_ERROR_HANDLE, "\r\n", 2, &cbWritten, NULL);
717#endif
718
719 /* next */
720 pszMsg = pszNl + 1;
721 pszNl = kLdrHlpStrChr(pszMsg, '\n');
722 }
723
724 /*
725 * Remaining incomplete line.
726 */
727 if (*pszMsg)
728 {
729 cbWritten = kLdrHlpStrLen(pszMsg);
730#ifdef __OS2__
731 DosWrite((HFILE)2, pszMsg, cbWritten, &cbWritten);
732#else /* __WIN32__ */
733 WriteFile((HANDLE)STD_ERROR_HANDLE, pszMsg, cbWritten, &cbWritten, NULL);
734#endif
735 }
736
737#else
738# error "port me"
739#endif
740}
741
742
743/**
744 * Internal worker for the kLdrHlpAssert() macro.
745 *
746 * @param pszExpr The assert expression.
747 * @param pszFile The filename.
748 * @param iLine The line number.
749 * @param pszFunction The function name.
750 */
751void kldrHlpAssertMsg(const char *pszExpr, const char *pszFile, unsigned iLine, const char *pszFunction)
752{
753 char szLine[16];
754
755 kldrHlpAssertWrite("\n!!!kLdr Assertion Failed!!!\nExpression: ");
756 kldrHlpAssertWrite(pszExpr);
757 kldrHlpAssertWrite("\nAt: ");
758 kldrHlpAssertWrite(pszFile);
759 kldrHlpAssertWrite("(");
760 kldrHlpAssertWrite(kldrHlpInt2Ascii(szLine, sizeof(szLine), iLine, 10));
761 kldrHlpAssertWrite(") ");
762 kldrHlpAssertWrite(pszFunction);
763 kldrHlpAssertWrite("\n");
764}
765
766
767#ifdef kLdrHlpStrChr_needed
768char *kLdrHlpStrChr(const char *psz, int ch)
769{
770 while (*psz)
771 {
772 if (*psz == ch)
773 return (char *)psz;
774 psz++;
775 }
776 return NULL;
777}
778#endif
779
780
781#ifdef kLdrHlpMemChr_needed
782void *kLdrHlpMemChr(const void *pv, int ch, size_t cb)
783{
784 const uint8_t *pb = (const uint8_t *)pv;
785 const uint8_t b = (uint8_t)ch;
786 while (cb-- > 0)
787 {
788 if (*pb == b)
789 return (void *)pb;
790 pb++;
791 }
792 return NULL;
793}
794#endif
795
796
797#ifdef kLdrHlpMemMove_needed
798void *kLdrHlpMemMove(void *pv1, const void *pv2, size_t cb)
799{
800 uint8_t *pbDst = (uint8_t *)pv1;
801 const uint8_t *pbSrc = (const uint8_t *)pv2;
802 while (cb-- > 0)
803 {
804 const uint8_t b = *pbSrc++;
805 *pbDst++ = b;
806 }
807 return pv1;
808}
809#endif
810
811
812int kLdrHlpMemIComp(const void *pv1, const void *pv2, size_t cb)
813{
814 const uint8_t *pb1 = (const uint8_t *)pv1;
815 const uint8_t *pb2 = (const uint8_t *)pv2;
816 while (cb-- > 0)
817 {
818 if (*pb1 != *pb2)
819 {
820 const uint8_t u1 = *pb1 >= 'a' && *pb1 <= 'z' ? *pb1 - 'a' : *pb1;
821 const uint8_t u2 = *pb2 >= 'a' && *pb2 <= 'z' ? *pb2 - 'a' : *pb2;
822 if (u1 != u2)
823 return (int)*pb1 - (int)*pb2;
824 }
825 pb1++;
826 pb2++;
827 }
828 return 0;
829}
830
831
832int kLdrHlpStrIComp(const char *pv1, const char *pv2)
833{
834 const uint8_t *pb1 = (const uint8_t *)pv1;
835 const uint8_t *pb2 = (const uint8_t *)pv2;
836 for (;;)
837 {
838 if (*pb1 != *pb2)
839 {
840 const uint8_t u1 = *pb1 >= 'a' && *pb1 <= 'z' ? *pb1 - 'a' : *pb1;
841 const uint8_t u2 = *pb2 >= 'a' && *pb2 <= 'z' ? *pb2 - 'a' : *pb2;
842 if (u1 != u2)
843 return (int)*pb1 - (int)*pb2;
844 }
845 if (!*pb1)
846 break;
847 pb1++;
848 pb2++;
849 }
850 return 0;
851}
852
Note: See TracBrowser for help on using the repository browser.