lib_str.c 191 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932
  1. /*
  2. *********************************************************************************************************
  3. * uC/LIB
  4. * CUSTOM LIBRARY MODULES
  5. *
  6. * (c) Copyright 2004-2011; Micrium, Inc.; Weston, FL
  7. *
  8. * All rights reserved. Protected by international copyright laws.
  9. *
  10. * uC/LIB is provided in source form to registered licensees ONLY. It is
  11. * illegal to distribute this source code to any third party unless you receive
  12. * written permission by an authorized Micrium representative. Knowledge of
  13. * the source code may NOT be used to develop a similar product.
  14. *
  15. * Please help us continue to provide the Embedded community with the finest
  16. * software available. Your honesty is greatly appreciated.
  17. *
  18. * You can contact us at www.micrium.com.
  19. *********************************************************************************************************
  20. */
  21. /*
  22. *********************************************************************************************************
  23. *
  24. * ASCII STRING MANAGEMENT
  25. *
  26. * Filename : lib_str.c
  27. * Version : V1.35.00
  28. * Programmer(s) : ITJ
  29. * BAN
  30. * JDH
  31. *********************************************************************************************************
  32. * Note(s) : (1) NO compiler-supplied standard library functions are used in library or product software.
  33. *
  34. * (a) ALL standard library functions are implemented in the custom library modules :
  35. *
  36. * (1) \<Custom Library Directory>\lib_*.*
  37. *
  38. * (2) \<Custom Library Directory>\Ports\<cpu>\<compiler>\lib*_a.*
  39. *
  40. * where
  41. * <Custom Library Directory> directory path for custom library software
  42. * <cpu> directory name for specific processor (CPU)
  43. * <compiler> directory name for specific compiler
  44. *
  45. * (b) Product-specific library functions are implemented in individual products.
  46. *
  47. *********************************************************************************************************
  48. * Notice(s) : (1) The Institute of Electrical and Electronics Engineers and The Open Group, have given
  49. * us permission to reprint portions of their documentation. Portions of this text are
  50. * reprinted and reproduced in electronic form from the IEEE Std 1003.1, 2004 Edition,
  51. * Standard for Information Technology -- Portable Operating System Interface (POSIX),
  52. * The Open Group Base Specifications Issue 6, Copyright (C) 2001-2004 by the Institute
  53. * of Electrical and Electronics Engineers, Inc and The Open Group. In the event of any
  54. * discrepancy between these versions and the original IEEE and The Open Group Standard,
  55. * the original IEEE and The Open Group Standard is the referee document. The original
  56. * Standard can be obtained online at http://www.opengroup.org/unix/online.html.
  57. *********************************************************************************************************
  58. */
  59. /*
  60. *********************************************************************************************************
  61. * INCLUDE FILES
  62. *********************************************************************************************************
  63. */
  64. #define LIB_STR_MODULE
  65. #include <lib_str.h>
  66. /*$PAGE*/
  67. /*
  68. *********************************************************************************************************
  69. * LOCAL DEFINES
  70. *********************************************************************************************************
  71. */
  72. /*
  73. *********************************************************************************************************
  74. * LOCAL CONSTANTS
  75. *********************************************************************************************************
  76. */
  77. /*
  78. *********************************************************************************************************
  79. * LOCAL DATA TYPES
  80. *********************************************************************************************************
  81. */
  82. /*
  83. *********************************************************************************************************
  84. * LOCAL TABLES
  85. *********************************************************************************************************
  86. */
  87. static const CPU_INT32U Str_MultOvfThTbl_Int32U[] = {
  88. (CPU_INT32U) DEF_INT_32U_MAX_VAL, /* Invalid base 0. */
  89. (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 1u), /* Invalid base 1. */
  90. (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 2u), /* 32-bit mult ovf th for base 2. */
  91. (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 3u), /* 32-bit mult ovf th for base 3. */
  92. (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 4u), /* 32-bit mult ovf th for base 4. */
  93. (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 5u), /* 32-bit mult ovf th for base 5. */
  94. (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 6u), /* 32-bit mult ovf th for base 6. */
  95. (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 7u), /* 32-bit mult ovf th for base 7. */
  96. (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 8u), /* 32-bit mult ovf th for base 8. */
  97. (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 9u), /* 32-bit mult ovf th for base 9. */
  98. (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 10u), /* 32-bit mult ovf th for base 10. */
  99. (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 11u), /* 32-bit mult ovf th for base 11. */
  100. (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 12u), /* 32-bit mult ovf th for base 12. */
  101. (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 13u), /* 32-bit mult ovf th for base 13. */
  102. (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 14u), /* 32-bit mult ovf th for base 14. */
  103. (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 15u), /* 32-bit mult ovf th for base 15. */
  104. (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 16u), /* 32-bit mult ovf th for base 16. */
  105. (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 17u), /* 32-bit mult ovf th for base 17. */
  106. (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 18u), /* 32-bit mult ovf th for base 18. */
  107. (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 19u), /* 32-bit mult ovf th for base 19. */
  108. (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 20u), /* 32-bit mult ovf th for base 20. */
  109. (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 21u), /* 32-bit mult ovf th for base 21. */
  110. (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 22u), /* 32-bit mult ovf th for base 22. */
  111. (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 23u), /* 32-bit mult ovf th for base 23. */
  112. (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 24u), /* 32-bit mult ovf th for base 24. */
  113. (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 25u), /* 32-bit mult ovf th for base 25. */
  114. (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 26u), /* 32-bit mult ovf th for base 26. */
  115. (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 27u), /* 32-bit mult ovf th for base 27. */
  116. (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 28u), /* 32-bit mult ovf th for base 28. */
  117. (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 29u), /* 32-bit mult ovf th for base 29. */
  118. (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 30u), /* 32-bit mult ovf th for base 30. */
  119. (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 31u), /* 32-bit mult ovf th for base 31. */
  120. (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 32u), /* 32-bit mult ovf th for base 32. */
  121. (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 33u), /* 32-bit mult ovf th for base 33. */
  122. (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 34u), /* 32-bit mult ovf th for base 34. */
  123. (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 35u), /* 32-bit mult ovf th for base 35. */
  124. (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 36u) /* 32-bit mult ovf th for base 36. */
  125. };
  126. /*
  127. *********************************************************************************************************
  128. * LOCAL GLOBAL VARIABLES
  129. *********************************************************************************************************
  130. */
  131. /*$PAGE*/
  132. /*
  133. *********************************************************************************************************
  134. * LOCAL FUNCTION PROTOTYPES
  135. *********************************************************************************************************
  136. */
  137. static CPU_CHAR *Str_FmtNbr_Int32 ( CPU_INT32U nbr,
  138. CPU_INT08U nbr_dig,
  139. CPU_INT08U nbr_base,
  140. CPU_BOOLEAN nbr_neg,
  141. CPU_CHAR lead_char,
  142. CPU_BOOLEAN lower_case,
  143. CPU_BOOLEAN nul,
  144. CPU_CHAR *pstr);
  145. static CPU_INT32U Str_ParseNbr_Int32(const CPU_CHAR *pstr,
  146. CPU_CHAR **pstr_next,
  147. CPU_INT08U nbr_base,
  148. CPU_BOOLEAN nbr_signed,
  149. CPU_BOOLEAN *pnbr_neg);
  150. /*
  151. *********************************************************************************************************
  152. * LOCAL CONFIGURATION ERRORS
  153. *********************************************************************************************************
  154. */
  155. /*$PAGE*/
  156. /*
  157. *********************************************************************************************************
  158. * Str_Len()
  159. *
  160. * Description : Calculate length of a string.
  161. *
  162. * Argument(s) : pstr Pointer to string (see Note #1).
  163. *
  164. * Return(s) : Length of string; number of characters in string before terminating NULL character
  165. * (see Note #2b1).
  166. *
  167. * Caller(s) : Application.
  168. *
  169. * Note(s) : (1) String buffer NOT modified.
  170. *
  171. * (2) (a) IEEE Std 1003.1, 2004 Edition, Section 'strlen() : DESCRIPTION' states that :
  172. *
  173. * (1) "The strlen() function shall compute the number of bytes in the string to
  174. * which 's' ('pstr') points," ...
  175. * (2) "not including the terminating null byte."
  176. *
  177. * (b) IEEE Std 1003.1, 2004 Edition, Section 'strlen() : RETURN VALUE' states that :
  178. *
  179. * (1) "The strlen() function shall return the length of 's' ('pstr');" ...
  180. * (2) "no return value shall be reserved to indicate an error."
  181. *
  182. * (3) String length calculation terminates when :
  183. *
  184. * (a) String pointer points to NULL.
  185. * (1) String buffer overlaps with NULL address.
  186. * (2) String length calculated for string up to but NOT beyond or including
  187. * the NULL address.
  188. *
  189. * (b) Terminating NULL character found.
  190. * (1) String length calculated for string up to but NOT including
  191. * the NULL character (see Note #2a2).
  192. *********************************************************************************************************
  193. */
  194. CPU_SIZE_T Str_Len (const CPU_CHAR *pstr)
  195. {
  196. CPU_SIZE_T len;
  197. len = Str_Len_N(pstr,
  198. DEF_INT_CPU_U_MAX_VAL);
  199. return (len);
  200. }
  201. /*$PAGE*/
  202. /*
  203. *********************************************************************************************************
  204. * Str_Len_N()
  205. *
  206. * Description : Calculate length of a string, up to a maximum number of characters.
  207. *
  208. * Argument(s) : pstr Pointer to string (see Note #1).
  209. *
  210. * len_max Maximum number of characters to search (see Note #3c).
  211. *
  212. * Return(s) : Length of string; number of characters in string before terminating NULL character,
  213. * if terminating NULL character found (see Note #2b1).
  214. *
  215. * Requested maximum number of characters to search,
  216. * if terminating NULL character NOT found (see Note #3c).
  217. *
  218. * Caller(s) : Application.
  219. *
  220. * Note(s) : (1) String buffer NOT modified.
  221. *
  222. * (2) (a) IEEE Std 1003.1, 2004 Edition, Section 'strlen() : DESCRIPTION' states that :
  223. *
  224. * (1) "The strlen() function shall compute the number of bytes in the string to
  225. * which 's' ('pstr') points," ...
  226. * (2) "not including the terminating null byte."
  227. *
  228. * (b) IEEE Std 1003.1, 2004 Edition, Section 'strlen() : RETURN VALUE' states that :
  229. *
  230. * (1) "The strlen() function shall return the length of 's' ('pstr');" ...
  231. * (2) "no return value shall be reserved to indicate an error."
  232. *
  233. * (3) String length calculation terminates when :
  234. *
  235. * (a) String pointer points to NULL.
  236. * (1) String buffer overlaps with NULL address.
  237. * (2) String length calculated for string up to but NOT beyond or including
  238. * the NULL address.
  239. *
  240. * (b) Terminating NULL character found.
  241. * (1) String length calculated for string up to but NOT including
  242. * the NULL character (see Note #2a2).
  243. *
  244. * (c) 'len_max' number of characters searched.
  245. * (1) 'len_max' number of characters does NOT include the terminating NULL character.
  246. *********************************************************************************************************
  247. */
  248. CPU_SIZE_T Str_Len_N (const CPU_CHAR *pstr,
  249. CPU_SIZE_T len_max)
  250. {
  251. const CPU_CHAR *pstr_len;
  252. CPU_SIZE_T len;
  253. pstr_len = pstr;
  254. len = 0u;
  255. while (( pstr_len != (const CPU_CHAR *) 0 ) && /* Calc str len until NULL ptr (see Note #3a) ... */
  256. (*pstr_len != ( CPU_CHAR )'\0') && /* ... or NULL char found (see Note #3b) ... */
  257. ( len < ( CPU_SIZE_T)len_max)) { /* ... or max nbr chars srch'd (see Note #3c). */
  258. pstr_len++;
  259. len++;
  260. }
  261. return (len); /* Rtn str len (see Note #3b1). */
  262. }
  263. /*$PAGE*/
  264. /*
  265. *********************************************************************************************************
  266. * Str_Copy()
  267. *
  268. * Description : Copy source string to destination string buffer.
  269. *
  270. * Argument(s) : pstr_dest Pointer to destination string buffer to receive source string copy (see Note #1a).
  271. *
  272. * pstr_src Pointer to source string to copy into destination string buffer (see Note #1b).
  273. *
  274. * Return(s) : Pointer to destination string, if NO error(s) [see Note #2b1].
  275. *
  276. * Pointer to NULL, otherwise (see Note #2b2A).
  277. *
  278. * Caller(s) : Application.
  279. *
  280. * Note(s) : (1) (a) Destination buffer size NOT validated; buffer overruns MUST be prevented by caller.
  281. *
  282. * (1) Destination buffer size MUST be large enough to accommodate the entire source
  283. * string size including the terminating NULL character.
  284. *
  285. * (b) Source buffer NOT modified.
  286. *
  287. * (2) (a) IEEE Std 1003.1, 2004 Edition, Section 'strcpy() : DESCRIPTION' states that :
  288. *
  289. * (1) "The strcpy() function shall copy the string pointed to by 's2' ('pstr_src')
  290. * ... into the array pointed to by 's1' ('pstr_dest')" ...
  291. * (2) "(including the terminating null byte)."
  292. *
  293. * (b) IEEE Std 1003.1, 2004 Edition, Section 'strcpy() : RETURN VALUE' states that :
  294. *
  295. * (1) "The strcpy() function shall return 's1' ('pstr_dest');" ...
  296. * (2) "no return value is reserved to indicate an error."
  297. * (A) #### This requirement is intentionally NOT implemented in order to return
  298. * NULL for any error(s).
  299. *
  300. * (c) IEEE Std 1003.1, 2004 Edition, Section 'strcpy() : DESCRIPTION' states that "if
  301. * copying takes place between objects that overlap, the behavior is undefined".
  302. *
  303. * (3) String copy terminates when :
  304. *
  305. * (a) Destination/Source string pointer(s) are passed NULL pointers.
  306. * (1) No string copy performed; NULL pointer returned.
  307. *
  308. * (b) Destination/Source string pointer(s) point to NULL.
  309. * (1) String buffer(s) overlap with NULL address; NULL pointer returned.
  310. *
  311. * (c) Source string's terminating NULL character found.
  312. * (1) Entire source string copied into destination string buffer (see Note #2a).
  313. *********************************************************************************************************
  314. */
  315. CPU_CHAR *Str_Copy ( CPU_CHAR *pstr_dest,
  316. const CPU_CHAR *pstr_src)
  317. {
  318. CPU_CHAR *pstr_rtn;
  319. pstr_rtn = Str_Copy_N(pstr_dest,
  320. pstr_src,
  321. DEF_INT_CPU_U_MAX_VAL);
  322. return (pstr_rtn);
  323. }
  324. /*$PAGE*/
  325. /*
  326. *********************************************************************************************************
  327. * Str_Copy_N()
  328. *
  329. * Description : Copy source string to destination string buffer, up to a maximum number of characters.
  330. *
  331. * Argument(s) : pstr_dest Pointer to destination string buffer to receive source string copy (see Note #1a).
  332. *
  333. * pstr_src Pointer to source string to copy into destination string buffer (see Note #1b).
  334. *
  335. * len_max Maximum number of characters to copy (see Notes #2a2 & #3d).
  336. *
  337. * Return(s) : Pointer to destination string, if NO error(s) [see Note #2b1].
  338. *
  339. * Pointer to NULL, otherwise (see Note #2b2A).
  340. *
  341. * Caller(s) : Application.
  342. *
  343. * Note(s) : (1) (a) Destination buffer size NOT validated; buffer overruns MUST be prevented by caller.
  344. *
  345. * (1) Destination buffer size MUST be large enough to accommodate the entire source
  346. * string size including the terminating NULL character.
  347. *
  348. * (b) Source string buffer NOT modified.
  349. *
  350. * (2) (a) (1) IEEE Std 1003.1, 2004 Edition, Section 'strncpy() : DESCRIPTION' states that :
  351. *
  352. * (A) "The strncpy() function shall copy ... the array pointed to by 's2'
  353. * ('pstr_src') to the array pointed to by 's1' ('pstr_dest')"; ...
  354. * (B) but "not more than 'n' ('len_max') bytes" ...
  355. * (C) & "(bytes that follow a null byte are not copied)".
  356. *
  357. * (2) (A) IEEE Std 1003.1, 2004 Edition, Section 'strncpy() : DESCRIPTION' adds that
  358. * "if the array pointed to by 's2' ('pstr_src') is a string that is shorter
  359. * than 'n' ('len_max') bytes, null bytes shall be appended to the copy in
  360. * the array pointed to by 's1' ('pstr_dest'), until 'n' ('len_max') bytes
  361. * in all are written."
  362. *
  363. * (1) #### Since Str_Copy() limits the maximum number of characters to copy
  364. * via Str_Copy_N() by the CPU's maximum number of addressable characters,
  365. * this requirement is intentionally NOT implemented to avoid appending
  366. * a potentially large number of unnecessary terminating NULL characters.
  367. *
  368. * (B) IEEE Std 1003.1, 2004 Edition, Section 'strncpy() : APPLICATION USAGE' also
  369. * states that "if there is no null byte in the first 'n' ('len_max') bytes of
  370. * the array pointed to by 's2' ('pstr_src'), the result is not null-terminated".
  371. *
  372. * (b) IEEE Std 1003.1, 2004 Edition, Section 'strncpy() : RETURN VALUE' states that :
  373. *
  374. * (1) "The strncpy() function shall return 's1' ('pstr_dest');" ...
  375. * (2) "no return value is reserved to indicate an error."
  376. * (A) #### This requirement is intentionally ignored in order to return NULL
  377. * for any error(s).
  378. *
  379. * (c) IEEE Std 1003.1, 2004 Edition, Section 'strncpy() : DESCRIPTION' states that "if
  380. * copying takes place between objects that overlap, the behavior is undefined".
  381. *
  382. * (3) String copy terminates when :
  383. *
  384. * (a) Destination/Source string pointer(s) are passed NULL pointers.
  385. * (1) No string copy performed; NULL pointer returned.
  386. *
  387. * (b) Destination/Source string pointer(s) point to NULL.
  388. * (1) String buffer(s) overlap with NULL address; NULL pointer returned.
  389. *
  390. * (c) Source string's terminating NULL character found.
  391. * (1) Entire source string copied into destination string buffer (see Note #2a1A).
  392. *
  393. * (d) 'len_max' number of characters copied.
  394. * (1) 'len_max' number of characters MAY include the terminating NULL character
  395. * (see Note #2a1C).
  396. * (2) Null copies allowed (i.e. zero-length copies).
  397. * (A) No string copy performed; destination string returned (see Note #2b1).
  398. *********************************************************************************************************
  399. */
  400. /*$PAGE*/
  401. CPU_CHAR *Str_Copy_N ( CPU_CHAR *pstr_dest,
  402. const CPU_CHAR *pstr_src,
  403. CPU_SIZE_T len_max)
  404. {
  405. CPU_CHAR *pstr_copy_dest;
  406. const CPU_CHAR *pstr_copy_src;
  407. CPU_SIZE_T len_copy;
  408. /* Rtn NULL if str ptr(s) NULL (see Note #3a1). */
  409. if (pstr_dest == (CPU_CHAR *)0) {
  410. return ((CPU_CHAR *)0);
  411. }
  412. if (pstr_src == (const CPU_CHAR *)0) {
  413. return ((CPU_CHAR *)0);
  414. }
  415. pstr_copy_dest = pstr_dest;
  416. pstr_copy_src = pstr_src;
  417. len_copy = 0u;
  418. while (( pstr_copy_dest != ( CPU_CHAR *) 0 ) && /* Copy str until NULL ptr(s) [see Note #3b] ... */
  419. ( pstr_copy_src != (const CPU_CHAR *) 0 ) &&
  420. (*pstr_copy_src != ( CPU_CHAR )'\0') && /* ... or NULL char found (see Note #3c); ... */
  421. ( len_copy < ( CPU_SIZE_T)len_max)) { /* ... or max nbr chars copied (see Note #3d). */
  422. *pstr_copy_dest = *pstr_copy_src;
  423. pstr_copy_dest++;
  424. pstr_copy_src++;
  425. len_copy++;
  426. }
  427. /* Rtn NULL if NULL ptr(s) found (see Note #3b1). */
  428. if ((pstr_copy_dest == ( CPU_CHAR *)0) ||
  429. (pstr_copy_src == (const CPU_CHAR *)0)) {
  430. return ((CPU_CHAR *)0);
  431. }
  432. if (len_copy < len_max) { /* If copy str len < max buf len (see Note #2a2A), ... */
  433. *pstr_copy_dest = (CPU_CHAR)'\0'; /* ... copy NULL char (see Note #3c1). */
  434. }
  435. return (pstr_dest); /* Rtn ptr to dest str (see Note #2b1). */
  436. }
  437. /*$PAGE*/
  438. /*
  439. *********************************************************************************************************
  440. * Str_Cat()
  441. *
  442. * Description : Append concatenation string to destination string.
  443. *
  444. * Argument(s) : pstr_dest Pointer to destination string to append concatenation string (see Note #1a).
  445. *
  446. * pstr_cat Pointer to concatenation string to append to destination string (see Note #1b).
  447. *
  448. * Return(s) : Pointer to destination string, if NO error(s) [see Note #2b1].
  449. *
  450. * Pointer to NULL, otherwise (see Note #2b2A).
  451. *
  452. * Caller(s) : Application.
  453. *
  454. * Note(s) : (1) (a) Destination buffer size NOT validated; buffer overruns MUST be prevented by caller.
  455. *
  456. * (1) Destination buffer size MUST be large enough to accommodate the entire
  457. * concatenated string size including the terminating NULL character.
  458. *
  459. * (b) Concatenation string buffer NOT modified.
  460. *
  461. * (2) (a) IEEE Std 1003.1, 2004 Edition, Section 'strcat() : DESCRIPTION' states that :
  462. *
  463. * (1) "The strcat() function shall append a copy of the string pointed to by 's2'
  464. * ('pstr_cat') ... to the end of the string pointed to by 's1' ('pstr_dest')."
  465. *
  466. * (2) (A) "The initial byte of 's2' ('pstr_cat') overwrites the null byte at the
  467. * end of 's1' ('pstr_dest')."
  468. * (B) A "terminating null byte" is appended at the end of the concatenated
  469. * destination strings.
  470. *
  471. * (b) IEEE Std 1003.1, 2004 Edition, Section 'strcat() : RETURN VALUE' states that :
  472. *
  473. * (1) "The strcat() function shall return 's1' ('pstr_dest');" ...
  474. * (2) "no return value shall be reserved to indicate an error."
  475. * (A) #### This requirement is intentionally NOT implemented in order to return
  476. * NULL for any error(s).
  477. *
  478. * (c) IEEE Std 1003.1, 2004 Edition, Section 'strcat() : DESCRIPTION' states that "if
  479. * copying takes place between objects that overlap, the behavior is undefined."
  480. *
  481. * (3) String concatenation terminates when :
  482. *
  483. * (a) Destination/Concatenation string pointer(s) are passed NULL pointers.
  484. * (1) No string concatenation performed; NULL pointer returned.
  485. *
  486. * (b) Destination/Concatenation string pointer(s) point to NULL.
  487. * (1) String buffer(s) overlap with NULL address; NULL pointer returned.
  488. *
  489. * (c) Concatenation string's terminating NULL character found.
  490. * (1) Entire concatenation string appended to destination string (see Note #2a1).
  491. *********************************************************************************************************
  492. */
  493. CPU_CHAR *Str_Cat ( CPU_CHAR *pstr_dest,
  494. const CPU_CHAR *pstr_cat)
  495. {
  496. CPU_CHAR *pstr_rtn;
  497. pstr_rtn = Str_Cat_N(pstr_dest,
  498. pstr_cat,
  499. DEF_INT_CPU_U_MAX_VAL);
  500. return (pstr_rtn);
  501. }
  502. /*$PAGE*/
  503. /*
  504. *********************************************************************************************************
  505. * Str_Cat_N()
  506. *
  507. * Description : Append concatenation string to destination string, up to a maximum number of characters.
  508. *
  509. * Argument(s) : pstr_dest Pointer to destination string to append concatenation string (see Note #1a).
  510. *
  511. * pstr_cat Pointer to concatenation string to append to destination string (see Note #1b).
  512. *
  513. * len_max Maximum number of characters to concatenate (see Notes #2a1B & #3d).
  514. *
  515. * Return(s) : Pointer to destination string, if NO error(s) [see Note #2b1].
  516. *
  517. * Pointer to NULL, otherwise (see Note #2b2A).
  518. *
  519. * Caller(s) : Application.
  520. *
  521. * Note(s) : (1) (a) Destination buffer size NOT validated; buffer overruns MUST be prevented by caller.
  522. *
  523. * (1) Destination buffer size MUST be large enough to accommodate the entire
  524. * concatenated string size including the terminating NULL character.
  525. *
  526. * (b) Concatenation string buffer NOT modified.
  527. *
  528. * (2) (a) IEEE Std 1003.1, 2004 Edition, Section 'strncat() : DESCRIPTION' states that :
  529. *
  530. * (1) (A) "The strncat() function shall append ... the array pointed to by 's2'
  531. * ('pstr_cat') to the end of the string pointed to by 's1' ('pstr_dest')" ...
  532. * (B) but "not more than 'n' ('len_max') bytes".
  533. *
  534. * (2) (A) "The initial byte of 's2' ('pstr_cat') overwrites the null byte at the
  535. * end of 's1' ('pstr_dest')."
  536. * (B) "(a null byte and bytes that follow it are not appended)."
  537. * (C) "A terminating null byte is always appended to the result."
  538. *
  539. * (b) IEEE Std 1003.1, 2004 Edition, Section 'strncat() : RETURN VALUE' states that :
  540. *
  541. * (1) "The strncat() function shall return 's1' ('pstr_dest');" ...
  542. * (2) "no return value shall be reserved to indicate an error."
  543. * (A) #### This requirement is intentionally NOT implemented in order to return
  544. * NULL for any error(s).
  545. *
  546. * (c) IEEE Std 1003.1, 2004 Edition, Section 'strncat() : DESCRIPTION' states that "if
  547. * copying takes place between objects that overlap, the behavior is undefined."
  548. *
  549. * (3) String concatenation terminates when :
  550. *
  551. * (a) Destination/Concatenation string pointer(s) are passed NULL pointers.
  552. * (1) No string concatenation performed; NULL pointer returned.
  553. *
  554. * (b) Destination/Concatenation string pointer(s) point to NULL.
  555. * (1) String buffer(s) overlap with NULL address; NULL pointer returned.
  556. *
  557. * (c) Concatenation string's terminating NULL character found.
  558. * (1) Entire concatenation string appended to destination string (see Note #2a1A).
  559. *
  560. * (d) 'len_max' number of characters concatenated.
  561. *
  562. * (1) 'len_max' number of characters does NOT include the terminating NULL character
  563. * (see Note #2a2).
  564. *
  565. * (2) Null concatenations allowed (i.e. zero-length concatenations).
  566. * (A) No string concatenation performed; destination string returned
  567. * (see Note #2b1).
  568. *********************************************************************************************************
  569. */
  570. /*$PAGE*/
  571. CPU_CHAR *Str_Cat_N ( CPU_CHAR *pstr_dest,
  572. const CPU_CHAR *pstr_cat,
  573. CPU_SIZE_T len_max)
  574. {
  575. CPU_CHAR *pstr_cat_dest;
  576. const CPU_CHAR *pstr_cat_src;
  577. CPU_SIZE_T len_cat;
  578. /* Rtn NULL if str ptr(s) NULL (see Note #3a1). */
  579. if (pstr_dest == (CPU_CHAR *)0) {
  580. return ((CPU_CHAR *)0);
  581. }
  582. if (pstr_cat == (const CPU_CHAR *)0) {
  583. return ((CPU_CHAR *)0);
  584. }
  585. if (len_max < 1) { /* Rtn dest str if cat len = 0 (see Note #3d2A). */
  586. return ((CPU_CHAR *)pstr_dest);
  587. }
  588. pstr_cat_dest = pstr_dest;
  589. while (( pstr_cat_dest != (CPU_CHAR *) 0 ) && /* Adv to end of cur dest str until NULL ptr ... */
  590. (*pstr_cat_dest != (CPU_CHAR )'\0')) { /* ... or NULL char found.. */
  591. pstr_cat_dest++;
  592. }
  593. if (pstr_cat_dest == (CPU_CHAR *)0) { /* Rtn NULL if NULL ptr found (see Note #3b1). */
  594. return ((CPU_CHAR *)0);
  595. }
  596. pstr_cat_src = pstr_cat;
  597. len_cat = 0u;
  598. while (( pstr_cat_dest != ( CPU_CHAR *) 0 ) && /* Cat str until NULL ptr(s) [see Note #3b] ... */
  599. ( pstr_cat_src != (const CPU_CHAR *) 0 ) &&
  600. (*pstr_cat_src != ( CPU_CHAR )'\0') && /* ... or NULL char found (see Note #3c); ... */
  601. ( len_cat < ( CPU_SIZE_T)len_max)) { /* ... or max nbr chars cat'd (see Note #3d). */
  602. *pstr_cat_dest = *pstr_cat_src;
  603. pstr_cat_dest++;
  604. pstr_cat_src++;
  605. len_cat++;
  606. }
  607. /* Rtn NULL if NULL ptr(s) found (see Note #3b1). */
  608. if ((pstr_cat_dest == ( CPU_CHAR *)0) ||
  609. (pstr_cat_src == (const CPU_CHAR *)0)) {
  610. return ((CPU_CHAR *)0);
  611. }
  612. *pstr_cat_dest = (CPU_CHAR)'\0'; /* Append NULL char (see Note #2a2C). */
  613. return (pstr_dest); /* Rtn ptr to dest str (see Note #2b1). */
  614. }
  615. /*$PAGE*/
  616. /*
  617. *********************************************************************************************************
  618. * Str_Cmp()
  619. *
  620. * Description : Determine if two strings are identical.
  621. *
  622. * Argument(s) : p1_str Pointer to first string (see Note #1).
  623. *
  624. * p2_str Pointer to second string (see Note #1).
  625. *
  626. * Return(s) : 0, if strings are identical (see Notes #3a1A, #3a2A, & #3b).
  627. *
  628. * Negative value, if 'p1_str' is less than 'p2_str' (see Notes #3a1B1, #3a2B1, & #3c).
  629. *
  630. * Positive value, if 'p1_str' is greater than 'p2_str' (see Notes #3a1B2, #3a2B2, & #3c).
  631. *
  632. * See also Note #2b.
  633. *
  634. * Caller(s) : Application.
  635. *
  636. * Note(s) : (1) String buffers NOT modified.
  637. *
  638. * (2) (a) IEEE Std 1003.1, 2004 Edition, Section 'strcmp() : DESCRIPTION' states that "the
  639. * strcmp() function shall compare the string pointed to by 's1' ('p1_str') to the
  640. * string pointed to by 's2' ('p2_str)".
  641. *
  642. * (b) (1) IEEE Std 1003.1, 2004 Edition, Section 'strcmp() : RETURN VALUE' states that
  643. * "upon successful completion, strcmp() shall return an integer greater than,
  644. * equal to, or less than 0".
  645. *
  646. * (2) IEEE Std 1003.1, 2004 Edition, Section 'strcmp() : DESCRIPTION' adds that "the
  647. * sign of a non-zero return value shall be determined by the sign of the difference
  648. * between the values of the first pair of bytes ... that differ in the strings
  649. * being compared".
  650. *
  651. * (3) String comparison terminates when :
  652. *
  653. * (a) (1) (A) BOTH string pointer(s) are passed NULL pointers.
  654. * (1) NULL strings identical; 0 returned.
  655. *
  656. * (B) (1) 'p1_str' passed a NULL pointer.
  657. * (a) Return negative value of character pointed to by 'p2_str'.
  658. *
  659. * (2) 'p2_str' passed a NULL pointer.
  660. * (a) Return positive value of character pointed to by 'p1_str'.
  661. *
  662. * (2) (A) BOTH strings point to NULL.
  663. * (1) Strings overlap with NULL address.
  664. * (2) Strings identical up to but NOT beyond or including the NULL address;
  665. * 0 returned.
  666. *
  667. * (B) (1) 'p1_str_cmp_next' points to NULL.
  668. * (a) 'p1_str' overlaps with NULL address.
  669. * (b) Strings compared up to but NOT beyond or including the NULL address.
  670. * (c) Return negative value of character pointed to by 'p2_str_cmp_next'.
  671. *
  672. * (2) 'p2_str_cmp_next' points to NULL.
  673. * (a) 'p2_str' overlaps with NULL address.
  674. * (b) Strings compared up to but NOT beyond or including the NULL address.
  675. * (c) Return positive value of character pointed to by 'p1_str_cmp_next'.
  676. *
  677. * (b) Terminating NULL character found in both strings.
  678. * (1) Strings identical; 0 returned.
  679. * (2) Only one NULL character test required in conditional since previous condition
  680. * tested character equality.
  681. *
  682. * (c) Non-matching characters found.
  683. * (1) Return signed-integer difference of the character pointed to by 'p2_str'
  684. * from the character pointed to by 'p1_str'.
  685. *
  686. * (4) Since 16-bit signed arithmetic is performed to calculate a non-identical comparison
  687. * return value, 'CPU_CHAR' native data type size MUST be 8-bit.
  688. *********************************************************************************************************
  689. */
  690. CPU_INT16S Str_Cmp (const CPU_CHAR *p1_str,
  691. const CPU_CHAR *p2_str)
  692. {
  693. CPU_INT16S cmp_val;
  694. cmp_val = Str_Cmp_N(p1_str,
  695. p2_str,
  696. DEF_INT_CPU_U_MAX_VAL);
  697. return (cmp_val);
  698. }
  699. /*$PAGE*/
  700. /*
  701. *********************************************************************************************************
  702. * Str_Cmp_N()
  703. *
  704. * Description : Determine if two strings are identical for up to a maximum number of characters.
  705. *
  706. * Argument(s) : p1_str Pointer to first string (see Note #1).
  707. *
  708. * p2_str Pointer to second string (see Note #1).
  709. *
  710. * len_max Maximum number of characters to compare (see Note #3d).
  711. *
  712. * Return(s) : 0, if strings are identical (see Notes #3a1A, #3a2A, #3b, & #3d).
  713. *
  714. * Negative value, if 'p1_str' is less than 'p2_str' (see Notes #3a1B1, #3a2B1, & #3c).
  715. *
  716. * Positive value, if 'p1_str' is greater than 'p2_str' (see Notes #3a1B2, #3a2B2, & #3c).
  717. *
  718. * See also Note #2b.
  719. *
  720. * Caller(s) : Application.
  721. *
  722. * Note(s) : (1) String buffers NOT modified.
  723. *
  724. * (2) (a) IEEE Std 1003.1, 2004 Edition, Section 'strncmp() : DESCRIPTION' states that :
  725. *
  726. * (1) "The strncmp() function shall compare ... the array pointed to by 's1' ('p1_str')
  727. * to the array pointed to by 's2' ('p2_str)" ...
  728. * (2) but "not more than 'n' ('len_max') bytes" of either array.
  729. *
  730. * (b) (1) IEEE Std 1003.1, 2004 Edition, Section 'strncmp() : RETURN VALUE' states that
  731. * "upon successful completion, strncmp() shall return an integer greater than,
  732. * equal to, or less than 0".
  733. *
  734. * (2) IEEE Std 1003.1, 2004 Edition, Section 'strncmp() : DESCRIPTION' adds that
  735. * "the sign of a non-zero return value is determined by the sign of the difference
  736. * between the values of the first pair of bytes ... that differ in the strings
  737. * being compared".
  738. *
  739. * (3) String comparison terminates when :
  740. *
  741. * (a) (1) (A) BOTH string pointer(s) are passed NULL pointers.
  742. * (1) NULL strings identical; 0 returned.
  743. *
  744. * (B) (1) 'p1_str' passed a NULL pointer.
  745. * (a) Return negative value of character pointed to by 'p2_str'.
  746. *
  747. * (2) 'p2_str' passed a NULL pointer.
  748. * (a) Return positive value of character pointed to by 'p1_str'.
  749. *
  750. * (2) (A) BOTH strings point to NULL.
  751. * (1) Strings overlap with NULL address.
  752. * (2) Strings identical up to but NOT beyond or including the NULL address;
  753. * 0 returned.
  754. *
  755. * (B) (1) 'p1_str_cmp_next' points to NULL.
  756. * (a) 'p1_str' overlaps with NULL address.
  757. * (b) Strings compared up to but NOT beyond or including the NULL address.
  758. * (c) Return negative value of character pointed to by 'p2_str_cmp_next'.
  759. *
  760. * (2) 'p2_str_cmp_next' points to NULL.
  761. * (a) 'p2_str' overlaps with NULL address.
  762. * (b) Strings compared up to but NOT beyond or including the NULL address.
  763. * (c) Return positive value of character pointed to by 'p1_str_cmp_next'.
  764. *
  765. * (b) Terminating NULL character found in both strings.
  766. * (1) Strings identical; 0 returned.
  767. * (2) Only one NULL character test required in conditional since previous condition
  768. * tested character equality.
  769. *
  770. * (c) Non-matching characters found.
  771. * (1) Return signed-integer difference of the character pointed to by 'p2_str'
  772. * from the character pointed to by 'p1_str'.
  773. *
  774. * (d) (1) 'len_max' passed a zero length.
  775. * (A) Zero-length strings identical; 0 returned.
  776. *
  777. * (2) First 'len_max' number of characters identical.
  778. * (A) Strings identical; 0 returned.
  779. *
  780. * See also Note #2a2.
  781. *
  782. * (4) Since 16-bit signed arithmetic is performed to calculate a non-identical comparison
  783. * return value, 'CPU_CHAR' native data type size MUST be 8-bit.
  784. *********************************************************************************************************
  785. */
  786. /*$PAGE*/
  787. CPU_INT16S Str_Cmp_N (const CPU_CHAR *p1_str,
  788. const CPU_CHAR *p2_str,
  789. CPU_SIZE_T len_max)
  790. {
  791. const CPU_CHAR *p1_str_cmp;
  792. const CPU_CHAR *p2_str_cmp;
  793. const CPU_CHAR *p1_str_cmp_next;
  794. const CPU_CHAR *p2_str_cmp_next;
  795. CPU_INT16S cmp_val;
  796. CPU_SIZE_T cmp_len;
  797. if (len_max < 1) { /* If cmp len = 0, rtn 0 (see Note #3d1A). */
  798. return (0);
  799. }
  800. if (p1_str == (const CPU_CHAR *)0) {
  801. if (p2_str == (const CPU_CHAR *)0) {
  802. return (0); /* If BOTH str ptrs NULL, rtn 0 (see Note #3a1A). */
  803. }
  804. cmp_val = (CPU_INT16S)0 - (CPU_INT16S)(*p2_str);
  805. return (cmp_val); /* If p1_str NULL, rtn neg p2_str val (see Note #3a1B1).*/
  806. }
  807. if (p2_str == (const CPU_CHAR *)0) {
  808. cmp_val = (CPU_INT16S)(*p1_str);
  809. return (cmp_val); /* If p2_str NULL, rtn pos p1_str val (see Note #3a1B2).*/
  810. }
  811. p1_str_cmp = p1_str;
  812. p2_str_cmp = p2_str;
  813. p1_str_cmp_next = p1_str_cmp;
  814. p2_str_cmp_next = p2_str_cmp;
  815. p1_str_cmp_next++;
  816. p2_str_cmp_next++;
  817. cmp_len = 0u;
  818. while ((*p1_str_cmp == *p2_str_cmp) && /* Cmp strs until non-matching chars (see Note #3c) ... */
  819. (*p1_str_cmp != ( CPU_CHAR )'\0') && /* ... or NULL chars (see Note #3b) ... */
  820. ( p1_str_cmp_next != (const CPU_CHAR *) 0 ) && /* ... or NULL ptr(s) found (see Note #3a2); */
  821. ( p2_str_cmp_next != (const CPU_CHAR *) 0 ) &&
  822. ( cmp_len < ( CPU_SIZE_T)len_max)) { /* ... or max nbr chars cmp'd (see Note #3d2). */
  823. p1_str_cmp++;
  824. p2_str_cmp++;
  825. p1_str_cmp_next++;
  826. p2_str_cmp_next++;
  827. cmp_len++;
  828. }
  829. if (cmp_len == len_max) { /* If strs identical for max len nbr of chars, ... */
  830. return (0); /* ... rtn 0 (see Note #3d2A). */
  831. }
  832. if (*p1_str_cmp != *p2_str_cmp) { /* If strs NOT identical, ... */
  833. /* ... calc & rtn char diff (see Note #3c1). */
  834. cmp_val = (CPU_INT16S)(*p1_str_cmp) - (CPU_INT16S)(*p2_str_cmp);
  835. } else if (*p1_str_cmp == (CPU_CHAR)'\0') { /* If NULL char(s) found, ... */
  836. cmp_val = (CPU_INT16S)0; /* ... strs identical; rtn 0 (see Note #3b). */
  837. } else {
  838. if (p1_str_cmp_next == (const CPU_CHAR *)0) {
  839. if (p2_str_cmp_next == (const CPU_CHAR *)0) { /* If BOTH next str ptrs NULL, ... */
  840. cmp_val = (CPU_INT16S)0; /* ... rtn 0 (see Note #3a2A). */
  841. } else { /* If p1_str_cmp_next NULL, ... */
  842. /* ... rtn neg p2_str_cmp_next val (see Note #3a2B1). */
  843. cmp_val = (CPU_INT16S)0 - (CPU_INT16S)(*p2_str_cmp_next);
  844. }
  845. } else { /* If p2_str_cmp_next NULL, ... */
  846. cmp_val = (CPU_INT16S)(*p1_str_cmp_next); /* ... rtn pos p1_str_cmp_next val (see Note #3a2B2). */
  847. }
  848. }
  849. return (cmp_val);
  850. }
  851. /*$PAGE*/
  852. /*
  853. *********************************************************************************************************
  854. * Str_CmpIgnoreCase()
  855. *
  856. * Description : Determine if two strings are identical, ignoring case.
  857. *
  858. * Argument(s) : p1_str Pointer to first string (see Note #1).
  859. *
  860. * p2_str Pointer to second string (see Note #1).
  861. *
  862. * Return(s) : 0, if strings are identical (see Notes #3a1A, #3a2A, & #3b).
  863. *
  864. * Negative value, if 'p1_str' is less than 'p2_str' (see Notes #3a1B1, #3a2B1, & #3c).
  865. *
  866. * Positive value, if 'p1_str' is greater than 'p2_str' (see Notes #3a1B2, #3a2B2, & #3c).
  867. *
  868. * See also Note #2b.
  869. *
  870. * Caller(s) : Application.
  871. *
  872. * Note(s) : (1) String buffers NOT modified.
  873. *
  874. * (2) (a) IEEE Std 1003.1, 2004 Edition, Section 'strcasecmp() : DESCRIPTION' states that :
  875. *
  876. * (1) (A) "The strcasecmp() function shall compare ... the string pointed to by 's1'
  877. * ('p1_str') to the string pointed to by 's2' ('p2_str')" ...
  878. * (B) "ignoring differences in case".
  879. *
  880. * (2) "strcasecmp() ... shall behave as if the strings had been converted to lowercase
  881. * and then a byte comparison performed."
  882. *
  883. * (b) (1) IEEE Std 1003.1, 2004 Edition, Section 'strcasecmp() : RETURN VALUE' states that
  884. * "upon successful completion, strcasecmp() shall return an integer greater than,
  885. * equal to, or less than 0".
  886. *
  887. * (2) IEEE Std 1003.1, 2004 Edition, Section 'strcmp() : DESCRIPTION' adds that "the
  888. * sign of a non-zero return value shall be determined by the sign of the difference
  889. * between the values of the first pair of bytes ... that differ in the strings
  890. * being compared".
  891. *
  892. * (3) String comparison terminates when :
  893. *
  894. * (a) (1) (A) BOTH string pointer(s) are passed NULL pointers.
  895. * (1) NULL strings identical; 0 returned.
  896. *
  897. * (B) (1) 'p1_str' passed a NULL pointer.
  898. * (a) Return negative value of character pointed to by 'p2_str', converted
  899. * to lower case (see Note #2a2).
  900. *
  901. * (2) 'p2_str' passed a NULL pointer.
  902. * (a) Return positive value of character pointed to by 'p1_str', converted
  903. * to lower case (see Note #2a2).
  904. *
  905. * (2) (A) BOTH strings point to NULL.
  906. * (1) Strings overlap with NULL address.
  907. * (2) Strings identical up to but NOT beyond or including the NULL address;
  908. * 0 returned.
  909. *
  910. * (B) (1) 'p1_str_cmp_next' points to NULL.
  911. * (a) 'p1_str' overlaps with NULL address.
  912. * (b) Strings compared up to but NOT beyond or including the NULL address.
  913. * (c) Return negative value of character pointed to by 'p2_str_cmp_next',
  914. * converted to lower case (see Note #2a2).
  915. *
  916. * (2) 'p2_str_cmp_next' points to NULL.
  917. * (a) 'p2_str' overlaps with NULL address.
  918. * (b) Strings compared up to but NOT beyond or including the NULL address.
  919. * (c) Return positive value of character pointed to by 'p1_str_cmp_next',
  920. * converted to lower case (see Note #2a2).
  921. *
  922. * (b) Terminating NULL character found in both strings.
  923. * (1) Strings identical; 0 returned.
  924. * (2) Only one NULL character test required in conditional since previous condition
  925. * tested character equality.
  926. *
  927. * (c) Non-matching characters found.
  928. * (1) Return signed-integer difference of the character pointed to by 'p2_str',
  929. * converted to lower case, from the character pointed to by 'p1_str', converted
  930. * to lower case.
  931. *
  932. * (4) Since 16-bit signed arithmetic is performed to calculate a non-identical comparison
  933. * return value, 'CPU_CHAR' native data type size MUST be 8-bit.
  934. *********************************************************************************************************
  935. */
  936. /*$PAGE*/
  937. CPU_INT16S Str_CmpIgnoreCase (const CPU_CHAR *p1_str,
  938. const CPU_CHAR *p2_str)
  939. {
  940. CPU_INT16S cmp_val;
  941. cmp_val = Str_CmpIgnoreCase_N(p1_str,
  942. p2_str,
  943. DEF_INT_CPU_U_MAX_VAL);
  944. return (cmp_val);
  945. }
  946. /*$PAGE*/
  947. /*
  948. *********************************************************************************************************
  949. * Str_CmpIgnoreCase_N()
  950. *
  951. * Description : Determine if two strings are identical for up to a maximum number of characters,
  952. * ignoring case.
  953. *
  954. * Argument(s) : p1_str Pointer to first string (see Note #1).
  955. *
  956. * p2_str Pointer to second string (see Note #1).
  957. *
  958. * len_max Maximum number of characters to compare (see Note #3d).
  959. *
  960. * Return(s) : 0, if strings are identical (see Notes #3a1A, #3a2A, #3b, & #3d).
  961. *
  962. * Negative value, if 'p1_str' is less than 'p2_str' (see Notes #3a1B1, #3a2B1, & #3c).
  963. *
  964. * Positive value, if 'p1_str' is greater than 'p2_str' (see Notes #3a1B2, #3a2B2, & #3c).
  965. *
  966. * See also Note #2b.
  967. *
  968. * Caller(s) : Application.
  969. *
  970. * Note(s) : (1) String buffers NOT modified.
  971. *
  972. * (2) (a) IEEE Std 1003.1, 2004 Edition, Section 'strncasecmp() : DESCRIPTION' states that :
  973. *
  974. * (1) (A) "The strncasecmp() function shall compare ... the string pointed to by 's1'
  975. * ('p1_str') to the string pointed to by 's2' ('p2_str')" ...
  976. * (B) "ignoring differences in case" ...
  977. * (C) but "not more than 'n' ('len_max') bytes" of either string.
  978. *
  979. * (2) "strncasecmp() shall behave as if the strings had been converted to lowercase
  980. * and then a byte comparison performed."
  981. *
  982. * (b) (1) IEEE Std 1003.1, 2004 Edition, Section 'strncasecmp() : RETURN VALUE' states that
  983. * "upon successful completion, strncasecmp() shall return an integer greater than,
  984. * equal to, or less than 0".
  985. *
  986. * (2) IEEE Std 1003.1, 2004 Edition, Section 'strcmp() : DESCRIPTION' adds that "the
  987. * sign of a non-zero return value shall be determined by the sign of the difference
  988. * between the values of the first pair of bytes ... that differ in the strings
  989. * being compared".
  990. *
  991. * (3) String comparison terminates when :
  992. *
  993. * (a) (1) (A) BOTH string pointer(s) are passed NULL pointers.
  994. * (1) NULL strings identical; 0 returned.
  995. *
  996. * (B) (1) 'p1_str' passed a NULL pointer.
  997. * (a) Return negative value of character pointed to by 'p2_str', converted
  998. * to lower case (see Note #2a2).
  999. *
  1000. * (2) 'p2_str' passed a NULL pointer.
  1001. * (a) Return positive value of character pointed to by 'p1_str', converted
  1002. * to lower case (see Note #2a2).
  1003. *
  1004. * (2) (A) BOTH strings point to NULL.
  1005. * (1) Strings overlap with NULL address.
  1006. * (2) Strings identical up to but NOT beyond or including the NULL address;
  1007. * 0 returned.
  1008. *
  1009. * (B) (1) 'p1_str_cmp_next' points to NULL.
  1010. * (a) 'p1_str' overlaps with NULL address.
  1011. * (b) Strings compared up to but NOT beyond or including the NULL address.
  1012. * (c) Return negative value of character pointed to by 'p2_str_cmp_next',
  1013. * converted to lower case (see Note #2a2).
  1014. *
  1015. * (2) 'p2_str_cmp_next' points to NULL.
  1016. * (a) 'p2_str' overlaps with NULL address.
  1017. * (b) Strings compared up to but NOT beyond or including the NULL address.
  1018. * (c) Return positive value of character pointed to by 'p1_str_cmp_next',
  1019. * converted to lower case (see Note #2a2).
  1020. *
  1021. * (b) Terminating NULL character found in both strings.
  1022. * (1) Strings identical; 0 returned.
  1023. * (2) Only one NULL character test required in conditional since previous condition
  1024. * tested character equality.
  1025. *
  1026. * (c) Non-matching characters found.
  1027. * (1) Return signed-integer difference of the character pointed to by 'p2_str',
  1028. * converted to lower case, from the character pointed to by 'p1_str', converted
  1029. * to lower case.
  1030. *
  1031. * (d) (1) 'len_max' passed a zero length.
  1032. * (A) Zero-length strings identical; 0 returned.
  1033. *
  1034. * (2) First 'len_max' number of characters identical.
  1035. * (A) Strings identical; 0 returned.
  1036. *
  1037. * See also Note #2a1C.
  1038. *$PAGE*
  1039. * (4) Since 16-bit signed arithmetic is performed to calculate a non-identical comparison
  1040. * return value, 'CPU_CHAR' native data type size MUST be 8-bit.
  1041. *********************************************************************************************************
  1042. */
  1043. CPU_INT16S Str_CmpIgnoreCase_N (const CPU_CHAR *p1_str,
  1044. const CPU_CHAR *p2_str,
  1045. CPU_SIZE_T len_max)
  1046. {
  1047. const CPU_CHAR *p1_str_cmp;
  1048. const CPU_CHAR *p2_str_cmp;
  1049. const CPU_CHAR *p1_str_cmp_next;
  1050. const CPU_CHAR *p2_str_cmp_next;
  1051. CPU_CHAR char_1;
  1052. CPU_CHAR char_2;
  1053. CPU_INT16S cmp_val;
  1054. CPU_SIZE_T cmp_len;
  1055. if (len_max < 1) { /* If cmp len = 0, rtn 0 (see Note #3d1A). */
  1056. return (0);
  1057. }
  1058. if (p1_str == (const CPU_CHAR *)0) {
  1059. if (p2_str == (const CPU_CHAR *)0) {
  1060. return (0); /* If BOTH str ptrs NULL, rtn 0 (see Note #3a1A). */
  1061. }
  1062. char_2 = ASCII_ToLower(*p2_str);
  1063. cmp_val = (CPU_INT16S)0 - (CPU_INT16S)char_2;
  1064. return (cmp_val); /* If p1_str NULL, rtn neg p2_str val (see Note #3a1B1).*/
  1065. }
  1066. if (p2_str == (const CPU_CHAR *)0) {
  1067. char_1 = ASCII_ToLower(*p1_str);
  1068. cmp_val = (CPU_INT16S)char_1;
  1069. return (cmp_val); /* If p2_str NULL, rtn pos p1_str val (see Note #3a1B2).*/
  1070. }
  1071. p1_str_cmp = p1_str;
  1072. p2_str_cmp = p2_str;
  1073. p1_str_cmp_next = p1_str_cmp;
  1074. p2_str_cmp_next = p2_str_cmp;
  1075. p1_str_cmp_next++;
  1076. p2_str_cmp_next++;
  1077. char_1 = ASCII_ToLower(*p1_str_cmp);
  1078. char_2 = ASCII_ToLower(*p2_str_cmp);
  1079. cmp_len = 0u;
  1080. while (( char_1 == char_2) && /* Cmp strs until non-matching chars (see Note #3c) ... */
  1081. (*p1_str_cmp != ( CPU_CHAR )'\0') && /* ... or NULL chars (see Note #3b) ... */
  1082. ( p1_str_cmp_next != (const CPU_CHAR *) 0 ) && /* ... or NULL ptr(s) found (see Note #3a2); */
  1083. ( p2_str_cmp_next != (const CPU_CHAR *) 0 ) &&
  1084. ( cmp_len < ( CPU_SIZE_T)len_max)) { /* ... or max nbr chars cmp'd (see Note #3d2). */
  1085. p1_str_cmp++;
  1086. p2_str_cmp++;
  1087. p1_str_cmp_next++;
  1088. p2_str_cmp_next++;
  1089. cmp_len++;
  1090. char_1 = ASCII_ToLower(*p1_str_cmp);
  1091. char_2 = ASCII_ToLower(*p2_str_cmp);
  1092. }
  1093. if (cmp_len == len_max) { /* If strs identical for max len nbr of chars, ... */
  1094. return (0); /* ... rtn 0 (see Note #3d2A). */
  1095. }
  1096. if (char_1 != char_2) { /* If strs NOT identical, ... */
  1097. cmp_val = (CPU_INT16S)char_1 - (CPU_INT16S)char_2; /* ... calc & rtn char diff (see Note #3c1). */
  1098. } else if (char_1 == (CPU_CHAR)'\0') { /* If NULL char(s) found, ... */
  1099. cmp_val = (CPU_INT16S)0; /* ... strs identical; rtn 0 (see Note #3b). */
  1100. } else {
  1101. if (p1_str_cmp_next == (const CPU_CHAR *)0) {
  1102. if (p2_str_cmp_next == (const CPU_CHAR *)0) { /* If BOTH next str ptrs NULL, ... */
  1103. cmp_val = (CPU_INT16S)0; /* ... rtn 0 (see Note #3a2A). */
  1104. } else { /* If p1_str_cmp_next NULL, ... */
  1105. char_2 = ASCII_ToLower(*p2_str_cmp_next);
  1106. cmp_val = (CPU_INT16S)0 - (CPU_INT16S)char_2; /* ... rtn neg p2_str_cmp_next val (see Note #3a2B1). */
  1107. }
  1108. } else { /* If p2_str_cmp_next NULL, ... */
  1109. char_1 = ASCII_ToLower(*p1_str_cmp_next);
  1110. cmp_val = (CPU_INT16S)char_1; /* ... rtn pos p1_str_cmp_next val (see Note #3a2B2). */
  1111. }
  1112. }
  1113. return (cmp_val);
  1114. }
  1115. /*$PAGE*/
  1116. /*
  1117. *********************************************************************************************************
  1118. * Str_Char()
  1119. *
  1120. * Description : Search string for first occurrence of specific character.
  1121. *
  1122. * Argument(s) : pstr Pointer to string (see Note #1).
  1123. *
  1124. * srch_char Search character.
  1125. *
  1126. * Return(s) : Pointer to first occurrence of search character in string, if any (see Note #2b1).
  1127. *
  1128. * Pointer to NULL, otherwise (see Note #2b2).
  1129. *
  1130. * Caller(s) : Application.
  1131. *
  1132. * Note(s) : (1) String buffer NOT modified.
  1133. *
  1134. * (2) (a) IEEE Std 1003.1, 2004 Edition, Section 'strchr() : DESCRIPTION' states that :
  1135. *
  1136. * (1) "The strchr() function shall locate the first occurrence of 'c' ('srch_char')
  1137. * ... in the string pointed to by 's' ('pstr')."
  1138. * (2) "The terminating null byte is considered to be part of the string."
  1139. *
  1140. * (b) IEEE Std 1003.1, 2004 Edition, Section 'strchr() : RETURN VALUE' states that
  1141. * "upon completion, strchr() shall return" :
  1142. *
  1143. * (1) "a pointer to the byte," ...
  1144. * (2) "or a null pointer if the byte was not found."
  1145. * (A) #### Although NO strchr() specification states to return NULL for
  1146. * any other reason(s), NULL is also returned for any error(s).
  1147. *
  1148. * (3) String search terminates when :
  1149. *
  1150. * (a) String pointer passed a NULL pointer.
  1151. * (1) No string search performed; NULL pointer returned.
  1152. *
  1153. * (b) String pointer points to NULL.
  1154. * (1) String overlaps with NULL address; NULL pointer returned.
  1155. *
  1156. * (c) String's terminating NULL character found.
  1157. * (1) Search character NOT found in search string; NULL pointer returned
  1158. * (see Note #2b2).
  1159. * (2) Applicable even if search character is the terminating NULL character
  1160. * (see Note #2a2).
  1161. *
  1162. * (d) Search character found.
  1163. * (1) Return pointer to first occurrence of search character in search string
  1164. * (see Note #2a1).
  1165. *********************************************************************************************************
  1166. */
  1167. CPU_CHAR *Str_Char (const CPU_CHAR *pstr,
  1168. CPU_CHAR srch_char)
  1169. {
  1170. CPU_CHAR *pstr_rtn;
  1171. pstr_rtn = Str_Char_N(pstr,
  1172. DEF_INT_CPU_U_MAX_VAL,
  1173. srch_char);
  1174. return (pstr_rtn);
  1175. }
  1176. /*$PAGE*/
  1177. /*
  1178. *********************************************************************************************************
  1179. * Str_Char_N()
  1180. *
  1181. * Description : Search string for first occurrence of specific character, up to a maximum number
  1182. * of characters.
  1183. *
  1184. * Argument(s) : pstr Pointer to string (see Note #1).
  1185. *
  1186. * len_max Maximum number of characters to search (see Notes #2c & #3e).
  1187. *
  1188. * srch_char Search character.
  1189. *
  1190. * Return(s) : Pointer to first occurrence of search character in string, if any (see Note #2b1).
  1191. *
  1192. * Pointer to NULL, otherwise (see Note #2b2).
  1193. *
  1194. * Caller(s) : Application.
  1195. *
  1196. * Note(s) : (1) String buffer NOT modified.
  1197. *
  1198. * (2) (a) IEEE Std 1003.1, 2004 Edition, Section 'strchr() : DESCRIPTION' states that :
  1199. *
  1200. * (1) "The strchr() function shall locate the first occurrence of 'c' ('srch_char')
  1201. * ... in the string pointed to by 's' ('pstr')."
  1202. * (2) "The terminating null byte is considered to be part of the string."
  1203. *
  1204. * (b) IEEE Std 1003.1, 2004 Edition, Section 'strchr() : RETURN VALUE' states that
  1205. * "upon completion, strchr() shall return" :
  1206. *
  1207. * (1) "a pointer to the byte," ...
  1208. * (2) "or a null pointer if the byte was not found."
  1209. * (A) #### Although NO strchr() specification states to return NULL for
  1210. * any other reason(s), NULL is also returned for any error(s).
  1211. *
  1212. * (c) Ideally, the 'len_max' argument would be the last argument in this function's
  1213. * argument list for consistency with all other custom string library functions.
  1214. * However, the 'len_max' argument is sequentially ordered as the second argument
  1215. * to comply with most standard library's strnchr() argument list.
  1216. *
  1217. * (3) String search terminates when :
  1218. *
  1219. * (a) String pointer passed a NULL pointer.
  1220. * (1) No string search performed; NULL pointer returned.
  1221. *
  1222. * (b) String pointer points to NULL.
  1223. * (1) String overlaps with NULL address; NULL pointer returned.
  1224. *
  1225. * (c) String's terminating NULL character found.
  1226. * (1) Search character NOT found in search string; NULL pointer returned
  1227. * (see Note #2b2).
  1228. * (2) Applicable even if search character is the terminating NULL character
  1229. * (see Note #2a2).
  1230. *
  1231. * (d) Search character found.
  1232. * (1) Return pointer to first occurrence of search character in search string
  1233. * (see Note #2a1).
  1234. *
  1235. * (e) 'len_max' number of characters searched.
  1236. * (1) Search character NOT found in search string within first 'len_max' number
  1237. * of characters; NULL pointer returned.
  1238. * (2) 'len_max' number of characters MAY include terminating NULL character
  1239. * (see Note #2a2).
  1240. *********************************************************************************************************
  1241. */
  1242. /*$PAGE*/
  1243. CPU_CHAR *Str_Char_N (const CPU_CHAR *pstr,
  1244. CPU_SIZE_T len_max,
  1245. CPU_CHAR srch_char)
  1246. {
  1247. const CPU_CHAR *pstr_char;
  1248. CPU_SIZE_T len_srch;
  1249. if (pstr == (const CPU_CHAR *)0) { /* Rtn NULL if srch str ptr NULL (see Note #3a1). */
  1250. return ((CPU_CHAR *)0);
  1251. }
  1252. if (len_max < 1) { /* Rtn NULL if srch len = 0 (see Note #3e1). */
  1253. return ((CPU_CHAR *)0);
  1254. }
  1255. pstr_char = pstr;
  1256. len_srch = 0u;
  1257. while (( pstr_char != (const CPU_CHAR *) 0 ) && /* Srch str until NULL ptr [see Note #3b] ... */
  1258. (*pstr_char != ( CPU_CHAR )'\0') && /* ... or NULL char (see Note #3c) ... */
  1259. (*pstr_char != ( CPU_CHAR )srch_char) && /* ... or srch char found (see Note #3d); ... */
  1260. ( len_srch < ( CPU_SIZE_T)len_max)) { /* ... or max nbr chars srch'd (see Note #3e). */
  1261. pstr_char++;
  1262. len_srch++;
  1263. }
  1264. if (pstr_char == (const CPU_CHAR *)0) { /* Rtn NULL if NULL ptr found (see Note #3b1). */
  1265. return ((CPU_CHAR *)0);
  1266. }
  1267. if (len_srch >= len_max) { /* Rtn NULL if srch char NOT found ... */
  1268. return ((CPU_CHAR *)0); /* ... within max nbr of chars (see Note #3e1). */
  1269. }
  1270. if (*pstr_char != srch_char) { /* Rtn NULL if srch char NOT found (see Note #3c1). */
  1271. return ((CPU_CHAR *)0);
  1272. }
  1273. return ((CPU_CHAR *)pstr_char); /* Else rtn ptr to found srch char (see Note #3d1). */
  1274. }
  1275. /*$PAGE*/
  1276. /*
  1277. *********************************************************************************************************
  1278. * Str_Char_Last()
  1279. *
  1280. * Description : Search string for last occurrence of specific character.
  1281. *
  1282. * Argument(s) : pstr Pointer to string (see Note #1).
  1283. *
  1284. * srch_char Search character.
  1285. *
  1286. * Return(s) : Pointer to last occurrence of search character in string, if any (see Note #2b1).
  1287. *
  1288. * Pointer to NULL, otherwise (see Note #2b2).
  1289. *
  1290. * Caller(s) : Application.
  1291. *
  1292. * Note(s) : (1) String buffer NOT modified.
  1293. *
  1294. * (2) (a) IEEE Std 1003.1, 2004 Edition, Section 'strrchr() : DESCRIPTION' states that :
  1295. *
  1296. * (1) "The strrchr() function shall locate the last occurrence of 'c' ('srch_char')
  1297. * ... in the string pointed to by 's' ('pstr')."
  1298. * (2) "The terminating null byte is considered to be part of the string."
  1299. *
  1300. * (b) IEEE Std 1003.1, 2004 Edition, Section 'strrchr() : RETURN VALUE' states that
  1301. * "upon successful completion, strrchr() shall return" :
  1302. *
  1303. * (1) "a pointer to the byte" ...
  1304. * (2) "or a null pointer if 'c' ('srch_char') does not occur in the string."
  1305. * (A) #### Although NO strrchr() specification states to return NULL for
  1306. * any other reason(s), NULL is also returned for any error(s).
  1307. *
  1308. * (3) String search terminates when :
  1309. *
  1310. * (a) String pointer passed a NULL pointer.
  1311. * (1) No string search performed; NULL pointer returned.
  1312. *
  1313. * (b) String pointer points to NULL.
  1314. * (1) String overlaps with NULL address; NULL pointer returned.
  1315. *
  1316. * (c) String searched from end to beginning.
  1317. * (1) Search character NOT found in search string; NULL pointer returned.
  1318. * (2) Applicable even if search character is the terminating NULL character
  1319. * (see Note #2a2).
  1320. *
  1321. * (d) Search character found.
  1322. * (1) Return pointer to last occurrence of search character in search string
  1323. * (see Note #2a1).
  1324. *********************************************************************************************************
  1325. */
  1326. CPU_CHAR *Str_Char_Last (const CPU_CHAR *pstr,
  1327. CPU_CHAR srch_char)
  1328. {
  1329. CPU_CHAR *pstr_rtn;
  1330. pstr_rtn = Str_Char_Last_N(pstr,
  1331. DEF_INT_CPU_U_MAX_VAL,
  1332. srch_char);
  1333. return (pstr_rtn);
  1334. }
  1335. /*$PAGE*/
  1336. /*
  1337. *********************************************************************************************************
  1338. * Str_Char_Last_N()
  1339. *
  1340. * Description : Search string for last occurrence of specific character, up to a maximum number
  1341. * of characters.
  1342. *
  1343. * Argument(s) : pstr Pointer to string (see Note #1).
  1344. *
  1345. * len_max Maximum number of characters to search (see Notes #2c & #3e).
  1346. *
  1347. * srch_char Search character.
  1348. *
  1349. * Return(s) : Pointer to last occurrence of search character in string, if any (see Note #2b1).
  1350. *
  1351. * Pointer to NULL, otherwise (see Note #2b2).
  1352. *
  1353. * Caller(s) : Application.
  1354. *
  1355. * Note(s) : (1) String buffer NOT modified.
  1356. *
  1357. * (2) (a) IEEE Std 1003.1, 2004 Edition, Section 'strrchr() : DESCRIPTION' states that :
  1358. *
  1359. * (1) "The strrchr() function shall locate the last occurrence of 'c' ('srch_char')
  1360. * ... in the string pointed to by 's' ('pstr')."
  1361. * (2) "The terminating null byte is considered to be part of the string."
  1362. *
  1363. * (b) IEEE Std 1003.1, 2004 Edition, Section 'strrchr() : RETURN VALUE' states that
  1364. * "upon successful completion, strrchr() shall return" :
  1365. *
  1366. * (1) "a pointer to the byte" ...
  1367. * (2) "or a null pointer if 'c' ('srch_char') does not occur in the string."
  1368. * (A) #### Although NO strrchr() specification states to return NULL for
  1369. * any other reason(s), NULL is also returned for any error(s).
  1370. *
  1371. * (c) Ideally, the 'len_max' argument would be the last argument in this function's
  1372. * argument list for consistency with all other custom string library functions.
  1373. * However, the 'len_max' argument is sequentially ordered as the second argument
  1374. * to comply with most standard library's strnrchr() argument list.
  1375. *
  1376. * See also 'Str_Char_N() Note #2c'.
  1377. *
  1378. * (3) String search terminates when :
  1379. *
  1380. * (a) String pointer passed a NULL pointer.
  1381. * (1) No string search performed; NULL pointer returned.
  1382. *
  1383. * (b) String pointer points to NULL.
  1384. * (1) String overlaps with NULL address; NULL pointer returned.
  1385. *
  1386. * (c) String searched from end to beginning.
  1387. * (1) Search character NOT found in search string; NULL pointer returned
  1388. * (see Note #2b2).
  1389. * (2) Applicable even if search character is the terminating NULL character
  1390. * (see Note #2a2).
  1391. *
  1392. * (d) Search character found.
  1393. * (1) Return pointer to last occurrence of search character in search string
  1394. * (see Note #2a1).
  1395. *
  1396. * (e) 'len_max' number of characters searched.
  1397. * (1) Search character NOT found in search string within last 'len_max' number
  1398. * of characters; NULL pointer returned.
  1399. * (2) 'len_max' number of characters MAY include terminating NULL character
  1400. * (see Note #2a2).
  1401. *********************************************************************************************************
  1402. */
  1403. /*$PAGE*/
  1404. CPU_CHAR *Str_Char_Last_N (const CPU_CHAR *pstr,
  1405. CPU_SIZE_T len_max,
  1406. CPU_CHAR srch_char)
  1407. {
  1408. const CPU_CHAR *pstr_char;
  1409. CPU_SIZE_T str_len_max;
  1410. CPU_SIZE_T str_len;
  1411. if (pstr == (const CPU_CHAR *)0) { /* Rtn NULL if srch str ptr NULL (see Note #3a1). */
  1412. return ((CPU_CHAR *)0);
  1413. }
  1414. if (len_max < 1) { /* Rtn NULL if srch len = 0 (see Note #3e1). */
  1415. return ((CPU_CHAR *)0);
  1416. }
  1417. pstr_char = pstr;
  1418. str_len_max = len_max - sizeof((CPU_CHAR)'\0'); /* Str len adj'd for NULL char len. */
  1419. str_len = Str_Len_N(pstr_char, str_len_max);
  1420. pstr_char += str_len;
  1421. if (pstr_char == (const CPU_CHAR *)0) { /* Rtn NULL if NULL ptr found (see Note #3b1). */
  1422. return ((CPU_CHAR *)0);
  1423. }
  1424. while (( pstr_char != pstr) && /* Srch str from end until begining (see Note #3c) ... */
  1425. (*pstr_char != srch_char)) { /* ... until srch char found (see Note #3d). */
  1426. pstr_char--;
  1427. }
  1428. if (*pstr_char != srch_char) { /* Rtn NULL if srch char NOT found (see Note #3c1). */
  1429. return ((CPU_CHAR *)0);
  1430. }
  1431. return ((CPU_CHAR *)pstr_char); /* Else rtn ptr to found srch char (see Note #3d1). */
  1432. }
  1433. /*$PAGE*/
  1434. /*
  1435. *********************************************************************************************************
  1436. * Str_Str()
  1437. *
  1438. * Description : Search string for first occurence of a specific search string.
  1439. *
  1440. * Argument(s) : pstr Pointer to string (see Note #1).
  1441. *
  1442. * pstr_srch Pointer to search string (see Note #1).
  1443. *
  1444. * Return(s) : Pointer to first occurrence of search string in string, if any (see Note #2b1A).
  1445. *
  1446. * Pointer to string, if NULL search string (see Note #2b2).
  1447. *
  1448. * Pointer to NULL, otherwise (see Note #2b1B).
  1449. *
  1450. * Caller(s) : Application.
  1451. *
  1452. * Note(s) : (1) String buffers NOT modified.
  1453. *
  1454. * (2) (a) IEEE Std 1003.1, 2004 Edition, Section 'strstr() : DESCRIPTION' states that :
  1455. *
  1456. * (1) "The strstr() function shall locate the first occurrence in the string
  1457. * pointed to by 's1' ('pstr') of the sequence of bytes ... in the string
  1458. * pointed to by 's2' ('pstr_srch')" ...
  1459. * (2) "(excluding the terminating null byte)."
  1460. *
  1461. * (b) IEEE Std 1003.1, 2004 Edition, Section 'strstr() : RETURN VALUE' states that :
  1462. *
  1463. * (1) "Upon successful completion, strstr() shall return" :
  1464. * (A) "a pointer to the located string" ...
  1465. * (B) "or a null pointer if the string is not found."
  1466. * (1) #### Although NO strstr() specification states to return NULL for
  1467. * any other reason(s), NULL is also returned for any error(s).
  1468. *
  1469. * (2) "If 's2' ('pstr_srch') points to a string with zero length, the function
  1470. * shall return 's1' ('pstr')."
  1471. *
  1472. * (3) String search terminates when :
  1473. *
  1474. * (a) String pointer(s) are passed NULL pointers.
  1475. * (1) No string search performed; NULL pointer returned.
  1476. *
  1477. * (b) String pointer(s) point to NULL.
  1478. * (1) String buffer(s) overlap with NULL address; NULL pointer returned.
  1479. *
  1480. * (c) Search string length equal to zero.
  1481. * (1) No string search performed; string pointer returned (see Note #2b2).
  1482. *
  1483. * (d) Search string length greater than string length.
  1484. * (1) No string search performed; NULL pointer returned (see Note #2b1B).
  1485. *
  1486. * (e) Entire string has been searched.
  1487. * (1) Search string not found; NULL pointer returned (see Note #2b1B).
  1488. *
  1489. * (f) Search string found.
  1490. * (1) Return pointer to first occurrence of search string in string (see Note #2b1A).
  1491. *********************************************************************************************************
  1492. */
  1493. CPU_CHAR *Str_Str (const CPU_CHAR *pstr,
  1494. const CPU_CHAR *pstr_srch)
  1495. {
  1496. CPU_CHAR *pstr_rtn;
  1497. pstr_rtn = Str_Str_N(pstr,
  1498. pstr_srch,
  1499. DEF_INT_CPU_U_MAX_VAL);
  1500. return (pstr_rtn);
  1501. }
  1502. /*$PAGE*/
  1503. /*
  1504. *********************************************************************************************************
  1505. * Str_Str_N()
  1506. *
  1507. * Description : Search string for first occurence of a specific search string, up to a maximum number
  1508. * of characters.
  1509. *
  1510. * Argument(s) : pstr Pointer to string (see Note #1).
  1511. *
  1512. * pstr_srch Pointer to search string (see Note #1).
  1513. *
  1514. * len_max Maximum number of characters to search (see Note #3g).
  1515. *
  1516. * Return(s) : Pointer to first occurrence of search string in string, if any (see Note #2b1A).
  1517. *
  1518. * Pointer to string, if NULL search string (see Note #2b2).
  1519. *
  1520. * Pointer to NULL, otherwise (see Note #2b1B).
  1521. *
  1522. * Caller(s) : Application.
  1523. *
  1524. * Note(s) : (1) String buffers NOT modified.
  1525. *
  1526. * (2) (a) IEEE Std 1003.1, 2004 Edition, Section 'strstr() : DESCRIPTION' states that :
  1527. *
  1528. * (1) "The strstr() function shall locate the first occurrence in the string
  1529. * pointed to by 's1' ('pstr') of the sequence of bytes ... in the string
  1530. * pointed to by 's2' ('pstr_srch')" ...
  1531. * (2) "(excluding the terminating null byte)."
  1532. *
  1533. * (b) IEEE Std 1003.1, 2004 Edition, Section 'strstr() : RETURN VALUE' states that :
  1534. *
  1535. * (1) "Upon successful completion, strstr() shall return" :
  1536. * (A) "a pointer to the located string" ...
  1537. * (B) "or a null pointer if the string is not found."
  1538. * (1) #### Although NO strstr() specification states to return NULL for
  1539. * any other reason(s), NULL is also returned for any error(s).
  1540. *
  1541. * (2) "If 's2' ('pstr_srch') points to a string with zero length, the function
  1542. * shall return 's1' ('pstr')."
  1543. *
  1544. * (3) String search terminates when :
  1545. *
  1546. * (a) String pointer(s) are passed NULL pointers.
  1547. * (1) No string search performed; NULL pointer returned.
  1548. *
  1549. * (b) String pointer(s) point to NULL.
  1550. * (1) String buffer(s) overlap with NULL address; NULL pointer returned.
  1551. *
  1552. * (c) Search string length equal to zero.
  1553. * (1) No string search performed; string pointer returned (see Note #2b2).
  1554. *
  1555. * (d) Search string length greater than string length.
  1556. * (1) No string search performed; NULL pointer returned (see Note #2b1B).
  1557. *
  1558. * (e) Entire string has been searched.
  1559. * (1) Search string not found; NULL pointer returned (see Note #2b1B).
  1560. * (2) Maximum size of the search is defined as the subtraction of the
  1561. * search string length from the string length.
  1562. *
  1563. * (f) Search string found.
  1564. * (1) Return pointer to first occurrence of search string in string (see Note #2b1A).
  1565. * (2) Search string found via Str_Cmp_N().
  1566. *
  1567. * (g) 'len_max' number of characters searched.
  1568. * (1) 'len_max' number of characters does NOT include terminating NULL character
  1569. * (see Note #2a2).
  1570. *********************************************************************************************************
  1571. */
  1572. /*$PAGE*/
  1573. CPU_CHAR *Str_Str_N (const CPU_CHAR *pstr,
  1574. const CPU_CHAR *pstr_srch,
  1575. CPU_SIZE_T len_max)
  1576. {
  1577. CPU_SIZE_T str_len;
  1578. CPU_SIZE_T str_len_srch;
  1579. CPU_SIZE_T len_max_srch;
  1580. CPU_SIZE_T srch_len;
  1581. CPU_SIZE_T srch_ix;
  1582. CPU_BOOLEAN srch_done;
  1583. CPU_INT16S srch_cmp;
  1584. const CPU_CHAR *pstr_str;
  1585. const CPU_CHAR *pstr_srch_ix;
  1586. /* Rtn NULL if str ptr(s) NULL (see Note #3a). */
  1587. if (pstr == (const CPU_CHAR *)0) {
  1588. return ((CPU_CHAR *)0);
  1589. }
  1590. if (pstr_srch == (const CPU_CHAR *)0) {
  1591. return ((CPU_CHAR *)0);
  1592. }
  1593. if (len_max < 1) { /* Rtn NULL if srch len = 0 (see Note #3g). */
  1594. return ((CPU_CHAR *)0);
  1595. }
  1596. /* Lim max srch str len (to chk > str len). */
  1597. len_max_srch = (len_max < DEF_INT_CPU_U_MAX_VAL)
  1598. ? (len_max + 1u) : DEF_INT_CPU_U_MAX_VAL;
  1599. str_len = Str_Len_N(pstr, len_max);
  1600. str_len_srch = Str_Len_N(pstr_srch, len_max_srch);
  1601. if (str_len_srch < 1) { /* Rtn ptr to str if srch str len = 0 (see Note #2b2). */
  1602. return ((CPU_CHAR *)pstr);
  1603. }
  1604. if (str_len_srch > str_len) { /* Rtn NULL if srch str len > str len (see Note #3d). */
  1605. return ((CPU_CHAR *)0);
  1606. }
  1607. /* Rtn NULL if NULL ptr found (see Note #3b1). */
  1608. pstr_str = pstr + str_len;
  1609. if (pstr_str == (const CPU_CHAR *)0) {
  1610. return ((CPU_CHAR *)0);
  1611. }
  1612. pstr_str = pstr_srch + str_len_srch;
  1613. if (pstr_str == (const CPU_CHAR *)0) {
  1614. return ((CPU_CHAR *)0);
  1615. }
  1616. srch_len = str_len - str_len_srch; /* Calc srch len (see Note #3e2). */
  1617. srch_ix = 0u;
  1618. srch_done = DEF_NO;
  1619. do {
  1620. pstr_srch_ix = (const CPU_CHAR *)(pstr + srch_ix);
  1621. srch_cmp = Str_Cmp_N(pstr_srch_ix, pstr_srch, str_len_srch);
  1622. srch_done = (srch_cmp == 0) ? DEF_YES : DEF_NO;
  1623. srch_ix++;
  1624. } while ((srch_done == DEF_NO) && (srch_ix <= srch_len));
  1625. if (srch_cmp != 0) { /* Rtn NULL if srch str NOT found (see Note #3e2). */
  1626. return ((CPU_CHAR *)0);
  1627. }
  1628. return ((CPU_CHAR *)pstr_srch_ix); /* Else rtn ptr to found srch str (see Note #3f1). */
  1629. }
  1630. /*$PAGE*/
  1631. /*
  1632. *********************************************************************************************************
  1633. * Str_FmtNbr_Int32U()
  1634. *
  1635. * Description : Format 32-bit unsigned integer into a multi-digit character string.
  1636. *
  1637. * Argument(s) : nbr Number to format.
  1638. *
  1639. * nbr_dig Number of digits to format (see Note #1).
  1640. *
  1641. * The following may be used to specify the number of digits to format :
  1642. *
  1643. * DEF_INT_32U_NBR_DIG_MIN Minimum number of 32-bit unsigned digits
  1644. * DEF_INT_32U_NBR_DIG_MAX Maximum number of 32-bit unsigned digits
  1645. *
  1646. * nbr_base Base of number to format (see Note #2).
  1647. *
  1648. * The following may be used to specify the number base :
  1649. *
  1650. * DEF_NBR_BASE_BIN Base 2
  1651. * DEF_NBR_BASE_OCT Base 8
  1652. * DEF_NBR_BASE_DEC Base 10
  1653. * DEF_NBR_BASE_HEX Base 16
  1654. *
  1655. * lead_char Prepend leading character (see Note #3) :
  1656. *
  1657. * '\0' Do NOT prepend leading character to string.
  1658. * Printable character Prepend leading character to string.
  1659. * Unprintable character Format invalid string (see Note #6).
  1660. *
  1661. * lower_case Format alphabetic characters (if any) in lower case :
  1662. *
  1663. * DEF_NO Format alphabetic characters in upper case.
  1664. * DEF_YES Format alphabetic characters in lower case.
  1665. *
  1666. * nul Append terminating NULL-character (see Note #4) :
  1667. *
  1668. * DEF_NO Do NOT append terminating NULL-character to string.
  1669. * DEF_YES Append terminating NULL-character to string.
  1670. *
  1671. * pstr Pointer to character array to return formatted number string (see Note #5).
  1672. *
  1673. * Return(s) : Pointer to formatted string, if NO error(s).
  1674. *
  1675. * Pointer to NULL, otherwise.
  1676. *
  1677. * Caller(s) : Application.
  1678. *
  1679. * Note(s) : (1) (a) If the number of digits to format ('nbr_dig') is zero; then NO formatting
  1680. * is performed except possible NULL-termination of the string (see Note #4).
  1681. *
  1682. * Example :
  1683. *
  1684. * nbr = 23456
  1685. * nbr_dig = 0
  1686. * nbr_base = 10
  1687. *
  1688. * pstr = "" See Note #6a
  1689. *
  1690. * (b) If the number of digits to format ('nbr_dig') is less than the number of
  1691. * significant integer digits of the number to format ('nbr'); then an invalid
  1692. * string is formatted instead of truncating any significant integer digits.
  1693. *
  1694. * Example :
  1695. *
  1696. * nbr = 23456
  1697. * nbr_dig = 3
  1698. * nbr_base = 10
  1699. *
  1700. * pstr = "???" See Note #6b
  1701. *
  1702. * (2) The number's base MUST be between 2 & 36, inclusive.
  1703. *$PAGE*
  1704. * (3) Leading character option prepends leading characters prior to the first non-zero digit.
  1705. *
  1706. * (a) (1) Leading character MUST be a printable ASCII character.
  1707. *
  1708. * (2) (A) Leading character MUST NOT be a number base digit, ...
  1709. * (B) with the exception of '0'.
  1710. *
  1711. * (b) The number of leading characters is such that the total number of significant
  1712. * integer digits plus the number of leading characters is equal to the requested
  1713. * number of integer digits to format ('nbr_dig').
  1714. *
  1715. * Example :
  1716. *
  1717. * nbr = 23456
  1718. * nbr_dig = 7
  1719. * nbr_base = 10
  1720. * lead_char = ' '
  1721. *
  1722. * pstr = " 23456"
  1723. *
  1724. * (c) (1) If the value of the number to format is zero ...
  1725. * (2) ... & the number of digits to format is non-zero, ...
  1726. * (3) ... but NO leading character available; ...
  1727. * (4) ... then one digit of '0' value is formatted.
  1728. *
  1729. * This is NOT a leading character; but a single integer digit of '0' value.
  1730. *
  1731. * (4) (a) NULL-character terminate option DISABLED prevents overwriting previous character
  1732. * array formatting.
  1733. *
  1734. * (b) WARNING: Unless 'pstr' character array is pre-/post-terminated, NULL-character
  1735. * terminate option DISABLED will cause character string run-on.
  1736. *
  1737. * (5) (a) Format buffer size NOT validated; buffer overruns MUST be prevented by caller.
  1738. *
  1739. * (b) To prevent character buffer overrun :
  1740. *
  1741. * Character array size MUST be >= ('nbr_dig' +
  1742. * 1 'NUL' terminator) characters
  1743. *
  1744. * (6) For any unsuccessful string format or error(s), an invalid string of question marks
  1745. * ('?') will be formatted, where the number of question marks is determined by the
  1746. * number of digits to format ('nbr_dig') :
  1747. *
  1748. * Invalid string's { (a) 0 (NULL string) , if 'nbr_dig' = 0
  1749. * number of = {
  1750. * question marks { (b) 'nbr_dig' , if 'nbr_dig' > 0
  1751. *
  1752. *********************************************************************************************************
  1753. */
  1754. CPU_CHAR *Str_FmtNbr_Int32U (CPU_INT32U nbr,
  1755. CPU_INT08U nbr_dig,
  1756. CPU_INT08U nbr_base,
  1757. CPU_CHAR lead_char,
  1758. CPU_BOOLEAN lower_case,
  1759. CPU_BOOLEAN nul,
  1760. CPU_CHAR *pstr)
  1761. {
  1762. CPU_CHAR *pstr_fmt;
  1763. pstr_fmt = Str_FmtNbr_Int32(nbr, /* Fmt unsigned int into str. */
  1764. nbr_dig,
  1765. nbr_base,
  1766. DEF_NO,
  1767. lead_char,
  1768. lower_case,
  1769. nul,
  1770. pstr);
  1771. return (pstr_fmt);
  1772. }
  1773. /*$PAGE*/
  1774. /*
  1775. *********************************************************************************************************
  1776. * Str_FmtNbr_Int32S()
  1777. *
  1778. * Description : Format 32-bit signed integer into a multi-digit character string.
  1779. *
  1780. * Argument(s) : nbr Number to format.
  1781. *
  1782. * nbr_dig Number of digits to format (see Note #1).
  1783. *
  1784. * The following may be used to specify the number of digits to format :
  1785. *
  1786. * DEF_INT_32S_NBR_DIG_MIN + 1 Minimum number of 32-bit signed digits
  1787. * DEF_INT_32S_NBR_DIG_MAX + 1 Maximum number of 32-bit signed digits
  1788. * (plus 1 digit for possible negative sign)
  1789. *
  1790. * nbr_base Base of number to format (see Note #2).
  1791. *
  1792. * The following may be used to specify the number base :
  1793. *
  1794. * DEF_NBR_BASE_BIN Base 2
  1795. * DEF_NBR_BASE_OCT Base 8
  1796. * DEF_NBR_BASE_DEC Base 10
  1797. * DEF_NBR_BASE_HEX Base 16
  1798. *
  1799. * lead_char Prepend leading character (see Note #3) :
  1800. *
  1801. * '\0' Do NOT prepend leading character to string.
  1802. * Printable character Prepend leading character to string.
  1803. * Unprintable character Format invalid string (see Note #6).
  1804. *
  1805. * lower_case Format alphabetic characters (if any) in lower case :
  1806. *
  1807. * DEF_NO Format alphabetic characters in upper case.
  1808. * DEF_YES Format alphabetic characters in lower case.
  1809. *
  1810. * nul Append terminating NULL-character (see Note #4) :
  1811. *
  1812. * DEF_NO Do NOT append terminating NULL-character to string.
  1813. * DEF_YES Append terminating NULL-character to string.
  1814. *
  1815. * pstr Pointer to character array to return formatted number string (see Note #5).
  1816. *
  1817. * Return(s) : Pointer to formatted string, if NO error(s).
  1818. *
  1819. * Pointer to NULL, otherwise.
  1820. *
  1821. * Caller(s) : Application.
  1822. *
  1823. * Note(s) : (1) (a) If the number of digits to format ('nbr_dig') is zero; then NO formatting
  1824. * is performed except possible NULL-termination of the string (see Note #4).
  1825. *
  1826. * Example :
  1827. *
  1828. * nbr = -23456
  1829. * nbr_dig = 0
  1830. * nbr_base = 10
  1831. *
  1832. * pstr = "" See Note #6a
  1833. *
  1834. * (b) If the number of digits to format ('nbr_dig') is less than the number of
  1835. * significant integer digits of the number to format ('nbr'); then an invalid
  1836. * string is formatted instead of truncating any significant integer digits.
  1837. *
  1838. * Example :
  1839. *
  1840. * nbr = 23456
  1841. * nbr_dig = 3
  1842. * nbr_base = 10
  1843. *
  1844. * pstr = "???" See Note #6b
  1845. *
  1846. * (c) If the number to format ('nbr') is negative but the number of digits to format
  1847. * ('nbr_dig') is equal to the number of significant integer digits of the number
  1848. * to format ('nbr'); then an invalid string is formatted instead of truncating
  1849. * the negative sign.
  1850. *
  1851. * Example :
  1852. *
  1853. * nbr = -23456
  1854. * nbr_dig = 5
  1855. * nbr_base = 10
  1856. *
  1857. * pstr = "?????" See Note #6b
  1858. *
  1859. * (2) The number's base MUST be between 2 & 36, inclusive.
  1860. *$PAGE*
  1861. * (3) Leading character option prepends leading characters prior to the first non-zero digit.
  1862. *
  1863. * (a) (1) Leading character MUST be a printable ASCII character.
  1864. *
  1865. * (2) (A) Leading character MUST NOT be a number base digit, ...
  1866. * (B) with the exception of '0'.
  1867. *
  1868. * (b) (1) The number of leading characters is such that the total number of significant
  1869. * integer digits plus the number of leading characters plus possible negative
  1870. * sign character is equal to the requested number of integer digits to format
  1871. * ('nbr_dig').
  1872. *
  1873. * Examples :
  1874. *
  1875. * nbr = 23456
  1876. * nbr_dig = 7
  1877. * nbr_base = 10
  1878. * lead_char = ' '
  1879. *
  1880. * pstr = " 23456"
  1881. *
  1882. *
  1883. * nbr = -23456
  1884. * nbr_dig = 7
  1885. * nbr_base = 10
  1886. * lead_char = ' '
  1887. *
  1888. * pstr = " -23456"
  1889. *
  1890. * (2) (A) If the number to format ('nbr') is negative AND the leading character
  1891. * ('lead_char') is a '0' digit; then the negative sign character
  1892. * prefixes all leading characters prior to the formatted number.
  1893. *
  1894. * Examples :
  1895. *
  1896. * nbr = -23456
  1897. * nbr_dig = 8
  1898. * nbr_base = 10
  1899. * lead_char = '0'
  1900. *
  1901. * pstr = "-0023456"
  1902. *
  1903. *
  1904. * nbr = -43981
  1905. * nbr_dig = 8
  1906. * nbr_base = 16
  1907. * lead_char = '0'
  1908. * lower_case = DEF_NO
  1909. *
  1910. * pstr = "-000ABCD"
  1911. *
  1912. * (B) If the number to format ('nbr') is negative AND the leading character
  1913. * ('lead_char') is NOT a '0' digit; then the negative sign character
  1914. * immediately prefixes the most significant digit of the formatted number.
  1915. *
  1916. * Examples :
  1917. *
  1918. * nbr = -23456
  1919. * nbr_dig = 8
  1920. * nbr_base = 10
  1921. * lead_char = '#'
  1922. *
  1923. * pstr = "##-23456"
  1924. *
  1925. *
  1926. * nbr = -43981
  1927. * nbr_dig = 8
  1928. * nbr_base = 16
  1929. * lead_char = '#'
  1930. * lower_case = DEF_YES
  1931. *
  1932. * pstr = "###-abcd"
  1933. *
  1934. * (c) (1) If the value of the number to format is zero ...
  1935. * (2) ... & the number of digits to format is non-zero, ...
  1936. * (3) ... but NO leading character available; ...
  1937. * (4) ... then one digit of '0' value is formatted.
  1938. *
  1939. * This is NOT a leading character; but a single integer digit of '0' value.
  1940. *$PAGE*
  1941. * (4) (a) NULL-character terminate option DISABLED prevents overwriting previous character
  1942. * array formatting.
  1943. *
  1944. * (b) WARNING: Unless 'pstr' character array is pre-/post-terminated, NULL-character
  1945. * terminate option DISABLED will cause character string run-on.
  1946. *
  1947. * (5) (a) Format buffer size NOT validated; buffer overruns MUST be prevented by caller.
  1948. *
  1949. * (b) To prevent character buffer overrun :
  1950. *
  1951. * Character array size MUST be >= ('nbr_dig' +
  1952. * 1 negative sign +
  1953. * 1 'NUL' terminator) characters
  1954. *
  1955. * (6) For any unsuccessful string format or error(s), an invalid string of question marks
  1956. * ('?') will be formatted, where the number of question marks is determined by the
  1957. * number of digits to format ('nbr_dig') :
  1958. *
  1959. * Invalid string's { (a) 0 (NULL string) , if 'nbr_dig' = 0
  1960. * number of = {
  1961. * question marks { (b) 'nbr_dig' , if 'nbr_dig' > 0
  1962. *
  1963. *********************************************************************************************************
  1964. */
  1965. CPU_CHAR *Str_FmtNbr_Int32S (CPU_INT32S nbr,
  1966. CPU_INT08U nbr_dig,
  1967. CPU_INT08U nbr_base,
  1968. CPU_CHAR lead_char,
  1969. CPU_BOOLEAN lower_case,
  1970. CPU_BOOLEAN nul,
  1971. CPU_CHAR *pstr)
  1972. {
  1973. CPU_CHAR *pstr_fmt;
  1974. CPU_INT32S nbr_fmt;
  1975. CPU_BOOLEAN nbr_neg;
  1976. if (nbr < 0) { /* If nbr neg, ... */
  1977. nbr_fmt = -nbr; /* ... negate nbr. */
  1978. nbr_neg = DEF_YES;
  1979. } else {
  1980. nbr_fmt = nbr;
  1981. nbr_neg = DEF_NO;
  1982. }
  1983. pstr_fmt = Str_FmtNbr_Int32((CPU_INT32U)nbr_fmt, /* Fmt signed int into str. */
  1984. nbr_dig,
  1985. nbr_base,
  1986. nbr_neg,
  1987. lead_char,
  1988. lower_case,
  1989. nul,
  1990. pstr);
  1991. return (pstr_fmt);
  1992. }
  1993. /*$PAGE*/
  1994. /*
  1995. *********************************************************************************************************
  1996. * Str_FmtNbr_32()
  1997. *
  1998. * Description : Format number into a multi-digit character string.
  1999. *
  2000. * Argument(s) : nbr Number to format (see Note #1).
  2001. *
  2002. * nbr_dig Number of decimal digits to format (see Note #2).
  2003. *
  2004. * nbr_dp Number of decimal point digits to format.
  2005. *
  2006. * lead_char Prepend leading character (see Note #3) :
  2007. *
  2008. * '\0' Do NOT prepend leading character to string.
  2009. * Printable character Prepend leading character to string.
  2010. * Unprintable character Format invalid string (see Note #6d).
  2011. *
  2012. * nul Append terminating NULL-character (see Note #4) :
  2013. *
  2014. * DEF_NO Do NOT append terminating NULL-character to string.
  2015. * DEF_YES Append terminating NULL-character to string.
  2016. *
  2017. * pstr Pointer to character array to return formatted number string (see Note #5).
  2018. *
  2019. * Return(s) : Pointer to formatted string, if NO error(s) [see Note #6c].
  2020. *
  2021. * Pointer to NULL, otherwise.
  2022. *
  2023. * Caller(s) : Application.
  2024. *
  2025. * Note(s) : (1) (a) The maximum accuracy for 32-bit floating-point numbers :
  2026. *
  2027. *
  2028. * Maximum Accuracy log [Internal-Base ^ (Number-Internal-Base-Digits)]
  2029. * 32-bit Floating-point Number = -----------------------------------------------------
  2030. * log [External-Base]
  2031. *
  2032. * log [2 ^ 24]
  2033. * = --------------
  2034. * log [10]
  2035. *
  2036. * < 7.225 Base-10 Digits
  2037. *
  2038. * where
  2039. * Internal-Base Internal number base of floating-
  2040. * point numbers (i.e. 2)
  2041. * External-Base External number base of floating-
  2042. * point numbers (i.e. 10)
  2043. * Number-Internal-Base-Digits Number of internal number base
  2044. * significant digits (i.e. 24)
  2045. *
  2046. * (b) Some CPUs' &/or compilers' floating-point implementations MAY further reduce the
  2047. * maximum accuracy.
  2048. *$PAGE*
  2049. * (2) (a) If the total number of digits to format ('nbr_dig + nbr_dp') is zero; then NO
  2050. * formatting is performed except possible NULL-termination of the string (see Note #4).
  2051. *
  2052. * Example :
  2053. *
  2054. * nbr = -23456.789
  2055. * nbr_dig = 0
  2056. * nbr_dp = 0
  2057. *
  2058. * pstr = "" See Note #7a
  2059. *
  2060. * (b) (1) If the number of digits to format ('nbr_dig') is less than the number of
  2061. * significant integer digits of the number to format ('nbr'); then an invalid
  2062. * string is formatted instead of truncating any significant integer digits.
  2063. *
  2064. * Example :
  2065. *
  2066. * nbr = 23456.789
  2067. * nbr_dig = 3
  2068. * nbr_dp = 2
  2069. *
  2070. * pstr = "??????" See Note #7d
  2071. *
  2072. * (2) If the number to format ('nbr') is negative but the number of digits to format
  2073. * ('nbr_dig') is equal to the number of significant integer digits of the number
  2074. * to format ('nbr'); then an invalid string is formatted instead of truncating
  2075. * the negative sign.
  2076. *
  2077. * Example :
  2078. *
  2079. * nbr = -23456.789
  2080. * nbr_dig = 5
  2081. * nbr_dp = 2
  2082. *
  2083. * pstr = "????????" See Note #7d
  2084. *
  2085. * (3) If the number to format ('nbr') is negative but the number of significant
  2086. * integer digits is zero, & the number of digits to format ('nbr_dig') is one
  2087. * but the number of decimal point digits to format ('nbr_dp') is zero; then
  2088. * an invalid string is formatted instead of truncating the negative sign.
  2089. *
  2090. * Example :
  2091. *
  2092. * nbr = -0.7895
  2093. * nbr_dig = 1
  2094. * nbr_dp = 0
  2095. *
  2096. * pstr = "?" See Note #7d
  2097. *
  2098. * (4) (A) If the number to format ('nbr') is negative but the number of significant
  2099. * integer digits is zero, & the number of digits to format ('nbr_dig') is
  2100. * zero but the number of decimal point digits to format ('nbr_dp') is non-
  2101. * zero; then the negative sign immediately prefixes the decimal point --
  2102. * with NO decimal digits formatted, NOT even a single decimal digit of '0'.
  2103. *
  2104. * Example :
  2105. *
  2106. * nbr = -0.7895
  2107. * nbr_dig = 0
  2108. * nbr_dp = 2
  2109. *
  2110. * pstr = "-.78"
  2111. *
  2112. * (B) If the number to format ('nbr') is positive but the number of significant
  2113. * integer digits is zero, & the number of digits to format ('nbr_dig') is
  2114. * zero but the number of decimal point digits to format ('nbr_dp') is non-
  2115. * zero; then a single decimal digit of '0' prefixes the decimal point.
  2116. *
  2117. * This '0' digit is used whenever a negative sign is not formatted (see
  2118. * Note #2b4A) so that the formatted string's decimal point is not floating,
  2119. * but fixed in the string as the 2nd character.
  2120. *
  2121. * Example :
  2122. *
  2123. * nbr = 0.7895
  2124. * nbr_dig = 0
  2125. * nbr_dp = 2
  2126. *
  2127. * pstr = "0.78"
  2128. *$PAGE*
  2129. * (c) (1) If the total number of digits to format ('nbr_dig + nbr_dp') is greater than ... :
  2130. *
  2131. * (A) ... the maximum accuracy of the CPU's &/or compiler's 32-bit floating-point
  2132. * numbers, digits following all significantly-accurate digits of the number to
  2133. * format ('nbr') will be inaccurate; ...
  2134. * (B) ... the configured maximum accuracy ('LIB_STR_CFG_FP_MAX_NBR_DIG_SIG'), all
  2135. * digits or decimal places following all significantly-accurate digits of the
  2136. * number to format ('nbr') will be replaced & formatted with zeros ('0').
  2137. *
  2138. * Example :
  2139. *
  2140. * nbr = 123456789.012345
  2141. * nbr_dig = 9
  2142. * nbr_dp = 6
  2143. * LIB_STR_CFG_FP_MAX_NBR_DIG_SIG = 7
  2144. *
  2145. * pstr = "123456700.000000"
  2146. *
  2147. * (2) Therefore, one or more least-significant digit(s) of the number to format ('nbr')
  2148. * MAY be rounded & not necessarily truncated due to the inaccuracy of the CPU's
  2149. * &/or compiler's floating-point implementation.
  2150. *
  2151. * See also Note #1.
  2152. *
  2153. * (3) Leading character option prepends leading characters prior to the first non-zero digit.
  2154. *
  2155. * (a) (1) Leading character MUST be a printable ASCII character.
  2156. *
  2157. * (2) (A) Leading character MUST NOT be a base-10 digit, ...
  2158. * (B) with the exception of '0'.
  2159. *
  2160. * (b) (1) The number of leading characters is such that the total number of significant
  2161. * integer digits plus the number of leading characters plus possible negative
  2162. * sign character is equal to the requested number of integer digits to format
  2163. * ('nbr_dig').
  2164. *
  2165. * Examples :
  2166. *
  2167. * nbr = 23456.789
  2168. * nbr_dig = 7
  2169. * nbr_dp = 2
  2170. * lead_char = ' '
  2171. *
  2172. * pstr = " 23456.78"
  2173. *
  2174. *
  2175. * nbr = -23456.789
  2176. * nbr_dig = 7
  2177. * nbr_dp = 2
  2178. * lead_char = ' '
  2179. *
  2180. * pstr = " -23456.78"
  2181. *
  2182. * (2) (A) If the number to format ('nbr') is negative AND the leading character
  2183. * ('lead_char') is a '0' digit; then the negative sign character
  2184. * prefixes all leading characters prior to the formatted number.
  2185. *
  2186. * Example :
  2187. *
  2188. * nbr = -23456.789
  2189. * nbr_dig = 8
  2190. * nbr_dp = 2
  2191. * lead_char = '0'
  2192. *
  2193. * pstr = "-0023456.78"
  2194. *
  2195. * (B) If the number to format ('nbr') is negative AND the leading character
  2196. * ('lead_char') is NOT a '0' digit; then the negative sign character
  2197. * immediately prefixes the most significant digit of the formatted number.
  2198. *
  2199. * Examples :
  2200. *
  2201. * nbr = -23456.789
  2202. * nbr_dig = 8
  2203. * nbr_dp = 2
  2204. * lead_char = '#'
  2205. *
  2206. * pstr = "##-23456.78"
  2207. *
  2208. * (c) (1) If the integer value of the number to format is zero & ...
  2209. * (2) ... the number of digits to format is greater than one ...
  2210. * (3) ... OR the number is NOT negative, ...
  2211. * (4) ... but NO leading character available; ...
  2212. * (5) ... then one digit of '0' value is formatted.
  2213. *
  2214. * This is NOT a leading character; but a single integer digit of '0' value.
  2215. *
  2216. * See also Note #2b4B.
  2217. *$PAGE*
  2218. * (4) (a) NULL-character terminate option DISABLED prevents overwriting previous character
  2219. * array formatting.
  2220. *
  2221. * (b) WARNING: Unless 'pstr' character array is pre-/post-terminated, NULL-character
  2222. * terminate option DISABLED will cause character string run-on.
  2223. *
  2224. * (5) (a) Format buffer size NOT validated; buffer overruns MUST be prevented by caller.
  2225. *
  2226. * (b) To prevent character buffer overrun :
  2227. *
  2228. * Character array size MUST be >= ('nbr_dig' +
  2229. * 'nbr_dp' +
  2230. * 1 negative sign +
  2231. * 1 decimal point +
  2232. * 1 'NUL' terminator) characters
  2233. *
  2234. * (6) String format terminates when :
  2235. *
  2236. * (a) Format string pointer is passed a NULL pointer.
  2237. * (1) No string formatted; NULL pointer returned.
  2238. *
  2239. * (b) Total number of digits to format ('nbr_dig + nbr_dp') is zero.
  2240. * (1) NULL string formatted (see Note #7a); NULL pointer returned.
  2241. *
  2242. * (c) Number of digits to format ('nbr_dig') is less than number of significant
  2243. * integer digits of the number to format ('nbr'), including possible
  2244. * negative sign.
  2245. * (1) Invalid string formatted (see Note #7); NULL pointer returned.
  2246. *
  2247. * (d) Lead character is NOT a valid, printable character (see Note #3a).
  2248. * (1) Invalid string formatted (see Note #7); NULL pointer returned.
  2249. *
  2250. * (e) Number successfully formatted into character string array.
  2251. *
  2252. * (7) For any unsuccessful string format or error(s), an invalid string of question marks
  2253. * ('?') will be formatted, where the number of question marks is determined by the
  2254. * number of digits ('nbr_dig') & number of decimal point digits ('nbr_dp') to format :
  2255. *
  2256. * { (a) 0 (NULL string) , if 'nbr_dig' = 0 AND
  2257. * { 'nbr_dp' = 0
  2258. * {
  2259. * { (b) 'nbr_dig' , if 'nbr_dig' > 0 AND
  2260. * { 'nbr_dp' = 0
  2261. * Invalid string's {
  2262. * number of = { (c) ['nbr_dp' + , if 'nbr_dig' = 0 AND
  2263. * question marks { 1 (for decimal point) + 'nbr_dp' > 0
  2264. * { 1 (for negative sign) ]
  2265. * {
  2266. * { (d) ['nbr_dig' + , if 'nbr_dig' > 0 AND
  2267. * { 'nbr_dp' + 'nbr_dp' > 0
  2268. * { 1 (for decimal point) ]
  2269. *
  2270. *********************************************************************************************************
  2271. */
  2272. #if (LIB_STR_CFG_FP_EN == DEF_ENABLED)
  2273. CPU_CHAR *Str_FmtNbr_32 (CPU_FP32 nbr,
  2274. CPU_INT08U nbr_dig,
  2275. CPU_INT08U nbr_dp,
  2276. CPU_CHAR lead_char,
  2277. CPU_BOOLEAN nul,
  2278. CPU_CHAR *pstr)
  2279. {
  2280. CPU_CHAR *pstr_fmt;
  2281. CPU_DATA i;
  2282. CPU_FP32 nbr_fmt;
  2283. CPU_FP32 nbr_log;
  2284. CPU_INT32U nbr_shiftd;
  2285. CPU_INT16U nbr_dig_max;
  2286. CPU_INT16U nbr_dig_sig;
  2287. CPU_INT08U nbr_neg_sign;
  2288. CPU_INT08U dig_val;
  2289. CPU_FP32 dig_exp;
  2290. CPU_FP32 dp_exp;
  2291. CPU_BOOLEAN lead_char_dig;
  2292. CPU_BOOLEAN lead_char_fmtd;
  2293. CPU_BOOLEAN lead_char_0;
  2294. CPU_BOOLEAN fmt_invalid;
  2295. CPU_BOOLEAN print_char;
  2296. CPU_BOOLEAN nbr_neg;
  2297. CPU_BOOLEAN nbr_neg_fmtd;
  2298. /*$PAGE*/
  2299. /* ---------------- VALIDATE FMT ARGS ----------------- */
  2300. if (pstr == (CPU_CHAR *)0) { /* Rtn NULL if str ptr NULL (see Note #6a). */
  2301. return ((CPU_CHAR *)0);
  2302. }
  2303. fmt_invalid = DEF_NO;
  2304. if ((nbr_dig < 1) && (nbr_dp < 1)) { /* If nbr digs/dps = 0, ... */
  2305. fmt_invalid = DEF_YES; /* ... fmt invalid str (see Note #6b). */
  2306. }
  2307. if (lead_char != (CPU_CHAR)'\0') {
  2308. print_char = ASCII_IsPrint(lead_char);
  2309. if (print_char != DEF_YES) { /* If lead char non-printable (see Note #3a1), ... */
  2310. fmt_invalid = DEF_YES; /* ... fmt invalid str (see Note #6d). */
  2311. } else if (lead_char != '0') { /* Chk lead char for non-0 dig. */
  2312. lead_char_dig = ASCII_IsDig(lead_char);
  2313. if (lead_char_dig == DEF_YES) { /* If lead char non-0 dig (see Note #3a2A), ... */
  2314. fmt_invalid = DEF_YES; /* ... fmt invalid str (see Note #6d). */
  2315. }
  2316. }
  2317. }
  2318. /* ----------------- PREPARE NBR FMT ------------------ */
  2319. pstr_fmt = pstr;
  2320. if (fmt_invalid == DEF_NO) {
  2321. if (nbr < 0.0f) { /* If nbr neg, ... */
  2322. nbr_fmt = -nbr; /* ... negate nbr. */
  2323. nbr_neg_sign = 1u;
  2324. nbr_neg = DEF_YES;
  2325. } else {
  2326. nbr_fmt = nbr;
  2327. nbr_neg_sign = 0u;
  2328. nbr_neg = DEF_NO;
  2329. }
  2330. nbr_log = nbr_fmt;
  2331. nbr_dig_max = 0u;
  2332. while (nbr_log >= 1.0f) { /* While base-10 digs avail, ... */
  2333. nbr_dig_max++; /* ... calc max nbr digs. */
  2334. nbr_log /= 10.0f;
  2335. }
  2336. if (((nbr_dig >= (nbr_dig_max + nbr_neg_sign)) || /* If req'd nbr digs >= (max nbr digs + neg sign) .. */
  2337. (nbr_dig_max < 1)) && /* .. or NO nbr digs, .. */
  2338. ((nbr_dig > 1) || /* .. but NOT [(req'd nbr dig = 1) AND .. */
  2339. (nbr_dp > 0) || /* .. (req'd nbr dp = 0) AND .. */
  2340. (nbr_neg == DEF_NO))) { /* .. ( nbr neg )] (see Note #2b3); */
  2341. /* .. prepare nbr digs to fmt. */
  2342. dig_exp = 1.0f;
  2343. for (i = 1u; i < nbr_dig; i++) {
  2344. dig_exp *= 10.0f;
  2345. }
  2346. nbr_neg_fmtd = DEF_NO;
  2347. nbr_dig_sig = 0u;
  2348. lead_char_fmtd = DEF_NO;
  2349. lead_char_0 = (lead_char == '0') /* Chk if lead char a '0' dig (see Note #3b2). */
  2350. ? DEF_YES : DEF_NO;
  2351. } else { /* Else if nbr trunc'd, ... */
  2352. fmt_invalid = DEF_YES; /* ... fmt invalid str (see Note #6c). */
  2353. }
  2354. }
  2355. /*$PAGE*/
  2356. /* ------------------- FMT NBR STR -------------------- */
  2357. for (i = nbr_dig; i > 0; i--) { /* Fmt str for desired nbr digs : */
  2358. if (fmt_invalid == DEF_NO) {
  2359. if (nbr_dig_sig < LIB_STR_CFG_FP_MAX_NBR_DIG_SIG) { /* If nbr sig digs < max, fmt str digs; ... */
  2360. nbr_shiftd = (CPU_INT32U)(nbr_fmt / dig_exp);
  2361. if ((nbr_shiftd > 0) || /* If shifted nbr > 0 ... */
  2362. (i == 1u)) { /* ... OR on one's dig to fmt (see Note #3c1), ... */
  2363. /* ... calc & fmt dig val; ... */
  2364. if ((nbr_neg == DEF_YES) && /* If nbr neg ... */
  2365. (nbr_neg_fmtd == DEF_NO )) { /* ... but neg sign NOT yet fmt'd; ... */
  2366. if (lead_char_fmtd == DEF_YES) { /* ... & if lead char(s) fmt'd, ... */
  2367. pstr_fmt--; /* ... replace last lead char w/ ... */
  2368. }
  2369. *pstr_fmt++ = '-'; /* ... prepend neg sign (see Notes #2b & #3b). */
  2370. nbr_neg_fmtd = DEF_YES;
  2371. }
  2372. if (nbr_shiftd > 0) { /* If shifted nbr > 0, ... */
  2373. dig_val = (CPU_INT08U)(nbr_shiftd % 10u);
  2374. *pstr_fmt++ = (CPU_CHAR )(dig_val + '0');
  2375. nbr_dig_sig++; /* ... inc nbr sig digs; ... */
  2376. } else if ((nbr_dig > 1) || /* ... else if req'd digs > 1 ... */
  2377. (nbr_neg == DEF_NO)) { /* ... or non-neg nbr, ... */
  2378. *pstr_fmt++ = '0'; /* ... fmt one '0' char (see Note #3c5). */
  2379. }
  2380. } else if ((nbr_neg == DEF_YES) && /* ... else if nbr neg ... */
  2381. (lead_char_0 == DEF_YES) && /* ... & lead char a '0' dig ... */
  2382. (nbr_neg_fmtd == DEF_NO )) { /* ... but neg sign NOT yet fmt'd, ... */
  2383. *pstr_fmt++ = '-'; /* ... prepend neg sign (see Note #3b); ... */
  2384. nbr_neg_fmtd = DEF_YES;
  2385. } else if (lead_char != (CPU_CHAR)'\0') { /* ... else if avail, ... */
  2386. *pstr_fmt++ = lead_char; /* ... fmt lead char. */
  2387. lead_char_fmtd = DEF_YES;
  2388. }
  2389. dig_exp /= 10.0f; /* Shift to next least-sig dig. */
  2390. } else { /* ... else append non-sig 0's (see Note #2c2). */
  2391. *pstr_fmt++ = '0';
  2392. }
  2393. } else { /* Else fmt '?' for invalid str (see Note #7). */
  2394. *pstr_fmt++ = '?';
  2395. }
  2396. }
  2397. /*$PAGE*/
  2398. if (nbr_dp > 0) { /* Fmt str for desired nbr dp : */
  2399. if (nbr_dig < 1) { /* If NO digs fmt'd; ... */
  2400. if (fmt_invalid == DEF_NO) { /* ... nbr fmt valid, ... */
  2401. if ((nbr_neg == DEF_YES) && /* ... nbr neg ... */
  2402. (nbr_neg_fmtd == DEF_NO )) { /* ... but neg sign NOT yet fmt'd, ... */
  2403. *pstr_fmt++ = '-'; /* ... prepend neg sign (see Notes #2b & #3b); ... */
  2404. } else { /* ... else prepend 1 dig of '0' (see Note #3c5) ... */
  2405. *pstr_fmt++ = '0';
  2406. }
  2407. } else { /* ... else fmt '?' for invalid str (see Note #7). */
  2408. *pstr_fmt++ = '?';
  2409. }
  2410. }
  2411. if (fmt_invalid == DEF_NO) { /* If nbr fmt valid, ... */
  2412. *pstr_fmt++ = '.'; /* ... append dp prior to dp conversion. */
  2413. } else { /* Else fmt '?' for invalid str (see Note #7). */
  2414. *pstr_fmt++ = '?';
  2415. }
  2416. dp_exp = 10.0f;
  2417. for (i = 0u; i < nbr_dp; i++) {
  2418. if (fmt_invalid == DEF_NO) {
  2419. /* If nbr sig digs < max, fmt str dps; ... */
  2420. if (nbr_dig_sig < LIB_STR_CFG_FP_MAX_NBR_DIG_SIG) {
  2421. nbr_shiftd = (CPU_INT32U)(nbr_fmt * dp_exp);
  2422. dig_val = (CPU_INT32U)(nbr_shiftd % 10u);
  2423. *pstr_fmt++ = (CPU_CHAR )(dig_val + '0');
  2424. dp_exp *= 10.0f; /* Shift to next least-sig dp. */
  2425. if ((nbr_shiftd > 0) || /* If shifted nbr > 0 ... */
  2426. (nbr_dig_sig > 0)) { /* ... OR > 0 sig digs already fmt'd, ... */
  2427. nbr_dig_sig++; /* ... inc nbr sig digs. */
  2428. }
  2429. } else { /* ... else append non-sig 0's (see Note #2c2). */
  2430. *pstr_fmt++ = '0';
  2431. }
  2432. } else { /* Else fmt '?' for invalid str (see Note #7). */
  2433. *pstr_fmt++ = '?';
  2434. }
  2435. }
  2436. }
  2437. if (nul != DEF_NO) { /* If NOT DISABLED, append NULL char (see Note #4). */
  2438. *pstr_fmt = (CPU_CHAR)'\0';
  2439. }
  2440. if (fmt_invalid != DEF_NO) { /* Rtn NULL for invalid str fmt (see Notes #6a - #6d). */
  2441. return ((CPU_CHAR *)0);
  2442. }
  2443. return (pstr); /* Rtn ptr to fmt'd str (see Note #6e). */
  2444. }
  2445. #endif
  2446. /*$PAGE*/
  2447. /*
  2448. *********************************************************************************************************
  2449. * Str_ParseNbr_Int32U()
  2450. *
  2451. * Description : Parse 32-bit unsigned integer from string.
  2452. *
  2453. * Argument(s) : pstr Pointer to string (see Notes #1 & #2a).
  2454. *
  2455. * pstr_next Optional pointer to a variable to ... :
  2456. *
  2457. * (a) Return a pointer to first character following the integer string,
  2458. * if NO error(s) [see Note #2a2B2];
  2459. * (b) Return a pointer to 'pstr',
  2460. * otherwise (see Note #2a2A2).
  2461. *
  2462. * nbr_base Base of number to parse (see Notes #2a1B1 & #2a2B1).
  2463. *
  2464. * Return(s) : Parsed integer, if integer parsed with NO overflow (see Note #2a3A).
  2465. *
  2466. * DEF_INT_32U_MAX_VAL, if integer parsed but overflowed (see Note #2a3A1).
  2467. *
  2468. * 0, otherwise (see Note #2a3B).
  2469. *
  2470. * Caller(s) : Application.
  2471. *
  2472. * Note(s) : (1) String buffer NOT modified.
  2473. *
  2474. * (2) (a) IEEE Std 1003.1, 2004 Edition, Section 'strtoul() : DESCRIPTION' states that "these
  2475. * functions shall convert the initial portion of the string pointed to by 'str' ('pstr')
  2476. * to a type unsigned long ... representation" :
  2477. *
  2478. * (1) "First, they decompose the input string into three parts" :
  2479. *
  2480. * (A) "An initial, possibly empty, sequence of white-space characters [as specified
  2481. * by isspace()]."
  2482. *
  2483. * (1) "The subject sequence is defined as the longest initial subsequence of the
  2484. * input string, starting with the first non-white-space character that is of
  2485. * the expected form. The subject sequence shall contain no characters if the
  2486. * input string is empty or consists entirely of white-space characters."
  2487. *
  2488. * (B) (1) "A subject sequence interpreted as an integer represented in some radix
  2489. * determined by the value of 'base' ('nbr_base')" :
  2490. *
  2491. * (a) "If the value of 'base' ('nbr_base') is 0, the expected form of the
  2492. * subject sequence is that of a decimal constant, octal constant, or
  2493. * hexadecimal constant" :
  2494. *
  2495. * (1) "A decimal constant begins with a non-zero digit, and consists of a
  2496. * sequence of decimal digits."
  2497. *
  2498. * (2) "An octal constant consists of the prefix '0' optionally followed by
  2499. * a sequence of the digits '0' to '7' only."
  2500. *
  2501. * (3) "A hexadecimal constant consists of the prefix '0x' or '0X' followed
  2502. * by a sequence of the decimal digits and letters 'a' (or 'A') to 'f'
  2503. * (or 'F') with values 10 to 15 respectively."
  2504. *
  2505. * (b) "If the value of 'base' ('nbr_base') is between 2 and 36, the expected form
  2506. * of the subject sequence is a sequence of letters and digits representing
  2507. * an integer with the radix specified by 'base' ('nbr_base')" :
  2508. *
  2509. * (1) (A) "The letters from 'a' (or 'A') to 'z' (or 'Z') inclusive are
  2510. * ascribed the values 10 to 35"; ...
  2511. * (B) "only letters whose ascribed values are less than that of base
  2512. * are permitted."
  2513. *
  2514. * (2) (A) "If the value of 'base' ('nbr_base') is 16, the characters '0x' or
  2515. * '0X' may optionally precede the sequence of letters and digits."
  2516. *
  2517. * (B) Although NO specification states that "if the value of 'base'
  2518. * ('nbr_base') is" 8, the '0' character "may optionally precede
  2519. * the sequence of letters and digits"; it seems reasonable to
  2520. * allow the '0' character to be optionally parsed.
  2521. *
  2522. * (2) "A subject sequence .... may be preceded by a '+' or '-' sign."
  2523. *
  2524. * (a) However, it does NOT seem reasonable to parse & convert a negative number
  2525. * integer string into an unsigned integer.
  2526. *
  2527. * (C) (1) (a) "A final string of one or more unrecognized characters," ...
  2528. * (b) "including the terminating null byte of the input string" ...
  2529. * (2) "other than a sign or a permissible letter or digit."
  2530. *$PAGE*
  2531. * (2) Second, "they shall attempt to convert the subject sequence to an unsigned integer" :
  2532. *
  2533. * (A) "If the subject sequence is empty or does not have the expected form" :
  2534. *
  2535. * (1) "no conversion [is] performed"; ...
  2536. * (2) "the value of 'str' ('pstr') [is] stored in the object pointed to by 'endptr'
  2537. * ('pstr_next'), provided that 'endptr' ('pstr_next') is not a null pointer."
  2538. *
  2539. * (B) "If the subject sequence has the expected form" :
  2540. *
  2541. * (1) (a) "and the value of 'base' ('nbr_base') is 0, the sequence of characters
  2542. * starting with the first digit shall be interpreted as an integer constant."
  2543. *
  2544. * (b) "and the value of 'base' ('nbr_base') is between 2 and 36, it shall be
  2545. * used as the base for conversion, ascribing to each letter its value as
  2546. * given above" (see Note #2a1B1b1A).
  2547. *
  2548. * (2) "A pointer to the final string shall be stored in the object pointed to by
  2549. * 'endptr' ('pstr_next'), provided that 'endptr' ('pstr_next') is not a null
  2550. * pointer."
  2551. *
  2552. * (3) Lastly, IEEE Std 1003.1, 2004 Edition, Section 'strtoul() : RETURN VALUE' states that :
  2553. *
  2554. * (A) "Upon successful completion, these functions shall return the converted value."
  2555. * (1) "If the correct value is outside the range of representable values, {ULONG_MAX}
  2556. * ... shall be returned."
  2557. *
  2558. * (B) "If no conversion could be performed, 0 shall be returned."
  2559. *
  2560. * (b) (1) IEEE Std 1003.1, 2004 Edition, Section 'strtoul() : ERRORS' states that "these functions
  2561. * shall fail if" :
  2562. *
  2563. * (A) "[EINVAL] - The value of 'base' ('nbr_base') is not supported."
  2564. *
  2565. * (B) "[ERANGE] - The value to be returned is not representable."
  2566. *
  2567. * (2) IEEE Std 1003.1, 2004 Edition, Section 'strtoul() : ERRORS' states that "these functions
  2568. * may fail if" :
  2569. *
  2570. * (A) "[EINVAL] - No conversion could be performed."
  2571. *
  2572. * (3) Return integer value & next string pointer should be used to diagnose parse success or failure :
  2573. *
  2574. * (a) Valid parse string integer :
  2575. *
  2576. * pstr = " ABCDE xyz"
  2577. * nbr_base = 16
  2578. *
  2579. * nbr = 703710
  2580. * pstr_next = " xyz"
  2581. *
  2582. *
  2583. * (b) Invalid parse string integer :
  2584. *
  2585. * pstr = " ABCDE"
  2586. * nbr_base = 10
  2587. *
  2588. * nbr = 0
  2589. * pstr_next = pstr = " ABCDE"
  2590. *
  2591. *
  2592. * (c) Valid hexadecimal parse string integer :
  2593. *
  2594. * pstr = " 0xGABCDE"
  2595. * nbr_base = 16
  2596. *
  2597. * nbr = 0
  2598. * pstr_next = "xGABCDE"
  2599. *
  2600. *
  2601. * (d) Valid decimal parse string integer ('0x' prefix ignored
  2602. * following invalid hexadecimal characters) :
  2603. *
  2604. * pstr = " 0xGABCDE"
  2605. * nbr_base = 0
  2606. *
  2607. * nbr = 0
  2608. * pstr_next = "xGABCDE"
  2609. *
  2610. *
  2611. * (e) Valid decimal parse string integer ('0' prefix ignored
  2612. * following invalid octal characters) :
  2613. *
  2614. * pstr = " 0GABCDE"
  2615. * nbr_base = 0
  2616. *
  2617. * nbr = 0
  2618. * pstr_next = "GABCDE"
  2619. *
  2620. *$PAGE*
  2621. * (f) Parse string integer overflow :
  2622. *
  2623. * pstr = " 12345678901234567890*123456"
  2624. * nbr_base = 10
  2625. *
  2626. * nbr = DEF_INT_32U_MAX_VAL
  2627. * pstr_next = "*123456"
  2628. *
  2629. *
  2630. * (g) Invalid negative unsigned parse string :
  2631. *
  2632. * pstr = " -12345678901234567890*123456"
  2633. * nbr_base = 10
  2634. *
  2635. * nbr = 0
  2636. * pstr_next = pstr = " -12345678901234567890*123456"
  2637. *
  2638. *********************************************************************************************************
  2639. */
  2640. CPU_INT32U Str_ParseNbr_Int32U (const CPU_CHAR *pstr,
  2641. CPU_CHAR **pstr_next,
  2642. CPU_INT08U nbr_base)
  2643. {
  2644. CPU_INT32U nbr;
  2645. nbr = Str_ParseNbr_Int32( pstr, /* Parse/convert str ... */
  2646. pstr_next,
  2647. nbr_base,
  2648. DEF_NO, /* ... as unsigned int (see Note #2a2). */
  2649. (CPU_BOOLEAN *)0);
  2650. return (nbr);
  2651. }
  2652. /*$PAGE*/
  2653. /*
  2654. *********************************************************************************************************
  2655. * Str_ParseNbr_Int32S()
  2656. *
  2657. * Description : Parse 32-bit signed integer from string.
  2658. *
  2659. * Argument(s) : pstr Pointer to string (see Notes #1 & #2a).
  2660. *
  2661. * pstr_next Optional pointer to a variable to ... :
  2662. *
  2663. * (a) Return a pointer to first character following the integer string,
  2664. * if NO error(s) [see Note #2a2B2];
  2665. * (b) Return a pointer to 'pstr',
  2666. * otherwise (see Note #2a2A2).
  2667. *
  2668. * nbr_base Base of number to parse (see Notes #2a1B1 & #2a2B1).
  2669. *
  2670. * Return(s) : Parsed integer, if integer parsed with NO over- or underflow (see Note #2a3A).
  2671. *
  2672. * DEF_INT_32S_MIN_VAL, if integer parsed but negatively underflowed (see Note #2a3A1a).
  2673. *
  2674. * DEF_INT_32U_MAX_VAL, if integer parsed but positively overflowed (see Note #2a3A1b).
  2675. *
  2676. * 0, otherwise (see Note #2a3B).
  2677. *
  2678. * Caller(s) : Application.
  2679. *
  2680. * Note(s) : (1) String buffer NOT modified.
  2681. *
  2682. * (2) (a) IEEE Std 1003.1, 2004 Edition, Section 'strtol() : DESCRIPTION' states that "these
  2683. * functions shall convert the initial portion of the string pointed to by 'str' ('pstr')
  2684. * to a type long ... representation" :
  2685. *
  2686. * (1) "First, they decompose the input string into three parts" :
  2687. *
  2688. * (A) "An initial, possibly empty, sequence of white-space characters [as specified
  2689. * by isspace()]."
  2690. *
  2691. * (1) "The subject sequence is defined as the longest initial subsequence of the
  2692. * input string, starting with the first non-white-space character that is of
  2693. * the expected form. The subject sequence shall contain no characters if the
  2694. * input string is empty or consists entirely of white-space characters."
  2695. *
  2696. * (B) (1) "A subject sequence interpreted as an integer represented in some radix
  2697. * determined by the value of 'base' ('nbr_base')" :
  2698. *
  2699. * (a) "If the value of 'base' ('nbr_base') is 0, the expected form of the
  2700. * subject sequence is that of a decimal constant, octal constant, or
  2701. * hexadecimal constant" :
  2702. *
  2703. * (1) "A decimal constant begins with a non-zero digit, and consists of a
  2704. * sequence of decimal digits."
  2705. *
  2706. * (2) "An octal constant consists of the prefix '0' optionally followed by
  2707. * a sequence of the digits '0' to '7' only."
  2708. *
  2709. * (3) "A hexadecimal constant consists of the prefix '0x' or '0X' followed
  2710. * by a sequence of the decimal digits and letters 'a' (or 'A') to 'f'
  2711. * (or 'F') with values 10 to 15 respectively."
  2712. *
  2713. * (b) "If the value of 'base' ('nbr_base') is between 2 and 36, the expected form
  2714. * of the subject sequence is a sequence of letters and digits representing
  2715. * an integer with the radix specified by 'base' ('nbr_base')" :
  2716. *
  2717. * (1) (A) "The letters from 'a' (or 'A') to 'z' (or 'Z') inclusive are
  2718. * ascribed the values 10 to 35"; ...
  2719. * (B) "only letters whose ascribed values are less than that of base
  2720. * are permitted."
  2721. *
  2722. * (2) (A) "If the value of 'base' ('nbr_base') is 16, the characters '0x' or
  2723. * '0X' may optionally precede the sequence of letters and digits."
  2724. *
  2725. * (B) Although NO specification states that "if the value of 'base'
  2726. * ('nbr_base') is" 8, the '0' character "may optionally precede
  2727. * the sequence of letters and digits"; it seems reasonable to
  2728. * allow the '0' character to be optionally parsed.
  2729. *
  2730. * (2) "A subject sequence .... may be preceded by a '+' or '-' sign."
  2731. *
  2732. * (a) However, it does NOT seem reasonable to parse & convert a negative number
  2733. * integer string into an unsigned integer.
  2734. *
  2735. * (C) (1) (a) "A final string of one or more unrecognized characters," ...
  2736. * (b) "including the terminating null byte of the input string" ...
  2737. * (2) "other than a sign or a permissible letter or digit."
  2738. *$PAGE*
  2739. * (2) Second, "they shall attempt to convert the subject sequence to an integer" :
  2740. *
  2741. * (A) "If the subject sequence is empty or does not have the expected form" :
  2742. *
  2743. * (1) "no conversion is performed"; ...
  2744. * (2) "the value of 'str' ('pstr') is stored in the object pointed to by 'endptr'
  2745. * ('pstr_next'), provided that 'endptr' ('pstr_next') is not a null pointer."
  2746. *
  2747. * (B) "If the subject sequence has the expected form" :
  2748. *
  2749. * (1) (a) "and the value of 'base' ('nbr_base') is 0, the sequence of characters
  2750. * starting with the first digit shall be interpreted as an integer constant."
  2751. *
  2752. * (b) "and the value of 'base' ('nbr_base') is between 2 and 36, it shall be
  2753. * used as the base for conversion, ascribing to each letter its value as
  2754. * given above" (see Note #2a1B1b1A).
  2755. *
  2756. * (2) "A pointer to the final string shall be stored in the object pointed to by
  2757. * 'endptr' ('pstr_next'), provided that 'endptr' ('pstr_next') is not a null
  2758. * pointer."
  2759. *
  2760. * (3) Lastly, IEEE Std 1003.1, 2004 Edition, Section 'strtol() : RETURN VALUE' states that :
  2761. *
  2762. * (A) "Upon successful completion, these functions shall return the converted value."
  2763. *
  2764. * (1) "If the correct value is outside the range of representable values", either
  2765. * of the following "shall be returned" :
  2766. * (a) "{LONG_MIN}" or ...
  2767. * (b) "{LONG_MAX}"
  2768. *
  2769. * (B) "If no conversion could be performed, 0 shall be returned."
  2770. *
  2771. * (b) (1) IEEE Std 1003.1, 2004 Edition, Section 'strtoul() : ERRORS' states that "these functions
  2772. * shall fail if" :
  2773. *
  2774. * (A) "[EINVAL] - The value of 'base' ('nbr_base') is not supported."
  2775. *
  2776. * (B) "[ERANGE] - The value to be returned is not representable."
  2777. *
  2778. * (2) IEEE Std 1003.1, 2004 Edition, Section 'strtoul() : ERRORS' states that "these functions
  2779. * may fail if" :
  2780. *
  2781. * (A) "[EINVAL] - No conversion could be performed."
  2782. *
  2783. * (3) Return integer value & next string pointer should be used to diagnose parse success or failure :
  2784. *
  2785. * (a) Valid parse string integer :
  2786. *
  2787. * pstr = " ABCDE xyz"
  2788. * nbr_base = 16
  2789. *
  2790. * nbr = 703710
  2791. * pstr_next = " xyz"
  2792. *
  2793. *
  2794. * (b) Invalid parse string integer :
  2795. *
  2796. * pstr = " ABCDE"
  2797. * nbr_base = 10
  2798. *
  2799. * nbr = 0
  2800. * pstr_next = pstr = " ABCDE"
  2801. *
  2802. *
  2803. * (c) Valid hexadecimal parse string integer :
  2804. *
  2805. * pstr = " 0xGABCDE"
  2806. * nbr_base = 16
  2807. *
  2808. * nbr = 0
  2809. * pstr_next = "xGABCDE"
  2810. *
  2811. *
  2812. * (d) Valid decimal parse string integer ('0x' prefix ignored
  2813. * following invalid hexadecimal characters) :
  2814. *
  2815. * pstr = " 0xGABCDE"
  2816. * nbr_base = 0
  2817. *
  2818. * nbr = 0
  2819. * pstr_next = "xGABCDE"
  2820. *
  2821. *
  2822. * (e) Valid decimal parse string integer ('0' prefix ignored
  2823. * following invalid octal characters) :
  2824. *
  2825. * pstr = " 0GABCDE"
  2826. * nbr_base = 0
  2827. *
  2828. * nbr = 0
  2829. * pstr_next = "GABCDE"
  2830. *
  2831. *$PAGE*
  2832. * (f) Parse string integer overflow :
  2833. *
  2834. * pstr = " 12345678901234567890*123456"
  2835. * nbr_base = 10
  2836. *
  2837. * nbr = DEF_INT_32S_MAX_VAL
  2838. * pstr_next = "*123456"
  2839. *
  2840. *
  2841. * (g) Parse string integer underflow :
  2842. *
  2843. * pstr = " -12345678901234567890*123456"
  2844. * nbr_base = 10
  2845. *
  2846. * nbr = DEF_INT_32S_MIN_VAL
  2847. * pstr_next = "*123456"
  2848. *
  2849. *********************************************************************************************************
  2850. */
  2851. CPU_INT32S Str_ParseNbr_Int32S (const CPU_CHAR *pstr,
  2852. CPU_CHAR **pstr_next,
  2853. CPU_INT08U nbr_base)
  2854. {
  2855. CPU_INT32S nbr;
  2856. CPU_INT32U nbr_abs;
  2857. CPU_BOOLEAN nbr_neg;
  2858. nbr_abs = Str_ParseNbr_Int32(pstr, /* Parse/convert str ... */
  2859. pstr_next,
  2860. nbr_base,
  2861. DEF_YES, /* ... as signed int (see Note #2a2). */
  2862. &nbr_neg);
  2863. if (nbr_neg == DEF_NO) { /* Chk for neg nbr & ovf/undf (see Note #2a3A1). */
  2864. nbr = (nbr_abs > (CPU_INT32U) DEF_INT_32S_MAX_VAL) ? (CPU_INT32S)DEF_INT_32S_MAX_VAL
  2865. : (CPU_INT32S)nbr_abs;
  2866. } else {
  2867. nbr = (nbr_abs > (CPU_INT32U)-DEF_INT_32S_MIN_VAL_ONES_CPL) ? (CPU_INT32S)DEF_INT_32S_MIN_VAL
  2868. : -(CPU_INT32S)nbr_abs;
  2869. }
  2870. return (nbr);
  2871. }
  2872. /*$PAGE*/
  2873. /*
  2874. *********************************************************************************************************
  2875. *********************************************************************************************************
  2876. * LOCAL FUNCTIONS
  2877. *********************************************************************************************************
  2878. *********************************************************************************************************
  2879. */
  2880. /*
  2881. *********************************************************************************************************
  2882. * Str_FmtNbr_Int32()
  2883. *
  2884. * Description : Format 32-bit integer into a multi-digit character string.
  2885. *
  2886. * Argument(s) : nbr Number to format.
  2887. *
  2888. * nbr_dig Number of digits to format (see Note #1).
  2889. *
  2890. * nbr_base Base of number to format (see Note #2).
  2891. *
  2892. * nbr_neg Indicates whether number to format is negative :
  2893. * -------
  2894. * DEF_NO Number is non-negative.
  2895. * DEF_YES Number is negative.
  2896. *
  2897. * Argument validated in Str_FmtNbr_Int32U(),
  2898. * Str_FmtNbr_Int32S().
  2899. *
  2900. * lead_char Prepend leading character (see Note #3) :
  2901. *
  2902. * '\0' Do NOT prepend leading character to string.
  2903. * Printable character Prepend leading character to string.
  2904. * Unprintable character Format invalid string (see Note #6e).
  2905. *
  2906. * lower_case Format alphabetic characters (if any) in lower case :
  2907. *
  2908. * DEF_NO Format alphabetic characters in upper case.
  2909. * DEF_YES Format alphabetic characters in lower case.
  2910. *
  2911. * nul Append terminating NULL-character (see Note #4) :
  2912. *
  2913. * DEF_NO Do NOT append terminating NULL-character to string.
  2914. * DEF_YES Append terminating NULL-character to string.
  2915. *
  2916. * pstr Pointer to character array to return formatted number string (see Note #5).
  2917. *
  2918. * Return(s) : Pointer to formatted string, if NO error(s) [see Note #6f].
  2919. *
  2920. * Pointer to NULL, otherwise.
  2921. *
  2922. * Caller(s) : Str_FmtNbr_Int32U(),
  2923. * Str_FmtNbr_Int32S().
  2924. *$PAGE*
  2925. * Note(s) : (1) (a) The maximum number of digits to format for 32-bit integer numbers :
  2926. *
  2927. *
  2928. * Maximum Number of [ log (Number) ]
  2929. * 32-bit Integer Digits = floor [ -------------- + 1 ]
  2930. * to Format [ log (Base) ]
  2931. *
  2932. * where
  2933. * Number Number to format
  2934. * Base Base of number to format
  2935. *
  2936. * (b) (1) If the number of digits to format ('nbr_dig') is zero; then NO formatting
  2937. * is performed except possible NULL-termination of the string (see Note #4).
  2938. *
  2939. * Example :
  2940. *
  2941. * nbr = -23456
  2942. * nbr_dig = 0
  2943. * nbr_base = 10
  2944. *
  2945. * pstr = "" See Note #7a
  2946. *
  2947. * (2) If the number of digits to format ('nbr_dig') is less than the number of
  2948. * significant integer digits of the number to format ('nbr'); then an invalid
  2949. * string is formatted instead of truncating any significant integer digits.
  2950. *
  2951. * Example :
  2952. *
  2953. * nbr = 23456
  2954. * nbr_dig = 3
  2955. * nbr_base = 10
  2956. *
  2957. * pstr = "???" See Note #7b
  2958. *
  2959. * (3) If the number to format ('nbr') is negative but the number of digits to format
  2960. * ('nbr_dig') is equal to the number of significant integer digits of the number
  2961. * to format ('nbr'); then an invalid string is formatted instead of truncating
  2962. * the negative sign.
  2963. *
  2964. * Example :
  2965. *
  2966. * nbr = -23456
  2967. * nbr_dig = 5
  2968. * nbr_base = 10
  2969. *
  2970. * pstr = "?????" See Note #7b
  2971. *
  2972. * (2) The number's base MUST be between 2 & 36, inclusive.
  2973. *$PAGE*
  2974. * (3) Leading character option prepends leading characters prior to the first non-zero digit.
  2975. *
  2976. * (a) (1) Leading character MUST be a printable ASCII character.
  2977. *
  2978. * (2) (A) Leading character MUST NOT be a number base digit, ...
  2979. * (B) with the exception of '0'.
  2980. *
  2981. * (b) (1) The number of leading characters is such that the total number of significant
  2982. * integer digits plus the number of leading characters plus possible negative
  2983. * sign character is equal to the requested number of integer digits to format
  2984. * ('nbr_dig').
  2985. *
  2986. * Examples :
  2987. *
  2988. * nbr = 23456
  2989. * nbr_dig = 7
  2990. * nbr_base = 10
  2991. * lead_char = ' '
  2992. *
  2993. * pstr = " 23456"
  2994. *
  2995. *
  2996. * nbr = -23456
  2997. * nbr_dig = 7
  2998. * nbr_base = 10
  2999. * lead_char = ' '
  3000. *
  3001. * pstr = " -23456"
  3002. *
  3003. * (2) (A) If the number to format ('nbr') is negative AND the leading character
  3004. * ('lead_char') is a '0' digit; then the negative sign character
  3005. * prefixes all leading characters prior to the formatted number.
  3006. *
  3007. * Examples :
  3008. *
  3009. * nbr = -23456
  3010. * nbr_dig = 8
  3011. * nbr_base = 10
  3012. * lead_char = '0'
  3013. *
  3014. * pstr = "-0023456"
  3015. *
  3016. *
  3017. * nbr = -43981
  3018. * nbr_dig = 8
  3019. * nbr_base = 16
  3020. * lead_char = '0'
  3021. * lower_case = DEF_NO
  3022. *
  3023. * pstr = "-000ABCD"
  3024. *
  3025. * (B) If the number to format ('nbr') is negative AND the leading character
  3026. * ('lead_char') is NOT a '0' digit; then the negative sign character
  3027. * immediately prefixes the most significant digit of the formatted number.
  3028. *
  3029. * Examples :
  3030. *
  3031. * nbr = -23456
  3032. * nbr_dig = 8
  3033. * nbr_base = 10
  3034. * lead_char = '#'
  3035. *
  3036. * pstr = "##-23456"
  3037. *
  3038. *
  3039. * nbr = -43981
  3040. * nbr_dig = 8
  3041. * nbr_base = 16
  3042. * lead_char = '#'
  3043. * lower_case = DEF_YES
  3044. *
  3045. * pstr = "###-abcd"
  3046. *
  3047. * (c) (1) If the value of the number to format is zero ...
  3048. * (2) ... & the number of digits to format is non-zero, ...
  3049. * (3) ... but NO leading character available; ...
  3050. * (4) ... then one digit of '0' value is formatted.
  3051. *
  3052. * This is NOT a leading character; but a single integer digit of '0' value.
  3053. *$PAGE*
  3054. * (4) (a) NULL-character terminate option DISABLED prevents overwriting previous character
  3055. * array formatting.
  3056. *
  3057. * (b) WARNING: Unless 'pstr' character array is pre-/post-terminated, NULL-character
  3058. * terminate option DISABLED will cause character string run-on.
  3059. *
  3060. * (5) (a) Format buffer size NOT validated; buffer overruns MUST be prevented by caller.
  3061. *
  3062. * (b) To prevent character buffer overrun :
  3063. *
  3064. * Character array size MUST be >= ('nbr_dig' +
  3065. * 1 negative sign +
  3066. * 1 'NUL' terminator) characters
  3067. *
  3068. * (6) String format terminates when :
  3069. *
  3070. * (a) Format string pointer is passed a NULL pointer.
  3071. * (1) No string formatted; NULL pointer returned.
  3072. *
  3073. * (b) Number of digits to format ('nbr_dig') is zero.
  3074. * (1) NULL string formatted (see Note #7a); NULL pointer returned.
  3075. *
  3076. * (c) Number of digits to format ('nbr_dig') is less than number of significant
  3077. * integer digits of the number to format ('nbr'), including possible
  3078. * negative sign.
  3079. * (1) Invalid string formatted (see Note #7); NULL pointer returned.
  3080. *
  3081. * (d) Base is passed an invalid base (see Note #2).
  3082. * (1) Invalid string format performed; NULL pointer returned.
  3083. *
  3084. * (e) Lead character is NOT a valid, printable character (see Note #3a).
  3085. * (1) Invalid string formatted (see Note #7); NULL pointer returned.
  3086. *
  3087. * (f) Number successfully formatted into character string array.
  3088. *
  3089. * (7) For any unsuccessful string format or error(s), an invalid string of question marks
  3090. * ('?') will be formatted, where the number of question marks is determined by the
  3091. * number of digits to format ('nbr_dig') :
  3092. *
  3093. * Invalid string's { (a) 0 (NULL string) , if 'nbr_dig' = 0
  3094. * number of = {
  3095. * question marks { (b) 'nbr_dig' , if 'nbr_dig' > 0
  3096. *
  3097. *********************************************************************************************************
  3098. */
  3099. static CPU_CHAR *Str_FmtNbr_Int32 (CPU_INT32U nbr,
  3100. CPU_INT08U nbr_dig,
  3101. CPU_INT08U nbr_base,
  3102. CPU_BOOLEAN nbr_neg,
  3103. CPU_CHAR lead_char,
  3104. CPU_BOOLEAN lower_case,
  3105. CPU_BOOLEAN nul,
  3106. CPU_CHAR *pstr)
  3107. {
  3108. CPU_CHAR *pstr_fmt;
  3109. CPU_DATA i;
  3110. CPU_INT32U nbr_fmt;
  3111. CPU_INT32U nbr_log;
  3112. CPU_INT08U nbr_dig_max;
  3113. CPU_INT08U nbr_dig_min;
  3114. CPU_INT08U nbr_dig_fmtd;
  3115. CPU_INT08U nbr_neg_sign;
  3116. CPU_INT08U nbr_lead_char;
  3117. CPU_INT08U dig_val;
  3118. CPU_INT08U lead_char_delta_0;
  3119. CPU_INT08U lead_char_delta_a;
  3120. CPU_BOOLEAN lead_char_dig;
  3121. CPU_BOOLEAN lead_char_0;
  3122. CPU_BOOLEAN fmt_invalid;
  3123. CPU_BOOLEAN print_char;
  3124. CPU_BOOLEAN nbr_neg_fmtd;
  3125. /*$PAGE*/
  3126. /* ---------------- VALIDATE FMT ARGS ----------------- */
  3127. if (pstr == (CPU_CHAR *)0) { /* Rtn NULL if str ptr NULL (see Note #6a). */
  3128. return ((CPU_CHAR *)0);
  3129. }
  3130. fmt_invalid = DEF_NO;
  3131. if (nbr_dig < 1) { /* If nbr digs = 0, ... */
  3132. fmt_invalid = DEF_YES; /* ... fmt invalid str (see Note #6b). */
  3133. }
  3134. /* If invalid base, ... */
  3135. if ((nbr_base < 2u) ||
  3136. (nbr_base > 36u)) {
  3137. fmt_invalid = DEF_YES; /* ... fmt invalid str (see Note #6d). */
  3138. }
  3139. if (lead_char != (CPU_CHAR)'\0') {
  3140. print_char = ASCII_IsPrint(lead_char);
  3141. if (print_char != DEF_YES) { /* If lead char non-printable (see Note #3a1), ... */
  3142. fmt_invalid = DEF_YES; /* ... fmt invalid str (see Note #6e). */
  3143. } else if (lead_char != '0') { /* Chk lead char for non-0 nbr base dig. */
  3144. lead_char_delta_0 = (CPU_INT08U)(lead_char - '0');
  3145. if (lower_case != DEF_YES) {
  3146. lead_char_delta_a = (CPU_INT08U)(lead_char - 'A');
  3147. } else {
  3148. lead_char_delta_a = (CPU_INT08U)(lead_char - 'a');
  3149. }
  3150. lead_char_dig = (((nbr_base <= 10u) && (lead_char_delta_0 < nbr_base)) ||
  3151. ((nbr_base > 10u) && ((lead_char_delta_0 < 10u) ||
  3152. (lead_char_delta_a < (nbr_base - 10u))))) ? DEF_YES : DEF_NO;
  3153. if (lead_char_dig == DEF_YES) { /* If lead char non-0 nbr base dig (see Note #3a2A), ...*/
  3154. fmt_invalid = DEF_YES; /* ... fmt invalid str (see Note #6e). */
  3155. }
  3156. }
  3157. }
  3158. /* ----------------- PREPARE NBR FMT ------------------ */
  3159. pstr_fmt = pstr;
  3160. if (fmt_invalid == DEF_NO) {
  3161. nbr_fmt = nbr;
  3162. nbr_log = nbr;
  3163. nbr_dig_max = 1u;
  3164. while (nbr_log >= nbr_base) { /* While nbr base digs avail, ... */
  3165. nbr_dig_max++; /* ... calc max nbr digs. */
  3166. nbr_log /= nbr_base;
  3167. }
  3168. nbr_neg_sign = (nbr_neg == DEF_YES) ? 1u : 0u;
  3169. if (nbr_dig >= (nbr_dig_max + nbr_neg_sign)) { /* If req'd nbr digs >= (max nbr digs + neg sign), ... */
  3170. nbr_neg_fmtd = DEF_NO;
  3171. nbr_dig_min = DEF_MIN(nbr_dig_max, nbr_dig);
  3172. /* ... calc nbr digs to fmt & nbr lead chars. */
  3173. if (lead_char != (CPU_CHAR)'\0') {
  3174. nbr_dig_fmtd = nbr_dig;
  3175. nbr_lead_char = nbr_dig -
  3176. nbr_dig_min - nbr_neg_sign;
  3177. } else {
  3178. nbr_dig_fmtd = nbr_dig_min + nbr_neg_sign;
  3179. nbr_lead_char = 0u;
  3180. }
  3181. if (nbr_lead_char > 0) { /* If lead chars to fmt, ... */
  3182. lead_char_0 = (lead_char == '0') /* ... chk if lead char a '0' dig (see Note #3a2B). */
  3183. ? DEF_YES : DEF_NO;
  3184. } else {
  3185. lead_char_0 = DEF_NO;
  3186. }
  3187. } else { /* Else if nbr trunc'd, ... */
  3188. fmt_invalid = DEF_YES; /* ... fmt invalid str (see Note #6c). */
  3189. }
  3190. }
  3191. if (fmt_invalid != DEF_NO) {
  3192. nbr_dig_fmtd = nbr_dig;
  3193. }
  3194. /*$PAGE*/
  3195. /* ------------------- FMT NBR STR -------------------- */
  3196. pstr_fmt += nbr_dig_fmtd; /* Start fmt @ least-sig dig. */
  3197. if (nul != DEF_NO) { /* If NOT DISABLED, append NULL char (see Note #4). */
  3198. *pstr_fmt = (CPU_CHAR)'\0';
  3199. }
  3200. pstr_fmt--;
  3201. for (i = 0u; i < nbr_dig_fmtd; i++) { /* Fmt str for desired nbr digs : */
  3202. if (fmt_invalid == DEF_NO) {
  3203. if ((nbr_fmt > 0) || /* If fmt nbr > 0 ... */
  3204. (i == 0u)) { /* ... OR on one's dig to fmt (see Note #3c1), ... */
  3205. /* ... calc & fmt dig val; ... */
  3206. dig_val = (CPU_INT08U)(nbr_fmt % nbr_base);
  3207. if (dig_val < 10u) {
  3208. *pstr_fmt-- = (CPU_CHAR)(dig_val + '0');
  3209. } else {
  3210. if (lower_case != DEF_YES) {
  3211. *pstr_fmt-- = (CPU_CHAR)((dig_val - 10u) + 'A');
  3212. } else {
  3213. *pstr_fmt-- = (CPU_CHAR)((dig_val - 10u) + 'a');
  3214. }
  3215. }
  3216. nbr_fmt /= nbr_base; /* Shift to next more-sig dig. */
  3217. } else if ((nbr_neg == DEF_YES) && /* ... else if nbr neg AND ... */
  3218. (((lead_char_0 == DEF_NO ) && /* ... lead char NOT a '0' dig ... */
  3219. (nbr_neg_fmtd == DEF_NO )) || /* ... but neg sign NOT yet fmt'd OR ... */
  3220. ((lead_char_0 != DEF_NO ) && /* ... lead char is a '0' dig ... */
  3221. (i == (nbr_dig_fmtd - 1u))))) { /* ... & on most-sig dig to fmt, ... */
  3222. *pstr_fmt-- = '-'; /* ... prepend neg sign (see Note #3b); ... */
  3223. nbr_neg_fmtd = DEF_YES;
  3224. } else if (lead_char != (CPU_CHAR)'\0') { /* ... else if avail, ... */
  3225. *pstr_fmt-- = lead_char; /* ... fmt lead char. */
  3226. }
  3227. } else { /* Else fmt '?' for invalid str (see Note #7). */
  3228. *pstr_fmt-- = '?';
  3229. }
  3230. }
  3231. if (fmt_invalid != DEF_NO) { /* Rtn NULL for invalid str fmt (see Notes #6a - #6e). */
  3232. return ((CPU_CHAR *)0);
  3233. }
  3234. return (pstr); /* Rtn ptr to fmt'd str (see Note #6f). */
  3235. }
  3236. /*$PAGE*/
  3237. /*
  3238. *********************************************************************************************************
  3239. * Str_ParseNbr_Int32()
  3240. *
  3241. * Description : Parse 32-bit integer from string.
  3242. *
  3243. * Argument(s) : pstr Pointer to string (see Notes #1 & #2a).
  3244. *
  3245. * pstr_next Optional pointer to a variable to ... :
  3246. *
  3247. * (a) Return a pointer to first character following the integer string,
  3248. * if NO error(s) [see Note #2a2B2];
  3249. * (b) Return a pointer to 'pstr',
  3250. * otherwise (see Note #2a2A2).
  3251. *
  3252. * nbr_base Base of number to parse (see Notes #2a1B1 & #2a2B1).
  3253. *
  3254. * nbr_signed Indicates whether number to parse is signed :
  3255. *
  3256. * DEF_NO Number is unsigned.
  3257. * DEF_YES Number is signed.
  3258. *
  3259. * pnbr_neg Pointer to a variable to return if the parsed (signed) number is negative :
  3260. *
  3261. * DEF_NO Number is non-negative.
  3262. * DEF_YES Number is negative.
  3263. *
  3264. * Return(s) : Parsed integer, if integer parsed with NO overflow (see Note #2a3A).
  3265. *
  3266. * DEF_INT_32U_MAX_VAL, if integer parsed but overflowed (see Note #2a3A1).
  3267. *
  3268. * 0, otherwise (see Note #2a3B).
  3269. *
  3270. * Caller(s) : Str_ParseNbr_Int32U(),
  3271. * Str_ParseNbr_Int32S().
  3272. *
  3273. * Note(s) : (1) String buffer NOT modified.
  3274. *
  3275. * (2) (a) IEEE Std 1003.1, 2004 Edition, Section 'strtol() : DESCRIPTION' states that "these
  3276. * functions shall convert the initial portion of the string pointed to by 'str' ('pstr')
  3277. * to a type long ... representation" :
  3278. *
  3279. * (1) "First, they decompose the input string into three parts" :
  3280. *
  3281. * (A) "An initial, possibly empty, sequence of white-space characters [as specified
  3282. * by isspace()]."
  3283. *
  3284. * (1) "The subject sequence is defined as the longest initial subsequence of the
  3285. * input string, starting with the first non-white-space character that is of
  3286. * the expected form. The subject sequence shall contain no characters if the
  3287. * input string is empty or consists entirely of white-space characters."
  3288. *
  3289. * (B) (1) "A subject sequence interpreted as an integer represented in some radix
  3290. * determined by the value of 'base' ('nbr_base')" :
  3291. *
  3292. * (a) "If the value of 'base' ('nbr_base') is 0, the expected form of the
  3293. * subject sequence is that of a decimal constant, octal constant, or
  3294. * hexadecimal constant" :
  3295. *
  3296. * (1) "A decimal constant begins with a non-zero digit, and consists of a
  3297. * sequence of decimal digits."
  3298. *
  3299. * (2) "An octal constant consists of the prefix '0' optionally followed by
  3300. * a sequence of the digits '0' to '7' only."
  3301. *
  3302. * (3) "A hexadecimal constant consists of the prefix '0x' or '0X' followed
  3303. * by a sequence of the decimal digits and letters 'a' (or 'A') to 'f'
  3304. * (or 'F') with values 10 to 15 respectively."
  3305. *
  3306. * (b) "If the value of 'base' ('nbr_base') is between 2 and 36, the expected form
  3307. * of the subject sequence is a sequence of letters and digits representing
  3308. * an integer with the radix specified by 'base' ('nbr_base')" :
  3309. *
  3310. * (1) (A) "The letters from 'a' (or 'A') to 'z' (or 'Z') inclusive are
  3311. * ascribed the values 10 to 35"; ...
  3312. * (B) "only letters whose ascribed values are less than that of base
  3313. * are permitted."
  3314. *
  3315. * (2) (A) "If the value of 'base' ('nbr_base') is 16, the characters '0x' or
  3316. * '0X' may optionally precede the sequence of letters and digits."
  3317. *
  3318. * (B) Although NO specification states that "if the value of 'base'
  3319. * ('nbr_base') is" 8, the '0' character "may optionally precede
  3320. * the sequence of letters and digits"; it seems reasonable to
  3321. * allow the '0' character to be optionally parsed.
  3322. *$PAGE*
  3323. * (2) "A subject sequence .... may be preceded by a '+' or '-' sign."
  3324. *
  3325. * (a) It does NOT seem reasonable to parse & convert a negative number
  3326. * integer string into an unsigned integer. However, a negative sign
  3327. * for an unsigned integer will automatically be parsed as an invalid
  3328. * character (see Note #2aC1).
  3329. *
  3330. * (C) (1) (a) "A final string of one or more unrecognized characters," ...
  3331. * (b) "including the terminating null byte of the input string" ...
  3332. * (2) "other than a sign or a permissible letter or digit."
  3333. *
  3334. * (2) Second, "they shall attempt to convert the subject sequence to an integer" :
  3335. *
  3336. * (A) "If the subject sequence is empty or does not have the expected form" :
  3337. *
  3338. * (1) "no conversion is performed"; ...
  3339. * (2) "the value of 'str' ('pstr') is stored in the object pointed to by 'endptr'
  3340. * ('pstr_next'), provided that 'endptr' ('pstr_next') is not a null pointer."
  3341. *
  3342. * (B) "If the subject sequence has the expected form" :
  3343. *
  3344. * (1) (a) "and the value of 'base' ('nbr_base') is 0, the sequence of characters
  3345. * starting with the first digit shall be interpreted as an integer constant."
  3346. *
  3347. * (b) "and the value of 'base' ('nbr_base') is between 2 and 36, it shall be
  3348. * used as the base for conversion, ascribing to each letter its value as
  3349. * given above" (see Note #2a1B1b1A).
  3350. *
  3351. * (2) "A pointer to the final string shall be stored in the object pointed to by
  3352. * 'endptr' ('pstr_next'), provided that 'endptr' ('pstr_next') is not a null
  3353. * pointer."
  3354. *
  3355. * (3) Lastly, IEEE Std 1003.1, 2004 Edition, Section 'strtol() : RETURN VALUE' states that :
  3356. *
  3357. * (A) "Upon successful completion, these functions shall return the converted value."
  3358. * (1) "If the correct value is outside the range of representable values, {LONG_MIN}
  3359. * [or] {LONG_MAX} ... shall be returned."
  3360. *
  3361. * (B) "If no conversion could be performed, 0 shall be returned."
  3362. *
  3363. * (b) (1) IEEE Std 1003.1, 2004 Edition, Section 'strtoul() : ERRORS' states that "these functions
  3364. * shall fail if" :
  3365. *
  3366. * (A) "[EINVAL] - The value of 'base' ('nbr_base') is not supported."
  3367. *
  3368. * (B) "[ERANGE] - The value to be returned is not representable."
  3369. *
  3370. * (2) IEEE Std 1003.1, 2004 Edition, Section 'strtoul() : ERRORS' states that "these functions
  3371. * may fail if" :
  3372. *
  3373. * (A) "[EINVAL] - No conversion could be performed."
  3374. *$PAGE*
  3375. * (3) Return integer value & next string pointer should be used to diagnose parse success or failure :
  3376. *
  3377. * (a) Valid parse string integer :
  3378. *
  3379. * pstr = " ABCDE xyz"
  3380. * nbr_base = 16
  3381. *
  3382. * nbr = 703710
  3383. * pstr_next = " xyz"
  3384. *
  3385. *
  3386. * (b) Invalid parse string integer :
  3387. *
  3388. * pstr = " ABCDE"
  3389. * nbr_base = 10
  3390. *
  3391. * nbr = 0
  3392. * pstr_next = pstr = " ABCDE"
  3393. *
  3394. *
  3395. * (c) Valid hexadecimal parse string integer :
  3396. *
  3397. * pstr = " 0xGABCDE"
  3398. * nbr_base = 16
  3399. *
  3400. * nbr = 0
  3401. * pstr_next = "xGABCDE"
  3402. *
  3403. *
  3404. * (d) Valid decimal parse string integer ('0x' prefix ignored
  3405. * following invalid hexadecimal characters) :
  3406. *
  3407. * pstr = " 0xGABCDE"
  3408. * nbr_base = 0
  3409. *
  3410. * nbr = 0
  3411. * pstr_next = "xGABCDE"
  3412. *
  3413. *
  3414. * (e) Valid decimal parse string integer ('0' prefix ignored
  3415. * following invalid octal characters) :
  3416. *
  3417. * pstr = " 0GABCDE"
  3418. * nbr_base = 0
  3419. *
  3420. * nbr = 0
  3421. * pstr_next = "GABCDE"
  3422. *
  3423. *
  3424. * (f) Parse string integer overflow :
  3425. *
  3426. * pstr = " 12345678901234567890*123456"
  3427. * nbr_base = 10
  3428. *
  3429. * nbr = DEF_INT_32U_MAX_VAL
  3430. * pstr_next = "*123456"
  3431. *
  3432. *
  3433. * (g) Parse string integer underflow :
  3434. *
  3435. * pstr = " -12345678901234567890*123456"
  3436. * nbr_base = 10
  3437. *
  3438. * nbr = DEF_INT_32S_MIN_VAL
  3439. * pstr_next = "*123456"
  3440. *
  3441. *
  3442. * (4) String parse terminates when :
  3443. *
  3444. * (a) Base passed an invalid base (see Note #2a1B1b).
  3445. * (1) No conversion performed; 0 returned.
  3446. *
  3447. * (b) (1) Parse string passed a NULL pointer OR empty integer sequence (see Note #2a2A).
  3448. * (A) No conversion performed; 0 returned.
  3449. *
  3450. * (2) Invalid parse string character found (see Note #2a1C).
  3451. * (A) Parsed integer returned.
  3452. * (B) 'pstr_next' points to invalid character.
  3453. *
  3454. * (3) Entire parse string converted (see Note #2a2B).
  3455. * (A) Parsed integer returned.
  3456. * (B) 'pstr_next' points to terminating NULL character.
  3457. *
  3458. * (5) Pointers to variables that return values MUST be initialized PRIOR to all other
  3459. * validation or function handling in case of any error(s).
  3460. *********************************************************************************************************
  3461. */
  3462. /*$PAGE*/
  3463. static CPU_INT32U Str_ParseNbr_Int32 (const CPU_CHAR *pstr,
  3464. CPU_CHAR **pstr_next,
  3465. CPU_INT08U nbr_base,
  3466. CPU_BOOLEAN nbr_signed,
  3467. CPU_BOOLEAN *pnbr_neg)
  3468. {
  3469. const CPU_CHAR *pstr_parse;
  3470. const CPU_CHAR *pstr_parse_nbr;
  3471. CPU_CHAR *pstr_parse_unused;
  3472. CPU_CHAR parse_char;
  3473. CPU_INT08U parse_dig;
  3474. CPU_INT32U nbr;
  3475. CPU_BOOLEAN nbr_neg_unused;
  3476. CPU_BOOLEAN nbr_dig;
  3477. CPU_BOOLEAN nbr_alpha;
  3478. CPU_BOOLEAN nbr_hex;
  3479. CPU_BOOLEAN nbr_hex_lower;
  3480. CPU_BOOLEAN whitespace;
  3481. CPU_BOOLEAN neg;
  3482. CPU_BOOLEAN ovf;
  3483. CPU_BOOLEAN done;
  3484. /* --------------- VALIDATE PARSE ARGS ---------------- */
  3485. if (pstr_next == (CPU_CHAR **) 0) { /* If NOT avail, ... */
  3486. pstr_next = (CPU_CHAR **)&pstr_parse_unused; /* ... re-cfg NULL rtn ptr to unused local var. */
  3487. (void)&pstr_parse_unused; /* Prevent possible 'variable unused' warning. */
  3488. }
  3489. *pstr_next = (CPU_CHAR *)pstr; /* Init rtn str for err (see Note #5). */
  3490. if (pnbr_neg == (CPU_BOOLEAN *) 0) { /* If NOT avail, ... */
  3491. pnbr_neg = (CPU_BOOLEAN *)&nbr_neg_unused; /* ... re-cfg NULL rtn ptr to unused local var. */
  3492. (void)&nbr_neg_unused; /* Prevent possible 'variable unused' warning. */
  3493. }
  3494. *pnbr_neg = DEF_NO; /* Init nbr neg for err (see Note #5). */
  3495. if (pstr == (CPU_CHAR *)0) { /* Rtn zero if str ptr NULL (see Note #4b1). */
  3496. return (0u);
  3497. }
  3498. /* Rtn zero if invalid base (see Note #4a). */
  3499. if ((nbr_base == 1u) ||
  3500. (nbr_base > 36u)) {
  3501. return (0u);
  3502. }
  3503. /* ------------- IGNORE PRECEDING CHAR(S) ------------- */
  3504. pstr_parse = pstr; /* Save ptr to init'l str for err (see Note #2a2A2). */
  3505. whitespace = ASCII_IsSpace(*pstr_parse);
  3506. while (whitespace == DEF_YES) { /* Ignore initial white-space char(s) [see Note #2a1A]. */
  3507. pstr_parse++;
  3508. whitespace = ASCII_IsSpace(*pstr_parse);
  3509. }
  3510. switch (*pstr_parse) {
  3511. case '+': /* Ignore pos sign (see Note #2a1B2). */
  3512. pstr_parse++;
  3513. neg = DEF_NO;
  3514. break;
  3515. case '-': /* Validate neg sign (see Note #2a1B2a). */
  3516. if (nbr_signed == DEF_YES) {
  3517. pstr_parse++;
  3518. }
  3519. neg = DEF_YES;
  3520. break;
  3521. default:
  3522. neg = DEF_NO;
  3523. break;
  3524. }
  3525. /*$PAGE*/
  3526. /* --------- IGNORE NBR BASE PRECEDING CHAR(S) -------- */
  3527. pstr_parse_nbr = pstr_parse; /* Save ptr to str's nbr (see Note #2a1A1). */
  3528. switch (nbr_base) {
  3529. case 0u: /* Determine unspecified nbr base (see Notes #2a1B1a). */
  3530. if (*pstr_parse == '0') { /* If avail, ... */
  3531. pstr_parse++; /* ... adv past '0' prefix (see Note #2a1B1b2). */
  3532. switch (*pstr_parse) {
  3533. case 'x': /* For '0x' prefix, ... */
  3534. case 'X':
  3535. nbr_base = 16u; /* ... set nbr base = 16 (see Note #2a1B1a3). */
  3536. parse_char = (CPU_CHAR)(*(pstr_parse + 1));
  3537. nbr_hex = ASCII_IsDigHex(parse_char);
  3538. if (nbr_hex == DEF_YES) { /* If next char is valid hex dig, ... */
  3539. pstr_parse++; /* ... adv past '0x' prefix (see Note #2a1B1b2A). */
  3540. }
  3541. break;
  3542. default: /* For '0' prefix, ... */
  3543. nbr_base = 8u; /* ... set nbr base = 8 (see Note #2a1B1a2). */
  3544. break;
  3545. }
  3546. } else { /* For non-'0' prefix, ... */
  3547. nbr_base = 10u; /* ... set nbr base = 10 (see Note #2a1B1a1). */
  3548. }
  3549. break;
  3550. case 8u: /* See Note #2a1B1a2. */
  3551. if (*pstr_parse == '0') { /* If avail, ... */
  3552. pstr_parse++; /* ... adv past '0' prefix (see Note #2a1B1b2B). */
  3553. }
  3554. break;
  3555. case 16u: /* See Note #2a1B1a3. */
  3556. if (*pstr_parse == '0') { /* If avail, ... */
  3557. pstr_parse++; /* ... adv past '0' prefix (see Note #2a1B1b2). */
  3558. switch (*pstr_parse) {
  3559. case 'x':
  3560. case 'X':
  3561. parse_char = (CPU_CHAR)(*(pstr_parse + 1));
  3562. nbr_hex = ASCII_IsDigHex(parse_char);
  3563. if (nbr_hex == DEF_YES) { /* If next char is valid hex dig, ... */
  3564. pstr_parse++; /* ... adv past '0x' prefix (see Note #2a1B1b2A). */
  3565. }
  3566. break;
  3567. default:
  3568. break;
  3569. }
  3570. }
  3571. break;
  3572. default: /* See Note #2a1B1b. */
  3573. break;
  3574. }
  3575. /*$PAGE*/
  3576. /* ------------------ PARSE INT STR ------------------- */
  3577. nbr = 0u;
  3578. ovf = DEF_NO;
  3579. done = DEF_NO;
  3580. while (done == DEF_NO) { /* Parse str for desired nbr base digs (see Note #2a2). */
  3581. parse_char = (CPU_CHAR)*pstr_parse;
  3582. nbr_alpha = ASCII_IsAlphaNum(parse_char);
  3583. if (nbr_alpha == DEF_YES) { /* If valid alpha num nbr dig avail, ... */
  3584. /* ... convert parse char into nbr dig. */
  3585. nbr_dig = ASCII_IsDig(parse_char);
  3586. if (nbr_dig == DEF_YES) {
  3587. parse_dig = (CPU_INT08U)(parse_char - '0');
  3588. } else {
  3589. nbr_hex_lower = ASCII_IsLower(parse_char);
  3590. if (nbr_hex_lower == DEF_YES) {
  3591. parse_dig = (CPU_INT08U)((parse_char - 'a') + 10u);
  3592. } else {
  3593. parse_dig = (CPU_INT08U)((parse_char - 'A') + 10u);
  3594. }
  3595. }
  3596. if (parse_dig < nbr_base) { /* If parse char valid for nbr base ... */
  3597. if (ovf == DEF_NO) { /* ... & nbr NOT yet ovf'd, ... */
  3598. if (nbr <= Str_MultOvfThTbl_Int32U[nbr_base]) {
  3599. /* ... merge parse char dig into nbr. */
  3600. nbr *= nbr_base;
  3601. nbr += parse_dig;
  3602. if (nbr < parse_dig) {
  3603. ovf = DEF_YES;
  3604. }
  3605. } else {
  3606. ovf = DEF_YES;
  3607. }
  3608. }
  3609. pstr_parse++;
  3610. } else { /* Invalid char parsed (see Note #2a1C1a). */
  3611. done = DEF_YES;
  3612. }
  3613. } else { /* Invalid OR NULL char parsed (see Note #2a1C1). */
  3614. done = DEF_YES;
  3615. }
  3616. }
  3617. if (ovf == DEF_YES) { /* If nbr ovf'd, ... */
  3618. nbr = DEF_INT_32U_MAX_VAL; /* ... rtn max int val (see Note #2a3A1). */
  3619. }
  3620. if (pstr_parse != pstr_parse_nbr) { /* If final parse str != init'l parse nbr str, .. */
  3621. *pstr_next = (CPU_CHAR *)pstr_parse; /* .. rtn parse str's next char (see Note #2a2B2); .. */
  3622. } else {
  3623. *pstr_next = (CPU_CHAR *)pstr; /* .. else rtn initial parse str (see Note #2a2A2). */
  3624. }
  3625. *pnbr_neg = neg; /* Rtn neg nbr status. */
  3626. return (nbr);
  3627. }