lib_str.c 200 KB

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