Windows NT 4.0 source code leak
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.

1109 lines
26 KiB

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