stdio.c 99 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677
  1. /* Copyright (C) 2002,2003,2004 Manuel Novoa III
  2. * My stdio library for linux and (soon) elks.
  3. *
  4. * This library is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU Library General Public
  6. * License as published by the Free Software Foundation; either
  7. * version 2 of the License, or (at your option) any later version.
  8. *
  9. * This library is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * Library General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU Library General Public
  15. * License along with this library; if not, write to the Free
  16. * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. */
  18. /* ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION!
  19. *
  20. * This code is currently under development. Also, I plan to port
  21. * it to elks which is a 16-bit environment with a fairly limited
  22. * compiler. Therefore, please refrain from modifying this code
  23. * and, instead, pass any bug-fixes, etc. to me. Thanks. Manuel
  24. *
  25. * ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION! */
  26. /* 8-05-2002
  27. * Changed fflush() behavior to no-op for r/w streams in read-mode.
  28. * This falls under undefined behavior wrt ANSI/ISO C99, but
  29. * SUSv3 seems to treat it as a no-op and it occurs in some apps.
  30. * Fixed a problem with _stdio_fwrite() not checking for underlying
  31. * write() failures.
  32. * Fixed both _stdio_fwrite() and _stdio_fread() to make sure that
  33. * the putc and getc macros were disabled if the stream was in
  34. * and error state.
  35. * The above changes should take care of a problem initially reported
  36. * by "Steven J. Hill" <sjhill@realitydiluted.com>.
  37. *
  38. * 8-25-2002
  39. * Changed fclose behavior when custom streams were enabled. Previously,
  40. * the cookie pointer was set to NULL as a debugging aid. However,
  41. * some of the perl 5.8 test rely on being able to close stderr and
  42. * still try writing to it. So now, the cookie pointer and handler
  43. * function pointers are set to that it is a "normal" file with a
  44. * file descriptor of -1. Note: The cookie pointer is reset to NULL
  45. * if the FILE struct is free'd by fclose.
  46. *
  47. * Nov 21, 2002
  48. * Added internal function _wstdio_fwrite.
  49. * Jan 3, 2003
  50. * Fixed a bug in _wstdio_fwrite.
  51. *
  52. * Jan 22, 2003
  53. * Fixed a bug related file position in append mode. _stdio_fwrite now
  54. * seeks to the end of the stream when append mode is set and we are
  55. * transitioning to write mode, so that subsequent ftell() return
  56. * values are correct.
  57. * Also fix _stdio_fopen to support fdopen() with append specified when
  58. * the underlying file didn't have O_APPEND set. It now sets the
  59. * O_APPEND flag as recommended by SUSv3 and is done by glibc.
  60. *
  61. * May 15, 2003
  62. * Modify __stdio_fread to deal with fake streams used by *sscanf.
  63. * Set EOF to end of buffer when fmemopen used on a readonly stream.
  64. * Note: I really need to run some tests on this to see what the
  65. * glibc code does in each case.
  66. *
  67. * Sept 21, 2003
  68. * Modify _stdio_READ to conform with C99, as stdio input behavior upon
  69. * encountering EOF changed with Defect Report #141. In the current
  70. * standard, the stream's EOF indicator is "sticky". Once it is set,
  71. * all further input from the stream should fail until the application
  72. * explicitly clears the EOF indicator (clearerr(), file positioning),
  73. * even if more data becomes available.
  74. * Fixed a bug in fgets. Wasn't checking for read errors.
  75. * Minor thread locking optimizations to avoid some unnecessary locking.
  76. * Remove the explicit calls to __builtin_* funcs, as we really need to
  77. * implement a more general solution.
  78. *
  79. * Nov 17, 2003
  80. * Fix the return value for fputs when passed an empty string.
  81. *
  82. * Jan 1, 2004
  83. * Fix __freadable and __fwritable... were using '~' instead of '!'. (ugh)
  84. * Fix (hopefully) a potential problem with failed freopen() calls. The
  85. * fix isn't tested since I've been working on the replacement stdio
  86. * core code which will go in after the next release.
  87. */
  88. /* Before we include anything, convert L_ctermid to L_ctermid_function
  89. * and undef L_ctermid if defined. This is necessary as L_ctermid is
  90. * a SUSv3 standard macro defined in stdio.h. */
  91. #ifdef L_ctermid
  92. #define L_ctermid_function
  93. #undef L_ctermid
  94. #endif
  95. #define _ISOC99_SOURCE /* for ULLONG primarily... */
  96. #define _GNU_SOURCE
  97. #define _STDIO_UTILITY /* for _stdio_fdout and _uintmaxtostr. */
  98. #include <stdio.h>
  99. #include <stddef.h>
  100. #include <stdlib.h>
  101. #include <string.h>
  102. #include <limits.h>
  103. #include <stdint.h>
  104. #include <stdarg.h>
  105. #include <errno.h>
  106. #include <assert.h>
  107. #include <stdio_ext.h>
  108. #include <unistd.h>
  109. #include <fcntl.h>
  110. #ifndef O_LARGEFILE /* uClibc undefines this if no large file support. */
  111. #ifdef __STDIO_LARGE_FILES
  112. #error missing define for O_LARGEFILE!
  113. #endif
  114. #define O_LARGEFILE 0
  115. #endif
  116. /**********************************************************************/
  117. /* First deal with some build issues... */
  118. #ifndef __STDIO_THREADSAFE
  119. /* Just build empty object files if any of these were defined. */
  120. /* Note though that we do keep the various *_unlocked names as aliases. */
  121. #undef L___fsetlocking
  122. #undef L___flockfile
  123. #undef L___ftrylockfile
  124. #undef L___funlockfile
  125. #endif
  126. #ifndef __STDIO_LARGE_FILES
  127. /* Just build empty object files if any of these were defined. */
  128. #undef L_fopen64
  129. #undef L_freopen64
  130. #undef L_ftello64
  131. #undef L_fseeko64
  132. #undef L_fsetpos64
  133. #undef L_fgetpos64
  134. #endif
  135. /**********************************************************************/
  136. #ifndef __STDIO_THREADSAFE
  137. #if defined(__BCC__) && 0
  138. #define UNLOCKED_STREAM(RETURNTYPE,NAME,PARAMS,ARGS,STREAM) \
  139. asm(".text\nexport _" "NAME" "_unlocked\n_" "NAME" "_unlocked = _" "NAME"); \
  140. RETURNTYPE NAME PARAMS
  141. #else
  142. #define UNLOCKED_STREAM(RETURNTYPE,NAME,PARAMS,ARGS,STREAM) \
  143. strong_alias(NAME,NAME##_unlocked) \
  144. RETURNTYPE NAME PARAMS
  145. #endif
  146. #define UNLOCKED(RETURNTYPE,NAME,PARAMS,ARGS) \
  147. UNLOCKED_STREAM(RETURNTYPE,NAME,PARAMS,ARGS,stream)
  148. #if defined(__BCC__) && 0
  149. #define UNLOCKED_VOID_RETURN(NAME,PARAMS,ARGS) \
  150. asm(".text\nexport _" "NAME" "_unlocked\n_" "NAME" "_unlocked = _" "NAME"); \
  151. void NAME PARAMS
  152. #else
  153. #define UNLOCKED_VOID_RETURN(NAME,PARAMS,ARGS) \
  154. strong_alias(NAME,NAME##_unlocked) \
  155. void NAME PARAMS
  156. #endif
  157. #define __STDIO_THREADLOCK_OPENLIST
  158. #define __STDIO_THREADUNLOCK_OPENLIST
  159. #else /* __STDIO_THREADSAFE */
  160. #include <pthread.h>
  161. #define UNLOCKED_STREAM(RETURNTYPE,NAME,PARAMS,ARGS,STREAM) \
  162. RETURNTYPE NAME PARAMS \
  163. { \
  164. RETURNTYPE retval; \
  165. __STDIO_THREADLOCK(STREAM); \
  166. retval = NAME##_unlocked ARGS ; \
  167. __STDIO_THREADUNLOCK(STREAM); \
  168. return retval; \
  169. } \
  170. RETURNTYPE NAME##_unlocked PARAMS
  171. #define UNLOCKED(RETURNTYPE,NAME,PARAMS,ARGS) \
  172. UNLOCKED_STREAM(RETURNTYPE,NAME,PARAMS,ARGS,stream)
  173. #define UNLOCKED_VOID_RETURN(NAME,PARAMS,ARGS) \
  174. void NAME PARAMS \
  175. { \
  176. __STDIO_THREADLOCK(stream); \
  177. NAME##_unlocked ARGS ; \
  178. __STDIO_THREADUNLOCK(stream); \
  179. } \
  180. void NAME##_unlocked PARAMS
  181. #define __STDIO_THREADLOCK_OPENLIST \
  182. __pthread_mutex_lock(&_stdio_openlist_lock)
  183. #define __STDIO_THREADUNLOCK_OPENLIST \
  184. __pthread_mutex_unlock(&_stdio_openlist_lock)
  185. #define __STDIO_THREADTRYLOCK_OPENLIST \
  186. __pthread_mutex_trylock(&_stdio_openlist_lock)
  187. #endif /* __STDIO_THREADSAFE */
  188. /**********************************************************************/
  189. #ifdef __STDIO_WIDE
  190. #define __STDIO_FILE_INIT_UNGOT { 0, 0 }, { 0, 0 },
  191. #else
  192. #define __STDIO_FILE_INIT_UNGOT { 0, 0 },
  193. #endif
  194. #ifdef __STDIO_GETC_MACRO
  195. #define __STDIO_FILE_INIT_BUFGETC(x) x,
  196. #else
  197. #define __STDIO_FILE_INIT_BUFGETC(x)
  198. #endif
  199. #ifdef __STDIO_PUTC_MACRO
  200. #define __STDIO_FILE_INIT_BUFPUTC(x) x,
  201. #else
  202. #define __STDIO_FILE_INIT_BUFPUTC(x)
  203. #endif
  204. #if defined(__STDIO_BUFFERS) || defined(__STDIO_GLIBC_CUSTOM_STREAMS)
  205. #define __STDIO_FILE_INIT_NEXT(next) (next),
  206. #else /* defined(__STDIO_BUFFERS) || defined(__STDIO_GLIBC_CUSTOM_STREAMS) */
  207. #define __STDIO_FILE_INIT_NEXT(next)
  208. #endif /* defined(__STDIO_BUFFERS) || defined(__STDIO_GLIBC_CUSTOM_STREAMS) */
  209. #ifdef __STDIO_BUFFERS
  210. #define __STDIO_FILE_INIT_BUFFERS(buf,bufsize) \
  211. (buf), (buf)+(bufsize), (buf), (buf),
  212. #else
  213. #define __STDIO_FILE_INIT_BUFFERS(buf,bufsize)
  214. #endif
  215. #ifdef __STDIO_GLIBC_CUSTOM_STREAMS
  216. #define __STDIO_FILE_INIT_CUSTOM_STREAM(stream) \
  217. &((stream).filedes), { _cs_read, _cs_write, NULL, _cs_close },
  218. #else
  219. #define __STDIO_FILE_INIT_CUSTOM_STREAM(stream)
  220. #endif
  221. #ifdef __STDIO_MBSTATE
  222. #define __STDIO_FILE_INIT_MBSTATE \
  223. { 0, 0 },
  224. #else
  225. #define __STDIO_FILE_INIT_MBSTATE
  226. #endif
  227. #ifdef __STDIO_THREADSAFE
  228. #define __STDIO_FILE_INIT_THREADSAFE \
  229. 0, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP,
  230. #else
  231. #define __STDIO_FILE_INIT_THREADSAFE
  232. #endif
  233. #define __STDIO_INIT_FILE_STRUCT(stream, flags, filedes, next, buf, bufsize) \
  234. { (flags), \
  235. __STDIO_FILE_INIT_UNGOT \
  236. (filedes), \
  237. __STDIO_FILE_INIT_NEXT(next) \
  238. __STDIO_FILE_INIT_BUFFERS(buf,bufsize) \
  239. __STDIO_FILE_INIT_BUFGETC((buf)) \
  240. __STDIO_FILE_INIT_BUFPUTC((buf)) \
  241. __STDIO_FILE_INIT_CUSTOM_STREAM(stream) \
  242. __STDIO_FILE_INIT_MBSTATE \
  243. __STDIO_FILE_INIT_THREADSAFE \
  244. } /* TODO: mbstate and builtin buf */
  245. #ifdef __STDIO_GLIBC_CUSTOM_STREAMS
  246. /* TODO -- what does glibc do for undefined funcs? errno set? */
  247. #define __READ(STREAMPTR,BUF,SIZE) \
  248. ((((STREAMPTR)->gcs.read) == NULL) ? -1 : \
  249. (((STREAMPTR)->gcs.read)((STREAMPTR)->cookie,(BUF),(SIZE))))
  250. #define __WRITE(STREAMPTR,BUF,SIZE) \
  251. ((((STREAMPTR)->gcs.write) == NULL) ? -1 : \
  252. (((STREAMPTR)->gcs.write)((STREAMPTR)->cookie,(BUF),(SIZE))))
  253. #define __CLOSE(STREAMPTR) \
  254. ((((STREAMPTR)->gcs.close) == NULL) ? 0 : \
  255. (((STREAMPTR)->gcs.close)((STREAMPTR)->cookie)))
  256. #else /* __STDIO_GLIBC_CUSTOM_STREAMS */
  257. #define __READ(STREAMPTR,BUF,SIZE) \
  258. (read((STREAMPTR)->filedes,(BUF),(SIZE)))
  259. #define __WRITE(STREAMPTR,BUF,SIZE) \
  260. (write((STREAMPTR)->filedes,(BUF),(SIZE)))
  261. #define __CLOSE(STREAMPTR) \
  262. (close((STREAMPTR)->filedes))
  263. #endif /* __STDIO_GLIBC_CUSTOM_STREAMS */
  264. /**********************************************************************/
  265. /* POSIX functions */
  266. /**********************************************************************/
  267. #ifdef L_getw
  268. /* SUSv2 Legacy function -- need not be reentrant. */
  269. int getw(FILE *stream)
  270. {
  271. int aw[1];
  272. #ifdef __STDIO_WIDE
  273. return (fread_unlocked((void *)aw, sizeof(int), 1, stream) > 0)
  274. ? (*aw) : EOF;
  275. #else /* __STDIO_WIDE */
  276. return (_stdio_fread((unsigned char *)(aw), sizeof(int), stream)
  277. == sizeof(int)) ? (*aw) : EOF;
  278. #endif /* __STDIO_WIDE */
  279. }
  280. #endif
  281. /**********************************************************************/
  282. #ifdef L_putw
  283. /* SUSv2 Legacy function -- need not be reentrant. */
  284. int putw(int w, FILE *stream)
  285. {
  286. int aw[1];
  287. *aw = w; /* In case 'w' is in a register... */
  288. #ifdef __STDIO_WIDE
  289. return (fwrite_unlocked((void *)aw, sizeof(int), 1, stream) == 1)
  290. ? 0 : EOF;
  291. #else /* __STDIO_WIDE */
  292. return (_stdio_fwrite((unsigned char *)aw, sizeof(int), stream)
  293. == sizeof(int)) ? 0 : EOF;
  294. #endif /* __STDIO_WIDE */
  295. }
  296. #endif
  297. /**********************************************************************/
  298. #ifdef L_fileno
  299. /* Reentrancy handled by UNLOCKED() macro. */
  300. UNLOCKED(int,fileno,(register FILE *stream),(stream))
  301. {
  302. #ifdef __STDIO_GLIBC_CUSTOM_STREAMS
  303. return ( (stream && (stream->cookie == &(stream->filedes)) && (stream->filedes >= 0))
  304. ? stream->filedes
  305. : (__set_errno(EBADF), -1) );
  306. #else /* __STDIO_GLIBC_CUSTOM_STREAMS */
  307. return ((stream && stream->filedes >= 0)) ? stream->filedes : (__set_errno(EBADF), -1);
  308. #endif /* __STDIO_GLIBC_CUSTOM_STREAMS */
  309. }
  310. #endif
  311. /**********************************************************************/
  312. #ifdef L_fdopen
  313. /* No reentrancy issues. */
  314. FILE *fdopen(int filedes, const char *mode)
  315. {
  316. register char *cur_mode; /* TODO -- use intptr_t?? (also fopencookie) */
  317. return (((int)(cur_mode = (char *) fcntl(filedes, F_GETFL))) != -1)
  318. ? _stdio_fopen(cur_mode, mode, NULL, filedes)
  319. : NULL;
  320. }
  321. #endif
  322. /**********************************************************************/
  323. #ifdef L_fopen64
  324. /* No reentrancy issues. */
  325. FILE *fopen64(const char * __restrict filename, const char * __restrict mode)
  326. {
  327. return _stdio_fopen(filename, mode, NULL, -2);
  328. }
  329. #endif
  330. /**********************************************************************/
  331. #ifdef L_ctermid_function
  332. /* Not required to be reentrant. */
  333. char *ctermid(register char *s)
  334. {
  335. static char sbuf[L_ctermid];
  336. #ifdef __BCC__
  337. /* Currently elks doesn't support /dev/tty. */
  338. if (!s) {
  339. s = sbuf;
  340. }
  341. *s = 0;
  342. return s;
  343. #else
  344. /* glibc always returns /dev/tty for linux. */
  345. return strcpy((s ? s : sbuf), "/dev/tty");
  346. #endif
  347. }
  348. #endif
  349. /**********************************************************************/
  350. /* BSD functions */
  351. /**********************************************************************/
  352. #ifdef L_setbuffer
  353. /* No reentrancy issues. */
  354. void setbuffer(FILE * __restrict stream, register char * __restrict buf,
  355. size_t size)
  356. {
  357. #ifdef __STDIO_BUFFERS
  358. setvbuf(stream, buf, (buf ? _IOFBF : _IONBF), size);
  359. #else /* __STDIO_BUFFERS */
  360. /* Nothing to do. */
  361. #endif /* __STDIO_BUFFERS */
  362. }
  363. #endif
  364. /**********************************************************************/
  365. #ifdef L_setlinebuf
  366. /* No reentrancy issues. */
  367. void setlinebuf(FILE * __restrict stream)
  368. {
  369. #ifdef __STDIO_BUFFERS
  370. setvbuf(stream, NULL, _IOLBF, (size_t) 0);
  371. #else /* __STDIO_BUFFERS */
  372. /* Nothing to do. */
  373. #endif /* __STDIO_BUFFERS */
  374. }
  375. #endif
  376. /**********************************************************************/
  377. /* GLIBC functions */
  378. /**********************************************************************/
  379. #ifdef L_fcloseall
  380. /* NOTE: GLIBC difference!!! -- fcloseall
  381. * According to the info pages, glibc actually fclose()s all open files.
  382. * Apparently, glibc's new version only fflush()s and unbuffers all
  383. * writing streams to cope with unordered destruction of c++ static
  384. * objects. Here we implement the old behavior as default.
  385. */
  386. /* Not reentrant. */
  387. int fcloseall (void)
  388. {
  389. #if defined(__STDIO_BUFFERS) || defined(__STDIO_GLIBC_CUSTOM_STREAMS)
  390. register FILE *stream;
  391. int rv;
  392. _stdio_term(); /* Let _stdio_term() do all the work. */
  393. rv = 0;
  394. for (stream = _stdio_openlist ; stream ; stream = stream->nextopen) {
  395. if (stream->modeflags & (__FLAG_WRITING|__FLAG_ERROR)) {
  396. /* TODO -- is this correct? Maybe ferror set before flush...
  397. * could check if pending writable but what if term unbuffers?
  398. * in that case, could clear error flag... */
  399. rv = EOF; /* Only care about failed writes. */
  400. }
  401. }
  402. /* Make sure _stdio_term() does nothing on exit. */
  403. _stdio_openlist = NULL;
  404. return rv;
  405. #else /* defined(__STDIO_BUFFERS) || defined(__STDIO_GLIBC_CUSTOM_STREAMS) */
  406. return 0;
  407. #endif /* defined(__STDIO_BUFFERS) || defined(__STDIO_GLIBC_CUSTOM_STREAMS) */
  408. }
  409. #endif
  410. /**********************************************************************/
  411. #ifdef L_fmemopen
  412. #ifdef __STDIO_GLIBC_CUSTOM_STREAMS
  413. typedef struct {
  414. size_t pos;
  415. size_t len;
  416. size_t eof;
  417. int dynbuf;
  418. unsigned char *buf;
  419. FILE *fp;
  420. } __fmo_cookie;
  421. #define COOKIE ((__fmo_cookie *) cookie)
  422. static ssize_t fmo_read(register void *cookie, char *buf, size_t bufsize)
  423. {
  424. size_t count = COOKIE->len - COOKIE->pos;
  425. /* Note: 0 < bufsize < SSIZE_MAX because of _stdio_READ. */
  426. if (!count) { /* EOF! */
  427. return 0;
  428. }
  429. if (bufsize > count) {
  430. bufsize = count;
  431. }
  432. #if 1 /* TODO - choose code option */
  433. memcpy(buf, COOKIE->buf + COOKIE->pos, bufsize);
  434. COOKIE->pos += bufsize;
  435. #else
  436. {
  437. register char *p = COOKIE->buf + COOKIE->pos;
  438. count = bufsize;
  439. while (count) {
  440. *buf++ = *p++;
  441. --count;
  442. }
  443. COOKIE->pos += bufsize;
  444. }
  445. #endif
  446. return bufsize;
  447. }
  448. static ssize_t fmo_write(register void *cookie, const char *buf, size_t bufsize)
  449. {
  450. size_t count;
  451. /* Note: bufsize < SSIZE_MAX because of _stdio_WRITE. */
  452. /* If appending, need to seek to end of file!!!! */
  453. if (COOKIE->fp->modeflags & __FLAG_APPEND) {
  454. COOKIE->pos = COOKIE->eof;
  455. }
  456. count = COOKIE->len - COOKIE->pos;
  457. if (bufsize > count) {
  458. bufsize = count;
  459. if (count == 0) { /* We're at the end of the buffer... */
  460. __set_errno(EFBIG);
  461. return -1;
  462. }
  463. }
  464. #if 1 /* TODO - choose code option */
  465. memcpy(COOKIE->buf + COOKIE->pos, buf, bufsize);
  466. COOKIE->pos += bufsize;
  467. if (COOKIE->pos > COOKIE->eof) {
  468. COOKIE->eof = COOKIE->pos;
  469. if (bufsize < count) { /* New eof and still room in buffer? */
  470. *(COOKIE->buf + COOKIE->pos) = 0;
  471. }
  472. }
  473. #else
  474. {
  475. register char *p = COOKIE->buf + COOKIE->pos;
  476. size_t i = bufsize;
  477. while (i > 0) {
  478. *p++ = *buf++;
  479. --i;
  480. }
  481. COOKIE->pos += bufsize;
  482. if (COOKIE->pos > COOKIE->eof) {
  483. COOKIE->eof = COOKIE->pos;
  484. if (bufsize < count) { /* New eof and still room in buffer? */
  485. *p = 0;
  486. }
  487. }
  488. }
  489. #endif
  490. return bufsize;
  491. }
  492. /* glibc doesn't allow seeking, but it has in-buffer seeks... we don't. */
  493. static int fmo_seek(register void *cookie, __offmax_t *pos, int whence)
  494. {
  495. __offmax_t p = *pos;
  496. /* Note: fseek already checks that whence is legal, so don't check here
  497. * unless debugging. */
  498. assert(((unsigned int) whence) <= 2);
  499. if (whence != SEEK_SET) {
  500. p += (whence == SEEK_CUR) ? COOKIE->pos : /* SEEK_END */ COOKIE->eof;
  501. }
  502. /* Note: glibc only allows seeking in the buffer. We'll actually restrict
  503. * to the data. */
  504. /* Check for offset < 0, offset > eof, or offset overflow... */
  505. if (((uintmax_t) p) > COOKIE->eof) {
  506. return -1;
  507. }
  508. COOKIE->pos = *pos = p;
  509. return 0;
  510. }
  511. static int fmo_close(register void *cookie)
  512. {
  513. if (COOKIE->dynbuf) {
  514. free(COOKIE->buf);
  515. }
  516. free(cookie);
  517. return 0;
  518. }
  519. #undef COOKIE
  520. static const cookie_io_functions_t _fmo_io_funcs = {
  521. fmo_read, fmo_write, fmo_seek, fmo_close
  522. };
  523. /* TODO: If we have buffers enabled, it might be worthwile to add a pointer
  524. * to the FILE in the cookie and have read, write, and seek operate directly
  525. * on the buffer itself (ie replace the FILE buffer with the cookie buffer
  526. * and update FILE bufstart, etc. whenever we seek). */
  527. FILE *fmemopen(void *s, size_t len, const char *modes)
  528. {
  529. FILE *fp;
  530. register __fmo_cookie *cookie;
  531. size_t i;
  532. if ((cookie = malloc(sizeof(__fmo_cookie))) != NULL) {
  533. cookie->len = len;
  534. cookie->eof = cookie->pos = 0; /* pos and eof adjusted below. */
  535. cookie->dynbuf = 0;
  536. if (((cookie->buf = s) == NULL) && (len > 0)) {
  537. if ((cookie->buf = malloc(len)) == NULL) {
  538. goto EXIT_cookie;
  539. }
  540. cookie->dynbuf = 1;
  541. *cookie->buf = 0; /* If we're appending, treat as empty file. */
  542. }
  543. #ifndef __BCC__
  544. fp = fopencookie(cookie, modes, _fmo_io_funcs);
  545. #else
  546. fp = fopencookie(cookie, modes, &_fmo_io_funcs);
  547. #endif
  548. /* Note: We don't need to worry about locking fp in the thread case
  549. * as the only possible access would be a close or flush with
  550. * nothing currently in the FILE's write buffer. */
  551. if (fp != NULL) {
  552. cookie->fp = fp;
  553. if (fp->modeflags & __FLAG_READONLY) {
  554. cookie->eof = len;
  555. }
  556. if ((fp->modeflags & __FLAG_APPEND) && (len > 0)) {
  557. for (i = 0 ; i < len ; i++) {
  558. if (cookie->buf[i] == 0) {
  559. break;
  560. }
  561. }
  562. cookie->eof = cookie->pos = i; /* Adjust eof and pos. */
  563. }
  564. return fp;
  565. }
  566. }
  567. if (!s) {
  568. free(cookie->buf);
  569. }
  570. EXIT_cookie:
  571. free(cookie);
  572. return NULL;
  573. }
  574. #endif /* __STDIO_GLIBC_CUSTOM_STREAMS */
  575. #endif
  576. /**********************************************************************/
  577. #ifdef L_open_memstream
  578. #ifdef __STDIO_GLIBC_CUSTOM_STREAMS
  579. #define COOKIE ((__oms_cookie *) cookie)
  580. typedef struct {
  581. char *buf;
  582. size_t len;
  583. size_t pos;
  584. size_t eof;
  585. char **bufloc;
  586. size_t *sizeloc;
  587. } __oms_cookie;
  588. /* Nothing to do here, as memstreams are write-only. */
  589. /* static ssize_t oms_read(void *cookie, char *buf, size_t bufsize) */
  590. /* { */
  591. /* } */
  592. static ssize_t oms_write(register void *cookie, const char *buf, size_t bufsize)
  593. {
  594. register char *newbuf;
  595. size_t count;
  596. /* Note: we already know bufsize < SSIZE_MAX... */
  597. count = COOKIE->len - COOKIE->pos - 1;
  598. assert(COOKIE->pos < COOKIE->len); /* Always nul-terminate! */
  599. if (bufsize > count) {
  600. newbuf = realloc(COOKIE->buf, COOKIE->len + bufsize - count);
  601. if (newbuf) {
  602. *COOKIE->bufloc = COOKIE->buf = newbuf;
  603. COOKIE->len += (bufsize - count);
  604. } else {
  605. bufsize = count;
  606. if (count == 0) {
  607. __set_errno(EFBIG); /* TODO: check glibc errno setting... */
  608. return -1;
  609. }
  610. }
  611. }
  612. memcpy(COOKIE->buf + COOKIE->pos, buf, bufsize);
  613. COOKIE->pos += bufsize;
  614. if (COOKIE->pos > COOKIE->eof) {
  615. *COOKIE->sizeloc = COOKIE->eof = COOKIE->pos;
  616. COOKIE->buf[COOKIE->eof] = 0; /* Need to nul-terminate. */
  617. }
  618. return bufsize;
  619. }
  620. static int oms_seek(register void *cookie, __offmax_t *pos, int whence)
  621. {
  622. __offmax_t p = *pos;
  623. register char *buf;
  624. size_t leastlen;
  625. /* Note: fseek already checks that whence is legal, so don't check here
  626. * unless debugging. */
  627. assert(((unsigned int) whence) <= 2);
  628. if (whence != SEEK_SET) {
  629. p += (whence == SEEK_CUR) ? COOKIE->pos : /* SEEK_END */ COOKIE->eof;
  630. }
  631. /* Note: glibc only allows seeking in the buffer. We'll actually restrict
  632. * to the data. */
  633. /* Check for offset < 0, offset >= too big (need nul), or overflow... */
  634. if (((uintmax_t) p) >= SIZE_MAX - 1) {
  635. return -1;
  636. }
  637. leastlen = ((size_t) p) + 1; /* New pos + 1 for nul if necessary. */
  638. if (leastlen >= COOKIE->len) { /* Need to grow buffer... */
  639. buf = realloc(COOKIE->buf, leastlen);
  640. if (buf) {
  641. *COOKIE->bufloc = COOKIE->buf = buf;
  642. COOKIE->len = leastlen;
  643. memset(buf + COOKIE->eof, leastlen - COOKIE->eof, 0); /* 0-fill */
  644. } else {
  645. /* TODO: check glibc errno setting... */
  646. return -1;
  647. }
  648. }
  649. *pos = COOKIE->pos = --leastlen;
  650. if (leastlen > COOKIE->eof) {
  651. memset(COOKIE->buf + COOKIE->eof, leastlen - COOKIE->eof, 0);
  652. *COOKIE->sizeloc = COOKIE->eof;
  653. }
  654. return 0;
  655. }
  656. static int oms_close(void *cookie)
  657. {
  658. free(cookie);
  659. return 0;
  660. }
  661. #undef COOKIE
  662. static const cookie_io_functions_t _oms_io_funcs = {
  663. NULL, oms_write, oms_seek, oms_close
  664. };
  665. /* TODO: If we have buffers enabled, it might be worthwile to add a pointer
  666. * to the FILE in the cookie and operate directly on the buffer itself
  667. * (ie replace the FILE buffer with the cookie buffer and update FILE bufstart,
  668. * etc. whenever we seek). */
  669. FILE *open_memstream(char **__restrict bufloc, size_t *__restrict sizeloc)
  670. {
  671. register __oms_cookie *cookie;
  672. register FILE *fp;
  673. if ((cookie = malloc(sizeof(__oms_cookie))) != NULL) {
  674. if ((cookie->buf = malloc(cookie->len = BUFSIZ)) == NULL) {
  675. goto EXIT_cookie;
  676. }
  677. *cookie->buf = 0; /* Set nul terminator for buffer. */
  678. *(cookie->bufloc = bufloc) = cookie->buf;
  679. *(cookie->sizeloc = sizeloc) = cookie->eof = cookie->pos = 0;
  680. #ifndef __BCC__
  681. fp = fopencookie(cookie, "w", _oms_io_funcs);
  682. #else
  683. fp = fopencookie(cookie, "w", &_oms_io_funcs);
  684. #endif
  685. /* Note: We don't need to worry about locking fp in the thread case
  686. * as the only possible access would be a close or flush with
  687. * nothing currently in the FILE's write buffer. */
  688. if (fp != NULL) {
  689. return fp;
  690. }
  691. }
  692. if (cookie->buf != NULL) {
  693. free(cookie->buf);
  694. }
  695. EXIT_cookie:
  696. free(cookie);
  697. return NULL;
  698. }
  699. #endif /* __STDIO_GLIBC_CUSTOM_STREAMS */
  700. #endif
  701. /**********************************************************************/
  702. #ifdef L_fopencookie
  703. #ifdef __STDIO_GLIBC_CUSTOM_STREAMS
  704. /* NOTE: GLIBC difference!!! -- fopencookie
  705. * According to the info pages, glibc allows seeking within buffers even if
  706. * no seek function is supplied. We don't. */
  707. /* NOTE: GLIBC difference!!! -- fopencookie
  708. * When compiled without large file support, the offset pointer for the
  709. * cookie_seek function is off_t * and not off64_t * as for glibc. */
  710. /* Currently no real reentrancy issues other than a possible double close(). */
  711. #ifndef __BCC__
  712. FILE *fopencookie(void * __restrict cookie, const char * __restrict mode,
  713. cookie_io_functions_t io_functions)
  714. {
  715. FILE *stream;
  716. /* Fake an fdopen guaranteed to pass the _stdio_fopen basic agreement
  717. * check without an fcntl call. */
  718. if ((stream = _stdio_fopen(((char *)(INT_MAX-1)),
  719. mode, NULL, INT_MAX)) /* TODO: use intptr_t? */
  720. != NULL
  721. ) {
  722. stream->filedes = -1;
  723. stream->gcs = io_functions;
  724. stream->cookie = cookie;
  725. }
  726. #if !defined(__STDIO_BUFFERS) && !defined(__STDIO_THREADSAFE)
  727. /* I we don't have buffers or threads, we only need to worry about
  728. * custom streams on the open list, as no flushing is necessary and
  729. * no locking of possible underlying normal streams need be done.
  730. * We do need to explicitly close custom streams on termination of stdio,
  731. * and we need to lock the list as it can be modified by fclose(). */
  732. __STDIO_THREADLOCK_OPENLIST;
  733. stream->nextopen = _stdio_openlist; /* New files are inserted at */
  734. _stdio_openlist = stream; /* the head of the list. */
  735. __STDIO_THREADUNLOCK_OPENLIST;
  736. #endif /* !defined(__STDIO_BUFFERS) && !defined(__STDIO_THREADSAFE) */
  737. return stream;
  738. }
  739. #else /* __BCC__ */
  740. /* NOTE: GLIBC difference!!! -- fopencookie (bcc only)
  741. * Since bcc doesn't support passing of structs, we define fopencookie as a
  742. * macro in terms of _fopencookie which takes a struct * for the io functions
  743. * instead.
  744. */
  745. FILE *_fopencookie(void * __restrict cookie, const char * __restrict mode,
  746. register cookie_io_functions_t *io_functions)
  747. {
  748. register FILE *stream;
  749. /* Fake an fdopen guaranteed to pass the _stdio_fopen basic agreement
  750. * check without an fcntl call. */
  751. if ((stream = _stdio_fopen(((char *)(INT_MAX-1)),
  752. mode, NULL, INT_MAX)) /* TODO: use intptr_t? */
  753. != NULL
  754. ) {
  755. stream->filedes = -1;
  756. stream->gcs.read = io_functions->read;
  757. stream->gcs.write = io_functions->write;
  758. stream->gcs.seek = io_functions->seek;
  759. stream->gcs.close = io_functions->close;
  760. stream->cookie = cookie;
  761. }
  762. #if !defined(__STDIO_BUFFERS) && !defined(__STDIO_THREADSAFE)
  763. /* I we don't have buffers or threads, we only need to worry about
  764. * custom streams on the open list, as no flushing is necessary and
  765. * no locking of possible underlying normal streams need be done.
  766. * We do need to explicitly close custom streams on termination of stdio,
  767. * and we need to lock the list as it can be modified by fclose(). */
  768. __STDIO_THREADLOCK_OPENLIST;
  769. stream->nextopen = _stdio_openlist; /* New files are inserted at */
  770. _stdio_openlist = stream; /* the head of the list. */
  771. __STDIO_THREADUNLOCK_OPENLIST;
  772. #endif /* !defined(__STDIO_BUFFERS) && !defined(__STDIO_THREADSAFE) */
  773. return stream;
  774. }
  775. #endif /* __BCC__ */
  776. #endif /* __STDIO_GLIBC_CUSTOM_STREAMS */
  777. #endif
  778. /**********************************************************************/
  779. #ifdef L___fbufsize
  780. /* Not reentrant. */
  781. size_t __fbufsize(register FILE * __restrict stream)
  782. {
  783. #ifdef __STDIO_BUFFERS
  784. return (stream->modeflags & __FLAG_NBF)
  785. ? 0 : (stream->bufend - stream->bufstart);
  786. #else /* __STDIO_BUFFERS */
  787. return 0;
  788. #endif /* __STDIO_BUFFERS */
  789. }
  790. #endif
  791. /**********************************************************************/
  792. #ifdef L___freading
  793. /* No reentrancy issues. */
  794. int __freading(FILE * __restrict stream)
  795. {
  796. return stream->modeflags & (__FLAG_READING|__FLAG_READONLY);
  797. }
  798. #endif
  799. /**********************************************************************/
  800. #ifdef L___fwriting
  801. /* No reentrancy issues. */
  802. int __fwriting(FILE * __restrict stream)
  803. {
  804. return stream->modeflags & (__FLAG_WRITING|__FLAG_WRITEONLY);
  805. }
  806. #endif
  807. /**********************************************************************/
  808. #ifdef L___freadable
  809. /* No reentrancy issues. */
  810. int __freadable(FILE * __restrict stream)
  811. {
  812. return !(stream->modeflags & __FLAG_WRITEONLY);
  813. }
  814. #endif
  815. /**********************************************************************/
  816. #ifdef L___fwritable
  817. /* No reentrancy issues. */
  818. int __fwritable(FILE * __restrict stream)
  819. {
  820. return !(stream->modeflags & __FLAG_READONLY);
  821. }
  822. #endif
  823. /**********************************************************************/
  824. #ifdef L___flbf
  825. /* No reentrancy issues. */
  826. int __flbf(FILE * __restrict stream)
  827. {
  828. #ifdef __STDIO_BUFFERS
  829. return (stream->modeflags & __FLAG_LBF);
  830. #else /* __STDIO_BUFFERS */
  831. /* TODO -- Even though there is no buffer, return flag setting? */
  832. return __FLAG_NBF;
  833. #endif /* __STDIO_BUFFERS */
  834. }
  835. #endif
  836. /**********************************************************************/
  837. #ifdef L___fpurge
  838. /* Not reentrant. */
  839. void __fpurge(register FILE * __restrict stream)
  840. {
  841. #ifdef __STDIO_BUFFERS
  842. #ifdef __STDIO_PUTC_MACRO
  843. stream->bufputc = /* Must disable putc. */
  844. #endif /* __STDIO_PUTC_MACRO */
  845. #ifdef __STDIO_GETC_MACRO
  846. stream->bufgetc = /* Must disable getc. */
  847. #endif
  848. stream->bufpos = stream->bufread = stream->bufstart; /* Reset pointers. */
  849. #endif /* __STDIO_BUFFERS */
  850. /* Reset r/w flags and clear ungots. */
  851. stream->modeflags &= ~(__FLAG_READING|__FLAG_WRITING|__MASK_UNGOT);
  852. }
  853. #endif
  854. /**********************************************************************/
  855. #ifdef L___fpending
  856. /* Not reentrant. */
  857. #ifdef __STDIO_WIDE
  858. #warning Unlike the glibc version, this __fpending returns bytes in buffer for wide streams too!
  859. link_warning(__fpending, "This version of __fpending returns bytes remaining in buffer for both narrow and wide streams. glibc's version returns wide chars in buffer for the wide stream case.")
  860. #endif /* __STDIO_WIDE */
  861. size_t __fpending(register FILE * __restrict stream)
  862. {
  863. #ifdef __STDIO_BUFFERS
  864. /* TODO -- should we check this? should we set errno? just assert? */
  865. return (stream->modeflags & (__FLAG_READING|__FLAG_READONLY))
  866. ? 0 : (stream->bufpos - stream->bufstart);
  867. #else /* __STDIO_BUFFERS */
  868. return 0;
  869. #endif /* __STDIO_BUFFERS */
  870. }
  871. #endif
  872. /**********************************************************************/
  873. #ifdef L__flushlbf
  874. /* No reentrancy issues. */
  875. void _flushlbf(void)
  876. {
  877. #if defined(__STDIO_BUFFERS) || defined(__STDIO_GLIBC_CUSTOM_STREAMS)
  878. fflush((FILE *) &_stdio_openlist); /* Uses an implementation hack!!! */
  879. #else /* defined(__STDIO_BUFFERS) || defined(__STDIO_GLIBC_CUSTOM_STREAMS) */
  880. /* Nothing to do. */
  881. #endif /* defined(__STDIO_BUFFERS) || defined(__STDIO_GLIBC_CUSTOM_STREAMS) */
  882. }
  883. #endif
  884. /**********************************************************************/
  885. #ifdef L___fsetlocking
  886. /* NOT threadsafe!!! (I don't think glibc's is either)
  887. *
  888. * This interacts badly with internal locking/unlocking. If you use this routine,
  889. * make sure the file isn't being accessed by any other threads. Typical use would
  890. * be to change to user locking immediately after opening the stream.
  891. */
  892. #ifdef __UCLIBC_MJN3_ONLY__
  893. link_warning(__fsetlocking, "Oddly enough, __fsetlocking() is NOT threadsafe.")
  894. #endif
  895. int __fsetlocking(FILE *stream, int locking_mode)
  896. {
  897. #ifdef __STDIO_THREADSAFE
  898. int old_mode;
  899. #endif
  900. assert((FSETLOCKING_QUERY == 0) && (FSETLOCKING_INTERNAL == 1)
  901. && (FSETLOCKING_BYCALLER == 2));
  902. assert(((unsigned int) locking_mode) <= 2);
  903. #ifdef __STDIO_THREADSAFE
  904. old_mode = stream->user_locking;
  905. assert(((unsigned int) old_mode) <= 1); /* Must be 0 (internal) or 1 (user). */
  906. if (locking_mode != FSETLOCKING_QUERY) {
  907. /* In case we're not debugging, treat any unknown as a request to
  908. * set internal locking, in order to match glibc behavior. */
  909. stream->user_locking = (locking_mode == FSETLOCKING_BYCALLER);
  910. }
  911. return 2 - old_mode;
  912. #else
  913. return FSETLOCKING_BYCALLER; /* Well, without thread support... */
  914. #endif
  915. }
  916. #endif
  917. /**********************************************************************/
  918. #ifdef L_flockfile
  919. void flockfile(FILE *stream)
  920. {
  921. #ifdef __STDIO_THREADSAFE
  922. __pthread_mutex_lock(&stream->lock);
  923. #endif
  924. }
  925. #endif
  926. /**********************************************************************/
  927. #ifdef L_ftrylockfile
  928. int ftrylockfile(FILE *stream)
  929. {
  930. #ifdef __STDIO_THREADSAFE
  931. return __pthread_mutex_trylock(&stream->lock);
  932. #else
  933. return 1;
  934. #endif
  935. }
  936. #endif
  937. /**********************************************************************/
  938. #ifdef L_funlockfile
  939. void funlockfile(FILE *stream)
  940. {
  941. #ifdef __STDIO_THREADSAFE
  942. __pthread_mutex_unlock(&stream->lock);
  943. #endif
  944. }
  945. #endif
  946. /**********************************************************************/
  947. #ifdef L_getline
  948. ssize_t getline(char **__restrict lineptr, size_t *__restrict n,
  949. FILE *__restrict stream)
  950. {
  951. return __getdelim(lineptr, n, '\n', stream);
  952. }
  953. #endif
  954. /**********************************************************************/
  955. #ifdef L_getdelim
  956. weak_alias(__getdelim,getdelim);
  957. #define GETDELIM_GROWBY 64
  958. ssize_t __getdelim(char **__restrict lineptr, size_t *__restrict n,
  959. int delimiter, register FILE *__restrict stream)
  960. {
  961. register char *buf;
  962. size_t pos;
  963. int c;
  964. if (!lineptr || !n || !stream) { /* Be compatable with glibc... even */
  965. __set_errno(EINVAL); /* though I think we should assert here */
  966. return -1; /* if anything. */
  967. }
  968. if (!(buf = *lineptr)) { /* If passed NULL for buffer, */
  969. *n = 0; /* ignore value passed and treat size as 0. */
  970. }
  971. pos = 1; /* Make sure we have space for terminating nul. */
  972. __STDIO_THREADLOCK(stream);
  973. do {
  974. if (pos >= *n) {
  975. if (!(buf = realloc(buf, *n + GETDELIM_GROWBY))) {
  976. __set_errno(ENOMEM); /* Emulate old uClibc implementation. */
  977. break;
  978. }
  979. *n += GETDELIM_GROWBY;
  980. *lineptr = buf;
  981. }
  982. } while (((c = (getc_unlocked)(stream)) != EOF) /* Disable the macro */
  983. && ((buf[pos++ - 1] = c) != delimiter));
  984. __STDIO_THREADUNLOCK(stream);
  985. if (--pos) {
  986. buf[pos] = 0;
  987. return pos;
  988. }
  989. return -1; /* Either initial realloc failed or first read was EOF. */
  990. }
  991. #endif
  992. /**********************************************************************/
  993. /* my extension functions */
  994. /**********************************************************************/
  995. #ifdef L__stdio_fsfopen
  996. /*
  997. * Stack|Static File open -- open a file where the FILE is either
  998. * stack or staticly allocated.
  999. */
  1000. /* No reentrancy issues. */
  1001. FILE *_stdio_fsfopen(const char * __restrict filename,
  1002. const char * __restrict mode,
  1003. register FILE * __restrict stream)
  1004. {
  1005. #ifdef __STDIO_BUFFERS
  1006. stream->modeflags = __FLAG_FBF;
  1007. #if __STDIO_BUILTIN_BUF_SIZE > 0
  1008. stream->bufstart = stream->builtinbuf;
  1009. stream->bufend = stream->builtinbuf + sizeof(stream->builtinbuf);
  1010. #else /* __STDIO_BUILTIN_BUF_SIZE > 0 */
  1011. stream->bufend = stream->bufstart = NULL;
  1012. #endif /* __STDIO_BUILTIN_BUF_SIZE > 0 */
  1013. #endif /* __STDIO_BUFFERS */
  1014. return _stdio_fopen(filename, mode, stream, -1);
  1015. }
  1016. #endif
  1017. /**********************************************************************/
  1018. /* stdio internal functions */
  1019. /**********************************************************************/
  1020. #ifdef L__stdio_adjpos
  1021. /* According to the ANSI/ISO C99 definition of ungetwc()
  1022. * For a text or binary stream, the value of its file position indicator
  1023. * after a successful call to the ungetwc function is unspecified until
  1024. * all pushed­back wide characters are read or discarded.
  1025. * Note however, that this applies only to _user_ calls to ungetwc. We
  1026. * need to allow for internal calls by scanf.
  1027. * So we store the byte count
  1028. * of the first ungot wide char in ungot_width. If it is 0 (user case)
  1029. * then the file position is treated as unknown.
  1030. */
  1031. /* Internal function -- not reentrant. */
  1032. int _stdio_adjpos(register FILE * __restrict stream, register __offmax_t *pos)
  1033. {
  1034. __offmax_t r;
  1035. int cor = stream->modeflags & __MASK_UNGOT; /* handle ungots */
  1036. assert(cor <= 2);
  1037. #ifdef __STDIO_WIDE
  1038. /* Assumed narrow stream so correct if wide. */
  1039. if (cor && (stream->modeflags & __FLAG_WIDE)) {
  1040. if ((((stream->modeflags & __MASK_UNGOT) > 1) || stream->ungot[1])) {
  1041. return -1; /* App did ungetwc, so position is indeterminate. */
  1042. }
  1043. if (stream->modeflags & __MASK_UNGOT) {
  1044. cor = cor - 1 + stream->ungot_width[1];
  1045. }
  1046. if (stream->state.mask > 0) { /* Incomplete character (possible bad) */
  1047. cor -= stream->ungot_width[0];
  1048. }
  1049. }
  1050. #endif /* __STDIO_WIDE */
  1051. #ifdef __STDIO_BUFFERS
  1052. if (stream->modeflags & __FLAG_WRITING) {
  1053. cor -= (stream->bufpos - stream->bufstart); /* pending writes */
  1054. }
  1055. if (stream->modeflags & __FLAG_READING) {
  1056. cor += (stream->bufread - stream->bufpos); /* extra's read */
  1057. }
  1058. #endif /* __STDIO_BUFFERS */
  1059. r = *pos;
  1060. return ((*pos -= cor) > r) ? -cor : cor;
  1061. }
  1062. #endif
  1063. /**********************************************************************/
  1064. #ifdef L__stdio_lseek
  1065. /*
  1066. * This function is only called by fseek and ftell.
  1067. * fseek -- doesn't care about pos val, just success or failure.
  1068. * ftell -- needs pos val but offset == 0 and whence == SET_CUR.
  1069. */
  1070. /* Internal function -- not reentrant. */
  1071. int _stdio_lseek(register FILE *stream, register __offmax_t *pos, int whence)
  1072. {
  1073. __offmax_t res;
  1074. #ifdef __STDIO_GLIBC_CUSTOM_STREAMS
  1075. if (stream->cookie != &stream->filedes) {
  1076. return (((stream->gcs.seek == NULL)
  1077. || ((stream->gcs.seek)(stream->cookie, pos, whence) < 0))
  1078. ? -1 : 0);
  1079. }
  1080. #endif /* __STDIO_GLIBC_CUSTOM_STREAMS */
  1081. #ifdef __STDIO_LARGE_FILES
  1082. res = lseek64(stream->filedes, *pos, whence);
  1083. #else
  1084. res = lseek(stream->filedes, *pos, whence);
  1085. #endif /* __STDIO_LARGE_FILES */
  1086. return (res >= 0) ? ((*pos = res), 0) : -1;
  1087. }
  1088. #endif
  1089. /**********************************************************************/
  1090. #ifdef L__stdio_fread
  1091. /*
  1092. * NOTE!!! This routine is meant to be callable by both narrow and wide
  1093. * functions. However, if called by a wide function, there must be
  1094. * NO pending ungetwc()s!!!
  1095. */
  1096. /* Unlike write, it's ok for read to return fewer than bufsize, since
  1097. * we may not need all of them. */
  1098. static ssize_t _stdio_READ(register FILE *stream, unsigned char *buf, size_t bufsize)
  1099. {
  1100. ssize_t rv;
  1101. /* NOTE: C99 change: Input fails once the stream's EOF indicator is set. */
  1102. if ((bufsize == 0) || (stream->modeflags & __FLAG_EOF)) {
  1103. return 0;
  1104. }
  1105. if (bufsize > SSIZE_MAX) {
  1106. bufsize = SSIZE_MAX;
  1107. }
  1108. #ifdef __BCC__
  1109. TRY_READ:
  1110. #endif
  1111. rv = __READ(stream, buf, bufsize);
  1112. if (rv > 0) {
  1113. #ifdef __STDIO_GLIBC_CUSTOM_STREAMS
  1114. assert(rv <= bufsize); /* buggy user handler... TODO: check? */
  1115. if (rv > bufsize) { /* Num reported written > number requested */
  1116. rv = bufsize; /* Treat as a full read??? */
  1117. }
  1118. #endif
  1119. } else if (rv == 0) {
  1120. stream->modeflags |= __FLAG_EOF;
  1121. } else {
  1122. #ifdef __BCC__
  1123. if (errno == EINTR) {
  1124. goto TRY_READ;
  1125. }
  1126. #endif
  1127. stream->modeflags |= __FLAG_ERROR;
  1128. rv = 0;
  1129. }
  1130. return rv;
  1131. }
  1132. /* Internal function -- not reentrant. */
  1133. size_t _stdio_fread(unsigned char *buffer, size_t bytes, register FILE *stream)
  1134. {
  1135. __stdio_validate_FILE(stream); /* debugging only */
  1136. #ifdef __STDIO_BUFFERS
  1137. if (stream->modeflags
  1138. #ifdef __STDIO_AUTO_RW_TRANSITION
  1139. & (__FLAG_WRITEONLY)
  1140. #else /* __STDIO_AUTO_RW_TRANSITION */
  1141. /* ANSI/ISO and SUSv3 require not currently writing. */
  1142. & (__FLAG_WRITEONLY|__FLAG_WRITING)
  1143. #endif /* __STDIO_AUTO_RW_TRANSITION */
  1144. ) {
  1145. #ifdef __STDIO_PUTC_MACRO
  1146. stream->bufputc = stream->bufstart; /* Must disable putc. */
  1147. #endif /* __STDIO_PUTC_MACRO */
  1148. stream->modeflags |= __FLAG_ERROR;
  1149. /* TODO: This is for posix behavior if writeonly. To save space, we
  1150. * use this errno for read attempt while writing, as no errno is
  1151. * specified by posix for this case, even though the restriction is
  1152. * mentioned in fopen(). */
  1153. __set_errno(EBADF);
  1154. return 0;
  1155. }
  1156. /* We need to disable putc and getc macros in case of error */
  1157. #if defined(__STDIO_PUTC_MACRO) || defined(__STDIO_GETC_MACRO)
  1158. #ifdef __STDIO_PUTC_MACRO
  1159. stream->bufputc =
  1160. #endif /* __STDIO_GETC_MACRO */
  1161. #ifdef __STDIO_GETC_MACRO
  1162. stream->bufgetc =
  1163. #endif /* __STDIO_GETC_MACRO */
  1164. stream->bufstart;
  1165. #endif /* defined(__STDIO_PUTC_MACRO) || defined(__STDIO_GETC_MACRO) */
  1166. if (stream->modeflags & __MASK_BUFMODE) {
  1167. /* If the stream is readable and not fully buffered, we must first
  1168. * flush all line buffered output streams. Do this before the
  1169. * error check as this may be a read/write line-buffered stream.
  1170. * Note: Uses an implementation-specific hack!!! */
  1171. fflush_unlocked((FILE *) &_stdio_openlist);
  1172. }
  1173. #ifdef __STDIO_AUTO_RW_TRANSITION
  1174. if ((stream->modeflags & __FLAG_WRITING)
  1175. && (fflush_unlocked(stream) == EOF)
  1176. ) {
  1177. return 0; /* Fail if we need to fflush but can't. */
  1178. }
  1179. #endif /* __STDIO_AUTO_RW_TRANSITION */
  1180. stream->modeflags |= __FLAG_READING; /* Make sure Reading flag is set. */
  1181. {
  1182. register unsigned char *p = (unsigned char *) buffer;
  1183. /* First, grab appropriate ungetc() chars. NOT FOR WIDE ORIENTATED! */
  1184. while (bytes && (stream->modeflags & __MASK_UNGOT)) {
  1185. #ifdef __STDIO_WIDE
  1186. assert(stream->modeflags & __FLAG_NARROW);
  1187. #endif /* __STDIO_WIDE */
  1188. *p++ = stream->ungot[(--stream->modeflags) & __MASK_UNGOT];
  1189. stream->ungot[1] = 0;
  1190. --bytes;
  1191. }
  1192. /* Now get any other needed chars from the buffer or the file. */
  1193. FROM_BUF:
  1194. while (bytes && (stream->bufpos < stream->bufread)) {
  1195. --bytes;
  1196. *p++ = *stream->bufpos++;
  1197. }
  1198. if (bytes > 0) {
  1199. ssize_t len;
  1200. if (stream->filedes == -2) {
  1201. stream->modeflags |= __FLAG_EOF;
  1202. goto DONE;
  1203. }
  1204. /* The buffer is exhausted, but we still need chars. */
  1205. stream->bufpos = stream->bufread = stream->bufstart;
  1206. if (bytes <= stream->bufend - stream->bufread) {
  1207. /* We have sufficient space in the buffer. */
  1208. len = _stdio_READ(stream, stream->bufread,
  1209. stream->bufend - stream->bufread);
  1210. if (len > 0) {
  1211. stream->bufread += len;
  1212. goto FROM_BUF;
  1213. }
  1214. } else {
  1215. /* More bytes needed than fit in the buffer, so read */
  1216. /* directly into caller's buffer. */
  1217. len = _stdio_READ(stream, p, bytes);
  1218. if (len > 0) {
  1219. p += len;
  1220. bytes -= len;
  1221. goto FROM_BUF; /* Redundant work, but stops extra read. */
  1222. }
  1223. }
  1224. }
  1225. #ifdef __STDIO_GETC_MACRO
  1226. if (!(stream->modeflags
  1227. & (__FLAG_WIDE|__MASK_UNGOT|__MASK_BUFMODE|__FLAG_ERROR))
  1228. ) {
  1229. stream->bufgetc = stream->bufread; /* Enable getc macro. */
  1230. }
  1231. #endif
  1232. DONE:
  1233. __stdio_validate_FILE(stream); /* debugging only */
  1234. return (p - (unsigned char *)buffer);
  1235. }
  1236. #else /* __STDIO_BUFFERS --------------------------------------- */
  1237. if (stream->modeflags
  1238. #ifdef __STDIO_AUTO_RW_TRANSITION
  1239. & (__FLAG_WRITEONLY)
  1240. #else /* __STDIO_AUTO_RW_TRANSITION */
  1241. /* ANSI/ISO and SUSv3 require not currently writing. */
  1242. & (__FLAG_WRITEONLY|__FLAG_WRITING)
  1243. #endif /* __STDIO_AUTO_RW_TRANSITION */
  1244. ) {
  1245. stream->modeflags |= __FLAG_ERROR;
  1246. /* TODO: This is for posix behavior if writeonly. To save space, we
  1247. * use this errno for read attempt while writing, as no errno is
  1248. * specified by posix for this case, even though the restriction is
  1249. * mentioned in fopen(). */
  1250. __set_errno(EBADF);
  1251. return 0;
  1252. }
  1253. #ifdef __STDIO_AUTO_RW_TRANSITION
  1254. stream->modeflags &= ~(__FLAG_WRITING); /* Make sure Writing flag clear. */
  1255. #endif /* __STDIO_AUTO_RW_TRANSITION */
  1256. stream->modeflags |= __FLAG_READING; /* Make sure Reading flag is set. */
  1257. {
  1258. register unsigned char *p = (unsigned char *) buffer;
  1259. /* First, grab appropriate ungetc() chars. NOT FOR WIDE ORIENTATED! */
  1260. while (bytes && (stream->modeflags & __MASK_UNGOT)) {
  1261. #ifdef __STDIO_WIDE
  1262. assert(stream->modeflags & __FLAG_NARROW);
  1263. #endif /* __STDIO_WIDE */
  1264. *p++ = stream->ungot[(--stream->modeflags) & __MASK_UNGOT];
  1265. stream->ungot[1] = 0;
  1266. --bytes;
  1267. }
  1268. while (bytes > 0) {
  1269. ssize_t len = _stdio_READ(stream, p, (unsigned) bytes);
  1270. if (len == 0) {
  1271. break;
  1272. }
  1273. p += len;
  1274. bytes -= len;
  1275. }
  1276. __stdio_validate_FILE(stream); /* debugging only */
  1277. return (p - (unsigned char *)buffer);
  1278. }
  1279. #endif /* __STDIO_BUFFERS */
  1280. }
  1281. #endif
  1282. /**********************************************************************/
  1283. #ifdef L__stdio_fwrite
  1284. /*
  1285. * If buffer == NULL, attempt to fflush and return number of chars
  1286. * remaining in buffer (0 if successful fflush).
  1287. */
  1288. /* WARNING!!!! Current standards say that termination due to an asyncronous
  1289. * signal may not result in stdio streams being flushed. This libary makes
  1290. * an effort to do so but there is no way, short of blocking signals for
  1291. * each _stdio_fwrite call, that we can maintain the correct state if a
  1292. * signal is recieved mid-call. So any stream in mid-_stdio_fwrite could
  1293. * not some flush data or even duplicate-flush some data. It is possible
  1294. * to avoid the duplicate-flush case by setting/clearing the stream
  1295. * error flag before/after the write process, but it doesn't seem worth
  1296. * the trouble. */
  1297. /* Like standard write, but always does a full write unless error, plus
  1298. * deals correctly with bufsize > SSIZE_MAX... not much on an issue on linux
  1299. * but definitly could be on Elks. Also on Elks, always loops for EINTR..
  1300. * Returns number of bytes written, so a short write indicates an error */
  1301. static size_t _stdio_WRITE(register FILE *stream,
  1302. register const unsigned char *buf, size_t bufsize)
  1303. {
  1304. size_t todo;
  1305. ssize_t rv, stodo;
  1306. todo = bufsize;
  1307. while (todo) {
  1308. stodo = (todo <= SSIZE_MAX) ? todo : SSIZE_MAX;
  1309. rv = __WRITE(stream, buf, stodo);
  1310. if (rv >= 0) {
  1311. #ifdef __STDIO_GLIBC_CUSTOM_STREAMS
  1312. assert(rv <= stodo); /* buggy user handler... TODO: check? */
  1313. if (rv > stodo) { /* Num reported written > number requested */
  1314. rv = stodo; /* Treat as a full write??? */
  1315. }
  1316. #endif
  1317. todo -= rv;
  1318. buf += rv;
  1319. } else
  1320. #ifdef __BCC__
  1321. if (errno != EINTR)
  1322. #endif
  1323. {
  1324. stream->modeflags |= __FLAG_ERROR;
  1325. break;
  1326. }
  1327. }
  1328. return bufsize - todo;
  1329. }
  1330. /* Internal function -- not reentrant. */
  1331. size_t _stdio_fwrite(const unsigned char *buffer, size_t bytes,
  1332. register FILE *stream)
  1333. {
  1334. #ifdef __STDIO_BUFFERS
  1335. register const unsigned char *p;
  1336. __stdio_validate_FILE(stream); /* debugging only */
  1337. if ((stream->modeflags & __FLAG_READONLY)
  1338. #ifndef __STDIO_AUTO_RW_TRANSITION
  1339. /* ANSI/ISO requires either at EOF or currently not reading. */
  1340. || ((stream->modeflags & (__FLAG_READING|__FLAG_EOF))
  1341. == __FLAG_READING)
  1342. #endif /* __STDIO_AUTO_RW_TRANSITION */
  1343. ) {
  1344. stream->modeflags |= __FLAG_ERROR;
  1345. /* TODO: This is for posix behavior if readonly. To save space, we
  1346. * use this errno for write attempt while reading, as no errno is
  1347. * specified by posix for this case, even though the restriction is
  1348. * mentioned in fopen(). */
  1349. __set_errno(EBADF);
  1350. return 0;
  1351. }
  1352. #ifdef __STDIO_AUTO_RW_TRANSITION
  1353. /* If reading, deal with ungots and read-buffered chars. */
  1354. if (stream->modeflags & __FLAG_READING) {
  1355. if (((stream->bufpos < stream->bufread)
  1356. || (stream->modeflags & __MASK_UNGOT))
  1357. /* If appending, we might as well seek to end to save a seek. */
  1358. /* TODO: set EOF in fseek when appropriate? */
  1359. && fseek(stream, 0L,
  1360. ((stream->modeflags & __FLAG_APPEND)
  1361. ? SEEK_END : SEEK_CUR))
  1362. ) {
  1363. /* Note: This differs from glibc's apparent behavior of
  1364. not setting the error flag and discarding the buffered
  1365. read data. */
  1366. stream->modeflags |= __FLAG_ERROR; /* fseek may not set this. */
  1367. return 0; /* Fail if we need to fseek but can't. */
  1368. }
  1369. /* Always reset even if fseek called (saves a test). */
  1370. #ifdef __STDIO_GETC_MACRO
  1371. stream->bufgetc =
  1372. #endif /* __STDIO_GETC_MACRO */
  1373. stream->bufpos = stream->bufread = stream->bufstart;
  1374. } else
  1375. #endif
  1376. if ((stream->modeflags & (__FLAG_WRITING|__FLAG_APPEND)) == __FLAG_APPEND) {
  1377. /* Append mode, but not currently writing. Need to seek to end for proper
  1378. * ftell() return values. Don't worry if the stream isn't seekable. */
  1379. __offmax_t pos[1];
  1380. *pos = 0;
  1381. if (_stdio_lseek(stream, pos, SEEK_END) && (errno != EPIPE)) { /* Too big? */
  1382. stream->modeflags |= __FLAG_ERROR;
  1383. return 0;
  1384. }
  1385. }
  1386. #ifdef __STDIO_PUTC_MACRO
  1387. /* We need to disable putc macro in case of error */
  1388. stream->bufputc = stream->bufstart;
  1389. #endif /* __STDIO_GETC_MACRO */
  1390. /* Clear both reading and writing flags. We need to clear the writing
  1391. * flag in case we're fflush()ing or in case of an error. */
  1392. stream->modeflags &= ~(__FLAG_READING|__FLAG_WRITING);
  1393. {
  1394. const unsigned char *buf0 = buffer;
  1395. size_t write_count = 1; /* 0 means a write failed */
  1396. if (!buffer) { /* fflush the stream */
  1397. FFLUSH:
  1398. {
  1399. size_t count = stream->bufpos - stream->bufstart;
  1400. p = stream->bufstart;
  1401. if (stream->filedes == -2) { /* TODO -- document this hack! */
  1402. stream->modeflags |= __FLAG_WRITING;
  1403. return (!buffer) ? 0 : ((buffer - buf0) + bytes);
  1404. }
  1405. {
  1406. write_count = _stdio_WRITE(stream, p, count);
  1407. p += write_count;
  1408. count -= write_count;
  1409. }
  1410. stream->bufpos = stream->bufstart;
  1411. while (count) {
  1412. *stream->bufpos++ = *p++;
  1413. --count;
  1414. }
  1415. if (!buffer) { /* fflush case... */
  1416. __stdio_validate_FILE(stream); /* debugging only */
  1417. return stream->bufpos - stream->bufstart;
  1418. }
  1419. }
  1420. }
  1421. #if 1
  1422. /* TODO: If the stream is buffered, we may be able to omit. */
  1423. if ((stream->bufpos == stream->bufstart) /* buf empty */
  1424. && (stream->bufend - stream->bufstart <= bytes) /* fills */
  1425. && (stream->filedes != -2)) { /* not strinf fake file */
  1426. /* so want to do a direct write of supplied buffer */
  1427. {
  1428. size_t rv = _stdio_WRITE(stream, buffer, bytes);
  1429. buffer += rv;
  1430. bytes -= rv;
  1431. }
  1432. } else
  1433. #endif
  1434. /* otherwise buffer not empty and/or data fits */
  1435. {
  1436. size_t count = stream->bufend - stream->bufpos;
  1437. p = buffer;
  1438. if (count > bytes) {
  1439. count = bytes;
  1440. }
  1441. bytes -= count;
  1442. while (count) {
  1443. *stream->bufpos++ = *buffer++;
  1444. --count;
  1445. }
  1446. if (write_count) { /* no write errors */
  1447. if (bytes) {
  1448. goto FFLUSH;
  1449. }
  1450. if (stream->modeflags & __FLAG_LBF) {
  1451. while (p < buffer) { /* check for newline. */
  1452. if (*p++ == '\n') {
  1453. goto FFLUSH;
  1454. }
  1455. }
  1456. }
  1457. }
  1458. }
  1459. #ifdef __STDIO_PUTC_MACRO
  1460. if (!(stream->modeflags & (__FLAG_WIDE|__MASK_BUFMODE|__FLAG_ERROR))) {
  1461. /* Not wide, no errors and fully buffered, so enable putc macro. */
  1462. stream->bufputc = stream->bufend;
  1463. }
  1464. #endif /* __STDIO_GETC_MACRO */
  1465. stream->modeflags |= __FLAG_WRITING; /* Ensure Writing flag is set. */
  1466. __stdio_validate_FILE(stream); /* debugging only */
  1467. return buffer - buf0;
  1468. }
  1469. #else /* __STDIO_BUFFERS --------------------------------------- */
  1470. __stdio_validate_FILE(stream); /* debugging only */
  1471. if ((stream->modeflags & __FLAG_READONLY)
  1472. #ifndef __STDIO_AUTO_RW_TRANSITION
  1473. /* ANSI/ISO requires either at EOF or currently not reading. */
  1474. || ((stream->modeflags & (__FLAG_READING|__FLAG_EOF))
  1475. == __FLAG_READING)
  1476. #endif /* __STDIO_AUTO_RW_TRANSITION */
  1477. ) {
  1478. stream->modeflags |= __FLAG_ERROR;
  1479. /* TODO: This is for posix behavior if readonly. To save space, we
  1480. * use this errno for write attempt while reading, as no errno is
  1481. * specified by posix for this case, even though the restriction is
  1482. * mentioned in fopen(). */
  1483. __set_errno(EBADF);
  1484. return 0;
  1485. }
  1486. /* We always clear the reading flag in case at EOF. */
  1487. stream->modeflags &= ~(__FLAG_READING);
  1488. /* Unlike the buffered case, we set the writing flag now since we don't
  1489. * need to do anything here for fflush(). */
  1490. stream->modeflags |= __FLAG_WRITING;
  1491. {
  1492. register unsigned char *p = (unsigned char *) buffer;
  1493. ssize_t rv = _stdio_WRITE(stream, p, bytes);
  1494. p += rv;
  1495. bytes -= rv;
  1496. __stdio_validate_FILE(stream); /* debugging only */
  1497. return (p - (unsigned char *)buffer);
  1498. }
  1499. #endif /* __STDIO_BUFFERS *****************************************/
  1500. }
  1501. #endif
  1502. /**********************************************************************/
  1503. #ifdef L__stdio_init
  1504. /* Internal functions -- _stdio_init() and __stdio_validate_FILE
  1505. * are not reentrant, but _stdio_term() is through fflush().
  1506. * Also, the _cs_{read|write|close} functions are not reentrant. */
  1507. #ifndef NDEBUG
  1508. void __stdio_validate_FILE(FILE *stream)
  1509. {
  1510. if (stream->filedes == -2) { /* fake FILE for sprintf, scanf, etc. */
  1511. return;
  1512. }
  1513. __STDIO_THREADLOCK(stream);
  1514. #ifdef __STDIO_BUFFERS
  1515. assert(stream->bufstart <= stream->bufread);
  1516. if (stream->modeflags & (__FLAG_READING)) {
  1517. assert(stream->bufpos <= stream->bufread);
  1518. }
  1519. assert(stream->bufread <= stream->bufend);
  1520. assert(stream->bufpos <= stream->bufend);
  1521. if ((stream->modeflags & __MASK_BUFMODE) == __FLAG_NBF) {
  1522. assert(stream->bufstart == stream->bufend);
  1523. }
  1524. assert((stream->modeflags & __MASK_BUFMODE) <= __FLAG_NBF);
  1525. #endif
  1526. #ifdef __STDIO_PUTC_MACRO
  1527. assert(stream->bufstart <= stream->bufputc);
  1528. assert(stream->bufputc <= stream->bufend);
  1529. if (stream->bufstart < stream->bufputc) {
  1530. assert(stream->bufputc == stream->bufend);
  1531. assert(stream->modeflags & (__FLAG_WRITING));
  1532. assert(!(stream->modeflags
  1533. & (__FLAG_WIDE|__MASK_BUFMODE|__MASK_UNGOT|__FLAG_READONLY))
  1534. );
  1535. }
  1536. #endif
  1537. #ifdef __STDIO_GETC_MACRO
  1538. assert(stream->bufstart <= stream->bufgetc);
  1539. assert(stream->bufgetc <= stream->bufread);
  1540. if (stream->bufstart < stream->bufgetc) {
  1541. assert(stream->modeflags & (__FLAG_READING));
  1542. assert(!(stream->modeflags
  1543. & (__FLAG_WIDE|__MASK_BUFMODE|__MASK_UNGOT|__FLAG_WRITEONLY))
  1544. );
  1545. }
  1546. #endif
  1547. assert((stream->modeflags & __MASK_UNGOT) != __MASK_UNGOT);
  1548. if (stream->modeflags & __MASK_UNGOT1) {
  1549. assert(stream->ungot[1] <= 1);
  1550. }
  1551. if (stream->modeflags & __MASK_UNGOT) {
  1552. assert(!(stream->modeflags & __FLAG_EOF));
  1553. }
  1554. assert((stream->modeflags & (__FLAG_READONLY|__FLAG_WRITEONLY))
  1555. != (__FLAG_READONLY|__FLAG_WRITEONLY));
  1556. /* TODO -- filepos? ungot_width? filedes? nextopen? */
  1557. __STDIO_THREADUNLOCK(stream);
  1558. }
  1559. #endif
  1560. #ifdef __STDIO_GLIBC_CUSTOM_STREAMS
  1561. ssize_t _cs_read(void *cookie, char *buf, size_t bufsize)
  1562. {
  1563. return read(*((int *) cookie), buf, bufsize);
  1564. }
  1565. ssize_t _cs_write(void *cookie, const char *buf, size_t bufsize)
  1566. {
  1567. return write(*((int *) cookie), (char *) buf, bufsize);
  1568. }
  1569. int _cs_close(void *cookie)
  1570. {
  1571. return close(*((int *) cookie));
  1572. }
  1573. #endif /* __STDIO_GLIBC_CUSTOM_STREAMS */
  1574. #ifdef __STDIO_BUFFERS
  1575. static unsigned char _fixed_buffers[2 * BUFSIZ];
  1576. #define bufin (_fixed_buffers)
  1577. #define bufout (_fixed_buffers + BUFSIZ)
  1578. #endif /* __STDIO_BUFFERS */
  1579. static FILE _stdio_streams[] = {
  1580. __STDIO_INIT_FILE_STRUCT(_stdio_streams[0], __FLAG_LBF|__FLAG_READONLY, \
  1581. 0, _stdio_streams + 1, bufin, BUFSIZ ),
  1582. __STDIO_INIT_FILE_STRUCT(_stdio_streams[1], __FLAG_LBF|__FLAG_WRITEONLY, \
  1583. 1, _stdio_streams + 2, bufout, BUFSIZ ),
  1584. __STDIO_INIT_FILE_STRUCT(_stdio_streams[2], __FLAG_NBF|__FLAG_WRITEONLY, \
  1585. 2, 0, 0, 0 )
  1586. };
  1587. FILE *stdin = _stdio_streams + 0;
  1588. FILE *stdout = _stdio_streams + 1;
  1589. FILE *stderr = _stdio_streams + 2;
  1590. #if defined(__STDIO_BUFFERS) || defined(__STDIO_GLIBC_CUSTOM_STREAMS)
  1591. #ifdef __STDIO_BUFFERS
  1592. FILE *_stdio_openlist = _stdio_streams;
  1593. #else /* __STDIO_BUFFERS */
  1594. FILE *_stdio_openlist = NULL;
  1595. #endif /* __STDIO_BUFFERS */
  1596. #ifdef __STDIO_THREADSAFE
  1597. pthread_mutex_t _stdio_openlist_lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
  1598. void __stdio_init_mutex(pthread_mutex_t *m)
  1599. {
  1600. static const pthread_mutex_t __stdio_mutex_initializer
  1601. = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
  1602. memcpy(m, &__stdio_mutex_initializer, sizeof(__stdio_mutex_initializer));
  1603. }
  1604. #endif /* __STDIO_THREADSAFE */
  1605. /* TODO - do we need to lock things, or do we just assume we're the only
  1606. * remaining thread? */
  1607. /* Note: We assume here that we are the only remaining thread. */
  1608. void _stdio_term(void)
  1609. {
  1610. #if defined(__STDIO_GLIBC_CUSTOM_STREAMS) || defined(__STDIO_THREADSAFE)
  1611. register FILE *ptr;
  1612. #endif
  1613. /* TODO: if called via a signal handler for a signal mid _stdio_fwrite,
  1614. * the stream may be in an unstable state... what do we do?
  1615. * perhaps set error flag before and clear when done if successful? */
  1616. #if defined(__STDIO_BUFFERS) || defined(__STDIO_GLIBC_CUSTOM_STREAMS)
  1617. #ifdef __STDIO_THREADSAFE
  1618. /* First, forceably unlock the open file list and all files.
  1619. * Note: Set locking mode to "by caller" to save some overhead later. */
  1620. __stdio_init_mutex(&_stdio_openlist_lock);
  1621. for (ptr = _stdio_openlist ; ptr ; ptr = ptr->nextopen ) {
  1622. ptr->user_locking = 1;
  1623. __stdio_init_mutex(&ptr->lock);
  1624. }
  1625. #endif /* __STDIO_THREADSAFE */
  1626. #endif /* defined(__STDIO_BUFFERS) || defined(__STDIO_GLIBC_CUSTOM_STREAMS) */
  1627. #ifdef __STDIO_BUFFERS
  1628. /* TODO -- set an alarm and flush each file "by hand"? to avoid blocking? */
  1629. /* Now flush all streams. */
  1630. fflush_unlocked(NULL);
  1631. #endif /* __STDIO_BUFFERS */
  1632. /* Next close all custom streams in case of any special cleanup, but
  1633. * don't use fclose() because that pulls in free and malloc. Also,
  1634. * don't worry about removing them from the list. Just set the cookie
  1635. * pointer to NULL so that an error will be generated if someone tries
  1636. * to use the stream. */
  1637. #ifdef __STDIO_GLIBC_CUSTOM_STREAMS
  1638. for (ptr = _stdio_openlist ; ptr ; ptr = ptr->nextopen ) {
  1639. if (ptr->cookie != &ptr->filedes) { /* custom stream */
  1640. __CLOSE(ptr);
  1641. ptr->cookie = NULL; /* Generate an error if used later. */
  1642. #if 0
  1643. /* #ifdef __STDIO_BUFFERS */
  1644. } else {
  1645. /* TODO: "unbuffer" files like glibc does? Inconsistent with
  1646. * custom stream handling above, but that's necessary to deal
  1647. * with special user-defined close behavior. */
  1648. stream->bufpos = stream->bufread = stream->bufend
  1649. #ifdef __STDIO_GETC_MACRO
  1650. = stream->bufgetc
  1651. #endif
  1652. #ifdef __STDIO_PUTC_MACRO
  1653. = stream->bufputc
  1654. #endif
  1655. = stream->bufstart;
  1656. #endif /* __STDIO_BUFFERS */
  1657. }
  1658. }
  1659. #endif /* __STDIO_GLIBC_CUSTOM_STREAMS */
  1660. }
  1661. #if defined(__STDIO_BUFFERS) || !defined(__UCLIBC__)
  1662. void _stdio_init(void)
  1663. {
  1664. #ifdef __STDIO_BUFFERS
  1665. int old_errno = errno;
  1666. /* stdin and stdout uses line buffering when connected to a tty. */
  1667. _stdio_streams[0].modeflags ^= (1-isatty(0)) * __FLAG_LBF;
  1668. _stdio_streams[1].modeflags ^= (1-isatty(1)) * __FLAG_LBF;
  1669. __set_errno(old_errno);
  1670. #endif /* __STDIO_BUFFERS */
  1671. #ifndef __UCLIBC__
  1672. /* __stdio_term is automatically when exiting if stdio is used.
  1673. * See misc/internals/__uClibc_main.c and and stdlib/atexit.c. */
  1674. atexit(_stdio_term);
  1675. #endif /* __UCLIBC__ */
  1676. }
  1677. #endif /* defined(__STDIO_BUFFERS) || !defined(__UCLIBC__) */
  1678. #endif /* defined(__STDIO_BUFFERS) || defined(__STDIO_GLIBC_CUSTOM_STREAMS) */
  1679. #endif
  1680. /**********************************************************************/
  1681. /* ANSI/ISO functions. */
  1682. /**********************************************************************/
  1683. #ifdef L_remove
  1684. #include <unistd.h>
  1685. #include <errno.h>
  1686. /* No reentrancy issues. */
  1687. int remove(register const char *filename)
  1688. {
  1689. int old_errno = errno;
  1690. /* SUSv3 says equivalent to rmdir() if a directory, and unlink()
  1691. * otherwise. Hence, we need to try rmdir() first. */
  1692. return (((rmdir(filename) == 0)
  1693. || ((errno == ENOTDIR)
  1694. && ((__set_errno(old_errno), unlink(filename)) == 0)))
  1695. ? 0 : -1);
  1696. }
  1697. #endif
  1698. /**********************************************************************/
  1699. /* rename is a syscall
  1700. #ifdef L_rename
  1701. int rename(const char *old, const char *new);
  1702. #endif
  1703. */
  1704. /**********************************************************************/
  1705. /* TODO: tmpfile */
  1706. /* #ifdef L_tmpfile */
  1707. /* FILE *tmpfile(void); */
  1708. /* #endif */
  1709. /**********************************************************************/
  1710. /* TODO: tmpname */
  1711. /* #ifdef L_tmpname */
  1712. /* char *tmpname(char *s); */
  1713. /* #endif */
  1714. /**********************************************************************/
  1715. #ifdef L_fclose
  1716. /* We need to be careful here to avoid deadlock when threading, as we
  1717. * need to lock both the file and the open file list. This can clash
  1718. * with fflush. Since fflush is much more common, we do the extra
  1719. * work here. */
  1720. int fclose(register FILE *stream)
  1721. {
  1722. #if defined(__STDIO_BUFFERS) || defined(__STDIO_GLIBC_CUSTOM_STREAMS)
  1723. register FILE *ptr;
  1724. int rv = 0;
  1725. #ifdef __STDIO_THREADSAFE
  1726. /* Need two non-heirchal mutexs... be careful to avoid deadlock*/
  1727. do {
  1728. __STDIO_THREADLOCK(stream);
  1729. if (__STDIO_THREADTRYLOCK_OPENLIST == 0) {
  1730. break;
  1731. }
  1732. __STDIO_THREADUNLOCK(stream);
  1733. usleep(10000);
  1734. } while (1);
  1735. #endif /* __STDIO_THREADSAFE */
  1736. __stdio_validate_FILE(stream); /* debugging only */
  1737. #ifdef __STDIO_BUFFERS
  1738. if (stream->modeflags & __FLAG_WRITING) {
  1739. rv = fflush_unlocked(stream); /* Write any pending buffered chars. */
  1740. } /* Also disables putc macro if used. */
  1741. #ifdef __STDIO_GETC_MACRO
  1742. /* Not necessary after fflush, but always do this to reduce size. */
  1743. stream->bufgetc = stream->bufstart; /* Disable getc macro for safety. */
  1744. #endif /* __STDIO_GETC_MACRO */
  1745. #endif /* __STDIO_BUFFERS */
  1746. /* Remove file from open list before closing file descriptor. */
  1747. ptr = _stdio_openlist;
  1748. if (ptr == stream) {
  1749. _stdio_openlist = stream->nextopen;
  1750. } else {
  1751. while (ptr) {
  1752. if (ptr->nextopen == stream) {
  1753. ptr->nextopen = stream->nextopen;
  1754. break;
  1755. }
  1756. ptr = ptr->nextopen;
  1757. }
  1758. }
  1759. __STDIO_THREADUNLOCK_OPENLIST; /* We're done with the open file list. */
  1760. if (__CLOSE(stream) < 0) { /* Must close even if fflush failed. */
  1761. rv = EOF;
  1762. }
  1763. #ifdef __STDIO_GLIBC_CUSTOM_STREAMS
  1764. stream->cookie = &(stream->filedes);
  1765. stream->gcs.read = _cs_read;
  1766. stream->gcs.write = _cs_write;
  1767. stream->gcs.seek = 0; /* The internal seek func handles normals. */
  1768. stream->gcs.close = _cs_close;
  1769. #endif
  1770. stream->filedes = -1; /* To aid debugging... */
  1771. #ifdef __STDIO_BUFFERS
  1772. if (stream->modeflags & __FLAG_FREEBUF) {
  1773. free(stream->bufstart);
  1774. }
  1775. #endif /* __STDIO_BUFFERS */
  1776. /* TODO -- leave the stream locked to catch any dangling refs? */
  1777. __STDIO_THREADUNLOCK(stream);
  1778. /* At this point, any dangling refs to the stream are the result of
  1779. * a programming bug... so free the unlocked stream. */
  1780. if (stream->modeflags & __FLAG_FREEFILE) {
  1781. #ifdef __STDIO_GLIBC_CUSTOM_STREAMS
  1782. stream->cookie = NULL; /* To aid debugging... */
  1783. #endif
  1784. free(stream);
  1785. }
  1786. return rv;
  1787. #else /* defined(__STDIO_BUFFERS) || defined(__STDIO_GLIBC_CUSTOM_STREAMS) */
  1788. int rv = 0;
  1789. __STDIO_THREADLOCK(stream);
  1790. __stdio_validate_FILE(stream); /* debugging only */
  1791. if (__CLOSE(stream) < 0) { /* Must close even if fflush failed. */
  1792. rv = EOF;
  1793. }
  1794. #ifdef __STDIO_GLIBC_CUSTOM_STREAMS
  1795. stream->cookie = &(stream->filedes);
  1796. stream->gcs.read = _cs_read;
  1797. stream->gcs.write = _cs_write;
  1798. stream->gcs.seek = 0; /* The internal seek func handles normals. */
  1799. stream->gcs.close = _cs_close;
  1800. #endif
  1801. stream->filedes = -1; /* To aid debugging... */
  1802. __STDIO_THREADUNLOCK(stream);
  1803. /* At this point, any dangling refs to the stream are the result of
  1804. * a programming bug... so free the unlocked stream. */
  1805. if (stream->modeflags & __FLAG_FREEFILE) {
  1806. #ifdef __STDIO_GLIBC_CUSTOM_STREAMS
  1807. stream->cookie = NULL; /* To aid debugging... */
  1808. #endif
  1809. free(stream);
  1810. }
  1811. return rv;
  1812. #endif /* defined(__STDIO_BUFFERS) || defined(__STDIO_GLIBC_CUSTOM_STREAMS )*/
  1813. }
  1814. #endif
  1815. /**********************************************************************/
  1816. #ifdef L_fflush
  1817. /*
  1818. * Special cases:
  1819. * stream == NULL means fflush all writing streams (ANSI/ISO).
  1820. * stream == (FILE *) &_stdio_openlist -- implementation-specific hack
  1821. * meaning fflush all line buffered writing streams
  1822. */
  1823. /*
  1824. * NOTE: ANSI/ISO difference!!! According to the standard, fflush is only
  1825. * defined for write-only streams, or read/write streams whose last op
  1826. * was a write. However, reading is allowed for a read/write stream if
  1827. * a file positioning operation was done (fseek, fsetpos) even though there
  1828. * is no guarantee of flushing the write data in that case. Hence, for
  1829. * this case we keep a flag to indicate whether or not the buffer needs to
  1830. * be flushed even if the last operation was a read. This falls under the
  1831. * implementation-defined behavior. Otherwise, we would need to flush
  1832. * every time we did fseek, etc. even if we were still in the buffer's range.
  1833. */
  1834. /* Since the stream pointer arg is allowed to be NULL, or the address of the
  1835. * stdio open file list if stdio is buffered in this implementation, we can't
  1836. * use the UNLOCKED() macro here. */
  1837. #ifndef __STDIO_THREADSAFE
  1838. strong_alias(fflush_unlocked,fflush)
  1839. #else /* __STDIO_THREADSAFE */
  1840. int fflush(register FILE *stream)
  1841. {
  1842. int retval;
  1843. if ((stream != NULL)
  1844. #if defined(__STDIO_BUFFERS) || defined(__STDIO_GLIBC_CUSTOM_STREAMS)
  1845. && (stream != (FILE *) &_stdio_openlist)
  1846. #endif /* defined(__STDIO_BUFFERS) || defined(__STDIO_GLIBC_CUSTOM_STREAMS) */
  1847. ) {
  1848. __STDIO_THREADLOCK(stream);
  1849. retval = fflush_unlocked(stream);
  1850. __STDIO_THREADUNLOCK(stream);
  1851. } else {
  1852. retval = fflush_unlocked(stream);
  1853. }
  1854. return retval;
  1855. }
  1856. #endif /* __STDIO_THREADSAFE */
  1857. int fflush_unlocked(register FILE *stream)
  1858. {
  1859. #ifdef __STDIO_BUFFERS
  1860. int rv = 0;
  1861. unsigned short mask = (__FLAG_NBF|__FLAG_LBF);
  1862. #ifndef NDEBUG
  1863. if ((stream != NULL) && (stream != (FILE *) &_stdio_openlist)) {
  1864. __stdio_validate_FILE(stream); /* debugging only */
  1865. }
  1866. #endif
  1867. if (stream == (FILE *) &_stdio_openlist) { /* fflush all line-buffered */
  1868. stream = NULL;
  1869. mask = __FLAG_LBF;
  1870. }
  1871. if (stream == NULL) { /* flush all (line) buffered writing streams */
  1872. /* Note -- We have to lock the list even in the unlocked function. */
  1873. __STDIO_THREADLOCK_OPENLIST;
  1874. /* TODO -- Can we work around locking the list to avoid keeping it
  1875. * locked if the write blocks? */
  1876. for (stream = _stdio_openlist; stream; stream = stream->nextopen) {
  1877. if (((stream->modeflags ^ __FLAG_NBF) & mask)
  1878. && (stream->modeflags & __FLAG_WRITING)
  1879. && fflush(stream)) {
  1880. rv = EOF;
  1881. }
  1882. }
  1883. __STDIO_THREADUNLOCK_OPENLIST;
  1884. } else if (stream->modeflags & __FLAG_WRITING) {
  1885. if (_stdio_fwrite(NULL, 0, stream) > 0) { /* flush buffer contents. */
  1886. rv = -1; /* Not all chars written. */
  1887. }
  1888. #ifdef __UCLIBC_MJN3_ONLY__
  1889. #warning WISHLIST: Add option to test for undefined behavior of fflush.
  1890. #endif /* __UCLIBC_MJN3_ONLY__ */
  1891. #if 0
  1892. } else if (stream->modeflags & (__FLAG_READING|__FLAG_READONLY)) {
  1893. /* ANSI/ISO says behavior in this case is undefined but also says you
  1894. * shouldn't flush a stream you were reading from. As usual, glibc
  1895. * caters to broken programs and simply ignores this. */
  1896. stream->modeflags |= __FLAG_ERROR;
  1897. __set_errno(EBADF);
  1898. rv = -1;
  1899. #endif
  1900. }
  1901. #ifndef NDEBUG
  1902. if ((stream != NULL) && (stream != (FILE *) &_stdio_openlist)) {
  1903. __stdio_validate_FILE(stream); /* debugging only */
  1904. }
  1905. #endif
  1906. return rv;
  1907. #else /* __STDIO_BUFFERS --------------------------------------- */
  1908. #ifndef NDEBUG
  1909. if ((stream != NULL)
  1910. #if defined(__STDIO_BUFFERS) || defined(__STDIO_GLIBC_CUSTOM_STREAMS)
  1911. && (stream != (FILE *) &_stdio_openlist)
  1912. #endif /* defined(__STDIO_BUFFERS) || defined(__STDIO_GLIBC_CUSTOM_STREAMS) */
  1913. ) {
  1914. __stdio_validate_FILE(stream); /* debugging only */
  1915. }
  1916. #endif
  1917. #ifdef __UCLIBC_MJN3_ONLY__
  1918. #warning WISHLIST: Add option to test for undefined behavior of fflush.
  1919. #endif /* __UCLIBC_MJN3_ONLY__ */
  1920. #if 0
  1921. return ((stream != NULL)
  1922. && (stream->modeflags & (__FLAG_READING|__FLAG_READONLY))
  1923. ? ((stream->modeflags |= __FLAG_ERROR), __set_errno(EBADF), EOF)
  1924. : 0 );
  1925. #else
  1926. return 0;
  1927. #endif
  1928. #endif /* __STDIO_BUFFERS */
  1929. }
  1930. #endif
  1931. /**********************************************************************/
  1932. #ifdef L_fopen
  1933. /* No reentrancy issues. */
  1934. FILE *fopen(const char * __restrict filename, const char * __restrict mode)
  1935. {
  1936. return _stdio_fopen(filename, mode, NULL, -1);
  1937. }
  1938. #endif
  1939. /**********************************************************************/
  1940. #ifdef L__stdio_fopen
  1941. /*
  1942. * Cases:
  1943. * fopen : filename != NULL, stream == NULL, filedes == -1
  1944. * freopen : filename != NULL, stream != NULL, filedes == -1
  1945. * fdopen : filename == NULL, stream == NULL, filedes valid
  1946. * fsfopen : filename != NULL, stream != NULL, filedes == -1
  1947. * fopen64 : filename != NULL, stream == NULL, filedes == -2
  1948. */
  1949. #if O_ACCMODE != 3 || O_RDONLY != 0 || O_WRONLY != 1 || O_RDWR != 2
  1950. #error Assumption violated - mode constants
  1951. #endif
  1952. /* Internal function -- reentrant (locks open file list) */
  1953. FILE *_stdio_fopen(const char * __restrict filename,
  1954. register const char * __restrict mode,
  1955. register FILE * __restrict stream, int filedes)
  1956. {
  1957. __mode_t open_mode;
  1958. /* parse mode */
  1959. open_mode = O_RDONLY;
  1960. if (*mode != 'r') { /* not read */
  1961. open_mode = (O_WRONLY | O_CREAT | O_TRUNC);
  1962. if (*mode != 'w') { /* not write (create or truncate)*/
  1963. open_mode = (O_WRONLY | O_CREAT | O_APPEND);
  1964. if (*mode != 'a') { /* not write (create or append) */
  1965. __set_errno(EINVAL); /* then illegal mode */
  1966. return NULL;
  1967. }
  1968. }
  1969. }
  1970. if ((*++mode == 'b')) { /* binary mode (NOP currently) */
  1971. ++mode;
  1972. }
  1973. if (*mode == '+') { /* read-write */
  1974. ++mode;
  1975. open_mode &= ~(O_RDONLY | O_WRONLY);
  1976. open_mode |= O_RDWR;
  1977. }
  1978. #if defined(__STDIO_FOPEN_EXCLUSIVE_MODE) || defined(__STDIO_FOPEN_LARGEFILE_MODE)
  1979. for ( ; *mode ; ++mode) { /* ignore everything else except ... */
  1980. #ifdef __STDIO_FOPEN_EXCLUSIVE_MODE
  1981. if (*mode == 'x') { /* open exclusive -- glibc extension */
  1982. open_mode |= O_EXCL;
  1983. continue;
  1984. }
  1985. #endif /* __STDIO_FOPEN_EXCLUSIVE_MODE */
  1986. #ifdef __STDIO_FOPEN_LARGEFILE_MODE
  1987. if (*mode == 'F') { /* open large file */
  1988. open_mode |= O_LARGEFILE;
  1989. continue;
  1990. }
  1991. #endif /* __STDIO_FOPEN_LARGEFILE_MODE */
  1992. }
  1993. #endif /* __STDIO_FOPEN_EXCLUSIVE_MODE or __STDIO_FOPEN_LARGEFILE_MODE def'd */
  1994. #ifdef __BCC__
  1995. mode = filename; /* TODO: help BCC with register allocation. */
  1996. #define filename mode
  1997. #endif /* __BCC__ */
  1998. if (!stream) { /* Need to allocate a FILE. */
  1999. #ifdef __STDIO_BUFFERS
  2000. if ((stream = malloc(sizeof(FILE))) == NULL) {
  2001. return stream;
  2002. }
  2003. stream->modeflags = __FLAG_FREEFILE;
  2004. if ((stream->bufstart = malloc(BUFSIZ)) != 0) {
  2005. stream->bufend = stream->bufstart + BUFSIZ;
  2006. stream->modeflags |= __FLAG_FREEBUF;
  2007. } else {
  2008. #if __STDIO_BUILTIN_BUF_SIZE > 0
  2009. stream->bufstart = stream->unbuf;
  2010. stream->bufend = stream->unbuf + sizeof(stream->unbuf);
  2011. #else /* __STDIO_BUILTIN_BUF_SIZE > 0 */
  2012. stream->bufstart = stream->bufend = NULL;
  2013. #endif /* __STDIO_BUILTIN_BUF_SIZE > 0 */
  2014. }
  2015. #else /* __STDIO_BUFFERS */
  2016. if ((stream = malloc(sizeof(FILE))) == NULL) {
  2017. return stream;
  2018. }
  2019. stream->modeflags = __FLAG_FREEFILE;
  2020. #endif /* __STDIO_BUFFERS */
  2021. }
  2022. if (filedes >= 0) { /* Handle fdopen trickery. */
  2023. /* NOTE: it is insufficient to just check R/W/RW agreement.
  2024. * We must also check largefile compatibility if applicable.
  2025. * Also, if append mode is desired for fdopen but O_APPEND isn't
  2026. * currently set, then set it as recommended by SUSv3. However,
  2027. * if append mode is not specified for fdopen but O_APPEND is set,
  2028. * leave it set (glibc compat). */
  2029. int i = (open_mode & (O_ACCMODE|O_LARGEFILE)) + 1;
  2030. /* NOTE: fopencookie needs changing if the basic check changes! */
  2031. if (((i & (((int) filename) + 1)) != i) /* Check basic agreement. */
  2032. || (((open_mode & O_APPEND)
  2033. && !(((int) filename) & O_APPEND)
  2034. && fcntl(filedes, F_SETFL, O_APPEND))) /* Need O_APPEND. */
  2035. ) {
  2036. __set_errno(EINVAL);
  2037. filedes = -1;
  2038. }
  2039. #ifdef __STDIO_LARGE_FILES
  2040. /* For later... to reflect largefile setting in stream flags. */
  2041. open_mode |= (((int) filename) & O_LARGEFILE);
  2042. #endif /* __STDIO_LARGE_FILES */
  2043. stream->filedes = filedes;
  2044. } else {
  2045. #ifdef __STDIO_LARGE_FILES
  2046. if (filedes < -1) {
  2047. open_mode |= O_LARGEFILE;
  2048. }
  2049. #endif /* __STDIO_LARGE_FILES */
  2050. stream->filedes = open(filename, open_mode, 0666);
  2051. }
  2052. if (stream->filedes < 0) {
  2053. #ifdef __STDIO_BUFFERS
  2054. if (stream->modeflags & __FLAG_FREEBUF) {
  2055. free(stream->bufstart);
  2056. }
  2057. #endif /* __STDIO_BUFFERS */
  2058. if (stream->modeflags & __FLAG_FREEFILE) {
  2059. free(stream);
  2060. }
  2061. return NULL;
  2062. }
  2063. #ifdef __STDIO_BUFFERS
  2064. {
  2065. /* Do not let isatty mess up errno */
  2066. int old_errno = errno;
  2067. stream->modeflags |= (isatty(stream->filedes) * __FLAG_LBF);
  2068. __set_errno(old_errno);
  2069. }
  2070. #endif
  2071. stream->modeflags |=
  2072. #if (O_APPEND == __FLAG_APPEND) \
  2073. && ((O_LARGEFILE == __FLAG_LARGEFILE) || (O_LARGEFILE == 0))
  2074. (open_mode & (O_APPEND|O_LARGEFILE)) | /* i386 linux and elks */
  2075. #else /* (O_APPEND == __FLAG_APPEND) && (O_LARGEFILE == __FLAG_LARGEFILE) */
  2076. ((open_mode & O_APPEND) ? __FLAG_APPEND : 0) |
  2077. #ifdef __STDIO_LARGE_FILES
  2078. ((open_mode & O_LARGEFILE) ? __FLAG_LARGEFILE : 0) |
  2079. #endif /* __STDIO_LARGE_FILES */
  2080. #endif /* (O_APPEND == __FLAG_APPEND) && (O_LARGEFILE == __FLAG_LARGEFILE) */
  2081. ((((open_mode & O_ACCMODE) + 1) ^ 0x03) * __FLAG_WRITEONLY);
  2082. #ifdef __STDIO_BUFFERS
  2083. #ifdef __STDIO_GETC_MACRO
  2084. stream->bufgetc =
  2085. #endif
  2086. #ifdef __STDIO_PUTC_MACRO
  2087. stream->bufputc =
  2088. #endif
  2089. stream->bufpos = stream->bufread = stream->bufstart;
  2090. #endif /* __STDIO_BUFFERS */
  2091. #ifdef __STDIO_GLIBC_CUSTOM_STREAMS
  2092. stream->cookie = &(stream->filedes);
  2093. stream->gcs.read = _cs_read;
  2094. stream->gcs.write = _cs_write;
  2095. stream->gcs.seek = 0; /* The internal seek func handles normals. */
  2096. stream->gcs.close = _cs_close;
  2097. #endif /* __STDIO_GLIBC_CUSTOM_STREAMS */
  2098. #ifdef __STDIO_WIDE
  2099. stream->ungot_width[0] = 0;
  2100. #endif /* __STDIO_WIDE */
  2101. #ifdef __STDIO_MBSTATE
  2102. __INIT_MBSTATE(&(stream->state));
  2103. #endif /* __STDIO_MBSTATE */
  2104. #ifdef __STDIO_THREADSAFE
  2105. stream->user_locking = 0;
  2106. __stdio_init_mutex(&stream->lock);
  2107. #endif /* __STDIO_THREADSAFE */
  2108. #if defined(__STDIO_BUFFERS) \
  2109. || (defined(__STDIO_THREADSAFE) && defined(__STDIO_GLIBC_CUSTOM_STREAMS))
  2110. __STDIO_THREADLOCK_OPENLIST;
  2111. stream->nextopen = _stdio_openlist; /* New files are inserted at */
  2112. _stdio_openlist = stream; /* the head of the list. */
  2113. __STDIO_THREADUNLOCK_OPENLIST;
  2114. #endif
  2115. __stdio_validate_FILE(stream); /* debugging only */
  2116. return stream;
  2117. #ifdef __BCC__
  2118. #undef filename
  2119. #endif /* __BCC__ */
  2120. }
  2121. #endif
  2122. /**********************************************************************/
  2123. #ifdef L_freopen
  2124. /* Reentrant. */
  2125. FILE *freopen(const char * __restrict filename, const char * __restrict mode,
  2126. register FILE * __restrict stream)
  2127. {
  2128. /*
  2129. * ANSI/ISO allow (implementation-defined) change of mode for an
  2130. * existing file if filename is NULL. It doesn't look like Linux
  2131. * supports this, so we don't here.
  2132. *
  2133. * NOTE: Whether or not the stream is free'd on failure is unclear
  2134. * w.r.t. ANSI/ISO. This implementation chooses to NOT free
  2135. * the stream and associated buffer if they were dynamically
  2136. * allocated.
  2137. * TODO: Check the above.
  2138. * TODO: Apparently linux allows setting append mode. Implement?
  2139. */
  2140. unsigned short dynmode;
  2141. register FILE *fp;
  2142. __STDIO_THREADLOCK(stream);
  2143. /* First, flush and close, but don't deallocate, the stream. */
  2144. /* This also removes the stream for the open file list. */
  2145. dynmode =
  2146. #ifdef __STDIO_BUFFERS
  2147. /* __MASK_BUFMODE | */ /* TODO: check */
  2148. #endif /* __STDIO_BUFFERS */
  2149. (stream->modeflags & (__FLAG_FREEBUF|__FLAG_FREEFILE));
  2150. stream->modeflags &= ~(__FLAG_FREEBUF|__FLAG_FREEFILE);
  2151. fclose(stream); /* Failures are ignored. */
  2152. fp = _stdio_fopen(filename, mode, stream, -1);
  2153. stream->modeflags |= dynmode;
  2154. __STDIO_THREADUNLOCK(stream);
  2155. return fp;
  2156. }
  2157. #endif
  2158. /**********************************************************************/
  2159. #ifdef L_freopen64
  2160. /* Reentrant. */
  2161. /* TODO -- is it worth collecting the common work (40 bytes) in a function? */
  2162. FILE *freopen64(const char * __restrict filename, const char * __restrict mode,
  2163. register FILE * __restrict stream)
  2164. {
  2165. unsigned short dynmode;
  2166. register FILE *fp;
  2167. __STDIO_THREADLOCK(stream);
  2168. /* First, flush and close, but don't deallocate, the stream. */
  2169. /* This also removes the stream for the open file list. */
  2170. dynmode =
  2171. #ifdef __STDIO_BUFFERS
  2172. /* __MASK_BUFMODE | */ /* TODO: check */
  2173. #endif /* __STDIO_BUFFERS */
  2174. (stream->modeflags & (__FLAG_FREEBUF|__FLAG_FREEFILE));
  2175. stream->modeflags &= ~(__FLAG_FREEBUF|__FLAG_FREEFILE);
  2176. fclose(stream); /* Failures are ignored. */
  2177. stream->modeflags = dynmode;
  2178. fp = _stdio_fopen(filename, mode, stream, -2); /* TODO -- magic const */
  2179. __STDIO_THREADUNLOCK(stream);
  2180. return fp;
  2181. }
  2182. #endif
  2183. /**********************************************************************/
  2184. #ifdef L_setbuf
  2185. /* Reentrant through setvbuf(). */
  2186. void setbuf(FILE * __restrict stream, register char * __restrict buf)
  2187. {
  2188. #ifdef __STDIO_BUFFERS
  2189. int mode;
  2190. mode = (buf != NULL) ? _IOFBF : _IONBF;
  2191. setvbuf(stream, buf, mode, BUFSIZ);
  2192. #else /* __STDIO_BUFFERS */
  2193. /* TODO -- assert on stream? */
  2194. /* Nothing to do. */
  2195. #endif /* __STDIO_BUFFERS */
  2196. }
  2197. #endif
  2198. /**********************************************************************/
  2199. #ifdef L_setvbuf
  2200. /* Reentrant. */
  2201. int setvbuf(register FILE * __restrict stream, register char * __restrict buf,
  2202. int mode, size_t size)
  2203. {
  2204. #ifdef __STDIO_BUFFERS
  2205. int allocated_buf_flag;
  2206. int rv = EOF;
  2207. __STDIO_THREADLOCK(stream);
  2208. __stdio_validate_FILE(stream); /* debugging only */
  2209. if (((unsigned int) mode) > 2) { /* Illegal mode. */
  2210. /* TODO -- set an errno? */
  2211. goto DONE;
  2212. }
  2213. #ifdef __STDIO_FLEXIBLE_SETVBUF
  2214. /* C89 standard requires no ops before setvbuf, but we can be flexible. */
  2215. /* NOTE: This will trash any chars ungetc'd!!! */
  2216. /* TODO: hmm could preserve unget count since ungot slots aren't changed (true?)
  2217. * but this will fail when buffered chars read from a pipe unless the user buf
  2218. * is big enough to copy everything over. */
  2219. if (fseek(stream, 0L, SEEK_CUR)) {
  2220. goto DONE;
  2221. }
  2222. #else /* __STDIO_FLEXIBLE_SETVBUF */
  2223. /*
  2224. * Note: ANSI/ISO requires setvbuf to be called after opening the file
  2225. * but before any other operation other than a failed setvbuf call.
  2226. * We'll cheat here and only test if the wide or narrow mode flag has
  2227. * been set; i.e. no read or write (or unget or fwide) operations have
  2228. * taken place.
  2229. */
  2230. #ifdef __STDIO_WIDE
  2231. if (stream->modeflags & (__FLAG_WIDE|__FLAG_NARROW)) {
  2232. goto DONE;
  2233. }
  2234. #else /* __STDIO_WIDE */
  2235. /* Note: This only checks if not currently reading or writing. */
  2236. if (stream->modeflags & (__FLAG_READING|__FLAG_WRITING)) {
  2237. goto DONE;
  2238. }
  2239. #endif /* __STDIO_WIDE */
  2240. #endif /* __STDIO_FLEXIBLE_SETVBUF */
  2241. if (mode == _IONBF) {
  2242. size = 0;
  2243. buf = NULL;
  2244. } else if (!buf && !size) {
  2245. /* If buf==NULL && size==0 && either _IOFBF or _IOLBF, keep
  2246. * current buffer and only set buffering mode. */
  2247. size = stream->bufend - stream->bufstart;
  2248. }
  2249. stream->modeflags &= ~(__MASK_BUFMODE); /* Clear current mode */
  2250. stream->modeflags |= mode * __FLAG_LBF; /* and set new one. */
  2251. allocated_buf_flag = 0;
  2252. if ((!buf) && (size != (stream->bufend - stream->bufstart))) {
  2253. /* No buffer supplied and requested size different from current. */
  2254. /* If size == 0, create a (hopefully) bogus non-null pointer... */
  2255. if (!(buf = ((size > 0)
  2256. ? ((allocated_buf_flag = __FLAG_FREEBUF), malloc(size))
  2257. : ((char *)NULL) + 1))
  2258. ) {
  2259. /* TODO -- should we really keep current buffer if it was passed
  2260. * to us earlier by the app? */
  2261. goto DONE; /* Keep current buffer. */
  2262. }
  2263. }
  2264. /* TODO: setvbuf "signal" safety */
  2265. if (buf && (buf != (char *) stream->bufstart)) { /* Want new buffer. */
  2266. if (stream->modeflags & __FLAG_FREEBUF) {
  2267. stream->modeflags &= ~(__FLAG_FREEBUF);
  2268. free(stream->bufstart);
  2269. }
  2270. stream->modeflags |= allocated_buf_flag; /* Free-able buffer? */
  2271. #ifdef __STDIO_GETC_MACRO
  2272. stream->bufgetc =
  2273. #endif
  2274. #ifdef __STDIO_PUTC_MACRO
  2275. stream->bufputc =
  2276. #endif
  2277. stream->bufpos = stream->bufread = stream->bufstart = buf;
  2278. stream->bufend = buf + size;
  2279. }
  2280. __stdio_validate_FILE(stream); /* debugging only */
  2281. rv = 0;
  2282. DONE:
  2283. __STDIO_THREADUNLOCK(stream);
  2284. return rv;
  2285. #else /* __STDIO_BUFFERS */
  2286. __stdio_validate_FILE(stream); /* debugging only */
  2287. /* TODO -- set errno for illegal mode? */
  2288. return EOF;
  2289. #endif /* __STDIO_BUFFERS */
  2290. }
  2291. #endif
  2292. /**********************************************************************
  2293. int fprintf(FILE * __restrict stream, const char * __restrict format, ...);
  2294. int fscanf(FILE * __restrict stream, const char * __restrict format, ...);
  2295. int printf(const char * __restrict format, ...);
  2296. int scanf(const char * __restrict format, ...);
  2297. int snprintf(char * __restrict s, size_t n,
  2298. const char * __restrict format, ...);
  2299. int sprintf(char * __restrict s, const char * __restrict format, ...);
  2300. int sscanf(char * __restrict s, const char * __restrict format, ...);
  2301. int vfprintf(FILE * __restrict stream, const char * __restrict format,
  2302. va_list arg);
  2303. int vfscanf(FILE * __restrict stream, const char * __restrict format,
  2304. va_list arg);
  2305. int vprintf(const char * __restrict format, va_list arg);
  2306. int vscanf(const char * __restrict format, va_list arg);
  2307. int vsnprintf(char * __restrict s, size_t n,
  2308. const char * __restrict format, va_list arg);
  2309. int vsprintf(char * __restrict s, const char * __restrict format,
  2310. va_list arg);
  2311. int vsscanf(char * __restrict s, const char * __restrict format,
  2312. va_list arg);
  2313. **********************************************************************/
  2314. #ifdef L_fgetc
  2315. /* Reentrancy handled by UNLOCKED() macro. */
  2316. UNLOCKED(int,fgetc,(FILE *stream),(stream))
  2317. {
  2318. unsigned char buf[1];
  2319. #ifdef __STDIO_WIDE
  2320. return (fread_unlocked(buf, (size_t) 1, (size_t) 1, stream) > 0)
  2321. ? *buf : EOF;
  2322. #else /* __STDIO_WIDE */
  2323. return (_stdio_fread(buf, (size_t) 1, stream) > 0) ? *buf : EOF;
  2324. #endif /* __STDIO_WIDE */
  2325. }
  2326. #endif
  2327. /**********************************************************************/
  2328. #ifdef L_fgets
  2329. /* Reentrancy handled by UNLOCKED() macro. */
  2330. UNLOCKED(char *,fgets,
  2331. (char *__restrict s, int n, register FILE * __restrict stream),
  2332. (s, n, stream))
  2333. {
  2334. register char *p;
  2335. int c;
  2336. #ifdef __UCLIBC_MJN3_ONLY__
  2337. #warning CONSIDER: What should fgets do if n <= 0?
  2338. #endif /* __UCLIBC_MJN3_ONLY__ */
  2339. /* Should we assert here? Or set errno? Or just fail... */
  2340. if (n <= 0) {
  2341. /* __set_errno(EINVAL); */
  2342. goto ERROR;
  2343. }
  2344. p = s;
  2345. while (--n) {
  2346. if ((c = (getc_unlocked)(stream)) == EOF) { /* Disable the macro. */
  2347. if (__FERROR(stream)) {
  2348. goto ERROR;
  2349. }
  2350. break;
  2351. }
  2352. if ((*p++ = c) == '\n') {
  2353. break;
  2354. }
  2355. }
  2356. #ifdef __UCLIBC_MJN3_ONLY__
  2357. #warning CONSIDER: If n==1 and not at EOF, should fgets return an empty string?
  2358. #endif /* __UCLIBC_MJN3_ONLY__ */
  2359. if (p > s) {
  2360. *p = 0;
  2361. return s;
  2362. }
  2363. ERROR:
  2364. return NULL;
  2365. }
  2366. #endif
  2367. /**********************************************************************/
  2368. #ifdef L_fputc
  2369. /* Reentrancy handled by UNLOCKED() macro. */
  2370. UNLOCKED(int,fputc,(int c, FILE *stream),(c,stream))
  2371. {
  2372. unsigned char buf[1];
  2373. *buf = (unsigned char) c;
  2374. #ifdef __STDIO_WIDE
  2375. return (fwrite_unlocked(buf, (size_t) 1, (size_t) 1, stream) > 0)
  2376. ? (*buf) : EOF;
  2377. #else /* __STDIO_WIDE */
  2378. return (_stdio_fwrite(buf, (size_t) 1, stream) > 0) ? (*buf) : EOF;
  2379. #endif /* __STDIO_WIDE */
  2380. }
  2381. #endif
  2382. /**********************************************************************/
  2383. #ifdef L_fputs
  2384. /* Reentrancy handled by UNLOCKED() macro. */
  2385. UNLOCKED(int,fputs,
  2386. (register const char * __restrict s, FILE * __restrict stream),
  2387. (s, stream))
  2388. {
  2389. size_t n = strlen(s);
  2390. #ifdef __STDIO_WIDE
  2391. return (fwrite_unlocked(s, (size_t) 1, n, stream) == n) ? n : EOF;
  2392. #else /* __STDIO_WIDE */
  2393. return (_stdio_fwrite(s, n, stream) == n) ? n : EOF;
  2394. #endif /* __STDIO_WIDE */
  2395. }
  2396. #endif
  2397. /**********************************************************************/
  2398. #ifdef L_getc
  2399. #undef getc
  2400. #undef getc_unlocked
  2401. /* Reentrancy handled by UNLOCKED() macro. */
  2402. UNLOCKED(int,getc,(register FILE *stream),(stream))
  2403. {
  2404. return __GETC(stream); /* Invoke the macro. */
  2405. }
  2406. #endif
  2407. /**********************************************************************/
  2408. #ifdef L_getchar
  2409. #undef getchar /* Just in case. */
  2410. /* Reentrancy handled by UNLOCKED() macro. */
  2411. UNLOCKED_STREAM(int,getchar,(void),(),stdin)
  2412. {
  2413. register FILE *stream = stdin; /* This helps bcc optimize. */
  2414. return __GETC(stream);
  2415. }
  2416. #endif
  2417. /**********************************************************************/
  2418. #ifdef L_gets
  2419. link_warning(gets, "the 'gets' function is dangerous and should not be used.")
  2420. /* Reentrant. */
  2421. char *gets(char *s) /* WARNING!!! UNSAFE FUNCTION!!! */
  2422. {
  2423. register FILE *stream = stdin; /* This helps bcc optimize. */
  2424. register char *p = s;
  2425. int c;
  2426. __STDIO_THREADLOCK(stream);
  2427. /* Note: don't worry about performance here... this shouldn't be used!
  2428. * Therefore, force actual function call. */
  2429. while (((c = (getc_unlocked)(stream)) != EOF) && ((*p = c) != '\n')) {
  2430. ++p;
  2431. }
  2432. if ((c == EOF) || (s == p)) {
  2433. s = NULL;
  2434. } else {
  2435. *p = 0;
  2436. }
  2437. __STDIO_THREADUNLOCK(stream);
  2438. return s;
  2439. }
  2440. #endif
  2441. /**********************************************************************/
  2442. #ifdef L_putc
  2443. #undef putc
  2444. #undef putc_unlocked
  2445. /* Reentrancy handled by UNLOCKED() macro. */
  2446. UNLOCKED(int,putc,(int c, register FILE *stream),(c,stream))
  2447. {
  2448. return __PUTC(c, stream); /* Invoke the macro. */
  2449. }
  2450. #endif
  2451. /**********************************************************************/
  2452. #ifdef L_putchar
  2453. #undef putchar /* Just in case. */
  2454. /* Reentrancy handled by UNLOCKED() macro. */
  2455. UNLOCKED_STREAM(int,putchar,(int c),(c),stdout)
  2456. {
  2457. register FILE *stream = stdout; /* This helps bcc optimize. */
  2458. return __PUTC(c, stream);
  2459. }
  2460. #endif
  2461. /**********************************************************************/
  2462. #ifdef L_puts
  2463. /* Reentrant. */
  2464. int puts(register const char *s)
  2465. {
  2466. register FILE *stream = stdout; /* This helps bcc optimize. */
  2467. int n;
  2468. __STDIO_THREADLOCK(stream);
  2469. n = fputs_unlocked(s,stream) + 1;
  2470. if (
  2471. #if 1
  2472. fputc_unlocked('\n',stream)
  2473. #else
  2474. fputs_unlocked("\n",stream)
  2475. #endif
  2476. == EOF) {
  2477. n = EOF;
  2478. }
  2479. __STDIO_THREADUNLOCK(stream);
  2480. return n;
  2481. }
  2482. #endif
  2483. /**********************************************************************/
  2484. #ifdef L_ungetc
  2485. /*
  2486. * Note: This is the application-callable ungetc. If scanf calls this, it
  2487. * should also set stream->ungot[1] to 0 if this is the only ungot.
  2488. */
  2489. /* Reentrant. */
  2490. int ungetc(int c, register FILE *stream)
  2491. {
  2492. __STDIO_THREADLOCK(stream);
  2493. __stdio_validate_FILE(stream); /* debugging only */
  2494. #ifdef __STDIO_WIDE
  2495. if (stream->modeflags & __FLAG_WIDE) {
  2496. stream->modeflags |= __FLAG_ERROR;
  2497. c = EOF;
  2498. goto DONE;
  2499. }
  2500. stream->modeflags |= __FLAG_NARROW;
  2501. #endif /* __STDIO_WIDE */
  2502. /* If can't read or c == EOF or ungot slots already filled, then fail. */
  2503. if ((stream->modeflags
  2504. & (__MASK_UNGOT2|__FLAG_WRITEONLY
  2505. #ifndef __STDIO_AUTO_RW_TRANSITION
  2506. |__FLAG_WRITING /* Note: technically no, but yes in spirit */
  2507. #endif /* __STDIO_AUTO_RW_TRANSITION */
  2508. ))
  2509. || ((stream->modeflags & __MASK_UNGOT1) && (stream->ungot[1]))
  2510. || (c == EOF) ) {
  2511. c = EOF;
  2512. goto DONE;;
  2513. }
  2514. #ifdef __STDIO_BUFFERS
  2515. #ifdef __STDIO_AUTO_RW_TRANSITION
  2516. if (stream->modeflags & __FLAG_WRITING) {
  2517. fflush_unlocked(stream); /* Commit any write-buffered chars. */
  2518. }
  2519. #endif /* __STDIO_AUTO_RW_TRANSITION */
  2520. #endif /* __STDIO_BUFFERS */
  2521. /* Clear EOF and WRITING flags, and set READING FLAG */
  2522. stream->modeflags &= ~(__FLAG_EOF|__FLAG_WRITING);
  2523. #ifdef __UCLIBC_MJN3_ONLY__
  2524. #warning CONSIDER: Is setting the reading flag after an ungetc necessary?
  2525. #endif /* __UCLIBC_MJN3_ONLY__ */
  2526. stream->modeflags |= __FLAG_READING;
  2527. stream->ungot[1] = 1; /* Flag as app ungetc call; scanf fixes up. */
  2528. stream->ungot[(stream->modeflags++) & __MASK_UNGOT] = c;
  2529. #ifdef __STDIO_GETC_MACRO
  2530. stream->bufgetc = stream->bufstart; /* Must disable getc macro. */
  2531. #endif
  2532. __stdio_validate_FILE(stream); /* debugging only */
  2533. DONE:
  2534. __STDIO_THREADUNLOCK(stream);
  2535. return c;
  2536. }
  2537. #endif
  2538. /**********************************************************************/
  2539. #ifdef L_fread
  2540. /* NOTE: Surely ptr cannot point to a buffer of size > SIZE_MAX.
  2541. * Therefore, we treat the case size * nmemb > SIZE_MAX as an error,
  2542. * and include an assert() for it. */
  2543. /* Reentrancy handled by UNLOCKED() macro. */
  2544. UNLOCKED(size_t,fread,
  2545. (void * __restrict ptr, size_t size, size_t nmemb,
  2546. FILE * __restrict stream),
  2547. (ptr,size,nmemb,stream))
  2548. {
  2549. #ifdef __STDIO_WIDE
  2550. if (stream->modeflags & __FLAG_WIDE) {
  2551. stream->modeflags |= __FLAG_ERROR;
  2552. /* TODO -- errno? it this correct? */
  2553. return 0;
  2554. }
  2555. stream->modeflags |= __FLAG_NARROW;
  2556. #endif /* __STDIO_WIDE */
  2557. return (size == 0)
  2558. ? 0
  2559. : ( assert( ((size_t)(-1)) / size >= nmemb ),
  2560. _stdio_fread(ptr, nmemb * size, stream) / size );
  2561. }
  2562. #endif
  2563. /**********************************************************************/
  2564. #ifdef L_fwrite
  2565. /* NOTE: Surely ptr cannot point to a buffer of size > SIZE_MAX.
  2566. * Therefore, we treat the case size * nmemb > SIZE_MAX as an error,
  2567. * and include an assert() for it. */
  2568. /* Reentrancy handled by UNLOCKED() macro. */
  2569. UNLOCKED(size_t,fwrite,
  2570. (const void * __restrict ptr, size_t size, size_t nmemb,
  2571. FILE * __restrict stream),
  2572. (ptr,size,nmemb,stream))
  2573. {
  2574. #ifdef __STDIO_WIDE
  2575. if (stream->modeflags & __FLAG_WIDE) {
  2576. stream->modeflags |= __FLAG_ERROR;
  2577. /* TODO -- errno? it this correct? */
  2578. return 0;
  2579. }
  2580. stream->modeflags |= __FLAG_NARROW;
  2581. #endif /* __STDIO_WIDE */
  2582. return (size == 0)
  2583. ? 0
  2584. : ( assert( ((size_t)(-1)) / size >= nmemb ),
  2585. _stdio_fwrite(ptr, nmemb * size, stream) / size );
  2586. }
  2587. #endif
  2588. /**********************************************************************/
  2589. #if defined(L_fgetpos) || defined(L_fgetpos64)
  2590. /* Reentrant -- fgetpos() and fgetpos64(). */
  2591. #if defined(L_fgetpos) && defined(L_fgetpos64)
  2592. #error L_fgetpos and L_fgetpos64 are defined simultaneously!
  2593. #endif
  2594. #ifndef L_fgetpos64
  2595. #define fgetpos64 fgetpos
  2596. #define fpos64_t fpos_t
  2597. #define ftello64 ftell
  2598. #endif
  2599. int fgetpos64(FILE * __restrict stream, register fpos64_t * __restrict pos)
  2600. {
  2601. int retval = -1;
  2602. #ifdef __STDIO_WIDE
  2603. if (pos == NULL) {
  2604. __set_errno(EINVAL);
  2605. } else {
  2606. __STDIO_THREADLOCK(stream);
  2607. if ((pos->__pos = ftello64(stream)) >= 0) {
  2608. __COPY_MBSTATE(&(pos->__mbstate), &(stream->state));
  2609. pos->mblen_pending = stream->ungot_width[0];
  2610. retval = 0;
  2611. }
  2612. __STDIO_THREADUNLOCK(stream);
  2613. }
  2614. #else /* __STDIO_WIDE */
  2615. if (pos == NULL) {
  2616. __set_errno(EINVAL);
  2617. } else if ((pos->__pos = ftello64(stream)) >= 0) {
  2618. retval = 0;
  2619. }
  2620. #endif /* __STDIO_WIDE */
  2621. return retval;
  2622. }
  2623. #ifndef L_fgetpos64
  2624. #undef fgetpos64
  2625. #undef fpos64_t
  2626. #undef ftello64
  2627. #endif
  2628. #endif
  2629. /**********************************************************************/
  2630. #ifdef L_fseek
  2631. strong_alias(fseek,fseeko);
  2632. #endif
  2633. #if defined(L_fseek) && defined(__STDIO_LARGE_FILES)
  2634. int fseek(register FILE *stream, long int offset, int whence)
  2635. {
  2636. return fseeko64(stream, offset, whence);
  2637. }
  2638. #endif
  2639. #if defined(L_fseeko64) || (defined(L_fseek) && !defined(__STDIO_LARGE_FILES))
  2640. #ifndef L_fseeko64
  2641. #define fseeko64 fseek
  2642. #define __off64_t long int
  2643. #endif
  2644. /* Reentrant -- fseek(), fseeko(), fseeko64() */
  2645. int fseeko64(register FILE *stream, __off64_t offset, int whence)
  2646. {
  2647. #if SEEK_SET != 0 || SEEK_CUR != 1 || SEEK_END != 2
  2648. #error Assumption violated -- values of SEEK_SET, SEEK_CUR, SEEK_END
  2649. #endif
  2650. __offmax_t pos[1];
  2651. int retval;
  2652. if ( ((unsigned int) whence) > 2 ) {
  2653. __set_errno(EINVAL);
  2654. return -1;
  2655. }
  2656. __STDIO_THREADLOCK(stream);
  2657. __stdio_validate_FILE(stream); /* debugging only */
  2658. retval = -1;
  2659. *pos = offset;
  2660. if (
  2661. #ifdef __STDIO_BUFFERS
  2662. /* First commit any pending buffered writes. */
  2663. ((stream->modeflags & __FLAG_WRITING) && fflush_unlocked(stream)) ||
  2664. #endif /* __STDIO_BUFFERS */
  2665. ((whence == SEEK_CUR) && (_stdio_adjpos(stream, pos) < 0))
  2666. || (_stdio_lseek(stream, pos, whence) < 0)
  2667. ) {
  2668. __stdio_validate_FILE(stream); /* debugging only */
  2669. goto DONE;
  2670. }
  2671. #ifdef __STDIO_BUFFERS
  2672. /* only needed if reading but do it anyway to avoid test */
  2673. #ifdef __STDIO_GETC_MACRO
  2674. stream->bufgetc = /* Must disable getc. */
  2675. #endif
  2676. stream->bufpos = stream->bufread = stream->bufstart;
  2677. #endif /* __STDIO_BUFFERS */
  2678. stream->modeflags &=
  2679. ~(__FLAG_READING|__FLAG_WRITING|__FLAG_EOF|__MASK_UNGOT);
  2680. #ifdef __UCLIBC_MJN3_ONLY__
  2681. #warning CONSIDER: How do we deal with fseek to an ftell position for incomplete or error wide? Right now, we clear all multibyte state info. If we do not clear, then fix rewind() to do so if fseek() succeeds.
  2682. #endif /* __UCLIBC_MJN3_ONLY__ */
  2683. #ifdef __STDIO_WIDE
  2684. /* TODO: don't clear state if don't move? */
  2685. stream->ungot_width[0] = 0;
  2686. #endif /* __STDIO_WIDE */
  2687. #ifdef __STDIO_MBSTATE
  2688. /* TODO: don't clear state if don't move? */
  2689. __INIT_MBSTATE(&(stream->state));
  2690. #endif /* __STDIO_MBSTATE */
  2691. __stdio_validate_FILE(stream); /* debugging only */
  2692. retval = 0;
  2693. DONE:
  2694. __STDIO_THREADUNLOCK(stream);
  2695. return retval;
  2696. }
  2697. #ifndef L_fseeko64
  2698. #undef fseeko64
  2699. #undef __off64_t
  2700. #endif
  2701. #endif
  2702. /**********************************************************************/
  2703. #if defined(L_fsetpos) || defined(L_fsetpos64)
  2704. #if defined(L_fsetpos) && defined(L_fsetpos64)
  2705. #error L_fsetpos and L_fsetpos64 are defined simultaneously!
  2706. #endif
  2707. #ifndef L_fsetpos64
  2708. #define fsetpos64 fsetpos
  2709. #define fpos64_t fpos_t
  2710. #define fseeko64 fseek
  2711. #endif
  2712. /* Reentrant -- fgetpos{64}() through fseek{64}(). */
  2713. int fsetpos64(FILE *stream, register const fpos64_t *pos)
  2714. {
  2715. if (!pos) {
  2716. __set_errno(EINVAL);
  2717. return EOF;
  2718. }
  2719. #ifdef __STDIO_WIDE
  2720. {
  2721. int retval;
  2722. __STDIO_THREADLOCK(stream);
  2723. if ((retval = fseeko64(stream, pos->__pos, SEEK_SET)) == 0) {
  2724. __COPY_MBSTATE(&(stream->state), &(pos->__mbstate));
  2725. #ifdef __UCLIBC_MJN3_ONLY__
  2726. #warning CONSIDER: Moving mblen_pending into some mbstate field might be useful. But we would need to modify all the mb<->wc funcs.
  2727. #endif /* __UCLIBC_MJN3_ONLY__ */
  2728. stream->ungot_width[0] = pos->mblen_pending;
  2729. }
  2730. __STDIO_THREADUNLOCK(stream);
  2731. return retval;
  2732. }
  2733. #else /* __STDIO_WIDE */
  2734. return fseeko64(stream, pos->__pos, SEEK_SET);
  2735. #endif /* __STDIO_WIDE */
  2736. }
  2737. #ifndef L_fsetpos64
  2738. #undef fsetpos64
  2739. #undef fpos64_t
  2740. #undef fseeko64
  2741. #endif
  2742. #endif
  2743. /**********************************************************************/
  2744. #ifdef L_ftell
  2745. strong_alias(ftell,ftello);
  2746. #endif
  2747. #if defined(L_ftell) && defined(__STDIO_LARGE_FILES)
  2748. long int ftell(register FILE *stream)
  2749. {
  2750. __offmax_t pos = ftello64(stream);
  2751. return (pos == ((long int) pos)) ? pos : (__set_errno(EOVERFLOW), -1);
  2752. }
  2753. #endif
  2754. #if defined(L_ftello64) || (defined(L_ftell) && !defined(__STDIO_LARGE_FILES))
  2755. #ifndef L_ftello64
  2756. #define ftello64 ftell
  2757. #define __off64_t long int
  2758. #endif
  2759. /* Reentrant -- ftell, ftello, ftello64. */
  2760. __off64_t ftello64(register FILE *stream)
  2761. {
  2762. __offmax_t pos[1];
  2763. __off64_t retval;
  2764. __STDIO_THREADLOCK(stream);
  2765. retval = (((*pos = 0), (_stdio_lseek(stream, pos, SEEK_CUR) < 0))
  2766. || (_stdio_adjpos(stream, pos) < 0)) ? -1 : *pos;
  2767. __STDIO_THREADUNLOCK(stream);
  2768. return retval;
  2769. }
  2770. #ifndef L_ftello64
  2771. #undef ftello64
  2772. #undef __off64_t
  2773. #endif
  2774. #endif
  2775. /**********************************************************************/
  2776. #ifdef L_rewind
  2777. void rewind(register FILE *stream)
  2778. {
  2779. __STDIO_THREADLOCK(stream);
  2780. __CLEARERR(stream); /* Clear errors first and then seek */
  2781. fseek(stream, 0L, SEEK_SET); /* in case there is an error seeking. */
  2782. __STDIO_THREADUNLOCK(stream);
  2783. }
  2784. #endif
  2785. /**********************************************************************/
  2786. #ifdef L_clearerr
  2787. #undef clearerr
  2788. /* Reentrancy handled by UNLOCKED_VOID_RETURN() macro. */
  2789. UNLOCKED_VOID_RETURN(clearerr,(FILE *stream),(stream))
  2790. {
  2791. __CLEARERR(stream);
  2792. }
  2793. #endif
  2794. /**********************************************************************/
  2795. #ifdef L_feof
  2796. #undef feof
  2797. /* Reentrancy handled by UNLOCKED() macro. */
  2798. UNLOCKED(int,feof,(FILE *stream),(stream))
  2799. {
  2800. return __FEOF(stream);
  2801. }
  2802. #endif
  2803. /**********************************************************************/
  2804. #ifdef L_ferror
  2805. #undef ferror
  2806. /* Reentrancy handled by UNLOCKED() macro. */
  2807. UNLOCKED(int,ferror,(FILE *stream),(stream))
  2808. {
  2809. return __FERROR(stream);
  2810. }
  2811. #endif
  2812. /**********************************************************************/
  2813. #ifdef L_perror
  2814. void perror(register const char *s)
  2815. {
  2816. /* If the program is calling perror, it's a safe bet that printf and
  2817. * friends are used as well. It is also possible that the calling
  2818. * program could buffer stderr, or reassign it. */
  2819. register const char *sep;
  2820. sep = ": ";
  2821. if (!(s && *s)) { /* Caller did not supply a prefix message */
  2822. s = (sep += 2); /* or passed an empty string. */
  2823. }
  2824. #if 1
  2825. #ifdef __STDIO_PRINTF_M_SPEC
  2826. fprintf(stderr, "%s%s%m\n", s, sep); /* Use the gnu %m feature. */
  2827. #else
  2828. {
  2829. char buf[64];
  2830. fprintf(stderr, "%s%s%s\n", s, sep,
  2831. _glibc_strerror_r(errno, buf, sizeof(buf)));
  2832. }
  2833. #endif
  2834. #else
  2835. /* Note: Assumes stderr not closed or buffered. */
  2836. {
  2837. char buf[64];
  2838. __STDIO_THREADLOCK(stderr);
  2839. _stdio_fdout(STDERR_FILENO, s, sep,
  2840. _glibc_strerror_r(errno, buf, sizeof(buf)));
  2841. __STDIO_THREADUNLOCK(stderr);
  2842. }
  2843. #endif
  2844. }
  2845. #endif
  2846. /**********************************************************************/
  2847. /* UTILITY funcs */
  2848. /**********************************************************************/
  2849. #ifdef L__stdio_fdout
  2850. /* Not reentrant -- TODO: lock associated stream if a know file descriptor? */
  2851. void _stdio_fdout(int fd, ...)
  2852. {
  2853. va_list arg;
  2854. register const char *p;
  2855. va_start(arg, fd);
  2856. while ((p = va_arg(arg, const char *)) != NULL) {
  2857. write(fd, p, strlen(p));
  2858. }
  2859. va_end(arg);
  2860. }
  2861. #endif
  2862. /**********************************************************************/
  2863. #ifdef L__uintmaxtostr
  2864. /* Avoid using long long / and % operations to cut down dependencies on
  2865. * libgcc.a. Definitely helps on i386 at least. */
  2866. #if (INTMAX_MAX > INT_MAX) && (((INTMAX_MAX/INT_MAX)/2) - 2 <= INT_MAX)
  2867. #define INTERNAL_DIV_MOD
  2868. #endif
  2869. #include <locale.h>
  2870. char *_uintmaxtostr(register char * __restrict bufend, uintmax_t uval,
  2871. int base, __UIM_CASE alphacase)
  2872. {
  2873. int negative;
  2874. unsigned int digit;
  2875. #ifdef INTERNAL_DIV_MOD
  2876. unsigned int H, L, high, low, rh;
  2877. #endif
  2878. #ifndef __LOCALE_C_ONLY
  2879. int grouping, outdigit;
  2880. const char *g; /* This does not need to be initialized. */
  2881. #endif /* __LOCALE_C_ONLY */
  2882. negative = 0;
  2883. if (base < 0) { /* signed value */
  2884. base = -base;
  2885. if (uval > INTMAX_MAX) {
  2886. uval = -uval;
  2887. negative = 1;
  2888. }
  2889. }
  2890. /* this is an internal routine -- we shouldn't need to check this */
  2891. assert(!((base < 2) || (base > 36)));
  2892. #ifndef __LOCALE_C_ONLY
  2893. grouping = -1;
  2894. outdigit = 0x80 & alphacase;
  2895. alphacase ^= outdigit;
  2896. if (alphacase == __UIM_GROUP) {
  2897. assert(base == 10);
  2898. if (*(g = __UCLIBC_CURLOCALE_DATA.grouping)) {
  2899. grouping = *g;
  2900. }
  2901. }
  2902. #endif /* __LOCALE_C_ONLY */
  2903. *bufend = '\0';
  2904. #ifndef INTERNAL_DIV_MOD
  2905. do {
  2906. #ifndef __LOCALE_C_ONLY
  2907. if (!grouping) { /* Finished a group. */
  2908. bufend -= __UCLIBC_CURLOCALE_DATA.thousands_sep_len;
  2909. memcpy(bufend, __UCLIBC_CURLOCALE_DATA.thousands_sep,
  2910. __UCLIBC_CURLOCALE_DATA.thousands_sep_len);
  2911. if (g[1] != 0) { /* g[1] == 0 means repeat last grouping. */
  2912. /* Note: g[1] == -1 means no further grouping. But since
  2913. * we'll never wrap around, we can set grouping to -1 without
  2914. * fear of */
  2915. ++g;
  2916. }
  2917. grouping = *g;
  2918. }
  2919. --grouping;
  2920. #endif /* __LOCALE_C_ONLY */
  2921. digit = uval % base;
  2922. uval /= base;
  2923. #ifndef __LOCALE_C_ONLY
  2924. if (unlikely(outdigit)) {
  2925. bufend -= __UCLIBC_CURLOCALE_DATA.outdigit_length[digit];
  2926. memcpy(bufend,
  2927. (&__UCLIBC_CURLOCALE_DATA.outdigit0_mb)[digit],
  2928. __UCLIBC_CURLOCALE_DATA.outdigit_length[digit]);
  2929. } else
  2930. #endif
  2931. {
  2932. *--bufend = ( (digit < 10) ? digit + '0' : digit + alphacase );
  2933. }
  2934. } while (uval);
  2935. #else /* ************************************************** */
  2936. H = (UINT_MAX / base);
  2937. L = UINT_MAX % base + 1;
  2938. if (L == base) {
  2939. ++H;
  2940. L = 0;
  2941. }
  2942. low = (unsigned int) uval;
  2943. high = (unsigned int) (uval >> (sizeof(unsigned int) * CHAR_BIT));
  2944. do {
  2945. #ifndef __LOCALE_C_ONLY
  2946. if (!grouping) { /* Finished a group. */
  2947. bufend -= __UCLIBC_CURLOCALE_DATA.thousands_sep_len;
  2948. memcpy(bufend, __UCLIBC_CURLOCALE_DATA.thousands_sep,
  2949. __UCLIBC_CURLOCALE_DATA.thousands_sep_len);
  2950. if (g[1] != 0) { /* g[1] == 0 means repeat last grouping. */
  2951. /* Note: g[1] == -1 means no further grouping. But since
  2952. * we'll never wrap around, we can set grouping to -1 without
  2953. * fear of */
  2954. ++g;
  2955. }
  2956. grouping = *g;
  2957. }
  2958. --grouping;
  2959. #endif /* __LOCALE_C_ONLY */
  2960. if (unlikely(high)) {
  2961. rh = high % base;
  2962. high /= base;
  2963. digit = (low % base) + (L * rh);
  2964. low = (low / base) + (H * rh) + (digit / base);
  2965. digit %= base;
  2966. } else {
  2967. digit = low % base;
  2968. low /= base;
  2969. }
  2970. #ifndef __LOCALE_C_ONLY
  2971. if (unlikely(outdigit)) {
  2972. bufend -= __UCLIBC_CURLOCALE_DATA.outdigit_length[digit];
  2973. memcpy(bufend,
  2974. (&__UCLIBC_CURLOCALE_DATA.outdigit0_mb)[digit],
  2975. __UCLIBC_CURLOCALE_DATA.outdigit_length[digit]);
  2976. } else
  2977. #endif
  2978. {
  2979. *--bufend = ( (digit < 10) ? digit + '0' : digit + alphacase );
  2980. }
  2981. } while (low | high);
  2982. #endif /******************************************************/
  2983. if (negative) {
  2984. *--bufend = '-';
  2985. }
  2986. return bufend;
  2987. }
  2988. #undef INTERNAL_DIV_MOD
  2989. #endif
  2990. /**********************************************************************/
  2991. #ifdef L__wstdio_fwrite
  2992. #include <wchar.h>
  2993. size_t _wstdio_fwrite(const wchar_t *__restrict ws, size_t n,
  2994. register FILE *__restrict stream)
  2995. {
  2996. size_t r, count;
  2997. char buf[64];
  2998. const wchar_t *pw;
  2999. #if defined(__STDIO_WIDE) && defined(__STDIO_BUFFERS)
  3000. if (stream->filedes == -3) { /* Special case to support {v}swprintf. */
  3001. count = ((wchar_t *)(stream->bufend)) - ((wchar_t *)(stream->bufpos));
  3002. if (count > n) {
  3003. count = n;
  3004. }
  3005. if (count) {
  3006. wmemcpy((wchar_t *)(stream->bufpos), ws, count);
  3007. stream->bufpos = (char *)(((wchar_t *)(stream->bufpos)) + count);
  3008. }
  3009. return n;
  3010. }
  3011. #endif /* defined(__STDIO_WIDE) && defined(__STDIO_BUFFERS) */
  3012. if (stream->modeflags & __FLAG_NARROW) {
  3013. stream->modeflags |= __FLAG_ERROR;
  3014. __set_errno(EBADF);
  3015. return 0;
  3016. }
  3017. stream->modeflags |= __FLAG_WIDE;
  3018. pw = ws;
  3019. count = 0;
  3020. while (n > count) {
  3021. r = wcsnrtombs(buf, &pw, n-count, sizeof(buf), &stream->state);
  3022. if (r != ((size_t) -1)) { /* No encoding errors */
  3023. if (!r) {
  3024. ++r; /* 0 is returned when nul is reached. */
  3025. pw = ws + count + r; /* pw was set to NULL, so correct. */
  3026. }
  3027. if (_stdio_fwrite(buf, r, stream) == r) {
  3028. count = pw - ws;
  3029. continue;
  3030. }
  3031. }
  3032. break;
  3033. }
  3034. /* Note: The count is incorrect if 0 < _stdio_fwrite return < r!!! */
  3035. return count;
  3036. }
  3037. #endif
  3038. /**********************************************************************/