Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1105 lines
25 KiB

  1. //==========================================================================;
  2. //
  3. // Copyright (c) 1991-1999 Microsoft Corporation
  4. //
  5. // You have a royalty-free right to use, modify, reproduce and
  6. // distribute the Sample Files (and/or any modified version) in
  7. // any way you find useful, provided that you agree that
  8. // Microsoft has no warranty obligations or liability for any
  9. // Sample Application Files which are modified.
  10. //
  11. //--------------------------------------------------------------------------;
  12. //
  13. // debug.c
  14. //
  15. // Description:
  16. // This file contains code yanked from several places to provide debug
  17. // support that works in win 16 and win 32.
  18. //
  19. // History:
  20. // 11/23/92 cjp [curtisp]
  21. //
  22. //==========================================================================;
  23. #ifdef DEBUG
  24. #include <windows.h>
  25. #include <windowsx.h>
  26. #include <mmsystem.h>
  27. #include <stdarg.h>
  28. #include "debug.h"
  29. #ifdef WIN32
  30. #define BCODE
  31. #else
  32. #define BCODE __based(__segname("_TEXT"))
  33. #endif
  34. #define WSPRINTF_LIMIT 1024
  35. typedef struct tagLOG
  36. {
  37. LPBYTE lpbQueue;
  38. UINT cbBuffer;
  39. UINT idxRead;
  40. UINT idxWrite;
  41. } LOG, FAR *LPLOG;
  42. #define LOG_INCIDX(pl,x) ((++(x) >= pl->cbBuffer) ? x = 0 : x)
  43. VOID FAR CDECL DbgVPrintF(LPSTR szFmt, LPSTR va) ;
  44. BOOL NEAR PASCAL LogInit(LPLOG lpLog, UINT ckBuffer);
  45. VOID NEAR PASCAL LogWrite(LPLOG lpLog, LPSTR lpstrEvent);
  46. BOOL NEAR PASCAL LogRead(LPLOG lpLog, LPSTR lpstrBuffer, UINT cbBuffer);
  47. #ifdef ISRDEBUG
  48. int wivsprintf(LPSTR lpOut, LPCSTR lpFmt, VOID FAR* lpParms) ;
  49. LPCSTR NEAR PASCAL SP_GetFmtValue(LPCSTR lpch, LPWORD lpw) ;
  50. UINT NEAR PASCAL SP_PutNumber(LPSTR lpb, DWORD n, UINT limit, UINT radix, UINT icase) ;
  51. VOID NEAR PASCAL SP_Reverse(LPSTR lpFirst, LPSTR lpLast) ;
  52. UINT NEAR PASCAL ilstrlen(LPSTR lpstr) ;
  53. VOID NEAR PASCAL ilstrcat(LPSTR lpstrDest, LPSTR lpstrSrc) ;
  54. #endif
  55. //
  56. // since we don't UNICODE our debugging messages, use the ASCII entry
  57. // points regardless of how we are compiled.
  58. //
  59. #define wvsprintfA wvsprintf
  60. #define GetProfileIntA GetProfileInt
  61. #define OutputDebugStringA OutputDebugString
  62. #ifdef ISRDEBUG
  63. #define wvsprintf wivsprintf
  64. #define lstrcatA ilstrcat
  65. #define lstrlenA ilstrlen
  66. #else
  67. #define lstrcatA lstrcat
  68. #define lstrlenA lstrlen
  69. #endif
  70. //
  71. //
  72. //
  73. BOOL __gfDbgEnabled = TRUE; // master enable
  74. UINT __guDbgLevel = 0; // current debug level
  75. BOOL __gfLogging = 0; // Are we logging as well?
  76. BOOL __gfAssertBreak = 0; // Break on assert?
  77. HWND ghWndCB = (HWND)NULL;
  78. LOG gLog;
  79. WORD wDebugLevel = 0;
  80. //************************************************************************
  81. //**
  82. //** DbgAssert();
  83. //**
  84. //** DESCRIPTION:
  85. //**
  86. //**
  87. //** ARGUMENTS:
  88. //** LPSTR lpstrExp
  89. //** LPSTR lpstrFile
  90. //** DWORD dwLine
  91. //**
  92. //** RETURNS:
  93. //** VOID
  94. //**
  95. //** HISTORY:
  96. //**
  97. //************************************************************************
  98. VOID WINAPI DbgAssert(
  99. LPSTR lpstrExp,
  100. LPSTR lpstrFile,
  101. DWORD dwLine)
  102. {
  103. static char BCODE szFormat[] =
  104. "Assert:%s@%lu %s";
  105. dprintf(0, szFormat, lpstrFile, dwLine, lpstrExp);
  106. if (__gfAssertBreak)
  107. DebugBreak();
  108. }
  109. //************************************************************************
  110. //**
  111. //** DbgVPrintF();
  112. //**
  113. //** DESCRIPTION:
  114. //**
  115. //**
  116. //** ARGUMENTS:
  117. //** LPSTR szFmt
  118. //** LPSTR va
  119. //**
  120. //** RETURNS:
  121. //** VOID
  122. //**
  123. //** HISTORY:
  124. //**
  125. //************************************************************************
  126. VOID FAR CDECL DbgVPrintF(
  127. LPSTR szFmt,
  128. LPSTR va)
  129. {
  130. char ach[DEBUG_MAX_LINE_LEN];
  131. BOOL fDebugBreak = FALSE;
  132. BOOL fPrefix = TRUE;
  133. BOOL fCRLF = TRUE;
  134. ach[0] = '\0';
  135. for (;;)
  136. {
  137. switch(*szFmt)
  138. {
  139. case '!':
  140. fDebugBreak = TRUE;
  141. szFmt++;
  142. continue;
  143. case '`':
  144. fPrefix = FALSE;
  145. szFmt++;
  146. continue;
  147. case '~':
  148. fCRLF = FALSE;
  149. szFmt++;
  150. continue;
  151. }
  152. break;
  153. }
  154. if (fDebugBreak)
  155. {
  156. ach[0] = '\007';
  157. ach[1] = '\0';
  158. }
  159. if (fPrefix)
  160. lstrcatA(ach, DEBUG_MODULE_NAME ": ");
  161. wvsprintfA(ach + lstrlenA(ach), szFmt, (LPSTR)va);
  162. if (fCRLF)
  163. lstrcatA(ach, "\r\n");
  164. if (__gfLogging)
  165. {
  166. LogWrite(&gLog, ach);
  167. if (ghWndCB)
  168. PostMessage(ghWndCB, WM_DEBUGUPDATE, 0, 0);
  169. }
  170. OutputDebugStringA(ach);
  171. if (fDebugBreak)
  172. DebugBreak();
  173. } //** DbgVPrintF()
  174. //************************************************************************
  175. //**
  176. //** dprintf();
  177. //**
  178. //** DESCRIPTION:
  179. //** dprintf() is called by the DPF macro if DEBUG is defined at compile
  180. //** time.
  181. //**
  182. //** The messages will be send to COM1: like any debug message. To
  183. //** enable debug output, add the following to WIN.INI :
  184. //**
  185. //** [debug]
  186. //** ICSAMPLE=1
  187. //**
  188. //**
  189. //** ARGUMENTS:
  190. //** UINT uDbgLevel
  191. //** LPCSTR szFmt
  192. //** ...
  193. //**
  194. //** RETURNS:
  195. //** VOID
  196. //**
  197. //** HISTORY:
  198. //** 06/12/93 [t-kyleb]
  199. //**
  200. //************************************************************************
  201. VOID FAR CDECL dprintf(
  202. UINT uDbgLevel,
  203. LPSTR szFmt,
  204. ...)
  205. {
  206. va_list va;
  207. if (!__gfDbgEnabled || (__guDbgLevel < uDbgLevel))
  208. return;
  209. va_start(va, szFmt);
  210. DbgVPrintF(szFmt, (LPSTR)va);
  211. va_end(va);
  212. } //** dprintf()
  213. //************************************************************************
  214. //**
  215. //** DbgEnable();
  216. //**
  217. //** DESCRIPTION:
  218. //**
  219. //**
  220. //** ARGUMENTS:
  221. //** BOOL fEnable
  222. //**
  223. //** RETURNS:
  224. //** BOOL
  225. //**
  226. //** HISTORY:
  227. //** 06/12/93 [t-kyleb]
  228. //**
  229. //************************************************************************
  230. BOOL WINAPI DbgEnable(
  231. BOOL fEnable)
  232. {
  233. BOOL fOldState;
  234. fOldState = __gfDbgEnabled;
  235. __gfDbgEnabled = fEnable;
  236. return (fOldState);
  237. } //** DbgEnable()
  238. //************************************************************************
  239. //**
  240. //** DbgSetLevel();
  241. //**
  242. //** DESCRIPTION:
  243. //**
  244. //**
  245. //** ARGUMENTS:
  246. //** UINT uLevel
  247. //**
  248. //** RETURNS:
  249. //** UINT
  250. //**
  251. //** HISTORY:
  252. //** 06/12/93 [t-kyleb]
  253. //**
  254. //************************************************************************
  255. UINT WINAPI DbgSetLevel(
  256. UINT uLevel)
  257. {
  258. UINT uOldLevel;
  259. uOldLevel = __guDbgLevel;
  260. __guDbgLevel = wDebugLevel = uLevel;
  261. return (uOldLevel);
  262. } //** DbgSetLevel()
  263. //--------------------------------------------------------------------------;
  264. //
  265. // UINT DbgInitialize(VOID)
  266. //
  267. // Description:
  268. //
  269. //
  270. // Arguments:
  271. //
  272. // Return (UINT):
  273. //
  274. //
  275. // History:
  276. // 11/24/92 cjp [curtisp]
  277. //
  278. //--------------------------------------------------------------------------;
  279. UINT WINAPI DbgInitialize(BOOL fEnable)
  280. {
  281. char szTemp[64];
  282. LPSTR pstr;
  283. UINT uLevel;
  284. UINT uLogMem;
  285. __gfAssertBreak = GetProfileInt(DEBUG_SECTION, ASSERT_BREAK, 0);
  286. GetProfileString(DEBUG_SECTION, DEBUG_MODULE_NAME, "", szTemp, sizeof(szTemp));
  287. pstr = szTemp;
  288. uLevel = 0;
  289. while (*pstr >= '0' && *pstr <= '9')
  290. {
  291. uLevel = uLevel*10 + (UINT)(*pstr - '0');
  292. pstr++;
  293. }
  294. __gfLogging = FALSE;
  295. if (*pstr == ',')
  296. {
  297. pstr++;
  298. uLogMem = 0;
  299. while (*pstr >= '0' && *pstr <= '9')
  300. {
  301. uLogMem = uLogMem*10 + (UINT)(*pstr - '0');
  302. pstr++;
  303. }
  304. if (0 == uLogMem) uLogMem = K_DEFAULT_LOGMEM;
  305. if (uLogMem > K_MAX_LOGMEM) uLogMem = K_MAX_LOGMEM;
  306. __gfLogging = TRUE;
  307. }
  308. if (__gfLogging)
  309. __gfLogging = LogInit(&gLog, uLogMem);
  310. DbgSetLevel(GetProfileIntA(DEBUG_SECTION, DEBUG_MODULE_NAME, 0));
  311. DbgEnable(fEnable);
  312. return (__guDbgLevel);
  313. } // DbgInitialize()
  314. VOID WINAPI DbgRegisterCallback(HWND hWnd)
  315. {
  316. ghWndCB = hWnd;
  317. }
  318. BOOL WINAPI DbgGetNextLogEntry(LPSTR lpstrBuffer, UINT cbBuffer)
  319. {
  320. if (!__gfLogging)
  321. return FALSE;
  322. return LogRead(&gLog, lpstrBuffer, cbBuffer);
  323. }
  324. BOOL NEAR PASCAL LogInit(LPLOG lpLog, UINT ckMem)
  325. {
  326. DWORD cbMem;
  327. cbMem = 1024L * ckMem;
  328. lpLog->lpbQueue = GlobalAllocPtr(GPTR, cbMem);
  329. if (NULL == lpLog->lpbQueue)
  330. return FALSE;
  331. if (!GlobalSmartPageLock(HIWORD(lpLog->lpbQueue)))
  332. {
  333. GlobalFreePtr(lpLog->lpbQueue);
  334. return FALSE;
  335. }
  336. lpLog->cbBuffer = (UINT)cbMem;
  337. lpLog->idxRead = 0;
  338. lpLog->idxWrite = 0;
  339. return TRUE;
  340. }
  341. VOID NEAR PASCAL LogWrite(LPLOG lpLog, LPSTR lpstrEvent)
  342. {
  343. if (!*lpstrEvent)
  344. return;
  345. while (*lpstrEvent)
  346. {
  347. lpLog->lpbQueue[lpLog->idxWrite] = *lpstrEvent++;
  348. LOG_INCIDX(lpLog,lpLog->idxWrite);
  349. }
  350. lpLog->idxRead = lpLog->idxWrite;
  351. while (lpLog->lpbQueue[lpLog->idxRead])
  352. {
  353. lpLog->lpbQueue[lpLog->idxRead] = '\0';
  354. LOG_INCIDX(lpLog,lpLog->idxRead);
  355. }
  356. LOG_INCIDX(lpLog,lpLog->idxRead);
  357. LOG_INCIDX(lpLog,lpLog->idxWrite);
  358. }
  359. BOOL NEAR PASCAL LogRead(LPLOG lpLog, LPSTR lpstrBuffer, UINT cbBuffer)
  360. {
  361. BYTE c;
  362. UINT idx;
  363. if (!cbBuffer)
  364. return FALSE;
  365. idx = lpLog->idxRead;
  366. while ('\0' == lpLog->lpbQueue[idx])
  367. {
  368. LOG_INCIDX(lpLog,idx);
  369. if (idx == lpLog->idxRead)
  370. return FALSE;
  371. }
  372. cbBuffer--;
  373. while (0 != (c = lpLog->lpbQueue[idx]))
  374. {
  375. if (cbBuffer)
  376. {
  377. *lpstrBuffer++ = c;
  378. cbBuffer--;
  379. }
  380. lpLog->lpbQueue[idx] = '\0';
  381. LOG_INCIDX(lpLog,idx);
  382. }
  383. *lpstrBuffer = '\0';
  384. LOG_INCIDX(lpLog,idx);
  385. lpLog->idxRead = idx;
  386. return TRUE;
  387. }
  388. //--------------------------------------------------------------------------;
  389. //
  390. // The rest of the code is only needed if we're in Win16 and need to be
  391. // interrupt callable.
  392. //
  393. //--------------------------------------------------------------------------;
  394. #ifdef ISRDEBUG
  395. #define OUT(ch) if (--cchLimit) *lpOut++=(ch); else goto error_Out
  396. //************************************************************************
  397. //**
  398. //** wivsprintf();
  399. //**
  400. //** DESCRIPTION:
  401. //** Interrupt callable version of wvsprintf()
  402. //**
  403. //**
  404. //** ARGUMENTS:
  405. //** LPSTR lpOut - Buffer to format into.
  406. //** LPCSTR lpFmt - Format string.
  407. //** VOID FAR* lpParms - Points to the first of args
  408. //** described by lpFmt.
  409. //**
  410. //** RETURNS:
  411. //** int - Number of characters stored.
  412. //**
  413. //** HISTORY:
  414. //** 3/28/93 jfg [jimge]
  415. //**
  416. //************************************************************************
  417. int wivsprintf(
  418. LPSTR lpOut,
  419. LPCSTR lpFmt,
  420. VOID FAR* lpParms)
  421. {
  422. int left ;
  423. char prefix ;
  424. int width ;
  425. int prec ;
  426. char fillch ;
  427. int size ;
  428. int sign ;
  429. int radix ;
  430. int upper ;
  431. int cchLimit = WSPRINTF_LIMIT;
  432. int cch ;
  433. LPSTR lpT ;
  434. union
  435. {
  436. long l ;
  437. unsigned long ul ;
  438. char sz[sizeof(long)] ;
  439. } val;
  440. while (*lpFmt)
  441. {
  442. if (*lpFmt=='%')
  443. {
  444. //
  445. // Read the format flags.
  446. //
  447. left = 0 ;
  448. prefix = 0 ;
  449. while (*++lpFmt)
  450. {
  451. if (*lpFmt=='-')
  452. {
  453. left++;
  454. }
  455. else if (*lpFmt=='#')
  456. {
  457. prefix++;
  458. }
  459. else
  460. {
  461. break;
  462. }
  463. }
  464. //
  465. // Find the fill character (either '0' or ' ')
  466. //
  467. if (*lpFmt=='0')
  468. {
  469. fillch = '0' ;
  470. lpFmt++ ;
  471. }
  472. else
  473. {
  474. fillch = ' ' ;
  475. }
  476. //
  477. // Now parse [width[.precision]]
  478. //
  479. lpFmt = SP_GetFmtValue(lpFmt,&cch);
  480. width = cch;
  481. if (*lpFmt=='.')
  482. {
  483. lpFmt = SP_GetFmtValue(++lpFmt,&cch);
  484. prec = cch;
  485. }
  486. else
  487. {
  488. prec = (UINT)-1 ;
  489. }
  490. //
  491. // Get the operand size modifier
  492. //
  493. if (*lpFmt=='l')
  494. {
  495. size = 1 ;
  496. lpFmt++ ;
  497. }
  498. else
  499. {
  500. size = 0 ;
  501. if (*lpFmt=='h')
  502. {
  503. lpFmt++ ;
  504. }
  505. }
  506. //
  507. // We've gotten all the modifier; now format the output
  508. // based on the type (which should now be pointed at
  509. // by lpFmt).
  510. //
  511. upper = 0 ;
  512. sign = 0 ;
  513. radix = 10 ;
  514. switch (*lpFmt)
  515. {
  516. case 0:
  517. goto error_Out ;
  518. case 'i' :
  519. case 'd' :
  520. sign++ ;
  521. case 'u':
  522. //
  523. // Don't show a prefix for decimal formats
  524. //
  525. prefix=0 ;
  526. do_Numeric:
  527. //
  528. // Special cases to act like MSC v5.10
  529. //
  530. if (left || prec>=0)
  531. {
  532. fillch = ' ';
  533. }
  534. //
  535. // Get value from parm list into val union
  536. //
  537. if (size)
  538. {
  539. val.l=*((long far *)lpParms)++;
  540. }
  541. else
  542. {
  543. if (sign)
  544. {
  545. val.l=(long)*((short far *)lpParms)++;
  546. }
  547. else
  548. {
  549. val.ul=(unsigned long)*((unsigned far *)lpParms)++;
  550. }
  551. }
  552. //
  553. // Save sign of val.l in sign and set val.l positive.
  554. //
  555. if (sign && val.l<0L)
  556. {
  557. val.l=-val.l;
  558. }
  559. else
  560. {
  561. sign=0;
  562. }
  563. //
  564. // Save start of output stream for later reverse
  565. //
  566. lpT = lpOut;
  567. //
  568. // Blast the number backwards into the user buffer
  569. //
  570. cch = SP_PutNumber(lpOut,val.l,cchLimit,radix,upper) ;
  571. if (!(cchLimit-=cch))
  572. goto error_Out ;
  573. lpOut += cch ;
  574. width -= cch ;
  575. prec -= cch ;
  576. if (prec>0)
  577. {
  578. width -= prec ;
  579. }
  580. //
  581. // Fill in up to precision
  582. //
  583. while (prec-- > 0)
  584. {
  585. OUT('0') ;
  586. }
  587. if (width>0 && !left)
  588. {
  589. //
  590. // If we're filling with spaces, put sign first
  591. //
  592. if (fillch != '0')
  593. {
  594. if (sign)
  595. {
  596. sign = 0 ;
  597. OUT('-') ;
  598. width-- ;
  599. }
  600. if (prefix)
  601. {
  602. OUT(prefix) ;
  603. OUT('0') ;
  604. prefix = 0 ;
  605. }
  606. }
  607. if (sign)
  608. {
  609. width-- ;
  610. }
  611. //
  612. // Now fill to width
  613. //
  614. while (width-- > 0)
  615. {
  616. OUT(fillch) ;
  617. }
  618. //
  619. // Still have a sign?
  620. //
  621. if (sign)
  622. {
  623. OUT('-') ;
  624. }
  625. if (prefix)
  626. {
  627. OUT(prefix) ;
  628. OUT('0') ;
  629. }
  630. //
  631. // Now reverse the string in place
  632. //
  633. SP_Reverse(lpT,lpOut-1);
  634. }
  635. else
  636. {
  637. //
  638. // Add the sign character
  639. //
  640. if (sign)
  641. {
  642. OUT('-') ;
  643. width-- ;
  644. }
  645. if (prefix)
  646. {
  647. OUT(prefix);
  648. OUT('0');
  649. }
  650. //
  651. // Now reverse the string in place
  652. //
  653. SP_Reverse(lpT,lpOut-1);
  654. //
  655. // Pad to the right of the string in case left aligned
  656. //
  657. while (width-- > 0)
  658. {
  659. OUT(fillch) ;
  660. }
  661. }
  662. break ;
  663. case 'X':
  664. upper++ ;
  665. //
  666. // Falling through...
  667. //
  668. case 'x':
  669. radix=16 ;
  670. if (prefix)
  671. {
  672. prefix = upper ? 'X' : 'x' ;
  673. }
  674. goto do_Numeric ;
  675. case 'c':
  676. //
  677. // Save as one character string and join common code
  678. //
  679. val.sz[0] = *((char far*)lpParms) ;
  680. val.sz[1]=0 ;
  681. lpT = val.sz ;
  682. cch = 1 ;
  683. (BYTE far*)lpParms += sizeof(WORD) ;
  684. goto put_String ;
  685. case 's':
  686. lpT = *((LPSTR FAR *)lpParms)++ ;
  687. cch = ilstrlen(lpT) ;
  688. put_String:
  689. if (prec>=0 && cch>prec)
  690. {
  691. cch = prec ;
  692. }
  693. width -= cch ;
  694. if (left)
  695. {
  696. while (cch--)
  697. {
  698. OUT(*lpT++) ;
  699. }
  700. while (width-->0)
  701. {
  702. OUT(fillch) ;
  703. }
  704. }
  705. else
  706. {
  707. while (width-- > 0)
  708. {
  709. OUT(fillch) ;
  710. }
  711. while (cch--)
  712. {
  713. OUT(*lpT++) ;
  714. }
  715. }
  716. break ;
  717. default:
  718. //
  719. // An unsupported type character was given. We just
  720. // print the character and go on.
  721. //
  722. OUT(*lpFmt) ;
  723. break ;
  724. } // switch(*lpfmt)
  725. } // if (*lpfmt == '%')
  726. else
  727. {
  728. //
  729. // Normal not-format character
  730. //
  731. OUT(*lpFmt) ;
  732. }
  733. lpFmt++ ;
  734. } // while (*lpFmt)
  735. error_Out:
  736. *lpOut = 0 ;
  737. return WSPRINTF_LIMIT-cchLimit ;
  738. } //** wivsprintf()
  739. //************************************************************************
  740. //**
  741. //** SP_GetFmtValue();
  742. //**
  743. //** DESCRIPTION:
  744. //** Parse a decimal integer forming part of a format string.
  745. //**
  746. //**
  747. //** ARGUMENTS:
  748. //** LPCSTR lpch - Points to the string to parse.
  749. //** LPWORD lpw - Points to a word where the value will be
  750. //** returned.
  751. //**
  752. //** RETURNS:
  753. //** LPCSTR - Pointer of first character past the format value.
  754. //**
  755. //** HISTORY:
  756. //** 3/28/93 jfg [jimge]
  757. //**
  758. //************************************************************************
  759. LPCSTR NEAR PASCAL SP_GetFmtValue(
  760. LPCSTR lpch,
  761. LPWORD lpw)
  762. {
  763. WORD i = 0 ;
  764. while (*lpch>='0' && *lpch<='9')
  765. {
  766. i *= 10;
  767. i += (UINT)(*lpch++-'0');
  768. }
  769. *lpw = i;
  770. return(lpch);
  771. } //** SP_GetFmtValue()
  772. //************************************************************************
  773. //**
  774. //** SP_PutNumber();
  775. //**
  776. //** DESCRIPTION:
  777. //** Formats the given number in the given radix into the buffer
  778. //** *backwards*. The entire string will be reversed after printf
  779. //** has added sign, prefix, etc. to it.
  780. //**
  781. //**
  782. //** ARGUMENTS:
  783. //** LPSTR lpb - Points to the output buffer.
  784. //** DWORD n - Number to convert.
  785. //** UINT limit - Maximum number of characters to store.
  786. //** UINT radix - Base to format in.
  787. //** UINT icase - Non-zero if the string should be upper case (hex).
  788. //**
  789. //** RETURNS:
  790. //** UINT - Number of characters output.
  791. //**
  792. //** HISTORY:
  793. //**
  794. //************************************************************************
  795. UINT NEAR PASCAL SP_PutNumber(
  796. LPSTR lpb,
  797. DWORD n,
  798. UINT limit,
  799. UINT radix,
  800. UINT icase)
  801. {
  802. BYTE bTemp;
  803. UINT cchStored = 0;
  804. //
  805. // Set icase to the offset to add to the character if it
  806. // represents a value > 10
  807. //
  808. icase = (icase ? 'A' : 'a') - '0' - 10 ;
  809. while (limit--)
  810. {
  811. //
  812. // AVOID a call to __aFulrem
  813. // This code words because radix is only a word
  814. //
  815. // bTemp = '0' + (BYTE)(n%radix) ;
  816. //
  817. _asm
  818. {
  819. mov cx, radix
  820. mov ax, word ptr n+2
  821. xor dx, dx
  822. div cx
  823. mov ax, word ptr n
  824. div cx
  825. add dl, '0'
  826. mov bTemp, dl
  827. }
  828. if (bTemp > '9')
  829. {
  830. bTemp += icase ;
  831. }
  832. *lpb++ = bTemp ;
  833. ++cchStored ;
  834. //
  835. // AVOID a call to __aFFauldiv
  836. // This code words because radix is only a word
  837. //
  838. // n /= radix
  839. //
  840. _asm
  841. {
  842. push bx
  843. mov cx, radix
  844. mov ax, word ptr n+2
  845. xor dx, dx
  846. div cx
  847. mov bx, ax
  848. mov ax, word ptr n
  849. div cx
  850. mov word ptr n+2, bx
  851. mov word ptr n, ax
  852. pop bx
  853. }
  854. if (n == 0)
  855. {
  856. break ;
  857. }
  858. }
  859. return cchStored ;
  860. } //** SP_PutNumber()
  861. //************************************************************************
  862. //**
  863. //** SP_Reverse();
  864. //**
  865. //** DESCRIPTION:
  866. //** Reverse string in place.
  867. //**
  868. //** ARGUMENTS:
  869. //** LPSTR pFirst
  870. //** LPSTR pLast
  871. //**
  872. //** RETURNS:
  873. //** VOID
  874. //**
  875. //** HISTORY:
  876. //**
  877. //************************************************************************
  878. VOID NEAR PASCAL SP_Reverse(
  879. LPSTR pFirst,
  880. LPSTR pLast)
  881. {
  882. UINT uSwaps = (pLast - pFirst + 1) / 2;
  883. BYTE bTemp;
  884. while (uSwaps--)
  885. {
  886. bTemp = *pFirst;
  887. *pFirst = *pLast;
  888. *pLast = bTemp;
  889. pFirst++, pLast--;
  890. }
  891. } //** SP_Reverse()
  892. //************************************************************************
  893. //**
  894. //** ilstrlen();
  895. //**
  896. //** DESCRIPTION:
  897. //** Interrupt callable version of strlen().
  898. //**
  899. //** ARGUMENTS:
  900. //** LPSTR pstr
  901. //**
  902. //** RETURNS:
  903. //** UINT
  904. //**
  905. //** HISTORY:
  906. //**
  907. //************************************************************************
  908. UINT NEAR PASCAL ilstrlen(
  909. LPSTR pstr)
  910. {
  911. UINT cch = 0 ;
  912. while (*pstr++)
  913. ++cch;
  914. return(cch);
  915. } //** ilstrlen()
  916. //************************************************************************
  917. //**
  918. //** ilstrcat();
  919. //**
  920. //** DESCRIPTION:
  921. //** Interrupt callable version of lstrcat().
  922. //**
  923. //** ARGUMENTS:
  924. //** LPSTR pstrDest
  925. //** LPSTR pstrSrc
  926. //**
  927. //** RETURNS:
  928. //** VOID
  929. //**
  930. //** HISTORY:
  931. //**
  932. //************************************************************************
  933. VOID NEAR PASCAL ilstrcat(
  934. LPSTR pstrDest,
  935. LPSTR pstrSrc)
  936. {
  937. while (*pstrDest)
  938. pstrDest++;
  939. while (*pstrDest++ = *pstrSrc++)
  940. ;
  941. } //** ilstrcat()
  942. #endif // #ifdef ISRDEBUG
  943. #endif // #ifdef DEBUG