source: trunk/kLdr/kLdrHlp.c@ 2854

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

Hacking away on the PE module interpreter.

  • Property svn:keywords set to Id
File size: 20.8 KB
RevLine 
[2826]1/* $Id: kLdrHlp.c 2854 2006-11-03 03:39:12Z bird $ */
[2825]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
[2830]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
[2825]68/**
[2830]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 APIRET rc;
99 HMTX hmtx = g_hmtx;
100 g_hmtx = NULLHANDLE;
101 rc = DosCloseMutexSem(hmtx);
102 if (rc)
103 return rc;
104
105#elif defined(__WIN__)
106 DeleteCriticalSection(&g_CritSect);
107
108#else
109# error "port me"
110#endif
111}
112
113
114/**
115 * Requests the loader sempahore ownership.
116 * This can be done recursivly.
117 *
118 * @returns 0 on success, non-zero OS status code on failure.
119 */
120int kldrHlpSemRequest(void)
121{
122#ifdef __OS2__
123 APIRET rc = DosRequestMutexSem(g_hmtx, 5000);
124 if (rc == ERROR_TIMEOUT || rc == ERROR_SEM_TIMEOUT || rc == ERROR_INTERRUPT)
125 {
126 unsigned i = 0;
127 do
128 {
129 /** @todo check for deadlocks etc. */
130 rc = DosRequestMutexSem(g_hmtx, 1000);
131 } while ( ( rc == ERROR_TIMEOUT
132 || rc == ERROR_SEM_TIMEOUT
133 || rc == ERROR_INTERRUPT)
134 && i++ < 120);
135 }
136 return rc;
137
138#elif defined(__WIN__)
139 EnterCriticalSection(&g_CritSect);
140 return 0;
141
142#else
143# error "port me"
144#endif
145}
146
147
148/**
149 * Releases the loader semaphore ownership.
150 * The caller is responsible for making sure it's the semaphore owner!
151 */
152void kldrHlpSemRelease(void)
153{
154#ifdef __OS2__
155 APIRET rc = DosReleaseMutexSem(g_hmtx);
156 kldrHlpAssert(!rc); (void)rc;
157
158#elif defined(__WIN__)
159 LeaveCriticalSection(&g_CritSect);
160
161#else
162# error "port me"
163#endif
164
165}
166
167#ifdef __OS2__
168static ULONG kldrHlpPageProtToNative(KLDRPROT enmProt)
169{
170 switch (enmProt)
171 {
172 case KLDRPROT_NOACCESS: return PAG_EXECUTE | PAG_READ | PAG_WRITE;
173 case KLDRPROT_READONLY: return PAG_COMMIT | PAG_READ;
174 case KLDRPROT_READWRITE: return PAG_COMMIT | PAG_READ | PAG_WRITE;
175 case KLDRPROT_EXECUTE: return PAG_COMMIT | PAG_EXECUTE;
176 case KLDRPROT_EXECUTE_READ: return PAG_COMMIT | PAG_EXECUTE | PAG_READ;
177 case KLDRPROT_EXECUTE_READWRITE: return PAG_COMMIT | PAG_EXECUTE | PAG_READ | PAG_WRITE;
178 default:
179 kldrHlpAssert(0);
180 return ~0U;
181 }
182}
183#elif defined(__WIN__)
184static DWORD kldrHlpPageProtToNative(KLDRPROT enmProt)
185{
186 switch (enmProt)
187 {
188 case KLDRPROT_NOACCESS: return PAGE_NOACCESS;
189 case KLDRPROT_READONLY: return PAGE_READONLY;
190 case KLDRPROT_READWRITE: return PAGE_READWRITE;
191 case KLDRPROT_EXECUTE: return PAGE_EXECUTE;
192 case KLDRPROT_EXECUTE_READ: return PAGE_EXECUTE_READ;
193 case KLDRPROT_EXECUTE_READWRITE: return PAGE_EXECUTE_READWRITE;
194 default:
195 kldrHlpAssert(0);
196 return ~0U;
197 }
198}
199#endif
200
201
202/**
203 * Allocate a chunk of memory with page granularity.
204 *
205 * @returns 0 on success, non-zero OS status code on failure.
206 * @param ppv Where to store the address of the allocated memory.
207 * If fFixed is set, *ppv will on entry contain the desired address (page aligned).
208 * @param cb Number of bytes. Page aligned.
209 * @param enmProt The new protection. Copy-on-write is invalid.
210 */
211int kldrHlpPageAlloc(void **ppv, size_t cb, KLDRPROT enmProt, unsigned fFixed)
212{
213#ifdef __OS2__
214 APIRET rc;
215 ULONG fFlags = kldrHlpPageProtToNative(enmProt);;
216
217 if (!fFixed)
218 {
219 /* simple */
220 rc = DosAllocMem(ppv, cb, fFlags | OBJ_ANY);
221 if (rc == ERROR_INVALID_PARAMETER)
222 rc = DosAllocMem(ppv, cb, fFlags);
223 }
224 else
225 {
226 /* not so simple. */
227 /** @todo I've got code for this in libc somewhere. */
228 }
229 if (!rc)
230 return 0;
231 kldrHlpAssert(0);
232 return rc;
233
234#elif defined(__WIN__)
[2831]235 /* (We don't have to care about the stub here, because the stub will be unmapped before we get here.) */
[2830]236 int rc;
237 DWORD fProt = kldrHlpPageProtToNative(enmProt);
238
239 if (!g_SystemInfo.dwPageSize)
240 GetSystemInfo(&g_SystemInfo);
241
242 *ppv = VirtualAlloc(fFixed ? *ppv : NULL, cb, MEM_COMMIT, fProt);
243 if (*ppv == NULL)
244 {
245 rc = GetLastError();
246 kldrHlpAssert(0);
247 }
248 return rc;
249
250#else
251# error "port me"
252#endif
253}
254
255
256/**
257 * Change the protection of one or more pages in an allocation.
258 *
259 * (This will of course only work correctly on memory allocated by kldrHlpPageAlloc().)
260 *
261 * @returns 0 on success, non-zero OS status code on failure.
262 * @param pv First page. Page aligned.
263 * @param cb Number of bytes. Page aligned.
264 * @param enmProt The new protection. Copy-on-write is invalid.
265 */
266int kldrHlpPageProtect(void *pv, size_t cb, KLDRPROT enmProt)
267{
268#ifdef __OS2__
269 APIRET rc;
270 uintptr_t offStub;
271 ULONG fFlags = kldrHlpPageProtToNative(enmProt);;
272
273 /*
274 * The non-stub pages.
275 */
276 rc = DosSetMem(pv, cb, fFlags);
277 if (rc && fFlags != PAG_DECOMMIT)
278 rc = DosSetMem(pv, cb, fFlags | PAG_COMMIT);
279 if (rc)
280 {
281 /* Try page by page. */
282 while (cb > 0)
283 {
284 rc = DosSetMem(pv, 0x1000, fFlags);
285 if (rc && fFlags != PAG_DECOMMIT)
286 rc = DosSetMem(pv, 0x1000, fFlags | PAG_COMMIT);
287 if (rc)
288 return rc;
289 pv = (void *)((uintptr_t)pv + 0x1000);
290 cb -= 0x1000;
291 }
292 }
293 kldrHlpAssert(!rc);
294 return rc;
295
296#elif defined(__WIN__)
297 DWORD fOldProt = 0;
298 DWORD fProt = kldrHlpPageProtToNative(enmProt);
299 int rc = 0;
300
301 if (!VirtualProtect(pv, cb, fProt, &fOldProt))
302 {
303 rc = GetLastError();
304 kldrHlpAssert(0);
305 }
306 return rc;
307#else
308# error "port me"
309#endif
310}
311
312
313/**
314 * Free memory allocated by kldrHlpPageAlloc().
315 *
316 * @returns 0 on success, non-zero OS status code on failure.
317 * @param pv The address returned by kldrHlpPageAlloc().
318 * @param cb The byte count requested from kldrHlpPageAlloc().
319 */
320int kldrHlpPageFree(void *pv, size_t cb)
321{
322#ifdef __OS2__
323 APIRET rc;
324
325 /*
326 * Deal with any portion overlapping with the stub.
327 */
328 uintptr_t offStub = (uintptr_t)pv - (uintptr_t)g_pvStub;
329 if (offStub < g_cbStub)
330 {
331 /* decommit the pages in the stub. */
332 size_t cbSub = KLDR_MIN(g_cbStub - offStub, cb);
333 rc = DosSetMem(pv, cbStub, PAG_DECOMMIT);
334 if (rc)
335 {
336 /* Page by page, ignoring errors after the first success. */
337 while (cbSub > 0)
338 {
339 if (!DosSetMem(pv, 0x1000, PAG_DECOMMIT))
340 rc = 0;
341 pv = (void *)((uintptr_t)pv + 0x1000);
342 cbSub -= 0x1000;
343 cb -= 0x1000;
344 }
345 if (rc)
346 {
347 kldrHlpAssert(!rc);
348 return rc;
349 }
350 }
351 else
352 {
353 cb -= cbSub;
354 if (!cb)
355 return 0;
356 pv = (void *)((uintptr_t)pv + cbSub);
357 }
358 }
359
360 /*
361 * Free the object.
362 */
363 rc = DosFreeMem(pv);
364 kldrHlpAssert(!rc);
365 return rc;
366
367#elif defined(__WIN__)
368 /*
369 * Free the object.
370 */
371 int rc = 0;
372 if (!VirtualFree(pv, 0 /*cb*/, MEM_RELEASE))
373 {
374 rc = GetLastError();
375 kldrHlpAssert(0);
376 }
377 return rc;
378
379#else
380# error "port me"
381#endif
382}
383
384
385/**
[2825]386 * Get an environment variable.
387 *
388 * @returns 0 on success, on failure an OS specific status code is returned.
389 * @param pszVar The variable name.
390 * @param pszVal Where to store the value. NULL is allowed if *pcchVal is 0.
391 * @param pcchVal On input the size of the buffer pointed to by pszVal.
392 * On output this contains the string length on success, while on
393 * failure (including buffer overflow) the require buffer size.
394 * If the variable wasn't found, it's set to 0.
395 */
396int kldrHlpGetEnv(const char *pszVar, char *pszVal, size_t *pcchVal)
397{
398#ifdef __OS2__
399 PSZ pszValue = NULL;
400 int rc = DosScanEnv((PCSZ)pszVar, &pszValue);
401 if (!rc)
402 {
[2828]403 size_t cch = kLdrHlpStrLen(pszValue);
[2825]404 if (pszVal)
405 {
406 if (*pcchVal > cch)
407 {
[2828]408 kLdrHlpMemCopy(pszVal, pszValue, cch + 1);
[2825]409 *pcchVal = cch;
410 }
411 else if (*pcchVal)
412 {
[2828]413 kLdrHlpMemCopy(pszVal, pszValue, *pcchVal);
[2825]414 pszVal[*pcchVal - 1] = '\0';
415 rc = ERROR_BUFFER_OVERFLOW;
416 *pcchVal = cch + 1;
417 }
418 }
419 else
420 {
421 rc = ERROR_BUFFER_OVERFLOW;
422 *pcchVal = cch + 1;
423 }
424 }
425 else
426 {
427 if (pszVal)
428 *pszVal = '\0';
429 *pcchVal = 0;
430 }
431
432 return rc;
433
434#elif defined(__WIN__)
435 DWORD cch;
436 SetLastError(0);
437 cch = GetEnvironmentVariable(pszVar, pszVal, *pcchVal);
438 if (cch)
439 {
440 *pcchVal = cch;
441 return 0;
442 }
443 if (!GetLastError() == ERROR_ENVVAR_NOT_FOUND)
444 {
445 *pcchVal = 0;
446 return ERROR_ENVVAR_NOT_FOUND;
447 }
448 *pcchVal = cch;
449 return ERROR_BUFFER_OVERFLOW;
450
451#else
452# error "Port me"
453#endif
454}
455
456
457/**
[2846]458 * Gets an environment variable and converts it to a size_t.
459 *
460 * @returns 0 and *pcb on success.
461 * Some non-zero OS or kLdr status code on failure.
462 * @param pszVar The name of the variable.
463 * @param pcb Where to put the value.
464 */
465int kldrHlpGetEnvUZ(const char *pszVar, size_t *pcb)
466{
467 size_t cb;
468 unsigned uBase;
469 char szVal[64];
470 size_t cchVal = sizeof(szVal);
471 const char *psz;
472 int rc;
473
474 *pcb = 0;
475 rc = kldrHlpGetEnv(pszVar, szVal, &cchVal);
476 if (rc)
477 return rc;
478
479 /* figure out the base. */
480 uBase = 10;
481 psz = szVal;
482 if ( *psz == '0'
483 && (psz[1] == 'x' || psz[1] == 'X'))
484 {
485 uBase = 16;
486 psz += 2;
487 }
488
489 /* convert it up to the first unknown char. */
490 cb = 0;
491 for(;;)
492 {
493 const char ch = *psz;
494 unsigned uDigit;
495 if (!ch)
496 break;
497 else if (ch >= '0' && ch <= '9')
498 uDigit = ch - '0';
499 else if (ch >= 'a' && ch <= 'z')
500 uDigit = ch - 'a' + 10;
501 else if (ch >= 'A' && ch <= 'Z')
502 uDigit = ch - 'A' + 10;
503 else
504 break;
505 if (uDigit >= uBase)
506 break;
507
508 /* add the digit */
509 cb *= uBase;
510 cb += uDigit;
511
512 psz++;
513 }
514
515 /* check for unit */
516 if (*psz == 'm' || *psz == 'M')
517 cb *= 1024*1024;
518 else if (*psz == 'k' ||*psz == 'K')
519 cb *= 1024;
520 else if (*psz == 'g' || *psz == 'G')
521 cb *= 1024*1024*1024;
522
523 *pcb = cb;
524 return 0;
525}
526
527
528/**
[2854]529 * Get the pointer to the filename part of the name.
530 *
531 * @returns Pointer to where the filename starts within the string pointed to by pszFilename.
532 * @returns Pointer to the terminator char if no filename.
533 * @param pszFilename The filename to parse.
534 */
535char *kldrHlpGetFilename(const char *pszFilename)
536{
537 const char *pszLast = NULL;
538 for (;;)
539 {
540 char ch = *pszFilename;
541#if defined(__OS2__) || defined(__WIN__)
542 if (ch == '/' || ch == '\\' || ch == ':')
543 {
544 while ((ch = *++pszFilename) == '/' || ch == '\\' || ch == ':')
545 /* nothing */;
546 pszLast = pszFilename;
547 }
548#else
549 if (ch == '/')
550 {
551 while ((ch = *++pszFilename) == '/')
552 /* betsuni */;
553 pszLast = pszFilename;
554 }
555#endif
556 if (!ch)
557 return (char *)(pszLast ? pszLast : pszFilename);
558 pszFilename++;
559 }
560}
561
562
563/**
564 * Gets the filename suffix.
565 *
566 * @returns Pointer to where the suffix starts within the string pointed to by pszFilename.
567 * @returns Pointer to the terminator char if no suffix.
568 * @param pszFilename The filename to parse.
569 */
570char *kldrHlpGetSuff(const char *pszFilename)
571{
572 const char *pszDot = NULL;
573 pszFilename = kldrHlpGetFilename(pszFilename);
574 for (;;)
575 {
576 char ch = *pszFilename;
577 if (ch == '.')
578 {
579 while ((ch = *++pszFilename) == '.')
580 /* nothing */;
581 if (ch)
582 pszDot = pszFilename - 1;
583 }
584 if (!ch)
585 return (char *)(pszDot ? pszDot : pszFilename);
586 pszFilename++;
587 }
588}
589
590
591/**
592 * Gets the filename extention.
593 *
594 * @returns Pointer to where the extension starts within the string pointed to by pszFilename.
595 * @returns Pointer to the terminator char if no extension.
596 * @param pszFilename The filename to parse.
597 */
598char *kldrHlpGetExt(const char *pszFilename)
599{
600 char *psz = kldrHlpGetSuff(pszFilename);
601 return *psz ? psz + 1 : psz;
602}
603
604
605
606/**
[2825]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
[2830]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
[2836]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)
[2825]655{
[2836]656 static const char s_szDigits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
657 char *pszRet = psz;
658
659 if (cch >= (lVal < 0 ? 3U : 2U) && psz)
[2825]660 {
[2836]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;
[2825]690}
691
692
693/**
[2832]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');
[2842]706 while (pszNl)
[2832]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/**
[2825]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{
[2832]754 char szLine[16];
[2825]755
[2832]756 kldrHlpAssertWrite("\n!!!kLdr Assertion Failed!!!\nExpression: ");
757 kldrHlpAssertWrite(pszExpr);
758 kldrHlpAssertWrite("\nAt: ");
759 kldrHlpAssertWrite(pszFile);
760 kldrHlpAssertWrite("(");
[2836]761 kldrHlpAssertWrite(kldrHlpInt2Ascii(szLine, sizeof(szLine), iLine, 10));
[2832]762 kldrHlpAssertWrite(") ");
763 kldrHlpAssertWrite(pszFunction);
764 kldrHlpAssertWrite("\n");
765}
[2825]766
767
[2832]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
[2825]780
[2832]781
782#ifdef kLdrHlpStrChr_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)
788 {
789 if (*pb == b)
790 return (void *)pb;
791 pb++;
792 }
793 return NULL;
794}
[2825]795#endif
796
[2854]797
798int kLdrHlpMemIComp(const void *pv1, const void *pv2, size_t cb)
799{
800 const uint8_t *pb1 = (const uint8_t *)pv1;
801 const uint8_t *pb2 = (const uint8_t *)pv2;
802 while (cb)
803 {
804 if (*pb1 != *pb2)
805 {
806 const uint8_t u1 = *pb1 >= 'a' && *pb1 <= 'z' ? *pb1 - 'a' : *pb1;
807 const uint8_t u2 = *pb2 >= 'a' && *pb2 <= 'z' ? *pb2 - 'a' : *pb2;
808 if (u1 != u2)
809 return (int)*pb1 - (int)*pb2;
810 }
811 pb1++;
812 pb2++;
813 }
814 return 0;
815}
816
817
818int kLdrHlpStrIComp(const char *pv1, const char *pv2)
819{
820 const uint8_t *pb1 = (const uint8_t *)pv1;
821 const uint8_t *pb2 = (const uint8_t *)pv2;
822 for (;;)
823 {
824 if (*pb1 != *pb2)
825 {
826 const uint8_t u1 = *pb1 >= 'a' && *pb1 <= 'z' ? *pb1 - 'a' : *pb1;
827 const uint8_t u2 = *pb2 >= 'a' && *pb2 <= 'z' ? *pb2 - 'a' : *pb2;
828 if (u1 != u2)
829 return (int)*pb1 - (int)*pb2;
830 }
831 if (!*pb1)
832 break;
833 pb1++;
834 pb2++;
835 }
836 return 0;
837}
838
Note: See TracBrowser for help on using the repository browser.