From owner-freebsd-hackers@FreeBSD.ORG Sun Sep 18 09:14:43 2011 Return-Path: Delivered-To: hackers@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id B005E106564A for ; Sun, 18 Sep 2011 09:14:43 +0000 (UTC) (envelope-from avg@FreeBSD.org) Received: from citadel.icyb.net.ua (citadel.icyb.net.ua [212.40.38.140]) by mx1.freebsd.org (Postfix) with ESMTP id EBD858FC12 for ; Sun, 18 Sep 2011 09:14:41 +0000 (UTC) Received: from porto.starpoint.kiev.ua (porto-e.starpoint.kiev.ua [212.40.38.100]) by citadel.icyb.net.ua (8.8.8p3/ICyb-2.3exp) with ESMTP id MAA20302 for ; Sun, 18 Sep 2011 12:14:40 +0300 (EEST) (envelope-from avg@FreeBSD.org) Received: from localhost ([127.0.0.1]) by porto.starpoint.kiev.ua with esmtp (Exim 4.34 (FreeBSD)) id 1R5DSS-000ESE-Ba for hackers@freebsd.org; Sun, 18 Sep 2011 12:14:40 +0300 Message-ID: <4E75B67E.1000802@FreeBSD.org> Date: Sun, 18 Sep 2011 12:14:38 +0300 From: Andriy Gapon User-Agent: Mozilla/5.0 (X11; FreeBSD amd64; rv:6.0.2) Gecko/20110907 Thunderbird/6.0.2 MIME-Version: 1.0 To: hackers@FreeBSD.org References: <4E712D11.7040202@FreeBSD.org> In-Reply-To: <4E712D11.7040202@FreeBSD.org> X-Enigmail-Version: undefined X-Forwarded-Message-Id: <4E712D11.7040202@FreeBSD.org> Content-Type: text/plain; charset=x-viet-vps Content-Transfer-Encoding: 7bit Cc: Subject: Fwd: my git development snapshot(s) X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 18 Sep 2011 09:14:43 -0000 Just decided to follow the global trends and trying to throw all of my local/private changes at you in hope that the "crowd-sourcing magic" might somehow happen :-) This seems definitely easier than carefully producing the patch files and keeping them up-to-date. So, my newly cloned gitorious repository: https://gitorious.org/~avg/freebsd/avgbsd And the first branch of interest: https://gitorious.org/~avg/freebsd/avgbsd/commits/devel-20110915 This is a snapshot of almost all of my local changes to the FreeBSD src tree. Please note that the branch is not intended to be public in the git sense. That is, there will be no linear history - I periodically rebase my changes on top of the svn head and also frequently reshuffle/merge/split commits. The snapshot is not tidied up, there are quite a few commits that should be merged into other commits, some commit messages are not accurate/pretty, etc. The older the commits, the more mature they are supposed to be. Based on the above, no new commits are expected to this snapshot branch. I will produce new snapshot branches from time to time. I am posting this information to this list initially, later I plan to share the code with the wider audience e.g. via hackers@. P.S. This code sharing is made easier for me by git, Gitorious and "git rebase --onto" in particular. Thanks to Fabien Thomas for the initial FreeBSD clone repository at Gitorious! -- Andriy Gapon From owner-freebsd-hackers@FreeBSD.ORG Sun Sep 18 16:03:45 2011 Return-Path: Delivered-To: hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 086CF106566B for ; Sun, 18 Sep 2011 16:03:45 +0000 (UTC) (envelope-from shiningarcanine@gmail.com) Received: from mail-ww0-f50.google.com (mail-ww0-f50.google.com [74.125.82.50]) by mx1.freebsd.org (Postfix) with ESMTP id 927A18FC0A for ; Sun, 18 Sep 2011 16:03:44 +0000 (UTC) Received: by wwe3 with SMTP id 3so6510264wwe.31 for ; Sun, 18 Sep 2011 09:03:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=mime-version:sender:date:x-google-sender-auth:message-id:subject :from:to:content-type; bh=1m8WHggyLiDo//jkQ5MWUgt/uwzaeQO8iwGUFoZaVSo=; b=KBkqv0kdRphLF1ctH8QuG5+n6DWj4/6DxMXaUm+R7vw87cMbfJGe13YwQgCcXiE+RH kvCGBf7f+4gpJXe7JH6cico5rJFBst0gvo5v9/ue9r3wU7psbJbWW3MAPE7ch4cgEt94 LX+AKdcx1ersVTVvTbaknJpDXjHxqlNPFSs6Q= MIME-Version: 1.0 Received: by 10.216.182.197 with SMTP id o47mr1519313wem.78.1316359928355; Sun, 18 Sep 2011 08:32:08 -0700 (PDT) Sender: shiningarcanine@gmail.com Received: by 10.216.171.80 with HTTP; Sun, 18 Sep 2011 08:32:08 -0700 (PDT) Date: Sun, 18 Sep 2011 11:32:08 -0400 X-Google-Sender-Auth: KYqL6yYg67ZeEi9SWrKNE9ADF7w Message-ID: From: Richard Yao To: hackers@freebsd.org Content-Type: text/plain; charset=ISO-8859-1 X-Mailman-Approved-At: Sun, 18 Sep 2011 16:17:36 +0000 Cc: Subject: Mixing Asynchronous Network I/O and POSIX Threads X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 18 Sep 2011 16:03:45 -0000 Dear FreeBSD Community: I wrote a program for Linux that uses Asynchronous Network I/O and POSIX Threads. It uses a mix of gettid(), fcntl() and F_SETOWN to specify which thread handles each connection's SIGIO interrupts. gettid() is Linux-specific and I would prefer to do this in a way that also works with FreeBSD. Is that possible? I am not on the mailing list. Please CC me any responses. Yours truly, Richard Yao From owner-freebsd-hackers@FreeBSD.ORG Sun Sep 18 17:21:15 2011 Return-Path: Delivered-To: hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id E97C7106566C for ; Sun, 18 Sep 2011 17:21:15 +0000 (UTC) (envelope-from uffe@uffe.org) Received: from mail.starion.dk (mx0.starion.dk [93.162.70.34]) by mx1.freebsd.org (Postfix) with SMTP id 30F6A8FC1C for ; Sun, 18 Sep 2011 17:21:14 +0000 (UTC) Received: (qmail 1587 invoked by uid 1004); 18 Sep 2011 16:54:41 -0000 Message-ID: <4E76221D.50605@uffe.org> Date: Sun, 18 Sep 2011 18:53:49 +0200 From: Uffe Jakobsen X-Mozilla-Draft-Info: internal/draft; vcard=0; receipt=0; DSN=0; uuencode=0 User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.21) Gecko/20110831 Lightning/1.0b2 Mnenhy/0.8.3 Thunderbird/3.1.13 MIME-Version: 1.0 To: hackers@freebsd.org References: In-Reply-To: Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Cc: Richard Yao Subject: Re: Mixing Asynchronous Network I/O and POSIX Threads X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 18 Sep 2011 17:21:16 -0000 On 2011-09-18 17:32, Richard Yao wrote: > Dear FreeBSD Community: > > I wrote a program for Linux that uses Asynchronous Network I/O and > POSIX Threads. It uses a mix of gettid(), fcntl() and F_SETOWN to > specify which thread handles each connection's SIGIO interrupts. > gettid() is Linux-specific and I would prefer to do this in a way that > also works with FreeBSD. Is that possible? > How about pthread_self() ? /Uffe From owner-freebsd-hackers@FreeBSD.ORG Sun Sep 18 19:14:32 2011 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 35A65106564A; Sun, 18 Sep 2011 19:14:32 +0000 (UTC) (envelope-from rysto32@gmail.com) Received: from mail-ww0-f50.google.com (mail-ww0-f50.google.com [74.125.82.50]) by mx1.freebsd.org (Postfix) with ESMTP id 9916B8FC17; Sun, 18 Sep 2011 19:14:31 +0000 (UTC) Received: by wwe3 with SMTP id 3so6618522wwe.31 for ; Sun, 18 Sep 2011 12:14:30 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=mime-version:in-reply-to:references:date:message-id:subject:from:to :cc:content-type; bh=cXBxjHIuqsYK8S0cA8Jj2Vo8bfJP0jvDDuGf97sJknU=; b=goAjdZOyjLPhHPQ3yllmjYbjGnpxaf27tw9zO3I/7kttF+9VkBE3uy6LbEUnEAP37v Y9tnajryvmecJnDBueuOGqSlPB/O32cxCHCMAfTu1ZfkHLxodjfH9l5FnhCTGuqka72z GnGTEbNIPLNKAlW8kv3oCn0oscvnKK3iH0GKU= MIME-Version: 1.0 Received: by 10.227.72.138 with SMTP id m10mr1769362wbj.90.1316371404082; Sun, 18 Sep 2011 11:43:24 -0700 (PDT) Received: by 10.180.96.104 with HTTP; Sun, 18 Sep 2011 11:43:24 -0700 (PDT) In-Reply-To: <4E742CC8.1070900@freebsd.org> References: <4E73B1E1.6020306@sgi.com> <4E742CC8.1070900@freebsd.org> Date: Sun, 18 Sep 2011 14:43:24 -0400 Message-ID: From: Ryan Stone To: Julian Elischer Content-Type: text/plain; charset=ISO-8859-1 Cc: freebsd-hackers@freebsd.org, Charlie Martin Subject: Re: dtrace in FreeBSD 7.2 X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 18 Sep 2011 19:14:32 -0000 On Sat, Sep 17, 2011 at 1:14 AM, Julian Elischer wrote: > > I' am not sure that user space dtrace suport was available in 7.2.. My > memory is that it came in 8.x but I'm not certain. Userland dtrace was merged to stable/8 shortly after 8.2 was released. From owner-freebsd-hackers@FreeBSD.ORG Sun Sep 18 19:19:48 2011 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 81CC81065675 for ; Sun, 18 Sep 2011 19:19:48 +0000 (UTC) (envelope-from lacombar@gmail.com) Received: from mail-ww0-f50.google.com (mail-ww0-f50.google.com [74.125.82.50]) by mx1.freebsd.org (Postfix) with ESMTP id E36178FC16 for ; Sun, 18 Sep 2011 19:19:47 +0000 (UTC) Received: by wwe3 with SMTP id 3so6621440wwe.31 for ; Sun, 18 Sep 2011 12:19:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=mime-version:in-reply-to:references:date:message-id:subject:from:to :cc:content-type; bh=R7ebOu4yv+tlzxqTnvGuLdaRJwAQrAlYwKudFQSThTA=; b=Ej/wgdOET1FKJx1cVtd/JWf0tSi8GXfU856A7XGJCsfCgItAZvnczbUrLkM6Wd9ojI Trz063893W/gvIMGJGXQnntdL1RZN5GU4gfcOa6RbFk58Aq6bpr/5oBUZr+PHNmXDgng htlUX6XobCHcqeM+gYckKifiopiVS7QaA+mds= MIME-Version: 1.0 Received: by 10.227.175.77 with SMTP id w13mr1787920wbz.53.1316373586716; Sun, 18 Sep 2011 12:19:46 -0700 (PDT) Received: by 10.180.95.169 with HTTP; Sun, 18 Sep 2011 12:19:46 -0700 (PDT) In-Reply-To: <20110917203218.GC13993@michelle.cdnetworks.com> References: <4E744BCE.7060302@sepehrs.com> <20110917203218.GC13993@michelle.cdnetworks.com> Date: Sun, 18 Sep 2011 15:19:46 -0400 Message-ID: From: Arnaud Lacombe To: jfv@freebsd.org Content-Type: text/plain; charset=ISO-8859-1 Cc: pyunyh@gmail.com, freebsd-hackers@freebsd.org, Hooman Fazaeli Subject: Re: intel checksum offload X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 18 Sep 2011 19:19:48 -0000 Hi, On Sat, Sep 17, 2011 at 4:32 PM, YongHyeon PYUN wrote: > On Sat, Sep 17, 2011 at 11:57:10AM +0430, Hooman Fazaeli wrote: >> Hi list, >> >> The data sheet for intel 82576 advertises IP TX/RX checksum offload >> but the driver does not set CSUM_IP in ifp->if_hwassist. Does this mean that >> driver (and chip) do not support IP TX checksum offload or the support for >> TX is not yet included in the driver? > > After reading this mail, I checked em(4)/lem(4) code and noticed > these drivers removed CSUM_IP capability as well. igb(4) didn't > support CSUM_IP from day 1 but em(4)/lem(4) used to take advantage > of IP checksum offloading capability. > Given that these drivers share many code with Linux, Jack may know > the details and why IP checksum offloading code was removed. Note, > Linux does not use IP checksum offloading so I guess this could be > oversight in shared code. > > BTW, hackers may not be right ML to post this kind of post. > CCed to jfv@, the driver maintainer. > This is slightly off-topic, but still.. FWIW, I'm not really impressed by what chips claim to support vs. what has been implemented in the driver. As per the product brief, the 82574 supports multiqueue (at least should support up to 5 MSI-X vectors, 2 RX and 2 TX), but this support was removed from em(4) in mid-2010[0]. Also, the 82571 and the 82574 should also support header split, but this is currently only implemented in igb(4), not em(4). - Arnaud [0]: the commit message say "performance was not good", but it is not the driver's developer to decide whether or not a feature is good or not. The developer's job is to implement the chip capabilities, and let it to the user to enable or disable the capabilities. At best, the developer can decide whether or not to enable the feature by default. From owner-freebsd-hackers@FreeBSD.ORG Sun Sep 18 19:44:10 2011 Return-Path: Delivered-To: hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id D01B2106566C for ; Sun, 18 Sep 2011 19:44:10 +0000 (UTC) (envelope-from jilles@stack.nl) Received: from mx1.stack.nl (relay04.stack.nl [IPv6:2001:610:1108:5010::107]) by mx1.freebsd.org (Postfix) with ESMTP id 6599F8FC08 for ; Sun, 18 Sep 2011 19:44:10 +0000 (UTC) Received: from turtle.stack.nl (turtle.stack.nl [IPv6:2001:610:1108:5010::132]) by mx1.stack.nl (Postfix) with ESMTP id B10121DD753; Sun, 18 Sep 2011 21:44:09 +0200 (CEST) Received: by turtle.stack.nl (Postfix, from userid 1677) id A823D17515; Sun, 18 Sep 2011 21:44:09 +0200 (CEST) Date: Sun, 18 Sep 2011 21:44:09 +0200 From: Jilles Tjoelker To: Richard Yao Message-ID: <20110918194409.GB36162@stack.nl> References: MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.5.21 (2010-09-15) Cc: hackers@freebsd.org Subject: Re: Mixing Asynchronous Network I/O and POSIX Threads X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 18 Sep 2011 19:44:10 -0000 On Sun, Sep 18, 2011 at 11:32:08AM -0400, Richard Yao wrote: > I wrote a program for Linux that uses Asynchronous Network I/O and > POSIX Threads. It uses a mix of gettid(), fcntl() and F_SETOWN to > specify which thread handles each connection's SIGIO interrupts. > gettid() is Linux-specific and I would prefer to do this in a way that > also works with FreeBSD. Is that possible? In FreeBSD, you can only F_SETOWN processes or process groups, not threads, so a direct port is probably not possible. Another Linux feature not in FreeBSD is F_SETSIG (to send a realtime signal instead of SIGIO and provide siginfo_t information). My recommendation is not to use SIGIO and SIGURG at all. If you use signal handlers, your program is very likely to suffer from race condition problems unless you unmask the signal only at well-defined safe points. If you use sigtimedwait() or similar, select()/poll() can provide similar functionality. Alternatively, if you have many descriptors to watch, use non-portable facilities like BSD kqueue, Linux epoll, Solaris ports or portable wrappers around them. Realtime signals are nasty for this -- the signal queue has a finite size and when it overflows you need a "resync" step that is expensive both in CPU and programmer time. -- Jilles Tjoelker From owner-freebsd-hackers@FreeBSD.ORG Sun Sep 18 21:06:44 2011 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id C1C49106566B; Sun, 18 Sep 2011 21:06:44 +0000 (UTC) (envelope-from luigi@onelab2.iet.unipi.it) Received: from onelab2.iet.unipi.it (onelab2.iet.unipi.it [131.114.59.238]) by mx1.freebsd.org (Postfix) with ESMTP id 86FD58FC15; Sun, 18 Sep 2011 21:06:44 +0000 (UTC) Received: by onelab2.iet.unipi.it (Postfix, from userid 275) id 9E4C07300A; Sun, 18 Sep 2011 23:06:47 +0200 (CEST) Date: Sun, 18 Sep 2011 23:06:47 +0200 From: Luigi Rizzo To: Arnaud Lacombe Message-ID: <20110918210647.GA8930@onelab2.iet.unipi.it> References: <4E744BCE.7060302@sepehrs.com> <20110917203218.GC13993@michelle.cdnetworks.com> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.4.2.3i Cc: jfv@freebsd.org, pyunyh@gmail.com, Hooman Fazaeli , freebsd-hackers@freebsd.org Subject: Re: intel checksum offload X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 18 Sep 2011 21:06:44 -0000 On Sun, Sep 18, 2011 at 03:19:46PM -0400, Arnaud Lacombe wrote: > Hi, > > On Sat, Sep 17, 2011 at 4:32 PM, YongHyeon PYUN wrote: > > On Sat, Sep 17, 2011 at 11:57:10AM +0430, Hooman Fazaeli wrote: > >> Hi list, > >> > >> The data sheet for intel 82576 advertises IP TX/RX checksum offload > >> but the driver does not set CSUM_IP in ifp->if_hwassist. Does this mean that > >> driver (and chip) do not support IP TX checksum offload or the support for > >> TX is not yet included in the driver? ... > This is slightly off-topic, but still.. > > FWIW, I'm not really impressed by what chips claim to support vs. what > has been implemented in the driver. As per the product brief, the ... > [0]: the commit message say "performance was not good", but it is not > the driver's developer to decide whether or not a feature is good or > not. The developer's job is to implement the chip capabilities, and > let it to the user to enable or disable the capabilities. At best, the > developer can decide whether or not to enable the feature by default. actually, this is a perfect example where the developer has done the right thing: implemented the feature, verified that performance is bad, hence presumably removed support for the feature from the code (which also means that the normal code path will run faster because there are no run-time decisions to be made). "optional" features are often costly even when disabled. cheers luigi From owner-freebsd-hackers@FreeBSD.ORG Sun Sep 18 22:05:35 2011 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 812931065670; Sun, 18 Sep 2011 22:05:35 +0000 (UTC) (envelope-from lacombar@gmail.com) Received: from mail-ww0-f50.google.com (mail-ww0-f50.google.com [74.125.82.50]) by mx1.freebsd.org (Postfix) with ESMTP id DE3578FC0A; Sun, 18 Sep 2011 22:05:34 +0000 (UTC) Received: by wwe3 with SMTP id 3so6703720wwe.31 for ; Sun, 18 Sep 2011 15:05:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=mime-version:in-reply-to:references:date:message-id:subject:from:to :cc:content-type; bh=pyOc+Jyi7JcAPPA62paWObIsxvEgxFb7jH6GwVeewZs=; b=rQxRfXgRJAfv2QZyo1akY+qIViXm/cQR5uxTgrgnAYXjabb8dtesggdq1/7CsH6Ub8 l8OvnIgpCB05Q6Lqu7TEJTA8cy+Q+kfiCR3KoVb17ozbeJr9tkdfOOvBMQGU44saMh1k SHh7aA/c+ZbZ7FlucmS82eEnAMONohJI9tciU= MIME-Version: 1.0 Received: by 10.227.175.77 with SMTP id w13mr1893559wbz.53.1316383533650; Sun, 18 Sep 2011 15:05:33 -0700 (PDT) Received: by 10.180.95.169 with HTTP; Sun, 18 Sep 2011 15:05:33 -0700 (PDT) In-Reply-To: <20110918210647.GA8930@onelab2.iet.unipi.it> References: <4E744BCE.7060302@sepehrs.com> <20110917203218.GC13993@michelle.cdnetworks.com> <20110918210647.GA8930@onelab2.iet.unipi.it> Date: Sun, 18 Sep 2011 18:05:33 -0400 Message-ID: From: Arnaud Lacombe To: Luigi Rizzo Content-Type: text/plain; charset=ISO-8859-1 Cc: jfv@freebsd.org, pyunyh@gmail.com, Hooman Fazaeli , freebsd-hackers@freebsd.org Subject: Re: intel checksum offload X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 18 Sep 2011 22:05:35 -0000 Hi, On Sun, Sep 18, 2011 at 5:06 PM, Luigi Rizzo wrote: > On Sun, Sep 18, 2011 at 03:19:46PM -0400, Arnaud Lacombe wrote: >> Hi, >> >> On Sat, Sep 17, 2011 at 4:32 PM, YongHyeon PYUN wrote: >> > On Sat, Sep 17, 2011 at 11:57:10AM +0430, Hooman Fazaeli wrote: >> >> Hi list, >> >> >> >> The data sheet for intel 82576 advertises IP TX/RX checksum offload >> >> but the driver does not set CSUM_IP in ifp->if_hwassist. Does this mean that >> >> driver (and chip) do not support IP TX checksum offload or the support for >> >> TX is not yet included in the driver? > ... >> This is slightly off-topic, but still.. >> >> FWIW, I'm not really impressed by what chips claim to support vs. what >> has been implemented in the driver. As per the product brief, the > ... >> [0]: the commit message say "performance was not good", but it is not >> the driver's developer to decide whether or not a feature is good or >> not. The developer's job is to implement the chip capabilities, and >> let it to the user to enable or disable the capabilities. At best, the >> developer can decide whether or not to enable the feature by default. > > actually, this is a perfect example where the developer has done the > right thing: implemented the feature, verified that performance is bad, > hence presumably removed support for the feature from the code (which also > means that the normal code path will run faster because there are no > run-time decisions to be made). > > "optional" features are often costly even when disabled. > I forgot to mention that in this case, the code full of EM_MULTIQUEUE's #ifdef and shared code is still fully compatible with the multiqueue's architecture. The only thing removed is a conditional and an assignation in the driver's attachment which was enabling the feature, ie. the cost you point out is still paid today, without any benefit. Now I might also openly question the test method used by the folks at Intel, just seeing how much issue I've had with the driver (I still have for some, even if not driver related), which have not been reproduced there. Finally, when someone say "performance are better that way", the first thing I'd be tempted to ask is: "What is your test ? How did you collects the numbers ? How did you reach the conclusion ?". None of this stuff is public. regards, - Arnaud From owner-freebsd-hackers@FreeBSD.ORG Sun Sep 18 22:51:23 2011 Return-Path: Delivered-To: hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 2C823106566B; Sun, 18 Sep 2011 22:51:23 +0000 (UTC) (envelope-from gleb.kurtsou@gmail.com) Received: from mail-fx0-f54.google.com (mail-fx0-f54.google.com [209.85.161.54]) by mx1.freebsd.org (Postfix) with ESMTP id 8613A8FC08; Sun, 18 Sep 2011 22:51:22 +0000 (UTC) Received: by fxg9 with SMTP id 9so4561060fxg.13 for ; Sun, 18 Sep 2011 15:51:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=date:from:to:cc:subject:message-id:references:mime-version :content-type:content-disposition:in-reply-to:user-agent; bh=9PIc4on4son74HIwbe+9jQrxqMxAd5bn1Q/GGxihNCg=; b=leAK2sQ7GnLRAHP59cIKP5HQNvxWI9DiR4iGCvsrcJQqF8ilCat8pvSDaGuJYHzjuJ ZciuNj4DypO24fj/8vAYh+N6LpdT1/pB1WfemIZOb/HNghj96alz0wpVIuLig7wducgK aJrSIhCNz36s2eo8fiA+Pluz/NLXl01DvCtro= Received: by 10.223.89.65 with SMTP id d1mr3961785fam.6.1316384813412; Sun, 18 Sep 2011 15:26:53 -0700 (PDT) Received: from localhost ([78.157.92.5]) by mx.google.com with ESMTPS id b10sm19736977fam.1.2011.09.18.15.26.51 (version=SSLv3 cipher=OTHER); Sun, 18 Sep 2011 15:26:52 -0700 (PDT) Date: Mon, 19 Sep 2011 01:25:41 +0300 From: Gleb Kurtsou To: Andriy Gapon Message-ID: <20110918222541.GA86842@tops> References: <4E712D11.7040202@FreeBSD.org> <4E75B67E.1000802@FreeBSD.org> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline In-Reply-To: <4E75B67E.1000802@FreeBSD.org> User-Agent: Mutt/1.5.21 (2010-09-15) Cc: hackers@FreeBSD.org Subject: Re: Fwd: my git development snapshot(s) X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 18 Sep 2011 22:51:23 -0000 On (18/09/2011 12:14), Andriy Gapon wrote: > > Just decided to follow the global trends and trying to throw all of my > local/private changes at you in hope that the "crowd-sourcing magic" might > somehow happen :-) This seems definitely easier than carefully producing the > patch files and keeping them up-to-date. > > So, my newly cloned gitorious repository: > https://gitorious.org/~avg/freebsd/avgbsd > > And the first branch of interest: > https://gitorious.org/~avg/freebsd/avgbsd/commits/devel-20110915 > > This is a snapshot of almost all of my local changes to the FreeBSD src tree. > Please note that the branch is not intended to be public in the git sense. That > is, there will be no linear history - I periodically rebase my changes on top of > the svn head and also frequently reshuffle/merge/split commits. > The snapshot is not tidied up, there are quite a few commits that should be > merged into other commits, some commit messages are not accurate/pretty, etc. > The older the commits, the more mature they are supposed to be. > > Based on the above, no new commits are expected to this snapshot branch. > I will produce new snapshot branches from time to time. > > I am posting this information to this list initially, later I plan to share the > code with the wider audience e.g. via hackers@. > > P.S. This code sharing is made easier for me by git, Gitorious and "git rebase > --onto" in particular. Thanks to Fabien Thomas for the initial FreeBSD clone > repository at Gitorious! Let me share my experience as well. My repo: https://github.com/glk/freebsd-head/ I used rebase to keep local branches as well, but no longer do so. Such setup worked for me at least for two years, I had local changes and worked on a larger patchset for 7,8-STABLE and CURRENT branches simultaneously (no longer do it either). But (imho) this approach his serious drawbacks. The biggest one is that it's hard to check if regression comes from your code or recently merged upstream code. The second one: once you screw rebase (merge) you are in big trouble. Both issues can be worked around by keeping previous master branches, but it hardly helps: once there are conflicts with upstream or your local changes get commited upstream it becomes only harder and harder. (I used to have master-prev-DATE similar to devel-DATE Andriy uses.) I like and use rebase a lot while working on the code: reorganize commits, small fixups, etc. But try not to touch code that is more than several days old unless really necessary. The reason is to maintain code base in well tested state: imagine you've changed or small bit in HEAD~20, a week later you find a bug, bisect to find that it showed up in orig-HEAD~10 because of your small fix in orig-HEAD~20. Fixing it would have taken less time without that rebase, or bug wouldn't appear in the first place. Once history stabilizes (i.e. remains untouched for 3-4 days) I push it public or backup (for local projects) repository. There is no history rewriting after this point. Use separate branches for independent patchsets. E.g. tmpfs branch - for tmpfs changes, misc - for smaller changes, etc. It lets me bisect and test code easier. For example if I get strange panic I could create temporal branch with all patchsets except pefs branch. Test it, find faulty branch, bisect individual changes. Besides it's also possible to bisect master branch, merge appropriate patchset revisions while bisecting upstream, etc. Upgrade procedure. Patchset branches are independently merged with upstream (vendor/master in my case). And all patchset branches are merged into master branch. In other words resolve conflicts in patchset branches, merge everything back to master. I usually merge individual branches only if there are conflicts or after important milestone. Octopus merge in git may not be as good as you I'd like it to if there are conflicts in several branches, but it's manageable. I also find identifying my changes vs upstream easier than in rebase scenario: - Use 'git log --first-parent'. Limiting number of commits to show in gitk is also good option for large repositories. - Use 'git merge --no-log --no-ff' to merge with upstream, it strips excessive logs from commit message, --no-ff is necessary only for the first time because fast-forward merges won't be possible. To keep history extremely clean: create empty git repo, make non-empty commit and merge with upstream. And there is hope that keeping independent branches would make "crowd-sourcing magic" more feasible :) I'd prefer to be able to merge code I'm interested in without touching unrelated bits. Thanks, Gleb. From owner-freebsd-hackers@FreeBSD.ORG Sun Sep 18 21:45:27 2011 Return-Path: Delivered-To: hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 6FAE5106566B for ; Sun, 18 Sep 2011 21:45:27 +0000 (UTC) (envelope-from shiningarcanine@gmail.com) Received: from mail-iy0-f182.google.com (mail-iy0-f182.google.com [209.85.210.182]) by mx1.freebsd.org (Postfix) with ESMTP id 3B0D68FC0A for ; Sun, 18 Sep 2011 21:45:27 +0000 (UTC) Received: by iadk27 with SMTP id k27so7273650iad.13 for ; Sun, 18 Sep 2011 14:45:26 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=mime-version:sender:in-reply-to:references:date :x-google-sender-auth:message-id:subject:from:to:cc:content-type; bh=vK+H5Q/9QczvtF7LJqKrx5m7sI5n0Tx4wB9VTI67HPw=; b=gs17ftwWQMTyBRjwS/wNFH6tQE819/bw4JMQTr5zzShx++2/ghNK2DKaMQaD4yNjVJ Kt3q6nSWH/qnH/dgquriTdKrjEn6R173kzSbPRXzm0OdrAOqZRzprLLJQHxHlzxIqgAQ taIYCYN3EbxP2M58ksJM2+qnaYppzAMXgKU7w= MIME-Version: 1.0 Received: by 10.42.159.201 with SMTP id m9mr3357908icx.10.1316382326752; Sun, 18 Sep 2011 14:45:26 -0700 (PDT) Sender: shiningarcanine@gmail.com Received: by 10.42.219.201 with HTTP; Sun, 18 Sep 2011 14:45:26 -0700 (PDT) In-Reply-To: References: Date: Sun, 18 Sep 2011 17:45:26 -0400 X-Google-Sender-Auth: y3fT0oPxOSlkIKi69FiF88L9ywE Message-ID: From: Richard Yao To: Jilles Tjoelker Content-Type: text/plain; charset=ISO-8859-1 X-Mailman-Approved-At: Sun, 18 Sep 2011 23:57:43 +0000 Cc: "hackers@freebsd.org" Subject: Re: Mixing Asynchronous Network I/O and POSIX Threads X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 18 Sep 2011 21:45:27 -0000 Dear Jilles, I am using sigwaitinfo() with all interrupts masked to avoid the possibility of race conditions in signal handlers, but I have not used any realtime signals. Linux 2.6.35 found a way to invoke the SIGIO handler despite it being masked, but that issue would not occur under production conditions and that is a bug for a different mailing list. Being unable to F_SETOWN individual threads would cause problems because it causes network traffic to become serialized. My code must run on Linux, but if I were to write FreeBSD-specific code so it would also work on FreeBSD, would using kqueue enable me to specify which threads handle events on specific file descriptors? Yours truly, Richard Yao On Sun, Sep 18, 2011 at 3:44 PM, Jilles Tjoelker wrote: > On Sun, Sep 18, 2011 at 11:32:08AM -0400, Richard Yao wrote: >> I wrote a program for Linux that uses Asynchronous Network I/O and >> POSIX Threads. It uses a mix of gettid(), fcntl() and F_SETOWN to >> specify which thread handles each connection's SIGIO interrupts. >> gettid() is Linux-specific and I would prefer to do this in a way that >> also works with FreeBSD. Is that possible? > > In FreeBSD, you can only F_SETOWN processes or process groups, not > threads, so a direct port is probably not possible. Another Linux > feature not in FreeBSD is F_SETSIG (to send a realtime signal instead of > SIGIO and provide siginfo_t information). > > My recommendation is not to use SIGIO and SIGURG at all. If you use > signal handlers, your program is very likely to suffer from race > condition problems unless you unmask the signal only at well-defined > safe points. If you use sigtimedwait() or similar, select()/poll() can > provide similar functionality. Alternatively, if you have many > descriptors to watch, use non-portable facilities like BSD kqueue, Linux > epoll, Solaris ports or portable wrappers around them. Realtime signals > are nasty for this -- the signal queue has a finite size and when it > overflows you need a "resync" step that is expensive both in CPU and > programmer time. > > -- > Jilles Tjoelker > From owner-freebsd-hackers@FreeBSD.ORG Mon Sep 19 00:01:40 2011 Return-Path: Delivered-To: hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id E9DE4106566C for ; Mon, 19 Sep 2011 00:01:40 +0000 (UTC) (envelope-from adrian.chadd@gmail.com) Received: from mail-yw0-f54.google.com (mail-yw0-f54.google.com [209.85.213.54]) by mx1.freebsd.org (Postfix) with ESMTP id ABEA58FC13 for ; Mon, 19 Sep 2011 00:01:40 +0000 (UTC) Received: by ywp17 with SMTP id 17so4681892ywp.13 for ; Sun, 18 Sep 2011 17:01:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=mime-version:sender:in-reply-to:references:date :x-google-sender-auth:message-id:subject:from:to:cc:content-type; bh=vuD928+pyjNvYfZ7Be1tbdBP+82ApmK+zbQ7uZAEeYU=; b=p51SoLRCmRmXSQ9Pn5a1hEXyi8lLBymQoJjwiGsyB9zGL9FweuNu0V+KImC6c03H7u 7U5M2+IJwCPT1bA30vXAGnLAHXDkg/Hg6aYmuZKcEBX4XS1YCtIP1Vrx3eIlUwz/KxTn 5sH2yKCRScOi1ub5jrdSmFuTMNBY0mPEZF6RA= MIME-Version: 1.0 Received: by 10.236.79.72 with SMTP id h48mr10394753yhe.4.1316390499978; Sun, 18 Sep 2011 17:01:39 -0700 (PDT) Sender: adrian.chadd@gmail.com Received: by 10.236.111.42 with HTTP; Sun, 18 Sep 2011 17:01:39 -0700 (PDT) In-Reply-To: References: Date: Mon, 19 Sep 2011 08:01:39 +0800 X-Google-Sender-Auth: GIv0ws6QmZzVUIpzO3QUG78CQHc Message-ID: From: Adrian Chadd To: Richard Yao Content-Type: text/plain; charset=ISO-8859-1 Cc: hackers@freebsd.org Subject: Re: Mixing Asynchronous Network I/O and POSIX Threads X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 19 Sep 2011 00:01:41 -0000 Why not just port to using libevent 2.x with the thread support, and thus be portable to all platforms? Adrian From owner-freebsd-hackers@FreeBSD.ORG Mon Sep 19 00:23:07 2011 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 9C2EE106566C for ; Mon, 19 Sep 2011 00:23:07 +0000 (UTC) (envelope-from dieterbsd@engineer.com) Received: from mailout-us.gmx.com (mailout-us.gmx.com [74.208.5.67]) by mx1.freebsd.org (Postfix) with SMTP id 6F1AB8FC0A for ; Mon, 19 Sep 2011 00:23:07 +0000 (UTC) Received: (qmail 12708 invoked by uid 0); 19 Sep 2011 00:23:05 -0000 Received: from 67.206.185.80 by rms-us017 with HTTP Content-Type: text/plain; charset="utf-8" Date: Sun, 18 Sep 2011 20:23:03 -0400 From: "Dieter BSD" Message-ID: <20110919002304.219780@gmx.com> MIME-Version: 1.0 To: freebsd-hackers@freebsd.org X-Authenticated: #74169980 X-Flags: 0001 X-Mailer: GMX.com Web Mailer x-registered: 0 Content-Transfer-Encoding: 8bit X-GMX-UID: J/4XKrM0zVK0IR3RHjUzY24/Njh6dA4M Subject: Re: checksum offload X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 19 Sep 2011 00:23:07 -0000 > The data sheet for intel 82576 advertises IP TX/RX checksum offload > but the driver does not set CSUM_IP in ifp->if_hwassist. Does this mean that > driver (and chip) do not support IP TX checksum offload or the support for > TX is not yet included in the driver? The first question is "is checksum offload a good idea?" There is less protection against errors. From owner-freebsd-hackers@FreeBSD.ORG Mon Sep 19 00:27:02 2011 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 7EF931065670 for ; Mon, 19 Sep 2011 00:27:02 +0000 (UTC) (envelope-from yanegomi@gmail.com) Received: from mail-qy0-f182.google.com (mail-qy0-f182.google.com [209.85.216.182]) by mx1.freebsd.org (Postfix) with ESMTP id 421488FC12 for ; Mon, 19 Sep 2011 00:27:01 +0000 (UTC) Received: by qyk4 with SMTP id 4so5957620qyk.13 for ; Sun, 18 Sep 2011 17:27:01 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=mime-version:in-reply-to:references:date:message-id:subject:from:to :cc:content-type; bh=121CO2c21tOW9dlFE3tA1GYLt9Jp3xepRKUCiJybna0=; b=afBC+HmdaILKzzBklxmS4SUsY1QVueGkP3/kicPUOFpbGeRLK/4Zzjl3MjHyc7j8vv Tgi5w7tmZq0EGd2izLiYnRiBB+JXEXw3WOpE7eoqmYcDmhOhCqWmcfbnCA/Fqef81ZlA n+ejRG/Ewpjc1d5b2ju3U3/ceG1rOxiT4uPlA= MIME-Version: 1.0 Received: by 10.224.218.132 with SMTP id hq4mr1520463qab.192.1316392021525; Sun, 18 Sep 2011 17:27:01 -0700 (PDT) Received: by 10.224.37.83 with HTTP; Sun, 18 Sep 2011 17:27:01 -0700 (PDT) In-Reply-To: <20110919002304.219780@gmx.com> References: <20110919002304.219780@gmx.com> Date: Sun, 18 Sep 2011 17:27:01 -0700 Message-ID: From: Garrett Cooper To: Dieter BSD Content-Type: text/plain; charset=ISO-8859-1 Cc: freebsd-hackers@freebsd.org Subject: Re: checksum offload X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 19 Sep 2011 00:27:02 -0000 On Sun, Sep 18, 2011 at 5:23 PM, Dieter BSD wrote: >> The data sheet for intel 82576 advertises IP TX/RX checksum offload >> but the driver does not set CSUM_IP in ifp->if_hwassist. Does this mean that >> driver (and chip) do not support IP TX checksum offload or the support for >> TX is not yet included in the driver? > > The first question is "is checksum offload a good idea?" > There is less protection against errors. This assumes firmware flaws, right? Albeit, it also does confuse some software like tcpdump. -Garrett From owner-freebsd-hackers@FreeBSD.ORG Mon Sep 19 01:45:56 2011 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 0C7B71065672; Mon, 19 Sep 2011 01:45:56 +0000 (UTC) (envelope-from luigi@onelab2.iet.unipi.it) Received: from onelab2.iet.unipi.it (onelab2.iet.unipi.it [131.114.59.238]) by mx1.freebsd.org (Postfix) with ESMTP id C3EAA8FC19; Mon, 19 Sep 2011 01:45:55 +0000 (UTC) Received: by onelab2.iet.unipi.it (Postfix, from userid 275) id B2B707300A; Mon, 19 Sep 2011 04:01:31 +0200 (CEST) Date: Mon, 19 Sep 2011 04:01:31 +0200 From: Luigi Rizzo To: Arnaud Lacombe Message-ID: <20110919020131.GA11657@onelab2.iet.unipi.it> References: <4E744BCE.7060302@sepehrs.com> <20110917203218.GC13993@michelle.cdnetworks.com> <20110918210647.GA8930@onelab2.iet.unipi.it> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.4.2.3i Cc: jfv@freebsd.org, pyunyh@gmail.com, Hooman Fazaeli , freebsd-hackers@freebsd.org Subject: Re: intel checksum offload X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 19 Sep 2011 01:45:56 -0000 On Sun, Sep 18, 2011 at 06:05:33PM -0400, Arnaud Lacombe wrote: > Hi, > > On Sun, Sep 18, 2011 at 5:06 PM, Luigi Rizzo wrote: > > On Sun, Sep 18, 2011 at 03:19:46PM -0400, Arnaud Lacombe wrote: > >> Hi, > >> > >> On Sat, Sep 17, 2011 at 4:32 PM, YongHyeon PYUN wrote: > >> > On Sat, Sep 17, 2011 at 11:57:10AM +0430, Hooman Fazaeli wrote: > >> >> Hi list, > >> >> > >> >> The data sheet for intel 82576 advertises IP TX/RX checksum offload > >> >> but the driver does not set CSUM_IP in ifp->if_hwassist. Does this mean that > >> >> driver (and chip) do not support IP TX checksum offload or the support for > >> >> TX is not yet included in the driver? > > ... > >> This is slightly off-topic, but still.. > >> > >> FWIW, I'm not really impressed by what chips claim to support vs. what > >> has been implemented in the driver. As per the product brief, the > > ... > >> [0]: the commit message say "performance was not good", but it is not > >> the driver's developer to decide whether or not a feature is good or > >> not. The developer's job is to implement the chip capabilities, and > >> let it to the user to enable or disable the capabilities. At best, the > >> developer can decide whether or not to enable the feature by default. > > > > actually, this is a perfect example where the developer has done the > > right thing: implemented the feature, verified that performance is bad, > > hence presumably removed support for the feature from the code (which also > > means that the normal code path will run faster because there are no > > run-time decisions to be made). > > > > "optional" features are often costly even when disabled. > > > I forgot to mention that in this case, the code full of > EM_MULTIQUEUE's #ifdef and shared code is still fully compatible with > the multiqueue's architecture. The only thing removed is a conditional > and an assignation in the driver's attachment which was enabling the > feature, ie. the cost you point out is still paid today, without any > benefit. the above suggests that you have a wonderful opportunity: with just a little bit of time and effort you should be able to complete/re-enable the missing code, run tests that you believe significant (given your statement below) and prove or disprove the comment about performance. cheers luigi > > Now I might also openly question the test method used by the folks at > Intel, just seeing how much issue I've had with the driver (I still > have for some, even if not driver related), which have not been > reproduced there. > > Finally, when someone say "performance are better that way", the first > thing I'd be tempted to ask is: "What is your test ? How did you > collects the numbers ? How did you reach the conclusion ?". None of > this stuff is public. > regards, > - Arnaud From owner-freebsd-hackers@FreeBSD.ORG Mon Sep 19 01:50:32 2011 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 93481106564A for ; Mon, 19 Sep 2011 01:50:32 +0000 (UTC) (envelope-from adrian.chadd@gmail.com) Received: from mail-yi0-f54.google.com (mail-yi0-f54.google.com [209.85.218.54]) by mx1.freebsd.org (Postfix) with ESMTP id 3E3878FC08 for ; Mon, 19 Sep 2011 01:50:31 +0000 (UTC) Received: by yia13 with SMTP id 13so2708496yia.13 for ; Sun, 18 Sep 2011 18:50:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=mime-version:sender:in-reply-to:references:date :x-google-sender-auth:message-id:subject:from:to:cc:content-type; bh=4R9JZIqMZeS6wEBszYl0DEfkS13AgMJsmfI4ySatfo8=; b=GWtFb9SHBMs0Y1Bc4a1F4aSQ7IbZsm9Uzwdpy1x7/PLxqG7x/B0NjztPJO2y37SdVO C0OsbNdfjpcGq8LkjR6BdCmgsbbiLQeAG5WcCKa+hSJ9Lic/+sRq/FIVBw5ktNEv3DSN DA63jT7DV1trYQY+7dJMPHeFAFY2/55QLPT6I= MIME-Version: 1.0 Received: by 10.236.176.65 with SMTP id a41mr10466579yhm.72.1316397031553; Sun, 18 Sep 2011 18:50:31 -0700 (PDT) Sender: adrian.chadd@gmail.com Received: by 10.236.111.42 with HTTP; Sun, 18 Sep 2011 18:50:31 -0700 (PDT) In-Reply-To: <20110919020131.GA11657@onelab2.iet.unipi.it> References: <4E744BCE.7060302@sepehrs.com> <20110917203218.GC13993@michelle.cdnetworks.com> <20110918210647.GA8930@onelab2.iet.unipi.it> <20110919020131.GA11657@onelab2.iet.unipi.it> Date: Mon, 19 Sep 2011 09:50:31 +0800 X-Google-Sender-Auth: ZJy0C3hSkjXfdT4mnmbXfZQvkZ4 Message-ID: From: Adrian Chadd To: Luigi Rizzo Content-Type: text/plain; charset=ISO-8859-1 Cc: jfv@freebsd.org, pyunyh@gmail.com, Hooman Fazaeli , Arnaud Lacombe , freebsd-hackers@freebsd.org Subject: Re: intel checksum offload X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 19 Sep 2011 01:50:32 -0000 .. and believe me, lots of people will appreciate it if you can verify/diagnose issues. :) Adrian From owner-freebsd-hackers@FreeBSD.ORG Mon Sep 19 02:48:34 2011 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id EFF571065678; Mon, 19 Sep 2011 02:48:33 +0000 (UTC) (envelope-from lacombar@gmail.com) Received: from mail-wy0-f178.google.com (mail-wy0-f178.google.com [74.125.82.178]) by mx1.freebsd.org (Postfix) with ESMTP id 5B35C8FC13; Mon, 19 Sep 2011 02:48:33 +0000 (UTC) Received: by wyf23 with SMTP id 23so5987572wyf.37 for ; Sun, 18 Sep 2011 19:48:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=mime-version:in-reply-to:references:date:message-id:subject:from:to :cc:content-type; bh=baR5NHxiHl5e60SJfP82kxruSihCN5II0XDot2v3gRk=; b=BXQZYS457n3A/tOUTmbIkfBUGxS2D6HEdy34zLkVppn6kt8A0sMS5fL0D6Au5P0JNB uEWTjbihyjK+XCxOyKvdhAcAluc9jVyJUR/OTXJGXeX0cq8u2rdoOIqRmCd1rt8EVkJm XaMmRZZrRgN3T5KN0JyXK+l4AQ7kRQpwS+p6s= MIME-Version: 1.0 Received: by 10.227.11.7 with SMTP id r7mr2168100wbr.53.1316400512180; Sun, 18 Sep 2011 19:48:32 -0700 (PDT) Received: by 10.180.95.169 with HTTP; Sun, 18 Sep 2011 19:48:32 -0700 (PDT) In-Reply-To: <20110919020131.GA11657@onelab2.iet.unipi.it> References: <4E744BCE.7060302@sepehrs.com> <20110917203218.GC13993@michelle.cdnetworks.com> <20110918210647.GA8930@onelab2.iet.unipi.it> <20110919020131.GA11657@onelab2.iet.unipi.it> Date: Sun, 18 Sep 2011 22:48:32 -0400 Message-ID: From: Arnaud Lacombe To: Luigi Rizzo Content-Type: text/plain; charset=ISO-8859-1 Cc: jfv@freebsd.org, pyunyh@gmail.com, Hooman Fazaeli , freebsd-hackers@freebsd.org Subject: Re: intel checksum offload X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 19 Sep 2011 02:48:34 -0000 Hi, On Sun, Sep 18, 2011 at 10:01 PM, Luigi Rizzo wrote: > On Sun, Sep 18, 2011 at 06:05:33PM -0400, Arnaud Lacombe wrote: >> Hi, >> >> On Sun, Sep 18, 2011 at 5:06 PM, Luigi Rizzo wrote: >> > On Sun, Sep 18, 2011 at 03:19:46PM -0400, Arnaud Lacombe wrote: >> >> Hi, >> >> >> >> On Sat, Sep 17, 2011 at 4:32 PM, YongHyeon PYUN wrote: >> >> > On Sat, Sep 17, 2011 at 11:57:10AM +0430, Hooman Fazaeli wrote: >> >> >> Hi list, >> >> >> >> >> >> The data sheet for intel 82576 advertises IP TX/RX checksum offload >> >> >> but the driver does not set CSUM_IP in ifp->if_hwassist. Does this mean that >> >> >> driver (and chip) do not support IP TX checksum offload or the support for >> >> >> TX is not yet included in the driver? >> > ... >> >> This is slightly off-topic, but still.. >> >> >> >> FWIW, I'm not really impressed by what chips claim to support vs. what >> >> has been implemented in the driver. As per the product brief, the >> > ... >> >> [0]: the commit message say "performance was not good", but it is not >> >> the driver's developer to decide whether or not a feature is good or >> >> not. The developer's job is to implement the chip capabilities, and >> >> let it to the user to enable or disable the capabilities. At best, the >> >> developer can decide whether or not to enable the feature by default. >> > >> > actually, this is a perfect example where the developer has done the >> > right thing: implemented the feature, verified that performance is bad, >> > hence presumably removed support for the feature from the code (which also >> > means that the normal code path will run faster because there are no >> > run-time decisions to be made). >> > >> > "optional" features are often costly even when disabled. >> > >> I forgot to mention that in this case, the code full of >> EM_MULTIQUEUE's #ifdef and shared code is still fully compatible with >> the multiqueue's architecture. The only thing removed is a conditional >> and an assignation in the driver's attachment which was enabling the >> feature, ie. the cost you point out is still paid today, without any >> benefit. > > the above suggests that you have a wonderful opportunity: with just > a little bit of time and effort you should be able to complete/re-enable > the missing code, run tests that you believe significant (given > your statement below) and prove or disprove the comment about > performance. > Which I did about a week ago, to finally discover that the NIC only had only 3 MSI-X vectors configured in its EEPROM[0], and thus the MSI-X PCI capability field ends up also with being assigned with those 3 vectors. However, the 82574 datasheet clearly say that up-to 5 vector can be configured, but I obviously did not find the magic trick to make it so. Maybe I'll find some time and try to reprogram the EEPROM. Beside that, it was clear that the old multiqueue did not support only 3 vector being available and thus fell back on MSI. It is not clear in jfv@'s comment whether he really tested multiqueue, or did he test the fall-back MSI mode. As the PCI spec is not public, I've not been able to find out from the few public datasheet how the PCI MSI-X capability field is first programmed. I'd assume that the BIOS is using the data in the NVM to program it at power up. - Arnaud [0]: at least, the MSI_X_NUM field of the NVM at offset 0x1b is 2, thus 3 vectors. From owner-freebsd-hackers@FreeBSD.ORG Mon Sep 19 03:53:09 2011 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 3239F106566C; Mon, 19 Sep 2011 03:53:09 +0000 (UTC) (envelope-from lacombar@gmail.com) Received: from mail-wy0-f178.google.com (mail-wy0-f178.google.com [74.125.82.178]) by mx1.freebsd.org (Postfix) with ESMTP id 8A88D8FC14; Mon, 19 Sep 2011 03:53:08 +0000 (UTC) Received: by wyf23 with SMTP id 23so6023047wyf.37 for ; Sun, 18 Sep 2011 20:53:07 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=mime-version:in-reply-to:references:date:message-id:subject:from:to :cc:content-type:content-transfer-encoding; bh=zlv5n24+GcZz9BEp0uysYzXFADJdGCL2EQztP3GMpWY=; b=mHdVJ3WlYTGahJahN1NHcZbKuEH5pLomg9ZA4qgwhoaMAPToxyMvSipQW5EfBThEz+ fqzjnpA1lBGXb8mLJivNCUCgeco8BkKswMGv/cW2KpfO5lFyKFMCyAmmG580icwrtdDP G1ClpVaVFKmODHAXXoOyauSJSTeNe4hs0RLqM= MIME-Version: 1.0 Received: by 10.216.136.159 with SMTP id w31mr2180394wei.53.1316404387237; Sun, 18 Sep 2011 20:53:07 -0700 (PDT) Received: by 10.180.95.169 with HTTP; Sun, 18 Sep 2011 20:53:07 -0700 (PDT) In-Reply-To: References: Date: Sun, 18 Sep 2011 23:53:07 -0400 Message-ID: From: Arnaud Lacombe To: "K. Macy" Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable Cc: FreeBSD Hackers Subject: Re: buf_ring(9) API precisions X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 19 Sep 2011 03:53:09 -0000 Hi, On Fri, Sep 16, 2011 at 10:41 AM, K. Macy wrote: > On Fri, Sep 16, 2011 at 3:02 AM, Arnaud Lacombe wrot= e: >> Hi, >> >> On Wed, Sep 14, 2011 at 10:53 PM, Arnaud Lacombe wr= ote: >>> Hi Kip, >>> >>> I've got a few question about the buf_ring(9) API. >>> >>> 1) what means the 'drbr_' prefix. I can guess the two last letter, 'b' >>> and 'r', for Buffer Ring, but what about 'd' and 'r' ? >>> >>> 2) in `sys/sys/buf_ring.h', you defined 'struct buf_ring' as: >>> >>> struct buf_ring { >>> =A0 =A0 =A0 =A0volatile uint32_t =A0 =A0 =A0 br_prod_head; >>> =A0 =A0 =A0 =A0volatile uint32_t =A0 =A0 =A0 br_prod_tail; >>> =A0 =A0 =A0 =A0int =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 br_prod_size= ; >>> =A0 =A0 =A0 =A0int =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 br_prod_mask= ; >>> =A0 =A0 =A0 =A0uint64_t =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0br_drops; >>> =A0 =A0 =A0 =A0uint64_t =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0br_prod_bufs; >>> =A0 =A0 =A0 =A0uint64_t =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0br_prod_bytes; >> shouldn't those 3 fields be updated atomically, especially on 32bits >> platforms ? That might pose a problem as, AFAIK, FreeBSD do not have >> MI 64bits atomics operations... > > Between the point at which br_prod_tail =3D=3D prod_head and when we > update br_prod_tail to point to prod_next we are the exclusive owners > of the fields in buf_ring. That is why we wait for any other > enqueueing threads to update br_prod_tail to point to prod_head before > continuing. > How do you enforce ordering ? I do not see anything particular forbidding the `br->br_prod_tail' to be committed first, leading other thread to believe they have access to the statistics, while the other thread has not yet committed its change. Thanks, - Arnaud > Cheers > > =A0 =A0 =A0 =A0/* > =A0 =A0 =A0 =A0 * If there are other enqueues in progress > =A0 =A0 =A0 =A0 * that preceeded us, we need to wait for them > =A0 =A0 =A0 =A0 * to complete > =A0 =A0 =A0 =A0 */ > =A0 =A0 =A0 =A0while (br->br_prod_tail !=3D prod_head) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0cpu_spinwait(); > =A0 =A0 =A0 =A0br->br_prod_bufs++; > =A0 =A0 =A0 =A0br->br_prod_bytes +=3D nbytes; > =A0 =A0 =A0 =A0br->br_prod_tail =3D prod_next; > =A0 =A0 =A0 =A0critical_exit(); > From owner-freebsd-hackers@FreeBSD.ORG Mon Sep 19 05:37:35 2011 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id C5379106564A; Mon, 19 Sep 2011 05:37:35 +0000 (UTC) (envelope-from lacombar@gmail.com) Received: from mail-ww0-f50.google.com (mail-ww0-f50.google.com [74.125.82.50]) by mx1.freebsd.org (Postfix) with ESMTP id 30D8A8FC0C; Mon, 19 Sep 2011 05:37:34 +0000 (UTC) Received: by wwe3 with SMTP id 3so6918434wwe.31 for ; Sun, 18 Sep 2011 22:37:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=mime-version:in-reply-to:references:date:message-id:subject:from:to :cc:content-type; bh=YuZeEC5ljK9+6HdhqUe3ZA0YrHDkJOWF9iQhY3tCqeo=; b=j7e0C4f3VyixqakTuC4EFOWAi2tfOyuFpx8HdoDZ2gUwP5zIMCDz5u+vWwuSR+nCGU xdw4YJbe+a2U3EVqX3fr01StE24ku0IOOcW3qmBColOWkhLtu7iuAi/ybF6iuwFKh+RG hvU4/Ss2HNVbGPDjqC7Kz2SH6a/z11JEpEyWE= MIME-Version: 1.0 Received: by 10.227.175.77 with SMTP id w13mr2206219wbz.53.1316410653960; Sun, 18 Sep 2011 22:37:33 -0700 (PDT) Received: by 10.180.95.169 with HTTP; Sun, 18 Sep 2011 22:37:33 -0700 (PDT) In-Reply-To: References: <4E744BCE.7060302@sepehrs.com> <20110917203218.GC13993@michelle.cdnetworks.com> <20110918210647.GA8930@onelab2.iet.unipi.it> <20110919020131.GA11657@onelab2.iet.unipi.it> Date: Mon, 19 Sep 2011 01:37:33 -0400 Message-ID: From: Arnaud Lacombe To: Jack Vogel Content-Type: text/plain; charset=ISO-8859-1 Cc: jfv@freebsd.org, pyunyh@gmail.com, Hooman Fazaeli , Luigi Rizzo , freebsd-hackers@freebsd.org Subject: Re: intel checksum offload X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 19 Sep 2011 05:37:35 -0000 Hi, On Mon, Sep 19, 2011 at 12:29 AM, Jack Vogel wrote: > [...] > If you notice, the Linux driver did not enable multiqueue on the hardware > either, so do you think a whole department of software engineers backed > by the hardware engineers who designed the damn thing might have had > a reason? > Let's find out :-) In the mean time, as a hacker, I'd be interested to know why the NVM ships with MSI_X_NUM == 2 at offset 0x1b when the datasheet say it does support up value to 4 ? This might be as simple as "the hardware needs special wiring to support 5 vectors.", or whatever... > IN FACT, as I have a bit more freedom with FreeBSD, I went ahead and > tried it for a while just because I could, implementing the code was not > difficult. Over time however that code proved to be a source of instability > and thus was disabled. > It would be interesting for the records to have this information public, especially the kind of instability seen. > I have heard a rumor that the Linux crew may actually be trying a second > time to make it work, and that might give me cause to look at it again too, > but its not clear if I'll have time with other priorities. > ack. Now, what about header-split support in em(4) ? Thanks, - Arnaud From owner-freebsd-hackers@FreeBSD.ORG Mon Sep 19 07:11:32 2011 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 69D55106564A; Mon, 19 Sep 2011 07:11:32 +0000 (UTC) (envelope-from fazaeli@sepehrs.com) Received: from sepehrs.com (sepehrs.com [213.217.59.98]) by mx1.freebsd.org (Postfix) with ESMTP id 517B48FC14; Mon, 19 Sep 2011 07:11:27 +0000 (UTC) Received: from [127.0.0.1] ([192.168.3.10]) by sepehrs.com (8.14.3/8.14.3) with ESMTP id p8J6iRA5030697; Mon, 19 Sep 2011 11:14:28 +0430 (IRDT) Message-ID: <4E76E5B9.9080301@sepehrs.com> Date: Mon, 19 Sep 2011 11:18:25 +0430 From: Hooman Fazaeli User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.22) Gecko/20110902 Thunderbird/3.1.14 MIME-Version: 1.0 To: Jack Vogel References: <4E744BCE.7060302@sepehrs.com> <20110917203218.GC13993@michelle.cdnetworks.com> <20110918210647.GA8930@onelab2.iet.unipi.it> <20110919020131.GA11657@onelab2.iet.unipi.it> In-Reply-To: Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit X-Content-Filtered-By: Mailman/MimeDel 2.1.5 Cc: jfv@freebsd.org, pyunyh@gmail.com, Luigi Rizzo , Arnaud Lacombe , freebsd-hackers@freebsd.org Subject: Re: intel checksum offload X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 19 Sep 2011 07:11:32 -0000 It is interesting that how a thread goes off topic! Anyway, I will appreciate if folks, especially Jack, provide a firm comment on the original question: Does intel chips (specifically 82576) support IP TX checksum offload? If so, why the driver does not support it? On 9/19/2011 8:59 AM, Jack Vogel wrote: > > > On Sun, Sep 18, 2011 at 7:48 PM, Arnaud Lacombe > wrote: > > Hi, > > On Sun, Sep 18, 2011 at 10:01 PM, Luigi Rizzo > wrote: > > On Sun, Sep 18, 2011 at 06:05:33PM -0400, Arnaud Lacombe wrote: > >> Hi, > >> > >> On Sun, Sep 18, 2011 at 5:06 PM, Luigi Rizzo > wrote: > >> > On Sun, Sep 18, 2011 at 03:19:46PM -0400, Arnaud Lacombe wrote: > >> >> Hi, > >> >> > >> >> On Sat, Sep 17, 2011 at 4:32 PM, YongHyeon PYUN > wrote: > >> >> > On Sat, Sep 17, 2011 at 11:57:10AM +0430, Hooman Fazaeli wrote: > >> >> >> Hi list, > >> >> >> > >> >> >> The data sheet for intel 82576 advertises IP TX/RX checksum offload > >> >> >> but the driver does not set CSUM_IP in ifp->if_hwassist. Does this mean that > >> >> >> driver (and chip) do not support IP TX checksum offload or the support for > >> >> >> TX is not yet included in the driver? > >> > ... > >> >> This is slightly off-topic, but still.. > >> >> > >> >> FWIW, I'm not really impressed by what chips claim to support vs. what > >> >> has been implemented in the driver. As per the product brief, the > >> > ... > >> >> [0]: the commit message say "performance was not good", but it is not > >> >> the driver's developer to decide whether or not a feature is good or > >> >> not. The developer's job is to implement the chip capabilities, and > >> >> let it to the user to enable or disable the capabilities. At best, the > >> >> developer can decide whether or not to enable the feature by default. > >> > > >> > actually, this is a perfect example where the developer has done the > >> > right thing: implemented the feature, verified that performance is bad, > >> > hence presumably removed support for the feature from the code (which also > >> > means that the normal code path will run faster because there are no > >> > run-time decisions to be made). > >> > > >> > "optional" features are often costly even when disabled. > >> > > >> I forgot to mention that in this case, the code full of > >> EM_MULTIQUEUE's #ifdef and shared code is still fully compatible with > >> the multiqueue's architecture. The only thing removed is a conditional > >> and an assignation in the driver's attachment which was enabling the > >> feature, ie. the cost you point out is still paid today, without any > >> benefit. > > > > the above suggests that you have a wonderful opportunity: with just > > a little bit of time and effort you should be able to complete/re-enable > > the missing code, run tests that you believe significant (given > > your statement below) and prove or disprove the comment about > > performance. > > > Which I did about a week ago, to finally discover that the NIC only > had only 3 MSI-X vectors configured in its EEPROM[0], and thus the > MSI-X PCI capability field ends up also with being assigned with those > 3 vectors. However, the 82574 datasheet clearly say that up-to 5 > vector can be configured, but I obviously did not find the magic trick > to make it so. Maybe I'll find some time and try to reprogram the > EEPROM. Beside that, it was clear that the old multiqueue did not > support only 3 vector being available and thus fell back on MSI. It is > not clear in jfv@'s comment whether he really tested multiqueue, or > did he test the fall-back MSI mode. > > As the PCI spec is not public, I've not been able to find out from the > few public datasheet how the PCI MSI-X capability field is first > programmed. I'd assume that the BIOS is using the data in the NVM to > program it at power up. > > - Arnaud > > [0]: at least, the MSI_X_NUM field of the NVM at offset 0x1b is 2, > thus 3 vectors. > > > I give answers to those who treat me with respect, I view them as > collaborators, we improve the drivers for everyone's benefit, rather > than jumping in to throw a critical remark here, a negative innuendo > there... > > If you notice, the Linux driver did not enable multiqueue on the hardware > either, so do you think a whole department of software engineers backed > by the hardware engineers who designed the damn thing might have had > a reason? > > IN FACT, as I have a bit more freedom with FreeBSD, I went ahead and > tried it for a while just because I could, implementing the code was not > difficult. Over time however that code proved to be a source of instability > and thus was disabled. > > I have heard a rumor that the Linux crew may actually be trying a second > time to make it work, and that might give me cause to look at it again too, > but its not clear if I'll have time with other priorities. > > Jack > From owner-freebsd-hackers@FreeBSD.ORG Mon Sep 19 07:41:15 2011 Return-Path: Delivered-To: hackers@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 57019106564A for ; Mon, 19 Sep 2011 07:41:15 +0000 (UTC) (envelope-from avg@FreeBSD.org) Received: from citadel.icyb.net.ua (citadel.icyb.net.ua [212.40.38.140]) by mx1.freebsd.org (Postfix) with ESMTP id 9FA578FC12 for ; Mon, 19 Sep 2011 07:41:14 +0000 (UTC) Received: from porto.starpoint.kiev.ua (porto-e.starpoint.kiev.ua [212.40.38.100]) by citadel.icyb.net.ua (8.8.8p3/ICyb-2.3exp) with ESMTP id KAA03833; Mon, 19 Sep 2011 10:41:12 +0300 (EEST) (envelope-from avg@FreeBSD.org) Received: from localhost ([127.0.0.1]) by porto.starpoint.kiev.ua with esmtp (Exim 4.34 (FreeBSD)) id 1R5YTX-000HUx-M4; Mon, 19 Sep 2011 10:41:11 +0300 Message-ID: <4E76F217.8040901@FreeBSD.org> Date: Mon, 19 Sep 2011 10:41:11 +0300 From: Andriy Gapon User-Agent: Mozilla/5.0 (X11; FreeBSD amd64; rv:6.0.2) Gecko/20110907 Thunderbird/6.0.2 MIME-Version: 1.0 To: Gleb Kurtsou References: <4E712D11.7040202@FreeBSD.org> <4E75B67E.1000802@FreeBSD.org> <20110918222541.GA86842@tops> In-Reply-To: <20110918222541.GA86842@tops> X-Enigmail-Version: undefined Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit Cc: hackers@FreeBSD.org Subject: Re: Fwd: my git development snapshot(s) X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 19 Sep 2011 07:41:15 -0000 on 19/09/2011 01:25 Gleb Kurtsou said the following: > Let me share my experience as well. > > My repo: https://github.com/glk/freebsd-head/ > > I used rebase to keep local branches as well, but no longer do so. Such > setup worked for me at least for two years, I had local changes and > worked on a larger patchset for 7,8-STABLE and CURRENT branches > simultaneously (no longer do it either). But (imho) this approach his > serious drawbacks. The biggest one is that it's hard to check if > regression comes from your code or recently merged upstream code. The > second one: once you screw rebase (merge) you are in big trouble. Both > issues can be worked around by keeping previous master branches, but it > hardly helps: once there are conflicts with upstream or your local > changes get commited upstream it becomes only harder and harder. (I used > to have master-prev-DATE similar to devel-DATE Andriy uses.) I have used both approaches and for now I prefer my current one (obviously). But I am really thinking more and more about topgit. Actually, not necessarily that tool and its implementation, but that kind of concept. With that approach one has an explicitly defined upstream (or upstreams) and explicitly defined local changes plus dependency graph for those changes, plus full history of each change. It's like another dimension to version control, now you have not only versions of a tree, but also versions of changes to the tree. topgit implements that idea by having a separate branch for each (developer defined) change and by stacking those branches on top of each other to get the tree that has all the dependent changes. -- Andriy Gapon From owner-freebsd-hackers@FreeBSD.ORG Mon Sep 19 07:47:11 2011 Return-Path: Delivered-To: hackers@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 42EE0106566B for ; Mon, 19 Sep 2011 07:47:11 +0000 (UTC) (envelope-from avg@FreeBSD.org) Received: from citadel.icyb.net.ua (citadel.icyb.net.ua [212.40.38.140]) by mx1.freebsd.org (Postfix) with ESMTP id 8DADC8FC0A for ; Mon, 19 Sep 2011 07:47:10 +0000 (UTC) Received: from porto.starpoint.kiev.ua (porto-e.starpoint.kiev.ua [212.40.38.100]) by citadel.icyb.net.ua (8.8.8p3/ICyb-2.3exp) with ESMTP id KAA03903; Mon, 19 Sep 2011 10:47:08 +0300 (EEST) (envelope-from avg@FreeBSD.org) Received: from localhost ([127.0.0.1]) by porto.starpoint.kiev.ua with esmtp (Exim 4.34 (FreeBSD)) id 1R5YZH-000HVF-SH; Mon, 19 Sep 2011 10:47:07 +0300 Message-ID: <4E76F37B.80307@FreeBSD.org> Date: Mon, 19 Sep 2011 10:47:07 +0300 From: Andriy Gapon User-Agent: Mozilla/5.0 (X11; FreeBSD amd64; rv:6.0.2) Gecko/20110907 Thunderbird/6.0.2 MIME-Version: 1.0 To: Gleb Kurtsou References: <4E712D11.7040202@FreeBSD.org> <4E75B67E.1000802@FreeBSD.org> <20110918222541.GA86842@tops> <4E76F217.8040901@FreeBSD.org> In-Reply-To: <4E76F217.8040901@FreeBSD.org> X-Enigmail-Version: undefined Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit Cc: hackers@FreeBSD.org Subject: Re: Fwd: my git development snapshot(s) X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 19 Sep 2011 07:47:11 -0000 on 19/09/2011 10:41 Andriy Gapon said the following: > on 19/09/2011 01:25 Gleb Kurtsou said the following: >> Let me share my experience as well. >> >> My repo: https://github.com/glk/freebsd-head/ >> >> I used rebase to keep local branches as well, but no longer do so. Such >> setup worked for me at least for two years, I had local changes and >> worked on a larger patchset for 7,8-STABLE and CURRENT branches >> simultaneously (no longer do it either). But (imho) this approach his >> serious drawbacks. The biggest one is that it's hard to check if >> regression comes from your code or recently merged upstream code. The >> second one: once you screw rebase (merge) you are in big trouble. Both >> issues can be worked around by keeping previous master branches, but it >> hardly helps: once there are conflicts with upstream or your local >> changes get commited upstream it becomes only harder and harder. (I used >> to have master-prev-DATE similar to devel-DATE Andriy uses.) > > I have used both approaches and for now I prefer my current one (obviously). > But I am really thinking more and more about topgit. Actually, not necessarily > that tool and its implementation, but that kind of concept. > With that approach one has an explicitly defined upstream (or upstreams) and > explicitly defined local changes plus dependency graph for those changes, plus > full history of each change. It's like another dimension to version control, > now you have not only versions of a tree, but also versions of changes to the > tree. topgit implements that idea by having a separate branch for each > (developer defined) change and by stacking those branches on top of each other > to get the tree that has all the dependent changes. > Forgot to add: I think that this is quite close to what you do, but with another layer on top of git to make change management easier. Or harder - if it has bugs or limitations ;-) -- Andriy Gapon From owner-freebsd-hackers@FreeBSD.ORG Mon Sep 19 09:28:49 2011 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 309DA106566B; Mon, 19 Sep 2011 09:28:49 +0000 (UTC) (envelope-from adrian.chadd@gmail.com) Received: from mail-yi0-f54.google.com (mail-yi0-f54.google.com [209.85.218.54]) by mx1.freebsd.org (Postfix) with ESMTP id CA4658FC0A; Mon, 19 Sep 2011 09:28:48 +0000 (UTC) Received: by yia13 with SMTP id 13so2889483yia.13 for ; Mon, 19 Sep 2011 02:28:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=mime-version:sender:in-reply-to:references:date :x-google-sender-auth:message-id:subject:from:to:cc:content-type; bh=K/wE/KS7A2h2IdPn9QgmiPOjufvnA6Ua5/1z/VUhaVM=; b=RbKKNTnTwgTOv8qu2k7nDIqkMv4yvVGoD+2SIKCQvMjKeSZqB9Vq+jLQc9LILg5g9u WUiFzm24EhSS7ajxJ5dCyAJwYpaJZ3S+/Qg5BuCBXOHF9K8dtnVawviCMEtfJPiUw/Bm uIthbiP2JoIOJ4QEdy/odKA2a2wA7qTDrmUGc= MIME-Version: 1.0 Received: by 10.52.72.16 with SMTP id z16mr1743792vdu.395.1316424528032; Mon, 19 Sep 2011 02:28:48 -0700 (PDT) Sender: adrian.chadd@gmail.com Received: by 10.52.161.138 with HTTP; Mon, 19 Sep 2011 02:28:47 -0700 (PDT) In-Reply-To: <4E76E5B9.9080301@sepehrs.com> References: <4E744BCE.7060302@sepehrs.com> <20110917203218.GC13993@michelle.cdnetworks.com> <20110918210647.GA8930@onelab2.iet.unipi.it> <20110919020131.GA11657@onelab2.iet.unipi.it> <4E76E5B9.9080301@sepehrs.com> Date: Mon, 19 Sep 2011 17:28:47 +0800 X-Google-Sender-Auth: hZP06z4XBSvKNsry5AQx0MoiAw8 Message-ID: From: Adrian Chadd To: Hooman Fazaeli Content-Type: text/plain; charset=ISO-8859-1 Cc: pyunyh@gmail.com, freebsd-hackers@freebsd.org, Jack Vogel , Arnaud Lacombe , jfv@freebsd.org, Luigi Rizzo Subject: Re: intel checksum offload X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 19 Sep 2011 09:28:49 -0000 Arnaud (and others), Liaising with vendors is not an easy task. The reason why Intel (and other vendors) don't supply detailed history and reasoning for their development efforts is that their engineers are likely tasked with "making it work" versus "writing lots of stuff down for public release." In some instances, the vendor support of FreeBSD (and "free" open source in general) is done as a side-project by some of the engineers inside the company. So in this case, you may find that Jack and the other engineers at Intel just don't have the time or resources to dedicate the kinds of feedback and support you seem to be after. He and others likely have a huge set of tasks to do at work and none of them officially include "support FreeBSD/Linux developers by providing detailed feedback and assistance." So whenever Jack pops up to help out, he's likely doing it in his spare time. :-) Developers can and will disable or remove functionality which is problematic because they don't have the time or resources to support it. Users may wish to turn on unsupported features and then will complain loudly when they don't work; even giving up and moving to another piece of equipment because of perceived issues. I agree that it would be nice if the developers included _all_ features, unsupported or not, so that developers can choose to work on them if they wish. It however is a trade-off between trying to provide developers with more useful things to tinker with and not increasing support load from users (and other developers) who seek to use incomplete features. I hope this helps. Adrian From owner-freebsd-hackers@FreeBSD.ORG Mon Sep 19 04:55:05 2011 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 405011065672 for ; Mon, 19 Sep 2011 04:55:05 +0000 (UTC) (envelope-from jfvogel@gmail.com) Received: from mail-ww0-f42.google.com (mail-ww0-f42.google.com [74.125.82.42]) by mx1.freebsd.org (Postfix) with ESMTP id B3B1E8FC12 for ; Mon, 19 Sep 2011 04:55:04 +0000 (UTC) Received: by wwn22 with SMTP id 22so3279275wwn.1 for ; Sun, 18 Sep 2011 21:55:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=mime-version:in-reply-to:references:date:message-id:subject:from:to :cc:content-type; bh=4edGWcBwq9m9yS5QNvNsp4r6+qufz8HH1NdHhje5toQ=; b=mlxv2Crc2IchegHTN9PE62cQzDWU0aqc8efJQcyEjfj1daEJMJsfuhd/y0ZiAY5vYV loDNAcE9zguWty0UmYcSzbbmu2GTsgvc8WCGxCBzT6ZNG7/SKJfiQTH9TNZSaTjnq6bx 3QF+6++3NY2jFH9ASrrJwWdPiHFYI0yobC0zE= MIME-Version: 1.0 Received: by 10.227.201.130 with SMTP id fa2mr1251623wbb.13.1316406568313; Sun, 18 Sep 2011 21:29:28 -0700 (PDT) Received: by 10.180.106.35 with HTTP; Sun, 18 Sep 2011 21:29:28 -0700 (PDT) In-Reply-To: References: <4E744BCE.7060302@sepehrs.com> <20110917203218.GC13993@michelle.cdnetworks.com> <20110918210647.GA8930@onelab2.iet.unipi.it> <20110919020131.GA11657@onelab2.iet.unipi.it> Date: Sun, 18 Sep 2011 21:29:28 -0700 Message-ID: From: Jack Vogel To: Arnaud Lacombe X-Mailman-Approved-At: Mon, 19 Sep 2011 10:55:34 +0000 Content-Type: text/plain; charset=ISO-8859-1 X-Content-Filtered-By: Mailman/MimeDel 2.1.5 Cc: jfv@freebsd.org, pyunyh@gmail.com, Hooman Fazaeli , Luigi Rizzo , freebsd-hackers@freebsd.org Subject: Re: intel checksum offload X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 19 Sep 2011 04:55:05 -0000 On Sun, Sep 18, 2011 at 7:48 PM, Arnaud Lacombe wrote: > Hi, > > On Sun, Sep 18, 2011 at 10:01 PM, Luigi Rizzo wrote: > > On Sun, Sep 18, 2011 at 06:05:33PM -0400, Arnaud Lacombe wrote: > >> Hi, > >> > >> On Sun, Sep 18, 2011 at 5:06 PM, Luigi Rizzo > wrote: > >> > On Sun, Sep 18, 2011 at 03:19:46PM -0400, Arnaud Lacombe wrote: > >> >> Hi, > >> >> > >> >> On Sat, Sep 17, 2011 at 4:32 PM, YongHyeon PYUN > wrote: > >> >> > On Sat, Sep 17, 2011 at 11:57:10AM +0430, Hooman Fazaeli wrote: > >> >> >> Hi list, > >> >> >> > >> >> >> The data sheet for intel 82576 advertises IP TX/RX checksum > offload > >> >> >> but the driver does not set CSUM_IP in ifp->if_hwassist. Does this > mean that > >> >> >> driver (and chip) do not support IP TX checksum offload or the > support for > >> >> >> TX is not yet included in the driver? > >> > ... > >> >> This is slightly off-topic, but still.. > >> >> > >> >> FWIW, I'm not really impressed by what chips claim to support vs. > what > >> >> has been implemented in the driver. As per the product brief, the > >> > ... > >> >> [0]: the commit message say "performance was not good", but it is not > >> >> the driver's developer to decide whether or not a feature is good or > >> >> not. The developer's job is to implement the chip capabilities, and > >> >> let it to the user to enable or disable the capabilities. At best, > the > >> >> developer can decide whether or not to enable the feature by default. > >> > > >> > actually, this is a perfect example where the developer has done the > >> > right thing: implemented the feature, verified that performance is > bad, > >> > hence presumably removed support for the feature from the code (which > also > >> > means that the normal code path will run faster because there are no > >> > run-time decisions to be made). > >> > > >> > "optional" features are often costly even when disabled. > >> > > >> I forgot to mention that in this case, the code full of > >> EM_MULTIQUEUE's #ifdef and shared code is still fully compatible with > >> the multiqueue's architecture. The only thing removed is a conditional > >> and an assignation in the driver's attachment which was enabling the > >> feature, ie. the cost you point out is still paid today, without any > >> benefit. > > > > the above suggests that you have a wonderful opportunity: with just > > a little bit of time and effort you should be able to complete/re-enable > > the missing code, run tests that you believe significant (given > > your statement below) and prove or disprove the comment about > > performance. > > > Which I did about a week ago, to finally discover that the NIC only > had only 3 MSI-X vectors configured in its EEPROM[0], and thus the > MSI-X PCI capability field ends up also with being assigned with those > 3 vectors. However, the 82574 datasheet clearly say that up-to 5 > vector can be configured, but I obviously did not find the magic trick > to make it so. Maybe I'll find some time and try to reprogram the > EEPROM. Beside that, it was clear that the old multiqueue did not > support only 3 vector being available and thus fell back on MSI. It is > not clear in jfv@'s comment whether he really tested multiqueue, or > did he test the fall-back MSI mode. > > As the PCI spec is not public, I've not been able to find out from the > few public datasheet how the PCI MSI-X capability field is first > programmed. I'd assume that the BIOS is using the data in the NVM to > program it at power up. > > - Arnaud > > [0]: at least, the MSI_X_NUM field of the NVM at offset 0x1b is 2, > thus 3 vectors. > I give answers to those who treat me with respect, I view them as collaborators, we improve the drivers for everyone's benefit, rather than jumping in to throw a critical remark here, a negative innuendo there... If you notice, the Linux driver did not enable multiqueue on the hardware either, so do you think a whole department of software engineers backed by the hardware engineers who designed the damn thing might have had a reason? IN FACT, as I have a bit more freedom with FreeBSD, I went ahead and tried it for a while just because I could, implementing the code was not difficult. Over time however that code proved to be a source of instability and thus was disabled. I have heard a rumor that the Linux crew may actually be trying a second time to make it work, and that might give me cause to look at it again too, but its not clear if I'll have time with other priorities. Jack From owner-freebsd-hackers@FreeBSD.ORG Mon Sep 19 12:41:19 2011 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 47F5E106566C; Mon, 19 Sep 2011 12:41:19 +0000 (UTC) (envelope-from jhb@freebsd.org) Received: from cyrus.watson.org (cyrus.watson.org [65.122.17.42]) by mx1.freebsd.org (Postfix) with ESMTP id 1D35B8FC0C; Mon, 19 Sep 2011 12:41:19 +0000 (UTC) Received: from bigwig.baldwin.cx (66.111.2.69.static.nyinternet.net [66.111.2.69]) by cyrus.watson.org (Postfix) with ESMTPSA id AEE5746B45; Mon, 19 Sep 2011 08:41:18 -0400 (EDT) Received: from jhbbsd.localnet (unknown [209.249.190.124]) by bigwig.baldwin.cx (Postfix) with ESMTPSA id 5023D8A02E; Mon, 19 Sep 2011 08:41:18 -0400 (EDT) From: John Baldwin To: freebsd-hackers@freebsd.org Date: Mon, 19 Sep 2011 08:23:32 -0400 User-Agent: KMail/1.13.5 (FreeBSD/8.2-CBSD-20110617; KDE/4.5.5; amd64; ; ) References: <4E744BCE.7060302@sepehrs.com> <20110919020131.GA11657@onelab2.iet.unipi.it> In-Reply-To: MIME-Version: 1.0 Content-Type: Text/Plain; charset="iso-8859-1" Content-Transfer-Encoding: 7bit Message-Id: <201109190823.32871.jhb@freebsd.org> X-Greylist: Sender succeeded SMTP AUTH, not delayed by milter-greylist-4.2.6 (bigwig.baldwin.cx); Mon, 19 Sep 2011 08:41:18 -0400 (EDT) Cc: jfv@freebsd.org, pyunyh@gmail.com, Hooman Fazaeli , Luigi Rizzo , Arnaud Lacombe Subject: Re: intel checksum offload X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 19 Sep 2011 12:41:19 -0000 On Sunday, September 18, 2011 10:48:32 pm Arnaud Lacombe wrote: > As the PCI spec is not public, I've not been able to find out from the > few public datasheet how the PCI MSI-X capability field is first > programmed. I'd assume that the BIOS is using the data in the NVM to > program it at power up. "PCI System Architecture" is quite public at Amazon. It's not the spec, but it will certainly give you enough info to understand MSI and it covers the question you are asking well enough. The MSI config registers are not touched by the BIOS at all (at least not in a standard way). It is the responsibility of the device to setup the read-only fields in the MSI and MSI-X config registers on reset. -- John Baldwin From owner-freebsd-hackers@FreeBSD.ORG Mon Sep 19 12:41:19 2011 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id EA5E8106564A for ; Mon, 19 Sep 2011 12:41:19 +0000 (UTC) (envelope-from jhb@freebsd.org) Received: from cyrus.watson.org (cyrus.watson.org [65.122.17.42]) by mx1.freebsd.org (Postfix) with ESMTP id BF5EE8FC14 for ; Mon, 19 Sep 2011 12:41:19 +0000 (UTC) Received: from bigwig.baldwin.cx (66.111.2.69.static.nyinternet.net [66.111.2.69]) by cyrus.watson.org (Postfix) with ESMTPSA id 7414446B46; Mon, 19 Sep 2011 08:41:19 -0400 (EDT) Received: from jhbbsd.localnet (unknown [209.249.190.124]) by bigwig.baldwin.cx (Postfix) with ESMTPSA id 13A868A02F; Mon, 19 Sep 2011 08:41:19 -0400 (EDT) From: John Baldwin To: freebsd-hackers@freebsd.org Date: Mon, 19 Sep 2011 08:25:54 -0400 User-Agent: KMail/1.13.5 (FreeBSD/8.2-CBSD-20110617; KDE/4.5.5; amd64; ; ) References: In-Reply-To: MIME-Version: 1.0 Content-Type: Text/Plain; charset="iso-8859-1" Content-Transfer-Encoding: 7bit Message-Id: <201109190825.54074.jhb@freebsd.org> X-Greylist: Sender succeeded SMTP AUTH, not delayed by milter-greylist-4.2.6 (bigwig.baldwin.cx); Mon, 19 Sep 2011 08:41:19 -0400 (EDT) Cc: Jilles Tjoelker , Richard Yao Subject: Re: Mixing Asynchronous Network I/O and POSIX Threads X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 19 Sep 2011 12:41:20 -0000 On Sunday, September 18, 2011 5:45:26 pm Richard Yao wrote: > Dear Jilles, > > I am using sigwaitinfo() with all interrupts masked to avoid the > possibility of race conditions in signal handlers, but I have not used > any realtime signals. Linux 2.6.35 found a way to invoke the SIGIO > handler despite it being masked, but that issue would not occur under > production conditions and that is a bug for a different mailing list. > > Being unable to F_SETOWN individual threads would cause problems > because it causes network traffic to become serialized. My code must > run on Linux, but if I were to write FreeBSD-specific code so it would > also work on FreeBSD, would using kqueue enable me to specify which > threads handle events on specific file descriptors? Yes in that you could give each thread its own kqueue fd and register other fd's on the desired thread's kqueue. However, Adrian's point about using libevent is probably worth investigating to see if it will let you achieve that in a portable way. -- John Baldwin From owner-freebsd-hackers@FreeBSD.ORG Mon Sep 19 12:46:38 2011 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 967B5106566B for ; Mon, 19 Sep 2011 12:46:38 +0000 (UTC) (envelope-from kmacybsd@gmail.com) Received: from mail-yx0-f182.google.com (mail-yx0-f182.google.com [209.85.213.182]) by mx1.freebsd.org (Postfix) with ESMTP id 532D08FC0C for ; Mon, 19 Sep 2011 12:46:38 +0000 (UTC) Received: by yxk36 with SMTP id 36so5031248yxk.13 for ; Mon, 19 Sep 2011 05:46:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=mime-version:sender:in-reply-to:references:date :x-google-sender-auth:message-id:subject:from:to:cc:content-type :content-transfer-encoding; bh=l8meStHq+UiLrd2LUzsJjxETUl/EWKoxkkLakykw1hk=; b=AR3wGPQP+maVLgUYxdzfGhP2bbJnNx0YVhjsajaxRUEML92jN9vpQQYVbV3mpin1AI lgJ3RU8Qy9IkeHyAaMY0a49SfjPMJGl7z4/9IHqWNrdUjVBFRVt8L74+AVMgJutfpuf0 5A9MUbknFrpsS1eXLbDvSkXkSULCqxtjpqugQ= MIME-Version: 1.0 Received: by 10.52.96.166 with SMTP id dt6mr2145925vdb.345.1316436397637; Mon, 19 Sep 2011 05:46:37 -0700 (PDT) Sender: kmacybsd@gmail.com Received: by 10.52.113.202 with HTTP; Mon, 19 Sep 2011 05:46:37 -0700 (PDT) In-Reply-To: References: Date: Mon, 19 Sep 2011 14:46:37 +0200 X-Google-Sender-Auth: C0fLcIppiAzxhc-Y_MUV96E2B1Q Message-ID: From: "K. Macy" To: Arnaud Lacombe Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable Cc: FreeBSD Hackers Subject: Re: buf_ring(9) API precisions X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 19 Sep 2011 12:46:38 -0000 If the value lags next by one then it is ours. This rule applies to all callers so the rule holds consistently. On Mon, Sep 19, 2011 at 5:53 AM, Arnaud Lacombe wrote: > Hi, > > On Fri, Sep 16, 2011 at 10:41 AM, K. Macy wrote: >> On Fri, Sep 16, 2011 at 3:02 AM, Arnaud Lacombe wro= te: >>> Hi, >>> >>> On Wed, Sep 14, 2011 at 10:53 PM, Arnaud Lacombe w= rote: >>>> Hi Kip, >>>> >>>> I've got a few question about the buf_ring(9) API. >>>> >>>> 1) what means the 'drbr_' prefix. I can guess the two last letter, 'b' >>>> and 'r', for Buffer Ring, but what about 'd' and 'r' ? >>>> >>>> 2) in `sys/sys/buf_ring.h', you defined 'struct buf_ring' as: >>>> >>>> struct buf_ring { >>>> =A0 =A0 =A0 =A0volatile uint32_t =A0 =A0 =A0 br_prod_head; >>>> =A0 =A0 =A0 =A0volatile uint32_t =A0 =A0 =A0 br_prod_tail; >>>> =A0 =A0 =A0 =A0int =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 br_prod_siz= e; >>>> =A0 =A0 =A0 =A0int =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 br_prod_mas= k; >>>> =A0 =A0 =A0 =A0uint64_t =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0br_drops; >>>> =A0 =A0 =A0 =A0uint64_t =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0br_prod_bufs; >>>> =A0 =A0 =A0 =A0uint64_t =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0br_prod_bytes; >>> shouldn't those 3 fields be updated atomically, especially on 32bits >>> platforms ? That might pose a problem as, AFAIK, FreeBSD do not have >>> MI 64bits atomics operations... >> >> Between the point at which br_prod_tail =3D=3D prod_head and when we >> update br_prod_tail to point to prod_next we are the exclusive owners >> of the fields in buf_ring. That is why we wait for any other >> enqueueing threads to update br_prod_tail to point to prod_head before >> continuing. >> > How do you enforce ordering ? I do not see anything particular > forbidding the `br->br_prod_tail' to be committed first, leading other > thread to believe they have access to the statistics, while the other > thread has not yet committed its change. > > Thanks, > =A0- Arnaud > >> Cheers >> >> =A0 =A0 =A0 =A0/* >> =A0 =A0 =A0 =A0 * If there are other enqueues in progress >> =A0 =A0 =A0 =A0 * that preceeded us, we need to wait for them >> =A0 =A0 =A0 =A0 * to complete >> =A0 =A0 =A0 =A0 */ >> =A0 =A0 =A0 =A0while (br->br_prod_tail !=3D prod_head) >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0cpu_spinwait(); >> =A0 =A0 =A0 =A0br->br_prod_bufs++; >> =A0 =A0 =A0 =A0br->br_prod_bytes +=3D nbytes; >> =A0 =A0 =A0 =A0br->br_prod_tail =3D prod_next; >> =A0 =A0 =A0 =A0critical_exit(); >> > From owner-freebsd-hackers@FreeBSD.ORG Mon Sep 19 13:10:12 2011 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 2DDF3106566C for ; Mon, 19 Sep 2011 13:10:12 +0000 (UTC) (envelope-from jlpetz@internode.on.net) Received: from ipmail06.adl6.internode.on.net (ipmail06.adl6.internode.on.net [150.101.137.145]) by mx1.freebsd.org (Postfix) with ESMTP id AFC1B8FC1F for ; Mon, 19 Sep 2011 13:10:11 +0000 (UTC) X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: Av8EANc7d055LEEa/2dsb2JhbABCpx14gVMBAQMCCAIeEhwTARsBAwIGAxEEAQEoBxkgDQkIAgQBEgkCBQuHYLVThngEnBmIbw Received: from ppp121-44-65-26.lns20.syd6.internode.on.net (HELO Minx) ([121.44.65.26]) by ipmail06.adl6.internode.on.net with ESMTP; 19 Sep 2011 22:40:09 +0930 From: "Jarrod Lee Petz" To: "'Daniel Hartmeier'" , References: <007301cc6979$a690f9a0$f3b2ece0$@internode.on.net> <4E616D6E.4030903@FreeBSD.org> <001701cc69d3$aea9a0b0$0bfce210$@internode.on.net> <4E61BA37.2060204@FreeBSD.org> <20110903134634.GA55652@owl.midgard.homeip.net> <4E62B99C.6020707@FreeBSD.org> <001e01cc6a9d$8e62c870$ab285950$@internode.on.net> <20110905151146.GA10185@insomnia.benzedrine.cx> In-Reply-To: <20110905151146.GA10185@insomnia.benzedrine.cx> Date: Mon, 19 Sep 2011 23:10:06 +1000 Message-ID: <000001cc76cd$744d7bb0$5ce87310$@internode.on.net> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit X-Mailer: Microsoft Outlook 14.0 Thread-Index: AQHuPCHqJDmDdIw669xIXvDN9LM1EADkjGxsAa6N1kUCHwUDBgGXq6DUAa0cmgEBYbJsPAKzPzumlLDAQpA= Content-Language: en-au Cc: Subject: RE: TIME_WAIT Assassination in FreeBSD??? X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list Reply-To: petz@nisshoko.net List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 19 Sep 2011 13:10:12 -0000 Hi Daniel, Thank you for the information. I agree with your comment below. " But if you're simply running the ftp client on an otherwise idle host, and two subsequent bind() calls get assigned the same 'random' port, I'd say the port randomization is not working properly :)" Does anyone have any further information or advice they could offer for this issue? I have found a few other references via Google to people experiencing issues with ephemeral port randomisation and FreeBSD. It appears this does not just impact FTP but also WebServers & Proxy software. So as I feared other protocols/software besides active FTP is impacted. To what extent it would seem no one really knows unless things have changed(this stuff is a few years dated). This link in particular http://www.silby.com/eurobsdcon05/eurobsdcon_silbersack.pdf " At present, FreeBSD attempts to avoid this quick port recycling problem by falling back to sequential port allocation whenever the machine is making more than 10 outbound connections per second. This solution is more of a hack than anything, and has been slated to be replaced as soon as a better method can be found." And this http://www.bsdcan.org/2006/papers/ImprovingTCPIP.pdf I retested again, this time on FreeBSD 9.0 Beta 2. I can confirm the behaviour described is still present. If I test with many worker FTP processes or even one process without a delay. Then the ten connections per second limit is reached and port randomisation is disabled making the problem disappear. However when I only have one worker process and a delay(which I usually have to capture a decent tcpdump) then the connection rate is lower and port randomisation stays in effect which produces the issue. So what should would be the best approach for this. I'm still not sure. Does anyone know of work being done on a different port randomisation algorithm? Should I disable port randomisation until/unless a better selection algorithm comes along? This is made out to sound like a fairly big security risk in practice I don't really understand how bad? For secured SSL/TLS traffic would this cause concern? OR Should I just move to passive FTP and try not to worry about other protocols/software encountering sporadic issues? Regards Jarrod -----Original Message----- From: Daniel Hartmeier [mailto:daniel@benzedrine.cx] Sent: Tuesday, 6 September 2011 1:12 AM To: petz@nisshoko.net Cc: freebsd-hackers@freebsd.org Subject: Re: TIME_WAIT Assassination in FreeBSD??? In FreeBSD, the ftp client allocates the port for an active-mode data connection by calling bind(2) with so_port set to 0, which means it lets the kernel pick a port, see http://www.freebsd.org/cgi/cvsweb.cgi/src/contrib/lukemftp/src/Attic/ftp.c?r ev=1.1.1.8;content-type=text%2Fplain;hideattic=0 The kernel code where the port is picked is in function in_pcb_lport(), see http://www.freebsd.org/cgi/cvsweb.cgi/src/sys/netinet/in_pcb.c?rev=1.281;con tent-type=text%2Fplain Basically, there is a range of ports (49152-65535, adjustable with sysctl), and the algorithm picks a random port within that range: if (dorandom) *lastport = first + (arc4random() % (last - first)); It checks whether that port is available. If not, it increments it by one, and tries again, etc. in a loop, until it finds one. So, for your case, it is unlikely that two subsequent bind() calls from the ftp client would result in the same port being picked randomly, unless a large part of the port range is unavailable. You can get port re-use that is quick enough to confuse pf, for instance, by opening new connections (to the same destination address and port) at a high rate, e.g. when running the Apache web server benchmark tool. But if you're simply running the ftp client on an otherwise idle host, and two subsequent bind() calls get assigned the same 'random' port, I'd say the port randomization is not working properly :) HTH, Daniel From owner-freebsd-hackers@FreeBSD.ORG Mon Sep 19 14:17:25 2011 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id F3F001065679; Mon, 19 Sep 2011 14:17:24 +0000 (UTC) (envelope-from lacombar@gmail.com) Received: from mail-wy0-f178.google.com (mail-wy0-f178.google.com [74.125.82.178]) by mx1.freebsd.org (Postfix) with ESMTP id 2507F8FC14; Mon, 19 Sep 2011 14:17:23 +0000 (UTC) Received: by wyf23 with SMTP id 23so6763992wyf.37 for ; Mon, 19 Sep 2011 07:17:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=mime-version:in-reply-to:references:date:message-id:subject:from:to :cc:content-type; bh=i94qpb5z18OJbHbgXzBTuhnjB7mI7s8NTZma90B6VL8=; b=PjQnrofQwa/vl8FXuYSj3pEDL1jCWMIfCiIX5Ht5VKOqdnufyDcMiBp5dGjC4v1rH3 HFLGSZGsex75ErjlpILEcEpthv8Pw4aHAwfTF/1pZhqoGeEX5M/OTmxYHJdVCt6zcohY lcfI1ftnz7s/r2AIuY9sZUZWpOndW7UR8N/kc= MIME-Version: 1.0 Received: by 10.227.28.69 with SMTP id l5mr2853032wbc.38.1316441842780; Mon, 19 Sep 2011 07:17:22 -0700 (PDT) Received: by 10.180.95.169 with HTTP; Mon, 19 Sep 2011 07:17:22 -0700 (PDT) In-Reply-To: References: <4E744BCE.7060302@sepehrs.com> <20110917203218.GC13993@michelle.cdnetworks.com> <20110918210647.GA8930@onelab2.iet.unipi.it> <20110919020131.GA11657@onelab2.iet.unipi.it> <4E76E5B9.9080301@sepehrs.com> Date: Mon, 19 Sep 2011 10:17:22 -0400 Message-ID: From: Arnaud Lacombe To: Adrian Chadd Content-Type: text/plain; charset=ISO-8859-1 Cc: pyunyh@gmail.com, freebsd-hackers@freebsd.org, Hooman Fazaeli , Jack Vogel , jfv@freebsd.org, Luigi Rizzo Subject: Re: intel checksum offload X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 19 Sep 2011 14:17:25 -0000 Hi, On Mon, Sep 19, 2011 at 5:28 AM, Adrian Chadd wrote: > Arnaud (and others), > > Liaising with vendors is not an easy task. The reason why Intel (and > other vendors) don't supply detailed history and reasoning for their > development efforts is that their engineers are likely tasked with > "making it work" versus "writing lots of stuff down for public > release." In some instances, the vendor support of FreeBSD (and "free" > open source in general) is done as a side-project by some of the > engineers inside the company. > > So in this case, you may find that Jack and the other engineers at > Intel just don't have the time or resources to dedicate the kinds of > feedback and support you seem to be after. He and others likely have a > huge set of tasks to do at work and none of them officially include > "support FreeBSD/Linux developers by providing detailed feedback and > assistance." So whenever Jack pops up to help out, he's likely doing > it in his spare time. :-) > Yes, and he seems to really like to waste his spare time by repeating me for two months to increase `kern.ipc.nmbclusters' to fix issue I was seeing, when the code was clearly buggy, even when I sent him patchs fixing issues. That's sure a very efficient way of managing time. - Arnaud > Developers can and will disable or remove functionality which is > problematic because they don't have the time or resources to support > it. Users may wish to turn on unsupported features and then will > complain loudly when they don't work; even giving up and moving to > another piece of equipment because of perceived issues. I agree that > it would be nice if the developers included _all_ features, > unsupported or not, so that developers can choose to work on them if > they wish. It however is a trade-off between trying to provide > developers with more useful things to tinker with and not increasing > support load from users (and other developers) who seek to use > incomplete features. > > I hope this helps. > > > Adrian > From owner-freebsd-hackers@FreeBSD.ORG Mon Sep 19 14:29:24 2011 Return-Path: Delivered-To: hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 57288106564A for ; Mon, 19 Sep 2011 14:29:24 +0000 (UTC) (envelope-from theraven@theravensnest.org) Received: from theravensnest.org (theravensnest.org [109.169.23.128]) by mx1.freebsd.org (Postfix) with ESMTP id 8EB9D8FC16 for ; Mon, 19 Sep 2011 14:29:22 +0000 (UTC) Received: from [192.168.0.128] (cpc1-cwma5-0-0-cust192.7-3.cable.virginmedia.com [80.4.12.193]) (authenticated bits=0) by theravensnest.org (8.14.4/8.14.4) with ESMTP id p8JEvdCk041064 (version=TLSv1/SSLv3 cipher=DHE-DSS-AES128-SHA bits=128 verify=NO); Mon, 19 Sep 2011 15:57:40 +0100 (BST) (envelope-from theraven@theravensnest.org) From: David Chisnall Content-Type: multipart/mixed; boundary="Apple-Mail=_F55C7A91-4420-4E40-9517-BE01711EE0A4" Date: Mon, 19 Sep 2011 15:00:36 +0100 Message-Id: To: Roman Divacky , hackers@freebsd.org Mime-Version: 1.0 (Apple Message framework v1244.3) X-Mailer: Apple Mail (2.1244.3) X-Mailman-Approved-At: Mon, 19 Sep 2011 15:35:36 +0000 Cc: Subject: xlocale patch X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 19 Sep 2011 14:29:24 -0000 --Apple-Mail=_F55C7A91-4420-4E40-9517-BE01711EE0A4 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=us-ascii Hello Roman et al., Here is a big patch that provides everything needed to get libc++ = building on FreeBSD (head), which I think means that the linker is now = the only bit of the C++ stack that is not permissively licensed. The = patch contains the following: - The POSIX2008 locale functions. The specifications of these are = evidence that the Austin Group has been indulging in the other product = that UCB is famous for. Where the specification is ambiguous (i.e. = everywhere), I have used the Darwin implementation as a guide. This was = done because libc++ is developed on Darwin, so will likely expect this = behaviour. - The xlocale (Darwin extension) APIs. These provide _l suffixed = versions of a load of libc functions, which take a locale_t as a special = argument. The standard libc functions are now modified to call the _l = version with the current locale. =20 - Some stub definitions in libm for the long double versions of the = functions ( needs them to be in ). These versions just = call the double versions, so they lose precision and are therefore = hidden if you define __NO_IMPRECISE_LIBM_FUNCTIONS. =20 I've also attached some tests. The check_functions tool can be used as = $(CC) when building libc. It scans each of the _l functions and ensures = that they don't refer to any global state or call any of the non-_l = versions. There are also tests for the new locale functions (these = expect a checkout of head in /root/head - modify the Makefile in the = tests if it is elsewhere). As well as running these tests, I've also = built world with this diff installed. This work was sponsored by The FreeBSD Foundation. Comments / bug = reports / test cases welcome! David --Apple-Mail=_F55C7A91-4420-4E40-9517-BE01711EE0A4 Content-Disposition: attachment; filename=xlocale.diff Content-Type: application/octet-stream; x-unix-mode=0644; name="xlocale.diff" Content-Transfer-Encoding: 7bit Index: include/wctype.h =================================================================== --- include/wctype.h (revision 225653) +++ include/wctype.h (working copy) @@ -25,7 +25,7 @@ * * citrus Id: wctype.h,v 1.4 2000/12/21 01:50:21 itojun Exp * $NetBSD: wctype.h,v 1.3 2000/12/22 14:16:16 itojun Exp $ - * $FreeBSD$ + * $FreeBSD: head/include/wctype.h 172630 2007-10-14 10:23:54Z ache $ */ #ifndef _WCTYPE_H_ Index: include/Makefile =================================================================== --- include/Makefile (revision 225653) +++ include/Makefile (working copy) @@ -1,5 +1,5 @@ # @(#)Makefile 8.2 (Berkeley) 1/4/94 -# $FreeBSD$ +# $FreeBSD: head/include/Makefile 220370 2011-04-05 18:41:01Z obrien $ # # Doing a "make install" builds /usr/include. @@ -24,7 +24,7 @@ strings.h sysexits.h tar.h termios.h tgmath.h \ time.h timeconv.h timers.h ttyent.h \ ulimit.h unistd.h utime.h utmpx.h uuid.h varargs.h vis.h \ - wchar.h wctype.h wordexp.h + wchar.h wctype.h wordexp.h xlocale.h _xlocale_ctype.h MHDRS= float.h floatingpoint.h stdarg.h Index: include/xlocale.h =================================================================== --- include/xlocale.h (revision 0) +++ include/xlocale.h (revision 0) @@ -0,0 +1,256 @@ +/*- + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by David Chisnall under sponsorship from + * the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions * are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _XLOCALE_H_ +#define _XLOCALE_H_ + +#include + +__BEGIN_DECLS + +/* + * Extended locale versions of the locale-aware functions from string.h. + * + * Include before to expose these. + */ +#ifdef _STRING_H_ +int strcoll_l(const char *, const char *, locale_t); +size_t strxfrm_l(char *, const char *, size_t, locale_t); +int strcasecmp_l(const char *, const char *, locale_t); +char *strcasestr_l(const char *, const char *, locale_t); +int strncasecmp_l(const char *, const char *, size_t, locale_t); +#endif +/* + * Extended locale versions of the locale-aware functions from inttypes.h. + * + * Include before to expose these. + */ +#ifdef _INTTYPES_H_ +intmax_t +strtoimax_l(const char * __restrict, char ** __restrict, int, locale_t); +uintmax_t +strtoumax_l(const char * __restrict, char ** __restrict, int, locale_t); +intmax_t +wcstoimax_l(const wchar_t * __restrict, wchar_t ** __restrict, int , locale_t); +uintmax_t +wcstoumax_l(const wchar_t * __restrict, wchar_t ** __restrict, int, locale_t); +#endif +/* + * Extended locale versions of the locale-aware functions from monetary.h. + * + * Include before to expose these. + */ +#ifdef _MONETARY_H_ +ssize_t strfmon_l(char *, size_t, locale_t, const char *, ...) +# if __GNUC__ > 2 || __GNUC__ == 2 && __GNUC_MINOR__ >= 7 + __attribute__((__format__ (__strfmon__, 4, 5))) +# endif + ; +#endif + +/* + * Extended locale versions of the locale-aware functions from stdlib.h. + * + * Include before to expose these. + */ +#ifdef _STDLIB_H_ +double atof_l(const char *, locale_t); +int atoi_l(const char *, locale_t); +long atol_l(const char *, locale_t); +long long atoll_l(const char *, locale_t); +int mblen_l(const char *, size_t, locale_t); +size_t +mbstowcs_l(wchar_t * __restrict, const char * __restrict, size_t, locale_t); +int +mbtowc_l(wchar_t * __restrict, const char * __restrict, size_t, locale_t); +double strtod_l(const char *, char **, locale_t); +float strtof_l(const char *, char **, locale_t); +long strtol_l(const char *, char **, int, locale_t); +long double strtold_l(const char *, char **, locale_t); +long long strtoll_l(const char *, char **, int, locale_t); +unsigned long strtoul_l(const char *, char **, int, locale_t); +unsigned long long strtoull_l(const char *, char **, int, locale_t); +size_t +wcstombs_l(char * __restrict, const wchar_t * __restrict, size_t, locale_t); +int wctomb_l(char *, wchar_t, locale_t); + +int ___mb_cur_max_l(locale_t); +#define MB_CUR_MAX_L(x) (___mb_cur_max_l(x)) + +#endif +/* + * Extended locale versions of the locale-aware functions from time.h. + * + * Include before to expose these. + */ +#ifdef _TIME_H_ +size_t +strftime_l(char * __restrict, size_t, const char * __restrict, const + struct tm * __restrict, locale_t) +# if __GNUC__ > 2 || __GNUC__ == 2 && __GNUC_MINOR__ >= 7 + __attribute__((__format__ (__strftime__, 3, 0))) +# endif + ; +char * +strptime_l(const char * __restrict, const char * __restrict, + struct tm * __restrict, locale_t); +#endif +#ifdef _LANGINFO_H_ +char *nl_langinfo_l(nl_item, locale_t); +#endif +#ifdef _CTYPE_H_ +#include <_xlocale_ctype.h> +#endif +#ifdef _WCTYPE_H_ +#define XLOCALE_WCTYPES 1 +#include <_xlocale_ctype.h> +#endif + +#ifdef _STDIO_H_ +int fprintf_l(FILE * __restrict, locale_t, const char * __restrict, ...) + __printflike(3, 4); +int fscanf_l(FILE * __restrict, locale_t, const char * __restrict, ...) + __scanflike(3, 4); +int printf_l(locale_t, const char * __restrict, ...) __printflike(2, 3); +int scanf_l(locale_t, const char * __restrict, ...) __scanflike(2, 3); +int sprintf_l(char * __restrict, locale_t, const char * __restrict, ...) + __printflike(3, 4); +int sscanf_l(const char * __restrict, locale_t, const char * __restrict, ...) + __scanflike(3, 4); +int vfprintf_l(FILE * __restrict, locale_t, const char * __restrict, __va_list) + __printflike(3, 0); +int vprintf_l(locale_t, const char * __restrict, __va_list) __printflike(2, 0); +int vsprintf_l(char * __restrict, locale_t, const char * __restrict, __va_list) + __printflike(3, 0); + +int snprintf_l(char * __restrict, size_t, locale_t, const char * __restrict, + ...) __printflike(4, 5); +int vfscanf_l(FILE * __restrict, locale_t, const char * __restrict, __va_list) + __scanflike(3, 0); +int vscanf_l(locale_t, const char * __restrict, __va_list) __scanflike(2, 0); +int vsnprintf_l(char * __restrict, size_t, locale_t, const char * __restrict, + va_list) __printflike(4, 0); +int vsscanf_l(const char * __restrict, locale_t, const char * __restrict, + va_list) __scanflike(3, 0); +int dprintf_l(int, locale_t, const char * __restrict, ...) __printflike(3, 4); +int vdprintf_l(int, locale_t, const char * __restrict, __va_list) + __printflike(3, 0); +int asprintf_l(char **, locale_t, const char *, ...) __printflike(3, 4); +int vasprintf_l(char **, locale_t, const char *, __va_list) __printflike(3, 0); +#endif +#ifdef _WCHAR_H_ +wint_t btowc_l(int, locale_t); +wint_t fgetwc_l(struct __sFILE *, locale_t); +wchar_t * +fgetws_l(wchar_t * __restrict, int, struct __sFILE * __restrict, locale_t); +wint_t fputwc_l(wchar_t, struct __sFILE *, locale_t); +int +fputws_l(const wchar_t * __restrict, struct __sFILE * __restrict, locale_t); +int +fwprintf_l(struct __sFILE * __restrict, locale_t, const wchar_t * __restrict, + ...); +int +fwscanf_l(struct __sFILE * __restrict, locale_t, const wchar_t * __restrict, ...); +wint_t getwc_l(struct __sFILE *, locale_t); +wint_t getwchar_l(locale_t); +size_t +mbrlen_l(const char * __restrict, size_t, mbstate_t * __restrict, locale_t); +size_t +mbrtowc_l(wchar_t * __restrict, const char * __restrict, size_t, + mbstate_t * __restrict, locale_t); +int mbsinit_l(const mbstate_t *, locale_t); +size_t +mbsrtowcs_l(wchar_t * __restrict, const char ** __restrict, size_t, + mbstate_t * __restrict, locale_t); +wint_t putwc_l(wchar_t, struct __sFILE *, locale_t); +wint_t putwchar_l(wchar_t, locale_t); +int +swprintf_l(wchar_t * __restrict, size_t n, locale_t, + const wchar_t * __restrict, ...); +int +swscanf_l(const wchar_t * __restrict, locale_t, const wchar_t * __restrict, + ...); +wint_t ungetwc_l(wint_t, struct __sFILE *, locale_t); +int +vfwprintf_l(struct __sFILE * __restrict, locale_t, const wchar_t * __restrict, + __va_list); +int +vswprintf_l(wchar_t * __restrict, size_t n, locale_t, + const wchar_t * __restrict, __va_list); +int vwprintf_l(locale_t, const wchar_t * __restrict, __va_list); +size_t +wcrtomb_l(char * __restrict, wchar_t, mbstate_t * __restrict, locale_t); +int wcscoll_l(const wchar_t *, const wchar_t *, locale_t); +size_t +wcsftime_l(wchar_t * __restrict, size_t, const wchar_t * __restrict, + const struct tm * __restrict, locale_t); +size_t +wcsrtombs_l(char * __restrict, const wchar_t ** __restrict, size_t, + mbstate_t * __restrict, locale_t); +double wcstod_l(const wchar_t * __restrict, wchar_t ** __restrict, locale_t); +long +wcstol_l(const wchar_t * __restrict, wchar_t ** __restrict, int, locale_t); +unsigned long +wcstoul_l(const wchar_t * __restrict, wchar_t ** __restrict, int, locale_t); +int wcswidth_l(const wchar_t *, size_t, locale_t); +size_t +wcsxfrm_l(wchar_t * __restrict, const wchar_t * __restrict, size_t, locale_t); +int wctob_l(wint_t, locale_t); +int wcwidth_l(wchar_t, locale_t); +int wprintf_l(locale_t, const wchar_t * __restrict, ...); +int wscanf_l(locale_t, const wchar_t * __restrict, ...); + +int +vfwscanf_l(struct __sFILE * __restrict, locale_t, const wchar_t * __restrict, + __va_list); +int vswscanf_l(const wchar_t * __restrict, locale_t, +const wchar_t * __restrict, __va_list); +int vwscanf_l(locale_t, const wchar_t * __restrict, __va_list); +float wcstof_l(const wchar_t * __restrict, wchar_t ** __restrict, locale_t); +long double +wcstold_l(const wchar_t * __restrict, wchar_t ** __restrict, locale_t); +long long +wcstoll_l(const wchar_t * __restrict, wchar_t ** __restrict, int, locale_t); +unsigned long long +wcstoull_l(const wchar_t * __restrict, wchar_t ** __restrict, int, locale_t); +size_t +mbsnrtowcs_l(wchar_t * __restrict, const char ** __restrict, size_t, size_t, + mbstate_t * __restrict, locale_t); +int wcscasecmp_l(const wchar_t *, const wchar_t *, locale_t); +int wcsncasecmp_l(const wchar_t *, const wchar_t *, size_t n, locale_t); +size_t +wcsnrtombs_l(char * __restrict, const wchar_t ** __restrict, size_t, size_t, + mbstate_t * __restrict, locale_t); + +#endif + +struct lconv * +localeconv_l(locale_t loc); +__END_DECLS + +#endif Index: include/locale.h =================================================================== --- include/locale.h (revision 225653) +++ include/locale.h (working copy) @@ -27,7 +27,7 @@ * SUCH DAMAGE. * * @(#)locale.h 8.1 (Berkeley) 6/2/93 - * $FreeBSD$ + * $FreeBSD: head/include/locale.h 203964 2010-02-16 19:39:50Z imp $ */ #ifndef _LOCALE_H_ @@ -79,4 +79,48 @@ char *setlocale(int, const char *); __END_DECLS +#if __POSIX_VISIBLE >= 200809 + +#define LC_COLLATE_MASK (1<<0) +#define LC_CTYPE_MASK (1<<1) +#define LC_MESSAGES_MASK (1<<2) +#define LC_MONETARY_MASK (1<<3) +#define LC_NUMERIC_MASK (1<<4) +#define LC_TIME_MASK (1<<5) +#define LC_ALL_MASK (LC_COLLATE_MASK | LC_CTYPE_MASK | LC_MESSAGES_MASK | \ + LC_MONETARY_MASK | LC_NUMERIC_MASK | LC_TIME_MASK) + +#define LC_GLOBAL_LOCALE ((locale_t)-1) + +__BEGIN_DECLS + +typedef struct _xlocale *locale_t; +/** + * Creates a new locale. + */ +locale_t newlocale(int mask, const char *locale, locale_t base); + +locale_t duplocale(locale_t base); +/* + * Free a locale_t. This is quite a poorly named function. It actually + * disclaims a reference to a locale_t, rather than freeing it. + */ +int +freelocale(locale_t loc); + +/* + * Returns the name of the locale for a particular component of a locale_t. + */ +const char *querylocale(int mask, locale_t loc); + +/* + * Installs the specified locale_t as this thread's locale. + */ +locale_t uselocale(locale_t loc); + +__END_DECLS + +#endif /* __POSIX_VISIBLE >= 200809 */ + + #endif /* _LOCALE_H_ */ Index: include/_xlocale_ctype.h =================================================================== --- include/_xlocale_ctype.h (revision 0) +++ include/_xlocale_ctype.h (revision 0) @@ -0,0 +1,160 @@ +/*- + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by David Chisnall under sponsorship from + * the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions * are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef _XLOCALE_H_ +#error This header should only be included by , never directly. +#endif + +#ifndef _XLOCALE_CTYPE_H_ +__BEGIN_DECLS +unsigned long ___runetype_l(__ct_rune_t, locale_t) __pure; +__ct_rune_t ___tolower_l(__ct_rune_t, locale_t) __pure; +__ct_rune_t ___toupper_l(__ct_rune_t, locale_t) __pure; +_RuneLocale *__runes_for_locale(locale_t, int*); +__END_DECLS +#endif + +#ifndef _XLOCALE_INLINE +# if __GNUC__ && !__GNUC_STDC_INLINE__ +# define _XLOCALE_INLINE extern inline +# else +# define _XLOCALE_INLINE inline +# endif +#endif + +#ifdef XLOCALE_WCTYPES +static __inline int +__maskrune_l(__ct_rune_t _c, unsigned long _f, locale_t locale) +{ + int mb_sb_limit; + _RuneLocale *runes = __runes_for_locale(locale, &mb_sb_limit); + return (_c < 0 || _c >= _CACHED_RUNES) ? ___runetype_l(_c, locale) : + runes->__runetype[_c] & _f; +} + +static __inline int +__istype_l(__ct_rune_t _c, unsigned long _f, locale_t locale) +{ + return (!!__maskrune_l(_c, _f, locale)); +} + +# define XLOCALE_ISCTYPE(fname, cat) \ + _XLOCALE_INLINE int isw##fname##_l(int c, locale_t l)\ + { return __istype_l(c, cat, l); } +#else +static __inline int +__sbmaskrune_l(__ct_rune_t _c, unsigned long _f, locale_t locale) +{ + int mb_sb_limit; + _RuneLocale *runes = __runes_for_locale(locale, &mb_sb_limit); + return (_c < 0 || _c >= mb_sb_limit) ? 0 : + runes->__runetype[_c] & _f; +} + +static __inline int +__sbistype_l(__ct_rune_t _c, unsigned long _f, locale_t locale) +{ + return (!!__sbmaskrune_l(_c, _f, locale)); +} + +# define XLOCALE_ISCTYPE(fname, cat) \ + _XLOCALE_INLINE int is##fname##_l(int c, locale_t l)\ + { return __sbistype_l(c, cat, l); } +#endif + +XLOCALE_ISCTYPE(alnum, _CTYPE_A|_CTYPE_D) +XLOCALE_ISCTYPE(alpha, _CTYPE_A) +XLOCALE_ISCTYPE(blank, _CTYPE_B) +XLOCALE_ISCTYPE(cntrl, _CTYPE_C) +XLOCALE_ISCTYPE(digit, _CTYPE_D) +XLOCALE_ISCTYPE(graph, _CTYPE_G) +XLOCALE_ISCTYPE(hexnumber, _CTYPE_X) +XLOCALE_ISCTYPE(ideogram, _CTYPE_I) +XLOCALE_ISCTYPE(lower, _CTYPE_L) +XLOCALE_ISCTYPE(number, _CTYPE_D) +XLOCALE_ISCTYPE(phonogram, _CTYPE_Q) +XLOCALE_ISCTYPE(print, _CTYPE_R) +XLOCALE_ISCTYPE(punct, _CTYPE_P) +XLOCALE_ISCTYPE(rune, 0xFFFFFF00L) +XLOCALE_ISCTYPE(space, _CTYPE_S) +XLOCALE_ISCTYPE(special, _CTYPE_T) +XLOCALE_ISCTYPE(upper, _CTYPE_U) +XLOCALE_ISCTYPE(xdigit, _CTYPE_X) +#undef XLOCALE_ISCTYPE + +#ifdef XLOCALE_WCTYPES +_XLOCALE_INLINE int towlower_l(int c, locale_t locale) +{ + int mb_sb_limit; + _RuneLocale *runes = __runes_for_locale(locale, &mb_sb_limit); + return (c < 0 || c >= _CACHED_RUNES) ? ___tolower_l(c, locale) : + runes->__maplower[c]; +} +_XLOCALE_INLINE int towupper_l(int c, locale_t locale) +{ + int mb_sb_limit; + _RuneLocale *runes = __runes_for_locale(locale, &mb_sb_limit); + return (c < 0 || c >= _CACHED_RUNES) ? ___toupper_l(c, locale) : + runes->__maplower[c]; +} +_XLOCALE_INLINE int +__wcwidth_l(__ct_rune_t _c, locale_t locale) +{ + unsigned int _x; + + if (_c == 0) + return (0); + _x = (unsigned int)__maskrune_l(_c, _CTYPE_SWM|_CTYPE_R, locale); + if ((_x & _CTYPE_SWM) != 0) + return ((_x & _CTYPE_SWM) >> _CTYPE_SWS); + return ((_x & _CTYPE_R) != 0 ? 1 : -1); +} +int iswctype_l(wint_t wc, wctype_t charclass, locale_t locale); +wctype_t wctype_l(const char *property, locale_t locale); +wint_t towctrans_l(wint_t wc, wctrans_t desc, locale_t locale); +wint_t nextwctype_l(wint_t wc, wctype_t wct, locale_t locale); +wctrans_t wctrans_l(const char *charclass, locale_t locale); +#undef XLOCALE_WCTYPES +#else +_XLOCALE_INLINE int digittoint_l(int c, locale_t locale) +{ return __sbmaskrune_l((c), 0xFF, locale); } + +_XLOCALE_INLINE int tolower_l(int c, locale_t locale) +{ + int mb_sb_limit; + _RuneLocale *runes = __runes_for_locale(locale, &mb_sb_limit); + return (c < 0 || c >= mb_sb_limit) ? c : + runes->__maplower[c]; +} +_XLOCALE_INLINE int toupper_l(int c, locale_t locale) +{ + int mb_sb_limit; + _RuneLocale *runes = __runes_for_locale(locale, &mb_sb_limit); + return (c < 0 || c >= mb_sb_limit) ? c : + runes->__maplower[c]; +} +#endif Index: include/string.h =================================================================== --- include/string.h (revision 225653) +++ include/string.h (working copy) @@ -27,7 +27,7 @@ * SUCH DAMAGE. * * @(#)string.h 8.1 (Berkeley) 6/2/93 - * $FreeBSD$ + * $FreeBSD: head/include/string.h 203964 2010-02-16 19:39:50Z imp $ */ #ifndef _STRING_H_ Index: include/runetype.h =================================================================== --- include/runetype.h (revision 225653) +++ include/runetype.h (working copy) @@ -30,7 +30,7 @@ * SUCH DAMAGE. * * @(#)runetype.h 8.1 (Berkeley) 6/2/93 - * $FreeBSD$ + * $FreeBSD: head/include/runetype.h 203964 2010-02-16 19:39:50Z imp $ */ #ifndef _RUNETYPE_H_ @@ -83,8 +83,14 @@ } _RuneLocale; #define _RUNE_MAGIC_1 "RuneMagi" /* Indicates version 0 of RuneLocale */ - -extern _RuneLocale _DefaultRuneLocale; +__BEGIN_DECLS +extern const _RuneLocale _DefaultRuneLocale; +__attribute__((deprecated)) extern _RuneLocale *_CurrentRuneLocale; +/* TODO: This is called quite a lot, so we should use a __thread variable when + * it's available. */ +extern _RuneLocale *__getCurrentRuneLocale(void); +#define _CurrentRuneLocale (__getCurrentRuneLocale()) +__END_DECLS #endif /* !_RUNETYPE_H_ */ Index: include/stdlib.h =================================================================== --- include/stdlib.h (revision 225653) +++ include/stdlib.h (working copy) @@ -27,7 +27,7 @@ * SUCH DAMAGE. * * @(#)stdlib.h 8.5 (Berkeley) 5/19/95 - * $FreeBSD$ + * $FreeBSD: head/include/stdlib.h 206997 2010-04-21 16:38:37Z kib $ */ #ifndef _STDLIB_H_ @@ -71,10 +71,11 @@ #define RAND_MAX 0x7fffffff +__BEGIN_DECLS extern int __mb_cur_max; -#define MB_CUR_MAX __mb_cur_max +extern int ___mb_cur_max(void); +#define MB_CUR_MAX (___mb_cur_max()) -__BEGIN_DECLS void abort(void) __dead2; int abs(int) __pure2; int atexit(void (*)(void)); Index: include/_ctype.h =================================================================== --- include/_ctype.h (revision 225653) +++ include/_ctype.h (working copy) @@ -36,7 +36,7 @@ * * From @(#)ctype.h 8.4 (Berkeley) 1/21/94 * From FreeBSD: src/include/ctype.h,v 1.27 2004/06/23 07:11:39 tjr Exp - * $FreeBSD$ + * $FreeBSD: head/include/_ctype.h 203964 2010-02-16 19:39:50Z imp $ */ #ifndef __CTYPE_H_ Index: contrib/gdtoa/gdtoaimp.h =================================================================== --- contrib/gdtoa/gdtoaimp.h (revision 225653) +++ contrib/gdtoa/gdtoaimp.h (working copy) @@ -26,7 +26,7 @@ ****************************************************************/ -/* $FreeBSD$ */ +/* $FreeBSD: head/contrib/gdtoa/gdtoaimp.h 219557 2011-03-12 07:03:06Z das $ */ /* This is a variation on dtoa.c that converts arbitary binary floating-point formats to and from decimal notation. It uses @@ -201,6 +201,7 @@ #include "namespace.h" #include #include "un-namespace.h" +#include "xlocale_private.h" #ifdef KR_headers #define Char char @@ -526,10 +527,13 @@ #define strtoIx __strtoIx #define strtoIxL __strtoIxL #define strtord __strtord +#define strtord_l __strtord_l #define strtordd __strtordd #define strtorf __strtorf #define strtorQ __strtorQ +#define strtorQ_l __strtorQ_l #define strtorx __strtorx +#define strtorx_l __strtorx_l #define strtorxL __strtorxL #define strtodI __strtodI #define strtopd __strtopd @@ -635,6 +639,7 @@ extern Bigint *set_ones ANSI((Bigint*, int)); extern char *strcp ANSI((char*, const char*)); extern int strtodg ANSI((CONST char*, char**, FPI*, Long*, ULong*)); + extern int strtodg_l ANSI((CONST char*, char**, FPI*, Long*, ULong*, locale_t)); extern int strtoId ANSI((CONST char *, char **, double *, double *)); extern int strtoIdd ANSI((CONST char *, char **, double *, double *)); @@ -644,6 +649,7 @@ extern int strtoIx ANSI((CONST char *, char **, void *, void *)); extern int strtoIxL ANSI((CONST char *, char **, void *, void *)); extern double strtod ANSI((const char *s00, char **se)); + extern double strtod_l ANSI((const char *s00, char **se, locale_t)); extern int strtopQ ANSI((CONST char *, char **, Void *)); extern int strtopf ANSI((CONST char *, char **, float *)); extern int strtopd ANSI((CONST char *, char **, double *)); @@ -651,10 +657,13 @@ extern int strtopx ANSI((CONST char *, char **, Void *)); extern int strtopxL ANSI((CONST char *, char **, Void *)); extern int strtord ANSI((CONST char *, char **, int, double *)); + extern int strtord_l ANSI((CONST char *, char **, int, double *, locale_t)); extern int strtordd ANSI((CONST char *, char **, int, double *)); extern int strtorf ANSI((CONST char *, char **, int, float *)); extern int strtorQ ANSI((CONST char *, char **, int, void *)); + extern int strtorQ_l ANSI((CONST char *, char **, int, void *, locale_t)); extern int strtorx ANSI((CONST char *, char **, int, void *)); + extern int strtorx_l ANSI((CONST char *, char **, int, void *, locale_t)); extern int strtorxL ANSI((CONST char *, char **, int, void *)); extern Bigint *sum ANSI((Bigint*, Bigint*)); extern int trailz ANSI((Bigint*)); Index: contrib/gdtoa/strtopQ.c =================================================================== --- contrib/gdtoa/strtopQ.c (revision 225653) +++ contrib/gdtoa/strtopQ.c (working copy) @@ -56,7 +56,7 @@ strtopQ(CONST char *s, char **sp, void *V) #endif { - static FPI fpi0 = { 113, 1-16383-113+1, 32766 - 16383 - 113 + 1, 1, SI }; + static const FPI fpi0 = { 113, 1-16383-113+1, 32766 - 16383 - 113 + 1, 1, SI }; ULong bits[4]; Long exp; int k; Index: contrib/gdtoa/strtorQ.c =================================================================== --- contrib/gdtoa/strtorQ.c (revision 225653) +++ contrib/gdtoa/strtorQ.c (working copy) @@ -29,7 +29,7 @@ /* Please send bug reports to David M. Gay (dmg at acm dot org, * with " at " changed at "@" and " dot " changed to "."). */ -/* $FreeBSD$ */ +/* $FreeBSD: head/contrib/gdtoa/strtorQ.c 174690 2007-12-16 23:31:55Z das $ */ #include "gdtoaimp.h" @@ -103,9 +103,10 @@ int #ifdef KR_headers -strtorQ(s, sp, rounding, L) CONST char *s; char **sp; int rounding; void *L; +strtorQ_l(s, sp, rounding, L, locale) CONST char *s; char **sp; int rounding; +void *L; locale_t locale; #else -strtorQ(CONST char *s, char **sp, int rounding, void *L) +strtorQ_l(CONST char *s, char **sp, int rounding, void *L, locale_t locale) #endif { static FPI fpi0 = { 113, 1-16383-113+1, 32766-16383-113+1, 1, SI }; @@ -120,7 +121,17 @@ fpi1.rounding = rounding; fpi = &fpi1; } - k = strtodg(s, sp, fpi, &exp, bits); + k = strtodg_l(s, sp, fpi, &exp, bits, locale); ULtoQ((ULong*)L, bits, exp, k); return k; } + + int +#ifdef KR_headers +strtorQ(s, sp, rounding, L) CONST char *s; char **sp; int rounding; void *L; +#else +strtorQ(CONST char *s, char **sp, int rounding, void *L) +#endif +{ + return strtorQ_l(s, sp, rounding, L, __get_locale()); +} Index: contrib/gdtoa/strtodg.c =================================================================== --- contrib/gdtoa/strtodg.c (revision 225653) +++ contrib/gdtoa/strtodg.c (working copy) @@ -34,6 +34,7 @@ #ifdef USE_LOCALE #include "locale.h" #endif +#include "xlocale_private.h" static CONST int fivesbits[] = { 0, 3, 5, 7, 10, 12, 14, 17, 19, 21, @@ -313,12 +314,12 @@ } int -strtodg +strtodg_l #ifdef KR_headers - (s00, se, fpi, exp, bits) - CONST char *s00; char **se; FPI *fpi; Long *exp; ULong *bits; + (s00, se, fpi, exp, bits, l) + CONST char *s00; char **se; FPI *fpi; Long *exp; ULong *bits; locale_t l; #else - (CONST char *s00, char **se, FPI *fpi, Long *exp, ULong *bits) + (CONST char *s00, char **se, FPI *fpi, Long *exp, ULong *bits, locale_t l) #endif { int abe, abits, asub; @@ -334,14 +335,14 @@ Bigint *ab, *bb, *bb1, *bd, *bd0, *bs, *delta, *rvb, *rvb0; #ifdef USE_LOCALE /*{{*/ #ifdef NO_LOCALE_CACHE - char *decimalpoint = localeconv()->decimal_point; + char *decimalpoint = localeconv_l(l)->decimal_point; int dplen = strlen(decimalpoint); #else char *decimalpoint; static char *decimalpoint_cache; static int dplen; if (!(s0 = decimalpoint_cache)) { - s0 = localeconv()->decimal_point; + s0 = localeconv_l(l)->decimal_point; if ((decimalpoint_cache = (char*)MALLOC(strlen(s0) + 1))) { strcpy(decimalpoint_cache, s0); s0 = decimalpoint_cache; @@ -1063,3 +1064,15 @@ } return irv; } + + int +strtodg +#ifdef KR_headers + (s00, se, fpi, exp, bits) + CONST char *s00; char **se; FPI *fpi; Long *exp; ULong *bits; +#else + (CONST char *s00, char **se, FPI *fpi, Long *exp, ULong *bits) +#endif +{ + return strtodg_l(s00, se, fpi, exp, bits, __get_locale()); +} Index: contrib/gdtoa/strtord.c =================================================================== --- contrib/gdtoa/strtord.c (revision 225653) +++ contrib/gdtoa/strtord.c (working copy) @@ -70,9 +70,10 @@ int #ifdef KR_headers -strtord(s, sp, rounding, d) CONST char *s; char **sp; int rounding; double *d; +strtord_l(s, sp, rounding, d, locale) CONST char *s; char **sp; int rounding; +double *d; locale_t locale; #else -strtord(CONST char *s, char **sp, int rounding, double *d) +strtord_l(CONST char *s, char **sp, int rounding, double *d, locale_t locale) #endif { static FPI fpi0 = { 53, 1-1023-53+1, 2046-1023-53+1, 1, SI }; @@ -87,7 +88,17 @@ fpi1.rounding = rounding; fpi = &fpi1; } - k = strtodg(s, sp, fpi, &exp, bits); + k = strtodg_l(s, sp, fpi, &exp, bits, locale); ULtod((ULong*)d, bits, exp, k); return k; } + int +#ifdef KR_headers +strtord(s, sp, rounding, L, locale) CONST char *s; char **sp; int rounding; +void *L; +#else +strtord(CONST char *s, char **sp, int rounding, double *d) +#endif +{ + return strtord_l(s, sp, rounding, d, __get_locale()); +} Index: contrib/gdtoa/strtod.c =================================================================== --- contrib/gdtoa/strtod.c (revision 225653) +++ contrib/gdtoa/strtod.c (working copy) @@ -29,7 +29,7 @@ /* Please send bug reports to David M. Gay (dmg at acm dot org, * with " at " changed at "@" and " dot " changed to "."). */ -/* $FreeBSD$ */ +/* $FreeBSD: head/contrib/gdtoa/strtod.c 219557 2011-03-12 07:03:06Z das $ */ #include "gdtoaimp.h" #ifndef NO_FENV_H @@ -39,6 +39,7 @@ #ifdef USE_LOCALE #include "locale.h" #endif +#include "xlocale_private.h" #ifdef IEEE_Arith #ifndef NO_IEEE_Scale @@ -82,11 +83,11 @@ #endif /*}*/ double -strtod +strtod_l #ifdef KR_headers - (s00, se) CONST char *s00; char **se; + (s00, se, l) CONST char *s00; char **se; locale_t l #else - (CONST char *s00, char **se) + (CONST char *s00, char **se, locale_t l) #endif { #ifdef Avoid_Underflow @@ -108,14 +109,14 @@ #endif #ifdef USE_LOCALE /*{{*/ #ifdef NO_LOCALE_CACHE - char *decimalpoint = localeconv()->decimal_point; + char *decimalpoint = localeconv_l(l)->decimal_point; int dplen = strlen(decimalpoint); #else char *decimalpoint; static char *decimalpoint_cache; static int dplen; if (!(s0 = decimalpoint_cache)) { - s0 = localeconv()->decimal_point; + s0 = localeconv_l(l)->decimal_point; if ((decimalpoint_cache = (char*)MALLOC(strlen(s0) + 1))) { strcpy(decimalpoint_cache, s0); s0 = decimalpoint_cache; @@ -168,7 +169,7 @@ if (*s == '0') { #ifndef NO_HEX_FP /*{*/ { - static FPI fpi = { 53, 1-1023-53+1, 2046-1023-53+1, 1, SI }; + static const FPI fpi = { 53, 1-1023-53+1, 2046-1023-53+1, 1, SI }; Long exp; ULong bits[2]; switch(s[1]) { @@ -295,7 +296,7 @@ #ifdef INFNAN_CHECK /* Check for Nan and Infinity */ ULong bits[2]; - static FPI fpinan = /* only 52 explicit bits */ + static const FPI fpinan = /* only 52 explicit bits */ { 52, 1-1023-53+1, 2046-1023-53+1, 1, SI }; if (!decpt) switch(c) { @@ -1074,3 +1075,13 @@ return sign ? -dval(&rv) : dval(&rv); } + double +strtod +#ifdef KR_headers + (s00, se, l) CONST char *s00; char **se; locale_t +#else + (CONST char *s00, char **se) +#endif +{ + return strtod_l(s00, se, __get_locale()); +} Index: contrib/gdtoa/strtof.c =================================================================== --- contrib/gdtoa/strtof.c (revision 225653) +++ contrib/gdtoa/strtof.c (working copy) @@ -29,18 +29,19 @@ /* Please send bug reports to David M. Gay (dmg at acm dot org, * with " at " changed at "@" and " dot " changed to "."). */ -/* $FreeBSD$ */ +/* $FreeBSD: head/contrib/gdtoa/strtof.c 219557 2011-03-12 07:03:06Z das $ */ #include "gdtoaimp.h" +#include "xlocale_private.h" float #ifdef KR_headers -strtof(s, sp) CONST char *s; char **sp; +strtof_l(s, sp, l) CONST char *s; char **sp; locale_t l; #else -strtof(CONST char *s, char **sp) +strtof_l(CONST char *s, char **sp, locale_t l) #endif { - static FPI fpi0 = { 24, 1-127-24+1, 254-127-24+1, 1, SI }; + static const FPI fpi0 = { 24, 1-127-24+1, 254-127-24+1, 1, SI }; ULong bits[1]; Long exp; int k; @@ -51,7 +52,7 @@ #define fpi &fpi0 #endif - k = strtodg(s, sp, fpi, &exp, bits); + k = strtodg_l(s, sp, fpi, &exp, bits, l); switch(k & STRTOG_Retmask) { case STRTOG_NoNumber: case STRTOG_Zero: @@ -82,3 +83,13 @@ u.L[0] |= 0x80000000L; return u.f; } + + float +#ifdef KR_headers +strtof(s, sp) CONST char *s; char **sp; +#else +strtof(CONST char *s, char **sp) +#endif +{ + return strtof_l(s, sp, __get_locale()); +} Index: contrib/gdtoa/strtorx.c =================================================================== --- contrib/gdtoa/strtorx.c (revision 225653) +++ contrib/gdtoa/strtorx.c (working copy) @@ -29,7 +29,7 @@ /* Please send bug reports to David M. Gay (dmg at acm dot org, * with " at " changed at "@" and " dot " changed to "."). */ -/* $FreeBSD$ */ +/* $FreeBSD: head/contrib/gdtoa/strtorx.c 219557 2011-03-12 07:03:06Z das $ */ #include "gdtoaimp.h" @@ -106,9 +106,10 @@ int #ifdef KR_headers -strtorx(s, sp, rounding, L) CONST char *s; char **sp; int rounding; void *L; +strtorx_l(s, sp, rounding, L, locale) CONST char *s; char **sp; int rounding; +void *L; locale_t locale; #else -strtorx(CONST char *s, char **sp, int rounding, void *L) +strtorx_l(CONST char *s, char **sp, int rounding, void *L, locale_t locale) #endif { static FPI fpi0 = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, SI }; @@ -123,7 +124,16 @@ fpi1.rounding = rounding; fpi = &fpi1; } - k = strtodg(s, sp, fpi, &exp, bits); + k = strtodg_l(s, sp, fpi, &exp, bits, locale); ULtox((UShort*)L, bits, exp, k); return k; } + int +#ifdef KR_headers +strtorx(s, sp, rounding, L) CONST char *s; char **sp; int rounding; void *L; +#else +strtorx(CONST char *s, char **sp, int rounding, void *L) +#endif +{ + return strtorx_l(s, sp, rounding, L, __get_locale()); +} Index: lib/msun/src/math.h =================================================================== --- lib/msun/src/math.h (revision 225653) +++ lib/msun/src/math.h (working copy) @@ -398,32 +398,32 @@ * long double versions of ISO/POSIX math functions */ #if __ISO_C_VISIBLE >= 1999 -#if 0 +#if !__NO_IMPRECISE_LIBM_FUNCTIONS long double acoshl(long double); #endif long double acosl(long double); -#if 0 +#if !__NO_IMPRECISE_LIBM_FUNCTIONS long double asinhl(long double); #endif long double asinl(long double); long double atan2l(long double, long double); -#if 0 +#if !__NO_IMPRECISE_LIBM_FUNCTIONS long double atanhl(long double); #endif long double atanl(long double); long double cbrtl(long double); long double ceill(long double); long double copysignl(long double, long double) __pure2; -#if 0 +#if !__NO_IMPRECISE_LIBM_FUNCTIONS long double coshl(long double); #endif long double cosl(long double); -#if 0 +#if !__NO_IMPRECISE_LIBM_FUNCTIONS long double erfcl(long double); long double erfl(long double); #endif long double exp2l(long double); -#if 0 +#if !__NO_IMPRECISE_LIBM_FUNCTIONS long double expl(long double); long double expm1l(long double); #endif @@ -438,18 +438,18 @@ long double hypotl(long double, long double); int ilogbl(long double) __pure2; long double ldexpl(long double, int); -#if 0 +#if !__NO_IMPRECISE_LIBM_FUNCTIONS long double lgammal(long double); #endif long long llrintl(long double); long long llroundl(long double); -#if 0 +#if !__NO_IMPRECISE_LIBM_FUNCTIONS long double log10l(long double); long double log1pl(long double); long double log2l(long double); #endif long double logbl(long double); -#if 0 +#if !__NO_IMPRECISE_LIBM_FUNCTIONS long double logl(long double); #endif long lrintl(long double); @@ -461,7 +461,7 @@ double nexttoward(double, long double); float nexttowardf(float, long double); long double nexttowardl(long double, long double); -#if 0 +#if !__NO_IMPRECISE_LIBM_FUNCTIONS long double powl(long double, long double); #endif long double remainderl(long double, long double); @@ -470,16 +470,16 @@ long double roundl(long double); long double scalblnl(long double, long); long double scalbnl(long double, int); -#if 0 +#if !__NO_IMPRECISE_LIBM_FUNCTIONS long double sinhl(long double); #endif long double sinl(long double); long double sqrtl(long double); -#if 0 +#if !__NO_IMPRECISE_LIBM_FUNCTIONS long double tanhl(long double); #endif long double tanl(long double); -#if 0 +#if !__NO_IMPRECISE_LIBM_FUNCTIONS long double tgammal(long double); #endif long double truncl(long double); Index: lib/msun/src/stubs.c =================================================================== --- lib/msun/src/stubs.c (revision 0) +++ lib/msun/src/stubs.c (revision 0) @@ -0,0 +1,22 @@ +#include + +#define LIBCXX_LONG_DOUBLE_STUB(fn) __attribute__((weak)) long double fn ## l(long double x) { return fn(x); } +#define LIBCXX_LONG_DOUBLE_STUB2(fn) __attribute__((weak)) long double fn ## l(long double x, long double y) { return fn(x, y); } + +LIBCXX_LONG_DOUBLE_STUB(cosh) +LIBCXX_LONG_DOUBLE_STUB(asinh) +LIBCXX_LONG_DOUBLE_STUB(atanh) +LIBCXX_LONG_DOUBLE_STUB(acosh) +LIBCXX_LONG_DOUBLE_STUB(erfc) +LIBCXX_LONG_DOUBLE_STUB(erf) +LIBCXX_LONG_DOUBLE_STUB(exp) +LIBCXX_LONG_DOUBLE_STUB(expm1) +LIBCXX_LONG_DOUBLE_STUB(lgamma) +LIBCXX_LONG_DOUBLE_STUB(log10) +LIBCXX_LONG_DOUBLE_STUB(log1p) +LIBCXX_LONG_DOUBLE_STUB(log2) +LIBCXX_LONG_DOUBLE_STUB(log) +LIBCXX_LONG_DOUBLE_STUB(tanh) +LIBCXX_LONG_DOUBLE_STUB(sinh) +LIBCXX_LONG_DOUBLE_STUB(tgamma) +LIBCXX_LONG_DOUBLE_STUB2(pow) Index: lib/msun/Makefile =================================================================== --- lib/msun/Makefile (revision 225653) +++ lib/msun/Makefile (working copy) @@ -1,5 +1,5 @@ # @(#)Makefile 5.1beta 93/09/24 -# $FreeBSD$ +# $FreeBSD: head/lib/msun/Makefile 219576 2011-03-12 19:37:35Z kargl $ # # ==================================================== # Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. @@ -70,7 +70,7 @@ s_scalbln.c s_scalbn.c s_scalbnf.c s_signbit.c \ s_signgam.c s_significand.c s_significandf.c s_sin.c s_sinf.c \ s_tan.c s_tanf.c s_tanh.c s_tanhf.c s_tgammaf.c s_trunc.c s_truncf.c \ - w_cabs.c w_cabsf.c w_drem.c w_dremf.c + w_cabs.c w_cabsf.c w_drem.c w_dremf.c stubs.c # Location of fpmath.h and _fpmath.h LIBCDIR= ${.CURDIR}/../libc Index: lib/libc/stdlib/Symbol.map =================================================================== --- lib/libc/stdlib/Symbol.map (revision 225653) +++ lib/libc/stdlib/Symbol.map (working copy) @@ -1,5 +1,5 @@ /* - * $FreeBSD$ + * $FreeBSD: head/lib/libc/stdlib/Symbol.map 182225 2008-08-27 02:00:53Z jasone $ */ FBSD_1.0 { @@ -90,6 +90,21 @@ tfind; tsearch; twalk; + atof_l; + atoi_l; + atol_l; + atoll_l; + strtod_l; + strtol_l; + strtoll_l; + strtof_l; + strtoimax_l; + strtold_l; + strtoq_l; + strtoul_l; + strtoull_l; + strtoumax_l; + strtouq_l; }; FBSDprivate_1.0 { Index: lib/libc/stdlib/atoll.c =================================================================== --- lib/libc/stdlib/atoll.c (revision 225653) +++ lib/libc/stdlib/atoll.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -28,9 +33,10 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdlib/atoll.c 165903 2007-01-09 00:28:16Z imp $"); #include +#include long long atoll(str) @@ -38,3 +44,11 @@ { return strtoll(str, (char **)NULL, 10); } + +long long +atoll_l(str, locale) + const char *str; + locale_t locale; +{ + return strtoll_l(str, (char **)NULL, 10, locale); +} Index: lib/libc/stdlib/strfmon.c =================================================================== --- lib/libc/stdlib/strfmon.c (revision 225653) +++ lib/libc/stdlib/strfmon.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2001 Alexey Zelkin * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -26,7 +31,7 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdlib/strfmon.c 203734 2010-02-10 00:02:09Z cracauer $"); #include #include @@ -38,6 +43,7 @@ #include #include #include +#include "xlocale_private.h" /* internal flags */ #define NEED_GROUPING 0x01 /* print digits grouped (default) */ @@ -92,11 +98,10 @@ static int __calc_left_pad(int, char *); static char *__format_grouped_double(double, int *, int, int, int); -ssize_t -strfmon(char * __restrict s, size_t maxsize, const char * __restrict format, - ...) +static ssize_t +vstrfmon_l(char * __restrict s, size_t maxsize, locale_t loc, + const char * __restrict format, va_list ap) { - va_list ap; char *dst; /* output destination pointer */ const char *fmt; /* current format poistion pointer */ struct lconv *lc; /* pointer to lconv structure */ @@ -119,10 +124,10 @@ char *tmpptr; /* temporary vars */ int sverrno; + FIX_LOCALE(loc); - va_start(ap, format); - lc = localeconv(); + lc = localeconv_l(loc); dst = s; fmt = format; asciivalue = NULL; @@ -380,7 +385,6 @@ } PRINT('\0'); - va_end(ap); free(asciivalue); free(currency_symbol); return (dst - s - 1); /* return size of put data except trailing '\0' */ @@ -399,10 +403,34 @@ if (currency_symbol != NULL) free(currency_symbol); errno = sverrno; - va_end(ap); return (-1); } +ssize_t +strfmon_l(char * __restrict s, size_t maxsize, locale_t loc, const char * __restrict format, + ...) +{ + size_t ret; + va_list ap; + FIX_LOCALE(loc); + va_start(ap, format); + ret = vstrfmon_l(s, maxsize, loc, format, ap); + va_end(ap); + return ret; +} +ssize_t +strfmon(char * __restrict s, size_t maxsize, const char * __restrict format, + ...) +{ + size_t ret; + va_list ap; + va_start(ap, format); + ret = vstrfmon_l(s, maxsize, __get_locale(), format, ap); + va_end(ap); + return ret; +} + + static void __setup_vars(int flags, char *cs_precedes, char *sep_by_space, char *sign_posn, char **signstr) { Index: lib/libc/stdlib/atof.c =================================================================== --- lib/libc/stdlib/atof.c (revision 225653) +++ lib/libc/stdlib/atof.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -31,9 +36,10 @@ static char sccsid[] = "@(#)atof.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdlib/atof.c 165903 2007-01-09 00:28:16Z imp $"); #include +#include double atof(ascii) @@ -41,3 +47,11 @@ { return strtod(ascii, (char **)NULL); } + +double +atof_l(ascii, locale) + const char *ascii; + locale_t locale; +{ + return strtod_l(ascii, (char **)NULL, locale); +} Index: lib/libc/stdlib/strtoimax.c =================================================================== --- lib/libc/stdlib/strtoimax.c (revision 225653) +++ lib/libc/stdlib/strtoimax.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -31,12 +36,13 @@ static char sccsid[] = "from @(#)strtol.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdlib/strtoimax.c 165903 2007-01-09 00:28:16Z imp $"); #include #include #include #include +#include "xlocale_private.h" /* * Convert a string to an intmax_t integer. @@ -45,13 +51,15 @@ * alphabets and digits are each contiguous. */ intmax_t -strtoimax(const char * __restrict nptr, char ** __restrict endptr, int base) +strtoimax_l(const char * __restrict nptr, char ** __restrict endptr, int base, + locale_t locale) { const char *s; uintmax_t acc; char c; uintmax_t cutoff; int neg, any, cutlim; + FIX_LOCALE(locale); /* * Skip white space and pick up leading +/- sign if any. @@ -61,7 +69,7 @@ s = nptr; do { c = *s++; - } while (isspace((unsigned char)c)); + } while (isspace_l((unsigned char)c, locale)); if (c == '-') { neg = 1; c = *s++; @@ -138,3 +146,8 @@ *endptr = (char *)(any ? s - 1 : nptr); return (acc); } +intmax_t +strtoimax(const char * __restrict nptr, char ** __restrict endptr, int base) +{ + return strtoimax_l(nptr, endptr, base, __get_locale()); +} Index: lib/libc/stdlib/atol.c =================================================================== --- lib/libc/stdlib/atol.c (revision 225653) +++ lib/libc/stdlib/atol.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -31,9 +36,10 @@ static char sccsid[] = "@(#)atol.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdlib/atol.c 165903 2007-01-09 00:28:16Z imp $"); #include +#include long atol(str) @@ -41,3 +47,11 @@ { return strtol(str, (char **)NULL, 10); } + +long +atol_l(str, locale) + const char *str; + locale_t locale; +{ + return strtol_l(str, (char **)NULL, 10, locale); +} Index: lib/libc/stdlib/strtoumax.c =================================================================== --- lib/libc/stdlib/strtoumax.c (revision 225653) +++ lib/libc/stdlib/strtoumax.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -31,12 +36,13 @@ static char sccsid[] = "from @(#)strtoul.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdlib/strtoumax.c 165903 2007-01-09 00:28:16Z imp $"); #include #include #include #include +#include "xlocale_private.h" /* * Convert a string to a uintmax_t integer. @@ -45,13 +51,15 @@ * alphabets and digits are each contiguous. */ uintmax_t -strtoumax(const char * __restrict nptr, char ** __restrict endptr, int base) +strtoumax_l(const char * __restrict nptr, char ** __restrict endptr, int base, + locale_t locale) { const char *s; uintmax_t acc; char c; uintmax_t cutoff; int neg, any, cutlim; + FIX_LOCALE(locale); /* * See strtoimax for comments as to the logic used. @@ -59,7 +67,7 @@ s = nptr; do { c = *s++; - } while (isspace((unsigned char)c)); + } while (isspace_l((unsigned char)c, locale)); if (c == '-') { neg = 1; c = *s++; @@ -116,3 +124,8 @@ *endptr = (char *)(any ? s - 1 : nptr); return (acc); } +uintmax_t +strtoumax(const char * __restrict nptr, char ** __restrict endptr, int base) +{ + return strtoumax_l(nptr, endptr, base, __get_locale()); +} Index: lib/libc/stdlib/strtoul.c =================================================================== --- lib/libc/stdlib/strtoul.c (revision 225653) +++ lib/libc/stdlib/strtoul.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -31,12 +36,13 @@ static char sccsid[] = "@(#)strtoul.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdlib/strtoul.c 165903 2007-01-09 00:28:16Z imp $"); #include #include #include #include +#include "xlocale_private.h" /* * Convert a string to an unsigned long integer. @@ -45,13 +51,14 @@ * alphabets and digits are each contiguous. */ unsigned long -strtoul(const char * __restrict nptr, char ** __restrict endptr, int base) +strtoul_l(const char * __restrict nptr, char ** __restrict endptr, int base, locale_t locale) { const char *s; unsigned long acc; char c; unsigned long cutoff; int neg, any, cutlim; + FIX_LOCALE(locale); /* * See strtol for comments as to the logic used. @@ -59,7 +66,7 @@ s = nptr; do { c = *s++; - } while (isspace((unsigned char)c)); + } while (isspace_l((unsigned char)c, locale)); if (c == '-') { neg = 1; c = *s++; @@ -116,3 +123,8 @@ *endptr = (char *)(any ? s - 1 : nptr); return (acc); } +unsigned long +strtoul(const char * __restrict nptr, char ** __restrict endptr, int base) +{ + return strtoul_l(nptr, endptr, base, __get_locale()); +} Index: lib/libc/stdlib/strtoull.c =================================================================== --- lib/libc/stdlib/strtoull.c (revision 225653) +++ lib/libc/stdlib/strtoull.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -31,12 +36,13 @@ static char sccsid[] = "@(#)strtouq.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdlib/strtoull.c 165903 2007-01-09 00:28:16Z imp $"); #include #include #include #include +#include "xlocale_private.h" /* * Convert a string to an unsigned long long integer. @@ -45,13 +51,15 @@ * alphabets and digits are each contiguous. */ unsigned long long -strtoull(const char * __restrict nptr, char ** __restrict endptr, int base) +strtoull_l(const char * __restrict nptr, char ** __restrict endptr, int base, + locale_t locale) { const char *s; unsigned long long acc; char c; unsigned long long cutoff; int neg, any, cutlim; + FIX_LOCALE(locale); /* * See strtoq for comments as to the logic used. @@ -59,7 +67,7 @@ s = nptr; do { c = *s++; - } while (isspace((unsigned char)c)); + } while (isspace_l((unsigned char)c, locale)); if (c == '-') { neg = 1; c = *s++; @@ -116,3 +124,8 @@ *endptr = (char *)(any ? s - 1 : nptr); return (acc); } +unsigned long long +strtoull(const char * __restrict nptr, char ** __restrict endptr, int base) +{ + return strtoull_l(nptr, endptr, base, __get_locale()); +} Index: lib/libc/stdlib/strtoll.c =================================================================== --- lib/libc/stdlib/strtoll.c (revision 225653) +++ lib/libc/stdlib/strtoll.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -31,12 +36,13 @@ static char sccsid[] = "@(#)strtoq.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdlib/strtoll.c 165903 2007-01-09 00:28:16Z imp $"); #include #include #include #include +#include /* * Convert a string to a long long integer. @@ -45,13 +51,15 @@ * alphabets and digits are each contiguous. */ long long -strtoll(const char * __restrict nptr, char ** __restrict endptr, int base) +strtoll_l(const char * __restrict nptr, char ** __restrict endptr, int base, + locale_t locale) { const char *s; unsigned long long acc; char c; unsigned long long cutoff; int neg, any, cutlim; + FIX_LOCALE(locale); /* * Skip white space and pick up leading +/- sign if any. @@ -61,7 +69,7 @@ s = nptr; do { c = *s++; - } while (isspace((unsigned char)c)); + } while (isspace_l((unsigned char)c, locale)); if (c == '-') { neg = 1; c = *s++; @@ -138,3 +146,8 @@ *endptr = (char *)(any ? s - 1 : nptr); return (acc); } +long long +strtoll(const char * __restrict nptr, char ** __restrict endptr, int base) +{ + return strtoll_l(nptr, endptr, base, __get_locale()); +} Index: lib/libc/stdlib/strtol.c =================================================================== --- lib/libc/stdlib/strtol.c (revision 225653) +++ lib/libc/stdlib/strtol.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -31,12 +36,13 @@ static char sccsid[] = "@(#)strtol.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdlib/strtol.c 165903 2007-01-09 00:28:16Z imp $"); #include #include #include #include +#include "xlocale_private.h" /* @@ -46,13 +52,15 @@ * alphabets and digits are each contiguous. */ long -strtol(const char * __restrict nptr, char ** __restrict endptr, int base) +strtol_l(const char * __restrict nptr, char ** __restrict endptr, int base, + locale_t locale) { const char *s; unsigned long acc; char c; unsigned long cutoff; int neg, any, cutlim; + FIX_LOCALE(locale); /* * Skip white space and pick up leading +/- sign if any. @@ -62,7 +70,7 @@ s = nptr; do { c = *s++; - } while (isspace((unsigned char)c)); + } while (isspace_l((unsigned char)c, locale)); if (c == '-') { neg = 1; c = *s++; @@ -138,3 +146,13 @@ *endptr = (char *)(any ? s - 1 : nptr); return (acc); } +long +strtol(const char * __restrict nptr, char ** __restrict endptr, int base) +{ + return strtol_l(nptr, endptr, base, __get_locale()); +} +long double +strtold(const char * __restrict nptr, char ** __restrict endptr) +{ + return strtold_l(nptr, endptr, __get_locale()); +} Index: lib/libc/stdlib/atoi.c =================================================================== --- lib/libc/stdlib/atoi.c (revision 225653) +++ lib/libc/stdlib/atoi.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -31,9 +36,10 @@ static char sccsid[] = "@(#)atoi.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdlib/atoi.c 165903 2007-01-09 00:28:16Z imp $"); #include +#include int atoi(str) @@ -41,3 +47,11 @@ { return (int)strtol(str, (char **)NULL, 10); } + +int +atoi_l(str, locale) + const char *str; + locale_t locale; +{ + return (int)strtol_l(str, (char **)NULL, 10, locale); +} Index: lib/libc/stdio/tempnam.c =================================================================== --- lib/libc/stdio/tempnam.c (revision 225653) +++ lib/libc/stdio/tempnam.c (working copy) @@ -31,7 +31,7 @@ static char sccsid[] = "@(#)tempnam.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/tempnam.c 165903 2007-01-09 00:28:16Z imp $"); #include #include Index: lib/libc/stdio/putwc.c =================================================================== --- lib/libc/stdio/putwc.c (revision 225653) +++ lib/libc/stdio/putwc.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -25,7 +30,7 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/putwc.c 129705 2004-05-25 10:42:52Z tjr $"); #include "namespace.h" #include @@ -33,6 +38,7 @@ #include "un-namespace.h" #include "libc_private.h" #include "local.h" +#include "xlocale_private.h" #undef putwc @@ -41,8 +47,13 @@ * macro, may evaluate `fp' more than once. */ wint_t +putwc_l(wchar_t wc, FILE *fp, locale_t locale) +{ + FIX_LOCALE(locale); + return (fputwc_l(wc, fp, locale)); +} +wint_t putwc(wchar_t wc, FILE *fp) { - - return (fputwc(wc, fp)); + return putwc_l(wc, fp, __get_locale()); } Index: lib/libc/stdio/printf.c =================================================================== --- lib/libc/stdio/printf.c (revision 225653) +++ lib/libc/stdio/printf.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Chris Torek. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -34,10 +39,11 @@ static char sccsid[] = "@(#)printf.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/printf.c 165903 2007-01-09 00:28:16Z imp $"); #include #include +#include int printf(char const * __restrict fmt, ...) @@ -50,3 +56,14 @@ va_end(ap); return (ret); } +int +printf_l(locale_t locale, char const * __restrict fmt, ...) +{ + int ret; + va_list ap; + + va_start(ap, fmt); + ret = vfprintf_l(stdout, locale, fmt, ap); + va_end(ap); + return (ret); +} Index: lib/libc/stdio/getwchar.c =================================================================== --- lib/libc/stdio/getwchar.c (revision 225653) +++ lib/libc/stdio/getwchar.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -25,11 +30,12 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/getwchar.c 129705 2004-05-25 10:42:52Z tjr $"); #include "namespace.h" #include #include +#include #include "un-namespace.h" #include "libc_private.h" #include "local.h" @@ -42,6 +48,10 @@ wint_t getwchar(void) { - return (fgetwc(stdin)); } +wint_t +getwchar_l(locale_t locale) +{ + return (fgetwc_l(stdin, locale)); +} Index: lib/libc/stdio/fwalk.c =================================================================== --- lib/libc/stdio/fwalk.c (revision 225653) +++ lib/libc/stdio/fwalk.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)fwalk.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/fwalk.c 165903 2007-01-09 00:28:16Z imp $"); #include #include Index: lib/libc/stdio/fgetpos.c =================================================================== --- lib/libc/stdio/fgetpos.c (revision 225653) +++ lib/libc/stdio/fgetpos.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)fgetpos.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/fgetpos.c 165903 2007-01-09 00:28:16Z imp $"); #include Index: lib/libc/stdio/fgets.c =================================================================== --- lib/libc/stdio/fgets.c (revision 225653) +++ lib/libc/stdio/fgets.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)fgets.c 8.2 (Berkeley) 12/22/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/fgets.c 165903 2007-01-09 00:28:16Z imp $"); #include "namespace.h" #include Index: lib/libc/stdio/perror.c =================================================================== --- lib/libc/stdio/perror.c (revision 225653) +++ lib/libc/stdio/perror.c (working copy) @@ -31,7 +31,7 @@ static char sccsid[] = "@(#)perror.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/perror.c 165903 2007-01-09 00:28:16Z imp $"); #include "namespace.h" #include Index: lib/libc/stdio/refill.c =================================================================== --- lib/libc/stdio/refill.c (revision 225653) +++ lib/libc/stdio/refill.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)refill.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/refill.c 178287 2008-04-17 22:17:54Z jhb $"); #include "namespace.h" #include Index: lib/libc/stdio/getc.c =================================================================== --- lib/libc/stdio/getc.c (revision 225653) +++ lib/libc/stdio/getc.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)getc.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/getc.c 178778 2008-05-05 16:03:52Z jhb $"); #include "namespace.h" #include Index: lib/libc/stdio/setbuffer.c =================================================================== --- lib/libc/stdio/setbuffer.c (revision 225653) +++ lib/libc/stdio/setbuffer.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)setbuffer.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/setbuffer.c 165903 2007-01-09 00:28:16Z imp $"); #include Index: lib/libc/stdio/getline.c =================================================================== --- lib/libc/stdio/getline.c (revision 225653) +++ lib/libc/stdio/getline.c (working copy) @@ -25,7 +25,7 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/getline.c 189136 2009-02-28 06:00:58Z das $"); #define _WITH_GETLINE #include Index: lib/libc/stdio/setbuf.c =================================================================== --- lib/libc/stdio/setbuf.c (revision 225653) +++ lib/libc/stdio/setbuf.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)setbuf.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/setbuf.c 165903 2007-01-09 00:28:16Z imp $"); #include #include "local.h" Index: lib/libc/stdio/fpurge.c =================================================================== --- lib/libc/stdio/fpurge.c (revision 225653) +++ lib/libc/stdio/fpurge.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)fpurge.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/fpurge.c 165903 2007-01-09 00:28:16Z imp $"); #include "namespace.h" #include Index: lib/libc/stdio/Symbol.map =================================================================== --- lib/libc/stdio/Symbol.map (revision 225653) +++ lib/libc/stdio/Symbol.map (working copy) @@ -1,5 +1,5 @@ /* - * $FreeBSD$ + * $FreeBSD: head/lib/libc/stdio/Symbol.map 189356 2009-03-04 03:38:51Z das $ */ FBSD_1.0 { @@ -108,6 +108,43 @@ __swbuf; wprintf; wscanf; + asprintf_l; + fprintf_l; + fwprintf_l; + printf_l; + snprintf_l; + sprintf_l; + swprintf_l; + vasprintf_l; + vfprintf_l; + vfwprintf_l; + vprintf_l; + vsnprintf_l; + vsprintf_l; + vswprintf_l; + vwprintf_l; + wprintf_l; + fgetwc_l; + fputwc_l; + ungetwc_l; + vfwscanf_l; + vswscanf_l; + fscanf_l; + fwscanf_l; + scanf_l; + sscanf_l; + swscanf_l; + vfscanf_l; + vscanf_l; + vsscanf_l; + vwscanf_l; + wscanf_l; + fgetws_l; + fputws_l; + getwc_l; + getwchar_l; + putwc_l; + putwchar_l; }; FBSD_1.1 { Index: lib/libc/stdio/gets.c =================================================================== --- lib/libc/stdio/gets.c (revision 225653) +++ lib/libc/stdio/gets.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)gets.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/gets.c 165903 2007-01-09 00:28:16Z imp $"); #include "namespace.h" #include Index: lib/libc/stdio/getw.c =================================================================== --- lib/libc/stdio/getw.c (revision 225653) +++ lib/libc/stdio/getw.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)getw.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/getw.c 165903 2007-01-09 00:28:16Z imp $"); #include Index: lib/libc/stdio/fgetwln.c =================================================================== --- lib/libc/stdio/fgetwln.c (revision 225653) +++ lib/libc/stdio/fgetwln.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002-2004 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -25,7 +30,7 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/fgetwln.c 133223 2004-08-06 17:00:09Z tjr $"); #include "namespace.h" #include @@ -33,18 +38,20 @@ #include "un-namespace.h" #include "libc_private.h" #include "local.h" +#include "xlocale_private.h" wchar_t * -fgetwln(FILE * __restrict fp, size_t *lenp) +fgetwln_l(FILE * __restrict fp, size_t *lenp, locale_t locale) { wint_t wc; size_t len; + FIX_LOCALE(locale); FLOCKFILE(fp); ORIENT(fp, 1); len = 0; - while ((wc = __fgetwc(fp)) != WEOF) { + while ((wc = __fgetwc(fp, locale)) != WEOF) { #define GROW 512 if (len * sizeof(wchar_t) >= fp->_lb._size && __slbexpand(fp, (len + GROW) * sizeof(wchar_t))) @@ -65,3 +72,8 @@ *lenp = 0; return (NULL); } +wchar_t * +fgetwln(FILE * __restrict fp, size_t *lenp) +{ + return fgetwln_l(fp, lenp, __get_locale()); +} Index: lib/libc/stdio/getwc.c =================================================================== --- lib/libc/stdio/getwc.c (revision 225653) +++ lib/libc/stdio/getwc.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -25,11 +30,12 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/getwc.c 129705 2004-05-25 10:42:52Z tjr $"); #include "namespace.h" #include #include +#include #include "un-namespace.h" #include "libc_private.h" #include "local.h" @@ -43,6 +49,10 @@ wint_t getwc(FILE *fp) { - return (fgetwc(fp)); } +wint_t +getwc_l(FILE *fp, locale_t locale) +{ + return (fgetwc_l(fp, locale)); +} Index: lib/libc/stdio/xprintf_vis.c =================================================================== --- lib/libc/stdio/xprintf_vis.c (revision 225653) +++ lib/libc/stdio/xprintf_vis.c (working copy) @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD$ + * $FreeBSD: head/lib/libc/stdio/xprintf_vis.c 154815 2006-01-25 12:45:24Z phk $ */ #include Index: lib/libc/stdio/xprintf_float.c =================================================================== --- lib/libc/stdio/xprintf_float.c (revision 225653) +++ lib/libc/stdio/xprintf_float.c (working copy) @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD$ + * $FreeBSD: head/lib/libc/stdio/xprintf_float.c 153486 2005-12-16 18:56:39Z phk $ */ #include Index: lib/libc/stdio/vsnprintf.c =================================================================== --- lib/libc/stdio/vsnprintf.c (revision 225653) +++ lib/libc/stdio/vsnprintf.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Chris Torek. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -34,20 +39,22 @@ static char sccsid[] = "@(#)vsnprintf.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/vsnprintf.c 205021 2010-03-11 17:03:32Z jhb $"); #include #include #include "local.h" +#include "xlocale_private.h" int -vsnprintf(char * __restrict str, size_t n, const char * __restrict fmt, - __va_list ap) +vsnprintf_l(char * __restrict str, size_t n, locale_t locale, + const char * __restrict fmt, __va_list ap) { size_t on; int ret; char dummy[2]; FILE f = FAKE_FILE; + FIX_LOCALE(locale); on = n; if (n != 0) @@ -64,8 +71,14 @@ f._flags = __SWR | __SSTR; f._bf._base = f._p = (unsigned char *)str; f._bf._size = f._w = n; - ret = __vfprintf(&f, fmt, ap); + ret = __vfprintf(&f, locale, fmt, ap); if (on > 0) *f._p = '\0'; return (ret); } +int +vsnprintf(char * __restrict str, size_t n, const char * __restrict fmt, + __va_list ap) +{ + return vsnprintf_l(str, n, __get_locale(), fmt, ap); +} Index: lib/libc/stdio/flags.c =================================================================== --- lib/libc/stdio/flags.c (revision 225653) +++ lib/libc/stdio/flags.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)flags.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/flags.c 165903 2007-01-09 00:28:16Z imp $"); #include #include Index: lib/libc/stdio/putwchar.c =================================================================== --- lib/libc/stdio/putwchar.c (revision 225653) +++ lib/libc/stdio/putwchar.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -25,7 +30,7 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/putwchar.c 129705 2004-05-25 10:42:52Z tjr $"); #include "namespace.h" #include @@ -33,6 +38,7 @@ #include "un-namespace.h" #include "libc_private.h" #include "local.h" +#include "xlocale_private.h" #undef putwchar @@ -40,8 +46,13 @@ * Synonym for fputwc(wc, stdout). */ wint_t +putwchar_l(wchar_t wc, locale_t locale) +{ + FIX_LOCALE(locale); + return (fputwc_l(wc, stdout, locale)); +} +wint_t putwchar(wchar_t wc) { - - return (fputwc(wc, stdout)); + return putwchar_l(wc, __get_locale()); } Index: lib/libc/stdio/ferror.c =================================================================== --- lib/libc/stdio/ferror.c (revision 225653) +++ lib/libc/stdio/ferror.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)ferror.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/ferror.c 178778 2008-05-05 16:03:52Z jhb $"); #include "namespace.h" #include Index: lib/libc/stdio/vswprintf.c =================================================================== --- lib/libc/stdio/vswprintf.c (revision 225653) +++ lib/libc/stdio/vswprintf.c (working copy) @@ -4,6 +4,11 @@ * Copyright (c) 1997 Todd C. Miller * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -31,17 +36,18 @@ #if 0 __FBSDID("FreeBSD: src/lib/libc/stdio/vasprintf.c,v 1.16 2002/08/21 16:19:57 mike Exp "); #endif -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/vswprintf.c 205021 2010-03-11 17:03:32Z jhb $"); #include #include #include #include #include "local.h" +#include "xlocale_private.h" int -vswprintf(wchar_t * __restrict s, size_t n, const wchar_t * __restrict fmt, - __va_list ap) +vswprintf_l(wchar_t * __restrict s, size_t n, locale_t locale, + const wchar_t * __restrict fmt, __va_list ap) { static const mbstate_t initial; mbstate_t mbs; @@ -49,6 +55,7 @@ char *mbp; int ret, sverrno; size_t nwc; + FIX_LOCALE(locale); if (n == 0) { errno = EINVAL; @@ -62,7 +69,7 @@ return (-1); } f._bf._size = f._w = 127; /* Leave room for the NUL */ - ret = __vfwprintf(&f, fmt, ap); + ret = __vfwprintf(&f, locale, fmt, ap); if (ret < 0) { sverrno = errno; free(f._bf._base); @@ -76,7 +83,7 @@ * fputwc() did in __vfwprintf(). */ mbs = initial; - nwc = mbsrtowcs(s, (const char **)&mbp, n, &mbs); + nwc = mbsrtowcs_l(s, (const char **)&mbp, n, &mbs, locale); free(f._bf._base); if (nwc == (size_t)-1) { errno = EILSEQ; @@ -90,3 +97,9 @@ return (ret); } +int +vswprintf(wchar_t * __restrict s, size_t n, const wchar_t * __restrict fmt, + __va_list ap) +{ + return vswprintf_l(s, n, __get_locale(), fmt, ap); +} Index: lib/libc/stdio/vsscanf.c =================================================================== --- lib/libc/stdio/vsscanf.c (revision 225653) +++ lib/libc/stdio/vsscanf.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * This code is derived from software contributed to Berkeley by * Donn Seeley at UUNET Technologies, Inc. * @@ -34,11 +39,12 @@ static char sccsid[] = "@(#)vsscanf.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/vsscanf.c 205021 2010-03-11 17:03:32Z jhb $"); #include #include #include "local.h" +#include "xlocale_private.h" static int eofread(void *, char *, int); @@ -52,14 +58,21 @@ } int -vsscanf(const char * __restrict str, const char * __restrict fmt, - __va_list ap) +vsscanf_l(const char * __restrict str, locale_t locale, + const char * __restrict fmt, __va_list ap) { FILE f = FAKE_FILE; + FIX_LOCALE(locale); f._flags = __SRD; f._bf._base = f._p = (unsigned char *)str; f._bf._size = f._r = strlen(str); f._read = eofread; - return (__svfscanf(&f, fmt, ap)); + return (__svfscanf(&f, locale, fmt, ap)); } +int +vsscanf(const char * __restrict str, const char * __restrict fmt, + __va_list ap) +{ + return vsscanf_l(str, __get_locale(), fmt, ap); +} Index: lib/libc/stdio/snprintf.c =================================================================== --- lib/libc/stdio/snprintf.c (revision 225653) +++ lib/libc/stdio/snprintf.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * This code is derived from software contributed to Berkeley by * Chris Torek. * @@ -34,11 +39,12 @@ static char sccsid[] = "@(#)snprintf.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/snprintf.c 205021 2010-03-11 17:03:32Z jhb $"); #include #include #include +#include "xlocale_private.h" #include "local.h" @@ -59,9 +65,34 @@ f._flags = __SWR | __SSTR; f._bf._base = f._p = (unsigned char *)str; f._bf._size = f._w = n; - ret = __vfprintf(&f, fmt, ap); + ret = __vfprintf(&f, __get_locale(), fmt, ap); if (on > 0) *f._p = '\0'; va_end(ap); return (ret); } +int +snprintf_l(char * __restrict str, size_t n, locale_t locale, + char const * __restrict fmt, ...) +{ + size_t on; + int ret; + va_list ap; + FILE f = FAKE_FILE; + FIX_LOCALE(locale); + + on = n; + if (n != 0) + n--; + if (n > INT_MAX) + n = INT_MAX; + va_start(ap, fmt); + f._flags = __SWR | __SSTR; + f._bf._base = f._p = (unsigned char *)str; + f._bf._size = f._w = n; + ret = __vfprintf(&f, locale, fmt, ap); + if (on > 0) + *f._p = '\0'; + va_end(ap); + return (ret); +} Index: lib/libc/stdio/ungetwc.c =================================================================== --- lib/libc/stdio/ungetwc.c (revision 225653) +++ lib/libc/stdio/ungetwc.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002-2004 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -25,7 +30,7 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/ungetwc.c 178287 2008-04-17 22:17:54Z jhb $"); #include "namespace.h" #include @@ -37,19 +42,21 @@ #include "libc_private.h" #include "local.h" #include "mblocal.h" +#include "xlocale_private.h" /* * Non-MT-safe version. */ wint_t -__ungetwc(wint_t wc, FILE *fp) +__ungetwc(wint_t wc, FILE *fp, locale_t locale) { char buf[MB_LEN_MAX]; size_t len; + struct xlocale_ctype *l = XLOCALE_CTYPE(locale); if (wc == WEOF) return (WEOF); - if ((len = __wcrtomb(buf, wc, &fp->_mbstate)) == (size_t)-1) { + if ((len = l->__wcrtomb(buf, wc, &fp->_mbstate)) == (size_t)-1) { fp->_flags |= __SERR; return (WEOF); } @@ -64,14 +71,20 @@ * MT-safe version. */ wint_t -ungetwc(wint_t wc, FILE *fp) +ungetwc_l(wint_t wc, FILE *fp, locale_t locale) { wint_t r; + FIX_LOCALE(locale); FLOCKFILE(fp); ORIENT(fp, 1); - r = __ungetwc(wc, fp); + r = __ungetwc(wc, fp, locale); FUNLOCKFILE(fp); return (r); } +wint_t +ungetwc(wint_t wc, FILE *fp) +{ + return ungetwc_l(wc, fp, __get_locale()); +} Index: lib/libc/stdio/swprintf.c =================================================================== --- lib/libc/stdio/swprintf.c (revision 225653) +++ lib/libc/stdio/swprintf.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002 Tim J. Robbins * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -25,11 +30,12 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/swprintf.c 103739 2002-09-21 13:00:30Z tjr $"); #include #include #include +#include int swprintf(wchar_t * __restrict s, size_t n, const wchar_t * __restrict fmt, ...) @@ -43,3 +49,16 @@ return (ret); } +int +swprintf_l(wchar_t * __restrict s, size_t n, locale_t locale, + const wchar_t * __restrict fmt, ...) +{ + int ret; + va_list ap; + + va_start(ap, fmt); + ret = vswprintf_l(s, n, locale, fmt, ap); + va_end(ap); + + return (ret); +} Index: lib/libc/stdio/getchar.c =================================================================== --- lib/libc/stdio/getchar.c (revision 225653) +++ lib/libc/stdio/getchar.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)getchar.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/getchar.c 178778 2008-05-05 16:03:52Z jhb $"); /* * A subroutine version of the macro getchar. Index: lib/libc/stdio/feof.c =================================================================== --- lib/libc/stdio/feof.c (revision 225653) +++ lib/libc/stdio/feof.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)feof.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/feof.c 178778 2008-05-05 16:03:52Z jhb $"); #include "namespace.h" #include Index: lib/libc/stdio/wscanf.c =================================================================== --- lib/libc/stdio/wscanf.c (revision 225653) +++ lib/libc/stdio/wscanf.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002 Tim J. Robbins * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -25,11 +30,12 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/wscanf.c 103856 2002-09-23 12:40:06Z tjr $"); #include #include #include +#include int wscanf(const wchar_t * __restrict fmt, ...) @@ -43,3 +49,15 @@ return (r); } +int +wscanf_l(locale_t locale, const wchar_t * __restrict fmt, ...) +{ + va_list ap; + int r; + + va_start(ap, fmt); + r = vfwscanf_l(stdin, locale, fmt, ap); + va_end(ap); + + return (r); +} Index: lib/libc/stdio/stdio.c =================================================================== --- lib/libc/stdio/stdio.c (revision 225653) +++ lib/libc/stdio/stdio.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)stdio.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/stdio.c 178782 2008-05-05 16:14:02Z jhb $"); #include "namespace.h" #include Index: lib/libc/stdio/fvwrite.c =================================================================== --- lib/libc/stdio/fvwrite.c (revision 225653) +++ lib/libc/stdio/fvwrite.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)fvwrite.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/fvwrite.c 199781 2009-11-25 04:21:42Z wollman $"); #include #include Index: lib/libc/stdio/wsetup.c =================================================================== --- lib/libc/stdio/wsetup.c (revision 225653) +++ lib/libc/stdio/wsetup.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)wsetup.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/wsetup.c 186887 2009-01-08 06:38:06Z das $"); #include #include Index: lib/libc/stdio/mktemp.c =================================================================== --- lib/libc/stdio/mktemp.c (revision 225653) +++ lib/libc/stdio/mktemp.c (working copy) @@ -31,7 +31,7 @@ static char sccsid[] = "@(#)mktemp.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/mktemp.c 204447 2010-02-28 13:31:29Z jh $"); #include "namespace.h" #include Index: lib/libc/stdio/xprintf_errno.c =================================================================== --- lib/libc/stdio/xprintf_errno.c (revision 225653) +++ lib/libc/stdio/xprintf_errno.c (working copy) @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD$ + * $FreeBSD: head/lib/libc/stdio/xprintf_errno.c 154815 2006-01-25 12:45:24Z phk $ */ #include Index: lib/libc/stdio/fscanf.c =================================================================== --- lib/libc/stdio/fscanf.c (revision 225653) +++ lib/libc/stdio/fscanf.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Chris Torek. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -34,7 +39,7 @@ static char sccsid[] = "@(#)fscanf.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/fscanf.c 165903 2007-01-09 00:28:16Z imp $"); #include "namespace.h" #include @@ -42,6 +47,7 @@ #include "un-namespace.h" #include "libc_private.h" #include "local.h" +#include "xlocale_private.h" int fscanf(FILE * __restrict fp, char const * __restrict fmt, ...) @@ -51,8 +57,22 @@ va_start(ap, fmt); FLOCKFILE(fp); - ret = __svfscanf(fp, fmt, ap); + ret = __svfscanf(fp, __get_locale(), fmt, ap); va_end(ap); FUNLOCKFILE(fp); return (ret); } +int +fscanf_l(FILE * __restrict fp, locale_t locale, char const * __restrict fmt, ...) +{ + int ret; + va_list ap; + FIX_LOCALE(locale); + + va_start(ap, fmt); + FLOCKFILE(fp); + ret = __svfscanf(fp, locale, fmt, ap); + va_end(ap); + FUNLOCKFILE(fp); + return (ret); +} Index: lib/libc/stdio/fcloseall.c =================================================================== --- lib/libc/stdio/fcloseall.c (revision 225653) +++ lib/libc/stdio/fcloseall.c (working copy) @@ -24,7 +24,7 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/fcloseall.c 157963 2006-04-22 16:47:59Z deischen $"); #include #include "local.h" Index: lib/libc/stdio/putchar.c =================================================================== --- lib/libc/stdio/putchar.c (revision 225653) +++ lib/libc/stdio/putchar.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)putchar.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/putchar.c 178778 2008-05-05 16:03:52Z jhb $"); #include "namespace.h" #include Index: lib/libc/stdio/dprintf.c =================================================================== --- lib/libc/stdio/dprintf.c (revision 225653) +++ lib/libc/stdio/dprintf.c (working copy) @@ -25,7 +25,7 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/dprintf.c 189356 2009-03-04 03:38:51Z das $"); #define _WITH_DPRINTF #include "namespace.h" Index: lib/libc/stdio/ftell.c =================================================================== --- lib/libc/stdio/ftell.c (revision 225653) +++ lib/libc/stdio/ftell.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)ftell.c 8.2 (Berkeley) 5/4/95"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/ftell.c 165903 2007-01-09 00:28:16Z imp $"); #include "namespace.h" #include Index: lib/libc/stdio/fprintf.c =================================================================== --- lib/libc/stdio/fprintf.c (revision 225653) +++ lib/libc/stdio/fprintf.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Chris Torek. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -34,10 +39,11 @@ static char sccsid[] = "@(#)fprintf.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/fprintf.c 165903 2007-01-09 00:28:16Z imp $"); #include #include +#include "xlocale_private.h" int fprintf(FILE * __restrict fp, const char * __restrict fmt, ...) @@ -46,7 +52,19 @@ va_list ap; va_start(ap, fmt); - ret = vfprintf(fp, fmt, ap); + ret = vfprintf_l(fp, __get_locale(), fmt, ap); va_end(ap); return (ret); } +int +fprintf_l(FILE * __restrict fp, locale_t locale, const char * __restrict fmt, ...) +{ + int ret; + va_list ap; + FIX_LOCALE(locale); + + va_start(ap, fmt); + ret = vfprintf_l(fp, locale, fmt, ap); + va_end(ap); + return (ret); +} Index: lib/libc/stdio/fgetln.c =================================================================== --- lib/libc/stdio/fgetln.c (revision 225653) +++ lib/libc/stdio/fgetln.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)fgetln.c 8.2 (Berkeley) 1/2/94"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/fgetln.c 165903 2007-01-09 00:28:16Z imp $"); #include "namespace.h" #include Index: lib/libc/stdio/vscanf.c =================================================================== --- lib/libc/stdio/vscanf.c (revision 225653) +++ lib/libc/stdio/vscanf.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Donn Seeley at UUNET Technologies, Inc. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -34,23 +39,33 @@ static char sccsid[] = "@(#)vscanf.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/vscanf.c 165903 2007-01-09 00:28:16Z imp $"); #include "namespace.h" #include #include "un-namespace.h" #include "libc_private.h" #include "local.h" +#include "xlocale_private.h" int -vscanf(fmt, ap) +vscanf_l(locale, fmt, ap) + locale_t locale; const char * __restrict fmt; __va_list ap; { int retval; + FIX_LOCALE(locale); FLOCKFILE(stdin); - retval = __svfscanf(stdin, fmt, ap); + retval = __svfscanf(stdin, locale, fmt, ap); FUNLOCKFILE(stdin); return (retval); } +int +vscanf(fmt, ap) + const char * __restrict fmt; + __va_list ap; +{ + return vscanf_l(__get_locale(), fmt, ap); +} Index: lib/libc/stdio/printfcommon.h =================================================================== --- lib/libc/stdio/printfcommon.h (revision 225653) +++ lib/libc/stdio/printfcommon.h (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Chris Torek. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -29,7 +34,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD$ + * $FreeBSD: head/lib/libc/stdio/printfcommon.h 187582 2009-01-22 08:14:28Z das $ */ /* @@ -79,14 +84,14 @@ * remain valid until io_flush() is called. */ static inline int -io_print(struct io_state *iop, const CHAR * __restrict ptr, int len) +io_print(struct io_state *iop, const CHAR * __restrict ptr, int len, locale_t locale) { iop->iov[iop->uio.uio_iovcnt].iov_base = (char *)ptr; iop->iov[iop->uio.uio_iovcnt].iov_len = len; iop->uio.uio_resid += len; if (++iop->uio.uio_iovcnt >= NIOV) - return (__sprint(iop->fp, &iop->uio)); + return (__sprint(iop->fp, &iop->uio, locale)); else return (0); } @@ -107,13 +112,14 @@ * or the zeroes array. */ static inline int -io_pad(struct io_state *iop, int howmany, const CHAR * __restrict with) +io_pad(struct io_state *iop, int howmany, const CHAR * __restrict with, + locale_t locale) { int n; while (howmany > 0) { n = (howmany >= PADSIZE) ? PADSIZE : howmany; - if (io_print(iop, with, n)) + if (io_print(iop, with, n, locale)) return (-1); howmany -= n; } @@ -126,7 +132,7 @@ */ static inline int io_printandpad(struct io_state *iop, const CHAR *p, const CHAR *ep, - int len, const CHAR * __restrict with) + int len, const CHAR * __restrict with, locale_t locale) { int p_len; @@ -134,19 +140,19 @@ if (p_len > len) p_len = len; if (p_len > 0) { - if (io_print(iop, p, p_len)) + if (io_print(iop, p, p_len, locale)) return (-1); } else { p_len = 0; } - return (io_pad(iop, len - p_len, with)); + return (io_pad(iop, len - p_len, with, locale)); } static inline int -io_flush(struct io_state *iop) +io_flush(struct io_state *iop, locale_t locale) { - return (__sprint(iop->fp, &iop->uio)); + return (__sprint(iop->fp, &iop->uio, locale)); } /* Index: lib/libc/stdio/sprintf.c =================================================================== --- lib/libc/stdio/sprintf.c (revision 225653) +++ lib/libc/stdio/sprintf.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Chris Torek. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -34,12 +39,13 @@ static char sccsid[] = "@(#)sprintf.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/sprintf.c 200802 2009-12-21 19:59:38Z delphij $"); #include #include #include #include "local.h" +#include "xlocale_private.h" int sprintf(char * __restrict str, char const * __restrict fmt, ...) @@ -52,3 +58,16 @@ va_end(ap); return (ret); } +int +sprintf_l(char * __restrict str, locale_t locale, char const * __restrict fmt, + ...) +{ + int ret; + va_list ap; + FIX_LOCALE(locale); + + va_start(ap, fmt); + ret = vsprintf_l(str, locale, fmt, ap); + va_end(ap); + return (ret); +} Index: lib/libc/stdio/vprintf.c =================================================================== --- lib/libc/stdio/vprintf.c (revision 225653) +++ lib/libc/stdio/vprintf.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Chris Torek. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -34,13 +39,18 @@ static char sccsid[] = "@(#)vprintf.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/vprintf.c 165903 2007-01-09 00:28:16Z imp $"); #include +#include int vprintf(const char * __restrict fmt, __va_list ap) { - return (vfprintf(stdout, fmt, ap)); } +int +vprintf_l(locale_t locale, const char * __restrict fmt, __va_list ap) +{ + return (vfprintf_l(stdout, locale, fmt, ap)); +} Index: lib/libc/stdio/rewind.c =================================================================== --- lib/libc/stdio/rewind.c (revision 225653) +++ lib/libc/stdio/rewind.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)rewind.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/rewind.c 165903 2007-01-09 00:28:16Z imp $"); #include "namespace.h" #include Index: lib/libc/stdio/clrerr.c =================================================================== --- lib/libc/stdio/clrerr.c (revision 225653) +++ lib/libc/stdio/clrerr.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)clrerr.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/clrerr.c 178778 2008-05-05 16:03:52Z jhb $"); #include "namespace.h" #include Index: lib/libc/stdio/wprintf.c =================================================================== --- lib/libc/stdio/wprintf.c (revision 225653) +++ lib/libc/stdio/wprintf.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002 Tim J. Robbins * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -25,11 +30,12 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/wprintf.c 103739 2002-09-21 13:00:30Z tjr $"); #include #include #include +#include int wprintf(const wchar_t * __restrict fmt, ...) @@ -43,3 +49,15 @@ return (ret); } +int +wprintf_l(locale_t locale, const wchar_t * __restrict fmt, ...) +{ + int ret; + va_list ap; + + va_start(ap, fmt); + ret = vfwprintf_l(stdout, locale, fmt, ap); + va_end(ap); + + return (ret); +} Index: lib/libc/stdio/xprintf.c =================================================================== --- lib/libc/stdio/xprintf.c (revision 225653) +++ lib/libc/stdio/xprintf.c (working copy) @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD$ + * $FreeBSD: head/lib/libc/stdio/xprintf.c 205021 2010-03-11 17:03:32Z jhb $ */ #include "namespace.h" Index: lib/libc/stdio/remove.c =================================================================== --- lib/libc/stdio/remove.c (revision 225653) +++ lib/libc/stdio/remove.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)remove.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/remove.c 165903 2007-01-09 00:28:16Z imp $"); #include #include Index: lib/libc/stdio/freopen.c =================================================================== --- lib/libc/stdio/freopen.c (revision 225653) +++ lib/libc/stdio/freopen.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)freopen.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/freopen.c 216334 2010-12-09 20:28:30Z jhb $"); #include "namespace.h" #include Index: lib/libc/stdio/fwide.c =================================================================== --- lib/libc/stdio/fwide.c (revision 225653) +++ lib/libc/stdio/fwide.c (working copy) @@ -25,7 +25,7 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/fwide.c 178287 2008-04-17 22:17:54Z jhb $"); #include "namespace.h" #include Index: lib/libc/stdio/printf-pos.c =================================================================== --- lib/libc/stdio/printf-pos.c (revision 225653) +++ lib/libc/stdio/printf-pos.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)vfprintf.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/printf-pos.c 216121 2010-12-02 13:40:21Z gavin $"); /* * This is the code responsible for handling positional arguments Index: lib/libc/stdio/xprintf_quote.c =================================================================== --- lib/libc/stdio/xprintf_quote.c (revision 225653) +++ lib/libc/stdio/xprintf_quote.c (working copy) @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD$ + * $FreeBSD: head/lib/libc/stdio/xprintf_quote.c 156207 2006-03-02 08:53:45Z phk $ */ #include Index: lib/libc/stdio/xprintf_str.c =================================================================== --- lib/libc/stdio/xprintf_str.c (revision 225653) +++ lib/libc/stdio/xprintf_str.c (working copy) @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD$ + * $FreeBSD: head/lib/libc/stdio/xprintf_str.c 153486 2005-12-16 18:56:39Z phk $ */ #include Index: lib/libc/stdio/fsetpos.c =================================================================== --- lib/libc/stdio/fsetpos.c (revision 225653) +++ lib/libc/stdio/fsetpos.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)fsetpos.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/fsetpos.c 165903 2007-01-09 00:28:16Z imp $"); #include #include Index: lib/libc/stdio/vfwprintf.c =================================================================== --- lib/libc/stdio/vfwprintf.c (revision 225653) +++ lib/libc/stdio/vfwprintf.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Chris Torek. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -36,7 +41,7 @@ #endif /* LIBC_SCCS and not lint */ #endif #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/vfwprintf.c 199782 2009-11-25 04:27:55Z wollman $"); /* * Actual wprintf innards. @@ -65,10 +70,11 @@ #include "local.h" #include "fvwrite.h" #include "printflocal.h" +#include "xlocale_private.h" -static int __sprint(FILE *, struct __suio *); -static int __sbprintf(FILE *, const wchar_t *, va_list) __noinline; -static wint_t __xfputwc(wchar_t, FILE *); +static int __sprint(FILE *, struct __suio *, locale_t); +static int __sbprintf(FILE *, locale_t, const wchar_t *, va_list) __noinline; +static wint_t __xfputwc(wchar_t, FILE *, locale_t); static wchar_t *__mbsconv(char *, int); #define CHAR wchar_t @@ -85,28 +91,28 @@ static const mbstate_t initial_mbs; static inline wchar_t -get_decpt(void) +get_decpt(locale_t locale) { mbstate_t mbs; wchar_t decpt; int nconv; mbs = initial_mbs; - nconv = mbrtowc(&decpt, localeconv()->decimal_point, MB_CUR_MAX, &mbs); + nconv = mbrtowc(&decpt, localeconv_l(locale)->decimal_point, MB_CUR_MAX, &mbs); if (nconv == (size_t)-1 || nconv == (size_t)-2) decpt = '.'; /* failsafe */ return (decpt); } static inline wchar_t -get_thousep(void) +get_thousep(locale_t locale) { mbstate_t mbs; wchar_t thousep; int nconv; mbs = initial_mbs; - nconv = mbrtowc(&thousep, localeconv()->thousands_sep, + nconv = mbrtowc(&thousep, localeconv_l(locale)->thousands_sep, MB_CUR_MAX, &mbs); if (nconv == (size_t)-1 || nconv == (size_t)-2) thousep = '\0'; /* failsafe */ @@ -119,11 +125,11 @@ * of wide characters that will be printed. */ static int -grouping_init(struct grouping_state *gs, int ndigits) +grouping_init(struct grouping_state *gs, int ndigits, locale_t locale) { - gs->grouping = localeconv()->grouping; - gs->thousands_sep = get_thousep(); + gs->grouping = localeconv_l(locale)->grouping; + gs->thousands_sep = get_thousep(locale); gs->nseps = gs->nrepeats = 0; gs->lead = ndigits; @@ -145,11 +151,11 @@ */ static int grouping_print(struct grouping_state *gs, struct io_state *iop, - const CHAR *cp, const CHAR *ep) + const CHAR *cp, const CHAR *ep, locale_t locale) { const CHAR *cp0 = cp; - if (io_printandpad(iop, cp, ep, gs->lead, zeroes)) + if (io_printandpad(iop, cp, ep, gs->lead, zeroes, locale)) return (-1); cp += gs->lead; while (gs->nseps > 0 || gs->nrepeats > 0) { @@ -159,9 +165,9 @@ gs->grouping--; gs->nseps--; } - if (io_print(iop, &gs->thousands_sep, 1)) + if (io_print(iop, &gs->thousands_sep, 1, locale)) return (-1); - if (io_printandpad(iop, cp, ep, *gs->grouping, zeroes)) + if (io_printandpad(iop, cp, ep, *gs->grouping, zeroes, locale)) return (-1); cp += *gs->grouping; } @@ -180,7 +186,7 @@ * string eclipses the benefits of buffering. */ static int -__sprint(FILE *fp, struct __suio *uio) +__sprint(FILE *fp, struct __suio *uio, locale_t locale) { struct __siov *iov; wchar_t *p; @@ -191,7 +197,7 @@ p = (wchar_t *)iov->iov_base; len = iov->iov_len; for (i = 0; i < len; i++) { - if (__xfputwc(p[i], fp) == WEOF) + if (__xfputwc(p[i], fp, locale) == WEOF) return (-1); } } @@ -205,7 +211,7 @@ * worries about ungetc buffers and so forth. */ static int -__sbprintf(FILE *fp, const wchar_t *fmt, va_list ap) +__sbprintf(FILE *fp, locale_t locale, const wchar_t *fmt, va_list ap) { int ret; FILE fake; @@ -229,7 +235,7 @@ fake._lbfsize = 0; /* not actually used, but Just In Case */ /* do the work, then copy any error status */ - ret = __vfwprintf(&fake, fmt, ap); + ret = __vfwprintf(&fake, locale, fmt, ap); if (ret >= 0 && __fflush(&fake)) ret = WEOF; if (fake._flags & __SERR) @@ -242,7 +248,7 @@ * File must already be locked. */ static wint_t -__xfputwc(wchar_t wc, FILE *fp) +__xfputwc(wchar_t wc, FILE *fp, locale_t locale) { mbstate_t mbs; char buf[MB_LEN_MAX]; @@ -251,7 +257,7 @@ size_t len; if ((fp->_flags & __SSTR) == 0) - return (__fputwc(wc, fp)); + return (__fputwc(wc, fp, locale)); mbs = initial_mbs; if ((len = wcrtomb(buf, wc, &mbs)) == (size_t)-1) { @@ -343,21 +349,27 @@ * MT-safe version */ int -vfwprintf(FILE * __restrict fp, const wchar_t * __restrict fmt0, va_list ap) +vfwprintf_l(FILE * __restrict fp, locale_t locale, + const wchar_t * __restrict fmt0, va_list ap) { int ret; - + FIX_LOCALE(locale); FLOCKFILE(fp); /* optimise fprintf(stderr) (and other unbuffered Unix files) */ if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) && fp->_file >= 0) - ret = __sbprintf(fp, fmt0, ap); + ret = __sbprintf(fp, locale, fmt0, ap); else - ret = __vfwprintf(fp, fmt0, ap); + ret = __vfwprintf(fp, locale, fmt0, ap); FUNLOCKFILE(fp); return (ret); } +int +vfwprintf(FILE * __restrict fp, const wchar_t * __restrict fmt0, va_list ap) +{ + return vfwprintf_l(fp, __get_locale(), fmt0, ap); +} /* * The size of the buffer we use as scratch space for integer @@ -374,7 +386,7 @@ * Non-MT-safe version */ int -__vfwprintf(FILE *fp, const wchar_t *fmt0, va_list ap) +__vfwprintf(FILE *fp, locale_t locale, const wchar_t *fmt0, va_list ap) { wchar_t *fmt; /* format string */ wchar_t ch; /* character from fmt */ @@ -437,19 +449,19 @@ /* BEWARE, these `goto error' on error. */ #define PRINT(ptr, len) do { \ - if (io_print(&io, (ptr), (len))) \ + if (io_print(&io, (ptr), (len), locale)) \ goto error; \ } while (0) #define PAD(howmany, with) { \ - if (io_pad(&io, (howmany), (with))) \ + if (io_pad(&io, (howmany), (with), locale)) \ goto error; \ } #define PRINTANDPAD(p, ep, len, with) { \ - if (io_printandpad(&io, (p), (ep), (len), (with))) \ + if (io_printandpad(&io, (p), (ep), (len), (with), locale)) \ goto error; \ } #define FLUSH() { \ - if (io_flush(&io)) \ + if (io_flush(&io, locale)) \ goto error; \ } @@ -529,7 +541,7 @@ io_init(&io, fp); ret = 0; #ifndef NO_FLOATING_POINT - decimal_point = get_decpt(); + decimal_point = get_decpt(locale); #endif /* @@ -816,7 +828,7 @@ if (prec || flags & ALT) size += prec + 1; if ((flags & GROUPING) && expt > 0) - size += grouping_init(&gs, expt); + size += grouping_init(&gs, expt, locale); } break; #endif /* !NO_FLOATING_POINT */ @@ -955,7 +967,7 @@ if (size > BUF) /* should never happen */ abort(); if ((flags & GROUPING) && size != 0) - size += grouping_init(&gs, size); + size += grouping_init(&gs, size, locale); break; default: /* "%?" prints ?, unless ? is NUL */ if (ch == '\0') @@ -1018,7 +1030,7 @@ /* leading zeroes from decimal precision */ PAD(dprec - size, zeroes); if (gs.grouping) { - if (grouping_print(&gs, &io, cp, buf+BUF) < 0) + if (grouping_print(&gs, &io, cp, buf+BUF, locale) < 0) goto error; } else { PRINT(cp, size); @@ -1036,7 +1048,7 @@ } else { if (gs.grouping) { n = grouping_print(&gs, &io, - cp, convbuf + ndig); + cp, convbuf + ndig, locale); if (n < 0) goto error; cp += n; Index: lib/libc/stdio/_flock_stub.c =================================================================== --- lib/libc/stdio/_flock_stub.c (revision 225653) +++ lib/libc/stdio/_flock_stub.c (working copy) @@ -35,7 +35,7 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/_flock_stub.c 178287 2008-04-17 22:17:54Z jhb $"); #include "namespace.h" #include Index: lib/libc/stdio/vdprintf.c =================================================================== --- lib/libc/stdio/vdprintf.c (revision 225653) +++ lib/libc/stdio/vdprintf.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2009 David Schultz * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -25,7 +30,7 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/vdprintf.c 205021 2010-03-11 17:03:32Z jhb $"); #include "namespace.h" #include @@ -35,6 +40,7 @@ #include "un-namespace.h" #include "local.h" +#include "xlocale_private.h" int vdprintf(int fd, const char * __restrict fmt, va_list ap) @@ -57,7 +63,7 @@ f._bf._base = buf; f._bf._size = sizeof(buf); - if ((ret = __vfprintf(&f, fmt, ap)) < 0) + if ((ret = __vfprintf(&f, __get_locale(), fmt, ap)) < 0) return (ret); return (__fflush(&f) ? EOF : ret); Index: lib/libc/stdio/vfprintf.c =================================================================== --- lib/libc/stdio/vfprintf.c (revision 225653) +++ lib/libc/stdio/vfprintf.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Chris Torek. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -34,7 +39,7 @@ static char sccsid[] = "@(#)vfprintf.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/vfprintf.c 205021 2010-03-11 17:03:32Z jhb $"); /* * Actual printf innards. @@ -57,6 +62,7 @@ #include #include +#include "xlocale_private.h" #include "un-namespace.h" #include "libc_private.h" @@ -64,8 +70,8 @@ #include "fvwrite.h" #include "printflocal.h" -static int __sprint(FILE *, struct __suio *); -static int __sbprintf(FILE *, const char *, va_list) __printflike(2, 0) +static int __sprint(FILE *, struct __suio *, locale_t); +static int __sbprintf(FILE *, locale_t, const char *, va_list) __printflike(3, 0) __noinline; static char *__wcsconv(wchar_t *, int); @@ -87,11 +93,11 @@ * of bytes that will be needed. */ static int -grouping_init(struct grouping_state *gs, int ndigits) +grouping_init(struct grouping_state *gs, int ndigits, locale_t loc) { struct lconv *locale; - locale = localeconv(); + locale = localeconv_l(loc); gs->grouping = locale->grouping; gs->thousands_sep = locale->thousands_sep; gs->thousep_len = strlen(gs->thousands_sep); @@ -116,11 +122,11 @@ */ static int grouping_print(struct grouping_state *gs, struct io_state *iop, - const CHAR *cp, const CHAR *ep) + const CHAR *cp, const CHAR *ep, locale_t locale) { const CHAR *cp0 = cp; - if (io_printandpad(iop, cp, ep, gs->lead, zeroes)) + if (io_printandpad(iop, cp, ep, gs->lead, zeroes, locale)) return (-1); cp += gs->lead; while (gs->nseps > 0 || gs->nrepeats > 0) { @@ -130,9 +136,9 @@ gs->grouping--; gs->nseps--; } - if (io_print(iop, gs->thousands_sep, gs->thousep_len)) + if (io_print(iop, gs->thousands_sep, gs->thousep_len, locale)) return (-1); - if (io_printandpad(iop, cp, ep, *gs->grouping, zeroes)) + if (io_printandpad(iop, cp, ep, *gs->grouping, zeroes, locale)) return (-1); cp += *gs->grouping; } @@ -146,7 +152,7 @@ * then reset it so that it can be reused. */ static int -__sprint(FILE *fp, struct __suio *uio) +__sprint(FILE *fp, struct __suio *uio, locale_t locale) { int err; @@ -166,7 +172,7 @@ * worries about ungetc buffers and so forth. */ static int -__sbprintf(FILE *fp, const char *fmt, va_list ap) +__sbprintf(FILE *fp, locale_t locale, const char *fmt, va_list ap) { int ret; FILE fake = FAKE_FILE; @@ -190,7 +196,7 @@ fake._lbfsize = 0; /* not actually used, but Just In Case */ /* do the work, then copy any error status */ - ret = __vfprintf(&fake, fmt, ap); + ret = __vfprintf(&fake, locale, fmt, ap); if (ret >= 0 && __fflush(&fake)) ret = EOF; if (fake._flags & __SERR) @@ -261,21 +267,27 @@ * MT-safe version */ int -vfprintf(FILE * __restrict fp, const char * __restrict fmt0, va_list ap) - +vfprintf_l(FILE * __restrict fp, locale_t locale, const char * __restrict fmt0, + va_list ap) { int ret; + FIX_LOCALE(locale); FLOCKFILE(fp); /* optimise fprintf(stderr) (and other unbuffered Unix files) */ if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) && fp->_file >= 0) - ret = __sbprintf(fp, fmt0, ap); + ret = __sbprintf(fp, locale, fmt0, ap); else - ret = __vfprintf(fp, fmt0, ap); + ret = __vfprintf(fp, locale, fmt0, ap); FUNLOCKFILE(fp); return (ret); } +int +vfprintf(FILE * __restrict fp, const char * __restrict fmt0, va_list ap) +{ + return vfprintf_l(fp, __get_locale(), fmt0, ap); +} /* * The size of the buffer we use as scratch space for integer @@ -292,7 +304,7 @@ * Non-MT-safe version */ int -__vfprintf(FILE *fp, const char *fmt0, va_list ap) +__vfprintf(FILE *fp, locale_t locale, const char *fmt0, va_list ap) { char *fmt; /* format string */ int ch; /* character from fmt */ @@ -357,19 +369,19 @@ /* BEWARE, these `goto error' on error. */ #define PRINT(ptr, len) { \ - if (io_print(&io, (ptr), (len))) \ + if (io_print(&io, (ptr), (len), locale)) \ goto error; \ } #define PAD(howmany, with) { \ - if (io_pad(&io, (howmany), (with))) \ + if (io_pad(&io, (howmany), (with), locale)) \ goto error; \ } #define PRINTANDPAD(p, ep, len, with) { \ - if (io_printandpad(&io, (p), (ep), (len), (with))) \ + if (io_printandpad(&io, (p), (ep), (len), (with), locale)) \ goto error; \ } #define FLUSH() { \ - if (io_flush(&io)) \ + if (io_flush(&io, locale)) \ goto error; \ } @@ -454,7 +466,7 @@ ret = 0; #ifndef NO_FLOATING_POINT dtoaresult = NULL; - decimal_point = localeconv()->decimal_point; + decimal_point = localeconv_l(locale)->decimal_point; /* The overwhelmingly common case is decpt_len == 1. */ decpt_len = (decimal_point[1] == '\0' ? 1 : strlen(decimal_point)); #endif @@ -750,7 +762,7 @@ if (prec || flags & ALT) size += prec + decpt_len; if ((flags & GROUPING) && expt > 0) - size += grouping_init(&gs, expt); + size += grouping_init(&gs, expt, locale); } break; #endif /* !NO_FLOATING_POINT */ @@ -887,7 +899,7 @@ if (size > BUF) /* should never happen */ abort(); if ((flags & GROUPING) && size != 0) - size += grouping_init(&gs, size); + size += grouping_init(&gs, size, locale); break; default: /* "%?" prints ?, unless ? is NUL */ if (ch == '\0') @@ -950,7 +962,7 @@ /* leading zeroes from decimal precision */ PAD(dprec - size, zeroes); if (gs.grouping) { - if (grouping_print(&gs, &io, cp, buf+BUF) < 0) + if (grouping_print(&gs, &io, cp, buf+BUF, locale) < 0) goto error; } else { PRINT(cp, size); @@ -968,7 +980,7 @@ } else { if (gs.grouping) { n = grouping_print(&gs, &io, - cp, dtoaend); + cp, dtoaend, locale); if (n < 0) goto error; cp += n; Index: lib/libc/stdio/local.h =================================================================== --- lib/libc/stdio/local.h (revision 225653) +++ lib/libc/stdio/local.h (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Chris Torek. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -30,13 +35,14 @@ * SUCH DAMAGE. * * @(#)local.h 8.3 (Berkeley) 7/3/94 - * $FreeBSD$ + * $FreeBSD: head/lib/libc/stdio/local.h 205021 2010-03-11 17:03:32Z jhb $ */ #include /* for off_t */ #include #include #include +#include /* * Information local to this implementation of stdio, @@ -50,8 +56,8 @@ extern int _fseeko(FILE *, off_t, int, int); extern int __fflush(FILE *fp); extern void __fcloseall(void); -extern wint_t __fgetwc(FILE *); -extern wint_t __fputwc(wchar_t, FILE *); +extern wint_t __fgetwc(FILE *, locale_t); +extern wint_t __fputwc(wchar_t, FILE *, locale_t); extern int __sflush(FILE *); extern FILE *__sfp(void); extern int __slbexpand(FILE *, size_t); @@ -65,15 +71,15 @@ extern void __smakebuf(FILE *); extern int __swhatbuf(FILE *, size_t *, int *); extern int _fwalk(int (*)(FILE *)); -extern int __svfscanf(FILE *, const char *, __va_list); +extern int __svfscanf(FILE *, locale_t, const char *, __va_list); extern int __swsetup(FILE *); extern int __sflags(const char *, int *); extern int __ungetc(int, FILE *); -extern wint_t __ungetwc(wint_t, FILE *); -extern int __vfprintf(FILE *, const char *, __va_list); +extern wint_t __ungetwc(wint_t, FILE *, locale_t); +extern int __vfprintf(FILE *, locale_t, const char *, __va_list); extern int __vfscanf(FILE *, const char *, __va_list); -extern int __vfwprintf(FILE *, const wchar_t *, __va_list); -extern int __vfwscanf(FILE * __restrict, const wchar_t * __restrict, +extern int __vfwprintf(FILE *, locale_t, const wchar_t *, __va_list); +extern int __vfwscanf(FILE * __restrict, locale_t, const wchar_t * __restrict, __va_list); extern size_t __fread(void * __restrict buf, size_t size, size_t count, FILE * __restrict fp); Index: lib/libc/stdio/fwprintf.c =================================================================== --- lib/libc/stdio/fwprintf.c (revision 225653) +++ lib/libc/stdio/fwprintf.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002 Tim J. Robbins * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -25,11 +30,12 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/fwprintf.c 103739 2002-09-21 13:00:30Z tjr $"); #include #include #include +#include int fwprintf(FILE * __restrict fp, const wchar_t * __restrict fmt, ...) @@ -43,3 +49,15 @@ return (ret); } +int +fwprintf_l(FILE * __restrict fp, locale_t locale, const wchar_t * __restrict fmt, ...) +{ + int ret; + va_list ap; + + va_start(ap, fmt); + ret = vfwprintf_l(fp, locale, fmt, ap); + va_end(ap); + + return (ret); +} Index: lib/libc/stdio/tmpfile.c =================================================================== --- lib/libc/stdio/tmpfile.c (revision 225653) +++ lib/libc/stdio/tmpfile.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)tmpfile.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/tmpfile.c 165903 2007-01-09 00:28:16Z imp $"); #include "namespace.h" #include Index: lib/libc/stdio/rget.c =================================================================== --- lib/libc/stdio/rget.c (revision 225653) +++ lib/libc/stdio/rget.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)rget.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/rget.c 165903 2007-01-09 00:28:16Z imp $"); #include #include "local.h" Index: lib/libc/stdio/fopen.c =================================================================== --- lib/libc/stdio/fopen.c (revision 225653) +++ lib/libc/stdio/fopen.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)fopen.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/fopen.c 178427 2008-04-22 17:03:32Z jhb $"); #include "namespace.h" #include Index: lib/libc/stdio/fputwc.c =================================================================== --- lib/libc/stdio/fputwc.c (revision 225653) +++ lib/libc/stdio/fputwc.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002-2004 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -25,7 +30,7 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/fputwc.c 178287 2008-04-17 22:17:54Z jhb $"); #include "namespace.h" #include @@ -42,10 +47,11 @@ * Non-MT-safe version. */ wint_t -__fputwc(wchar_t wc, FILE *fp) +__fputwc(wchar_t wc, FILE *fp, locale_t locale) { char buf[MB_LEN_MAX]; size_t i, len; + struct xlocale_ctype *l = XLOCALE_CTYPE(locale); if (MB_CUR_MAX == 1 && wc > 0 && wc <= UCHAR_MAX) { /* @@ -56,7 +62,7 @@ *buf = (unsigned char)wc; len = 1; } else { - if ((len = __wcrtomb(buf, wc, &fp->_mbstate)) == (size_t)-1) { + if ((len = l->__wcrtomb(buf, wc, &fp->_mbstate)) == (size_t)-1) { fp->_flags |= __SERR; return (WEOF); } @@ -73,14 +79,20 @@ * MT-safe version. */ wint_t -fputwc(wchar_t wc, FILE *fp) +fputwc_l(wchar_t wc, FILE *fp, locale_t locale) { wint_t r; + FIX_LOCALE(locale); FLOCKFILE(fp); ORIENT(fp, 1); - r = __fputwc(wc, fp); + r = __fputwc(wc, fp, locale); FUNLOCKFILE(fp); return (r); } +wint_t +fputwc(wchar_t wc, FILE *fp) +{ + return fputwc_l(wc, fp, __get_locale()); +} Index: lib/libc/stdio/vsprintf.c =================================================================== --- lib/libc/stdio/vsprintf.c (revision 225653) +++ lib/libc/stdio/vsprintf.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Chris Torek. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -34,22 +39,30 @@ static char sccsid[] = "@(#)vsprintf.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/vsprintf.c 205021 2010-03-11 17:03:32Z jhb $"); #include #include #include "local.h" +#include "xlocale_private.h" int -vsprintf(char * __restrict str, const char * __restrict fmt, __va_list ap) +vsprintf_l(char * __restrict str, locale_t locale, + const char * __restrict fmt, __va_list ap) { int ret; FILE f = FAKE_FILE; + FIX_LOCALE(locale); f._flags = __SWR | __SSTR; f._bf._base = f._p = (unsigned char *)str; f._bf._size = f._w = INT_MAX; - ret = __vfprintf(&f, fmt, ap); + ret = __vfprintf(&f, locale, fmt, ap); *f._p = 0; return (ret); } +int +vsprintf(char * __restrict str, const char * __restrict fmt, __va_list ap) +{ + return vsprintf_l(str, __get_locale(), fmt, ap); +} Index: lib/libc/stdio/fclose.c =================================================================== --- lib/libc/stdio/fclose.c (revision 225653) +++ lib/libc/stdio/fclose.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)fclose.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/fclose.c 165903 2007-01-09 00:28:16Z imp $"); #include "namespace.h" #include Index: lib/libc/stdio/vwprintf.c =================================================================== --- lib/libc/stdio/vwprintf.c (revision 225653) +++ lib/libc/stdio/vwprintf.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002 Tim J. Robbins * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -25,15 +30,20 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/vwprintf.c 103739 2002-09-21 13:00:30Z tjr $"); #include #include #include +#include int vwprintf(const wchar_t * __restrict fmt, va_list ap) { - return (vfwprintf(stdout, fmt, ap)); } +int +vwprintf_l(locale_t locale, const wchar_t * __restrict fmt, va_list ap) +{ + return (vfwprintf_l(stdout, locale, fmt, ap)); +} Index: lib/libc/stdio/fputc.c =================================================================== --- lib/libc/stdio/fputc.c (revision 225653) +++ lib/libc/stdio/fputc.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)fputc.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/fputc.c 165903 2007-01-09 00:28:16Z imp $"); #include "namespace.h" #include Index: lib/libc/stdio/fflush.c =================================================================== --- lib/libc/stdio/fflush.c (revision 225653) +++ lib/libc/stdio/fflush.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)fflush.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/fflush.c 165903 2007-01-09 00:28:16Z imp $"); #include "namespace.h" #include Index: lib/libc/stdio/fwscanf.c =================================================================== --- lib/libc/stdio/fwscanf.c (revision 225653) +++ lib/libc/stdio/fwscanf.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002 Tim J. Robbins * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -25,11 +30,12 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/fwscanf.c 103856 2002-09-23 12:40:06Z tjr $"); #include #include #include +#include int fwscanf(FILE * __restrict fp, const wchar_t * __restrict fmt, ...) @@ -43,3 +49,15 @@ return (r); } +int +fwscanf_l(FILE * __restrict fp, locale_t locale, const wchar_t * __restrict fmt, ...) +{ + va_list ap; + int r; + + va_start(ap, fmt); + r = vfwscanf_l(fp, locale, fmt, ap); + va_end(ap); + + return (r); +} Index: lib/libc/stdio/fputws.c =================================================================== --- lib/libc/stdio/fputws.c (revision 225653) +++ lib/libc/stdio/fputws.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002-2004 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -25,7 +30,7 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/fputws.c 187302 2009-01-15 18:53:52Z rdivacky $"); #include "namespace.h" #include @@ -39,13 +44,15 @@ #include "mblocal.h" int -fputws(const wchar_t * __restrict ws, FILE * __restrict fp) +fputws_l(const wchar_t * __restrict ws, FILE * __restrict fp, locale_t locale) { size_t nbytes; char buf[BUFSIZ]; struct __suio uio; struct __siov iov; const wchar_t *wsp; + FIX_LOCALE(locale); + struct xlocale_ctype *l = XLOCALE_CTYPE(locale); FLOCKFILE(fp); ORIENT(fp, 1); @@ -56,7 +63,7 @@ iov.iov_base = buf; do { wsp = ws; - nbytes = __wcsnrtombs(buf, &wsp, SIZE_T_MAX, sizeof(buf), + nbytes = l->__wcsnrtombs(buf, &wsp, SIZE_T_MAX, sizeof(buf), &fp->_mbstate); if (nbytes == (size_t)-1) goto error; @@ -71,3 +78,9 @@ FUNLOCKFILE(fp); return (-1); } + +int +fputws(const wchar_t * __restrict ws, FILE * __restrict fp) +{ + return fputws_l(ws, fp, __get_locale()); +} Index: lib/libc/stdio/scanf.c =================================================================== --- lib/libc/stdio/scanf.c (revision 225653) +++ lib/libc/stdio/scanf.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Chris Torek. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -34,7 +39,7 @@ static char sccsid[] = "@(#)scanf.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/scanf.c 165903 2007-01-09 00:28:16Z imp $"); #include "namespace.h" #include @@ -42,6 +47,7 @@ #include "un-namespace.h" #include "libc_private.h" #include "local.h" +#include "xlocale_private.h" int scanf(char const * __restrict fmt, ...) @@ -51,8 +57,22 @@ va_start(ap, fmt); FLOCKFILE(stdin); - ret = __svfscanf(stdin, fmt, ap); + ret = __svfscanf(stdin, __get_locale(), fmt, ap); FUNLOCKFILE(stdin); va_end(ap); return (ret); } +int +scanf_l(locale_t locale, char const * __restrict fmt, ...) +{ + int ret; + va_list ap; + FIX_LOCALE(locale); + + va_start(ap, fmt); + FLOCKFILE(stdin); + ret = __svfscanf(stdin, locale, fmt, ap); + FUNLOCKFILE(stdin); + va_end(ap); + return (ret); +} Index: lib/libc/stdio/getdelim.c =================================================================== --- lib/libc/stdio/getdelim.c (revision 225653) +++ lib/libc/stdio/getdelim.c (working copy) @@ -25,7 +25,7 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/getdelim.c 197752 2009-10-04 19:43:36Z das $"); #include "namespace.h" #include Index: lib/libc/stdio/tmpnam.c =================================================================== --- lib/libc/stdio/tmpnam.c (revision 225653) +++ lib/libc/stdio/tmpnam.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)tmpnam.c 8.3 (Berkeley) 3/28/94"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/tmpnam.c 165903 2007-01-09 00:28:16Z imp $"); #include Index: lib/libc/stdio/fputs.c =================================================================== --- lib/libc/stdio/fputs.c (revision 225653) +++ lib/libc/stdio/fputs.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)fputs.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/fputs.c 165903 2007-01-09 00:28:16Z imp $"); #include "namespace.h" #include Index: lib/libc/stdio/wbuf.c =================================================================== --- lib/libc/stdio/wbuf.c (revision 225653) +++ lib/libc/stdio/wbuf.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)wbuf.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/wbuf.c 165903 2007-01-09 00:28:16Z imp $"); #include #include "local.h" Index: lib/libc/stdio/swscanf.c =================================================================== --- lib/libc/stdio/swscanf.c (revision 225653) +++ lib/libc/stdio/swscanf.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002 Tim J. Robbins * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -25,11 +30,12 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/swscanf.c 103856 2002-09-23 12:40:06Z tjr $"); #include #include #include +#include int swscanf(const wchar_t * __restrict str, const wchar_t * __restrict fmt, ...) @@ -43,3 +49,16 @@ return (r); } +int +swscanf_l(const wchar_t * __restrict str, locale_t locale, + const wchar_t * __restrict fmt, ...) +{ + va_list ap; + int r; + + va_start(ap, fmt); + r = vswscanf_l(str, locale, fmt, ap); + va_end(ap); + + return (r); +} Index: lib/libc/stdio/xprintf_int.c =================================================================== --- lib/libc/stdio/xprintf_int.c (revision 225653) +++ lib/libc/stdio/xprintf_int.c (working copy) @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD$ + * $FreeBSD: head/lib/libc/stdio/xprintf_int.c 153641 2005-12-22 14:23:54Z cognet $ */ #include Index: lib/libc/stdio/findfp.c =================================================================== --- lib/libc/stdio/findfp.c (revision 225653) +++ lib/libc/stdio/findfp.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)findfp.c 8.2 (Berkeley) 1/4/94"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/findfp.c 205021 2010-03-11 17:03:32Z jhb $"); #include #include Index: lib/libc/stdio/vwscanf.c =================================================================== --- lib/libc/stdio/vwscanf.c (revision 225653) +++ lib/libc/stdio/vwscanf.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002 Tim J. Robbins * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -25,15 +30,20 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/vwscanf.c 103856 2002-09-23 12:40:06Z tjr $"); #include #include #include +#include int vwscanf(const wchar_t * __restrict fmt, va_list ap) { - return (vfwscanf(stdin, fmt, ap)); } +int +vwscanf_l(locale_t locale, const wchar_t * __restrict fmt, va_list ap) +{ + return (vfwscanf_l(stdin, locale, fmt, ap)); +} Index: lib/libc/stdio/xprintf_time.c =================================================================== --- lib/libc/stdio/xprintf_time.c (revision 225653) +++ lib/libc/stdio/xprintf_time.c (working copy) @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD$ + * $FreeBSD: head/lib/libc/stdio/xprintf_time.c 219346 2011-03-06 19:47:46Z pjd $ */ #include #include Index: lib/libc/stdio/makebuf.c =================================================================== --- lib/libc/stdio/makebuf.c (revision 225653) +++ lib/libc/stdio/makebuf.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)makebuf.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/makebuf.c 165903 2007-01-09 00:28:16Z imp $"); #include "namespace.h" #include Index: lib/libc/stdio/putc.c =================================================================== --- lib/libc/stdio/putc.c (revision 225653) +++ lib/libc/stdio/putc.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)putc.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/putc.c 178778 2008-05-05 16:03:52Z jhb $"); #include "namespace.h" #include Index: lib/libc/stdio/fdopen.c =================================================================== --- lib/libc/stdio/fdopen.c (revision 225653) +++ lib/libc/stdio/fdopen.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)fdopen.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/fdopen.c 178921 2008-05-10 18:39:20Z antoine $"); #include "namespace.h" #include Index: lib/libc/stdio/fileno.c =================================================================== --- lib/libc/stdio/fileno.c (revision 225653) +++ lib/libc/stdio/fileno.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)fileno.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/fileno.c 178778 2008-05-05 16:03:52Z jhb $"); #include "namespace.h" #include Index: lib/libc/stdio/sscanf.c =================================================================== --- lib/libc/stdio/sscanf.c (revision 225653) +++ lib/libc/stdio/sscanf.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Chris Torek. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -34,11 +39,12 @@ static char sccsid[] = "@(#)sscanf.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/sscanf.c 200800 2009-12-21 19:56:03Z delphij $"); #include #include #include +#include #include "local.h" int @@ -52,3 +58,15 @@ va_end(ap); return (ret); } +int +sscanf_l(const char * __restrict str, locale_t locale, + char const * __restrict fmt, ...) +{ + int ret; + va_list ap; + + va_start(ap, fmt); + ret = vsscanf_l(str, locale, fmt, ap); + va_end(ap); + return (ret); +} Index: lib/libc/stdio/setvbuf.c =================================================================== --- lib/libc/stdio/setvbuf.c (revision 225653) +++ lib/libc/stdio/setvbuf.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)setvbuf.c 8.2 (Berkeley) 11/16/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/setvbuf.c 165903 2007-01-09 00:28:16Z imp $"); #include "namespace.h" #include Index: lib/libc/stdio/fgetwc.c =================================================================== --- lib/libc/stdio/fgetwc.c (revision 225653) +++ lib/libc/stdio/fgetwc.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002-2004 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -25,7 +30,7 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/fgetwc.c 178287 2008-04-17 22:17:54Z jhb $"); #include "namespace.h" #include @@ -36,31 +41,39 @@ #include "libc_private.h" #include "local.h" #include "mblocal.h" +#include "xlocale_private.h" /* * MT-safe version. */ wint_t -fgetwc(FILE *fp) +fgetwc_l(FILE *fp, locale_t locale) { wint_t r; + FIX_LOCALE(locale); FLOCKFILE(fp); ORIENT(fp, 1); - r = __fgetwc(fp); + r = __fgetwc(fp, locale); FUNLOCKFILE(fp); return (r); } +wint_t +fgetwc(FILE *fp) +{ + return fgetwc_l(fp, __get_locale()); +} /* * Non-MT-safe version. */ wint_t -__fgetwc(FILE *fp) +__fgetwc(FILE *fp, locale_t locale) { wchar_t wc; size_t nconv; + struct xlocale_ctype *l = XLOCALE_CTYPE(locale); if (fp->_r <= 0 && __srefill(fp)) return (WEOF); @@ -71,7 +84,7 @@ return (wc); } do { - nconv = __mbrtowc(&wc, fp->_p, fp->_r, &fp->_mbstate); + nconv = l->__mbrtowc(&wc, fp->_p, fp->_r, &fp->_mbstate); if (nconv == (size_t)-1) break; else if (nconv == (size_t)-2) Index: lib/libc/stdio/ungetc.c =================================================================== --- lib/libc/stdio/ungetc.c (revision 225653) +++ lib/libc/stdio/ungetc.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)ungetc.c 8.2 (Berkeley) 11/3/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/ungetc.c 178287 2008-04-17 22:17:54Z jhb $"); #include "namespace.h" #include Index: lib/libc/stdio/vfscanf.c =================================================================== --- lib/libc/stdio/vfscanf.c (revision 225653) +++ lib/libc/stdio/vfscanf.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * This code is derived from software contributed to Berkeley by * Chris Torek. * @@ -34,7 +39,7 @@ static char sccsid[] = "@(#)vfscanf.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/vfscanf.c 187422 2009-01-19 06:19:51Z das $"); #include "namespace.h" #include @@ -51,6 +56,7 @@ #include "collate.h" #include "libc_private.h" #include "local.h" +#include "xlocale_private.h" #ifndef NO_FLOATING_POINT #include @@ -95,11 +101,12 @@ static const u_char *__sccl(char *, const u_char *); #ifndef NO_FLOATING_POINT -static int parsefloat(FILE *, char *, char *); +static int parsefloat(FILE *, char *, char *, locale_t); #endif __weak_reference(__vfscanf, vfscanf); + /* * __vfscanf - MT-safe version */ @@ -109,16 +116,27 @@ int ret; FLOCKFILE(fp); - ret = __svfscanf(fp, fmt0, ap); + ret = __svfscanf(fp, __get_locale(), fmt0, ap); FUNLOCKFILE(fp); return (ret); } +int +vfscanf_l(FILE *fp, locale_t locale, char const *fmt0, va_list ap) +{ + int ret; + FIX_LOCALE(locale); + FLOCKFILE(fp); + ret = __svfscanf(fp, locale, fmt0, ap); + FUNLOCKFILE(fp); + return (ret); +} + /* * __svfscanf - non-MT-safe version of __vfscanf */ int -__svfscanf(FILE *fp, const char *fmt0, va_list ap) +__svfscanf(FILE *fp, locale_t locale, const char *fmt0, va_list ap) { const u_char *fmt = (const u_char *)fmt0; int c; /* character from format, or conversion */ @@ -455,8 +473,7 @@ !ccltab[wctob(*wcp)]) { while (n != 0) { n--; - __ungetc(buf[n], - fp); + __ungetc(buf[n], fp); } break; } @@ -555,8 +572,7 @@ if (iswspace(*wcp)) { while (n != 0) { n--; - __ungetc(buf[n], - fp); + __ungetc(buf[n], fp); } break; } @@ -733,9 +749,9 @@ *p = 0; if ((flags & UNSIGNED) == 0) - res = strtoimax(buf, (char **)NULL, base); + res = strtoimax_l(buf, (char **)NULL, base, locale); else - res = strtoumax(buf, (char **)NULL, base); + res = strtoumax_l(buf, (char **)NULL, base, locale); if (flags & POINTER) *va_arg(ap, void **) = (void *)(uintptr_t)res; @@ -766,17 +782,17 @@ /* scan a floating point number as if by strtod */ if (width == 0 || width > sizeof(buf) - 1) width = sizeof(buf) - 1; - if ((width = parsefloat(fp, buf, buf + width)) == 0) + if ((width = parsefloat(fp, buf, buf + width, locale)) == 0) goto match_failure; if ((flags & SUPPRESS) == 0) { if (flags & LONGDBL) { - long double res = strtold(buf, &p); + long double res = strtold_l(buf, &p, locale); *va_arg(ap, long double *) = res; } else if (flags & LONG) { - double res = strtod(buf, &p); + double res = strtod_l(buf, &p, locale); *va_arg(ap, double *) = res; } else { - float res = strtof(buf, &p); + float res = strtof_l(buf, &p, locale); *va_arg(ap, float *) = res; } nassigned++; @@ -805,6 +821,8 @@ const u_char *fmt; { int c, n, v, i; + struct xlocale_collate *table = + (struct xlocale_collate*)__get_locale()->components[XLC_COLLATE]; /* first `clear' the whole table */ c = *fmt++; /* first char hat => negated scanset */ @@ -858,8 +876,8 @@ */ n = *fmt; if (n == ']' - || (__collate_load_error ? n < c : - __collate_range_cmp (n, c) < 0 + || (table->__collate_load_error ? n < c : + __collate_range_cmp (table, n, c) < 0 ) ) { c = '-'; @@ -867,14 +885,14 @@ } fmt++; /* fill in the range */ - if (__collate_load_error) { + if (table->__collate_load_error) { do { tab[++c] = v; } while (c < n); } else { for (i = 0; i < 256; i ++) - if ( __collate_range_cmp (c, i) < 0 - && __collate_range_cmp (i, n) <= 0 + if ( __collate_range_cmp (table, c, i) < 0 + && __collate_range_cmp (table, i, n) <= 0 ) tab[i] = v; } @@ -908,7 +926,7 @@ #ifndef NO_FLOATING_POINT static int -parsefloat(FILE *fp, char *buf, char *end) +parsefloat(FILE *fp, char *buf, char *end, locale_t locale) { char *commit, *p; int infnanpos = 0, decptpos = 0; @@ -917,7 +935,7 @@ S_DIGITS, S_DECPT, S_FRAC, S_EXP, S_EXPDIGITS } state = S_START; unsigned char c; - const char *decpt = localeconv()->decimal_point; + const char *decpt = localeconv_l(locale)->decimal_point; _Bool gotmantdig = 0, ishex = 0; /* Index: lib/libc/stdio/puts.c =================================================================== --- lib/libc/stdio/puts.c (revision 225653) +++ lib/libc/stdio/puts.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)puts.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/puts.c 165903 2007-01-09 00:28:16Z imp $"); #include "namespace.h" #include Index: lib/libc/stdio/fseek.c =================================================================== --- lib/libc/stdio/fseek.c (revision 225653) +++ lib/libc/stdio/fseek.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)fseek.c 8.3 (Berkeley) 1/2/94"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/fseek.c 178287 2008-04-17 22:17:54Z jhb $"); #include "namespace.h" #include Index: lib/libc/stdio/putw.c =================================================================== --- lib/libc/stdio/putw.c (revision 225653) +++ lib/libc/stdio/putw.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)putw.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/putw.c 165903 2007-01-09 00:28:16Z imp $"); #include "namespace.h" #include Index: lib/libc/stdio/fgetws.c =================================================================== --- lib/libc/stdio/fgetws.c (revision 225653) +++ lib/libc/stdio/fgetws.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002-2004 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -25,7 +30,7 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/fgetws.c 199784 2009-11-25 04:45:45Z wollman $"); #include "namespace.h" #include @@ -38,12 +43,14 @@ #include "mblocal.h" wchar_t * -fgetws(wchar_t * __restrict ws, int n, FILE * __restrict fp) +fgetws_l(wchar_t * __restrict ws, int n, FILE * __restrict fp, locale_t locale) { wchar_t *wsp; size_t nconv; const char *src; unsigned char *nl; + FIX_LOCALE(locale); + struct xlocale_ctype *l = XLOCALE_CTYPE(locale); FLOCKFILE(fp); ORIENT(fp, 1); @@ -60,7 +67,7 @@ do { src = fp->_p; nl = memchr(fp->_p, '\n', fp->_r); - nconv = __mbsnrtowcs(wsp, &src, + nconv = l->__mbsnrtowcs(wsp, &src, nl != NULL ? (nl - fp->_p + 1) : fp->_r, n - 1, &fp->_mbstate); if (nconv == (size_t)-1) @@ -86,7 +93,7 @@ if (wsp == ws) /* EOF */ goto error; - if (!__mbsinit(&fp->_mbstate)) + if (!l->__mbsinit(&fp->_mbstate)) /* Incomplete character */ goto error; *wsp = L'\0'; @@ -98,3 +105,8 @@ FUNLOCKFILE(fp); return (NULL); } +wchar_t * +fgetws(wchar_t * __restrict ws, int n, FILE * __restrict fp) +{ + return fgetws_l(ws, n, fp, __get_locale()); +} Index: lib/libc/stdio/fwrite.c =================================================================== --- lib/libc/stdio/fwrite.c (revision 225653) +++ lib/libc/stdio/fwrite.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)fwrite.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/fwrite.c 201999 2010-01-10 14:30:30Z cperciva $"); #include "namespace.h" #include Index: lib/libc/stdio/funopen.c =================================================================== --- lib/libc/stdio/funopen.c (revision 225653) +++ lib/libc/stdio/funopen.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)funopen.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/funopen.c 200150 2009-12-05 19:31:38Z ed $"); #include #include Index: lib/libc/stdio/vasprintf.c =================================================================== --- lib/libc/stdio/vasprintf.c (revision 225653) +++ lib/libc/stdio/vasprintf.c (working copy) @@ -4,6 +4,11 @@ * Copyright (c) 1997 Todd C. Miller * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -28,18 +33,20 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/vasprintf.c 206217 2010-04-05 22:09:29Z obrien $"); #include #include #include +#include "xlocale_private.h" #include "local.h" int -vasprintf(char **str, const char *fmt, __va_list ap) +vasprintf_l(char **str, locale_t locale, const char *fmt, __va_list ap) { FILE f = FAKE_FILE; int ret; + FIX_LOCALE(locale); f._flags = __SWR | __SSTR | __SALC; f._bf._base = f._p = malloc(128); @@ -49,7 +56,7 @@ return (-1); } f._bf._size = f._w = 127; /* Leave room for the NUL */ - ret = __vfprintf(&f, fmt, ap); + ret = __vfprintf(&f, locale, fmt, ap); if (ret < 0) { free(f._bf._base); *str = NULL; @@ -60,3 +67,8 @@ *str = (char *)f._bf._base; return (ret); } +int +vasprintf(char **str, const char *fmt, __va_list ap) +{ + return vasprintf_l(str, __get_locale(), fmt, ap); +} Index: lib/libc/stdio/vfwscanf.c =================================================================== --- lib/libc/stdio/vfwscanf.c (revision 225653) +++ lib/libc/stdio/vfwscanf.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Chris Torek. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -36,7 +41,7 @@ #endif /* LIBC_SCCS and not lint */ #endif #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/vfwscanf.c 187422 2009-01-19 06:19:51Z das $"); #include "namespace.h" #include @@ -53,11 +58,8 @@ #include "libc_private.h" #include "local.h" +#include "xlocale_private.h" -#ifndef NO_FLOATING_POINT -#include -#endif - #define BUF 513 /* Maximum length of numeric string. */ /* @@ -96,7 +98,7 @@ #define CT_FLOAT 4 /* %[efgEFG] conversion */ #ifndef NO_FLOATING_POINT -static int parsefloat(FILE *, wchar_t *, wchar_t *); +static int parsefloat(FILE *, wchar_t *, wchar_t *, locale_t); #endif #define INCCL(_c) \ @@ -109,22 +111,30 @@ * MT-safe version. */ int -vfwscanf(FILE * __restrict fp, const wchar_t * __restrict fmt, va_list ap) +vfwscanf_l(FILE * __restrict fp, locale_t locale, + const wchar_t * __restrict fmt, va_list ap) { int ret; + FIX_LOCALE(locale); FLOCKFILE(fp); ORIENT(fp, 1); - ret = __vfwscanf(fp, fmt, ap); + ret = __vfwscanf(fp, locale, fmt, ap); FUNLOCKFILE(fp); return (ret); } +int +vfwscanf(FILE * __restrict fp, const wchar_t * __restrict fmt, va_list ap) +{ + return vfwscanf_l(fp, __get_locale(), fmt, ap); +} /* * Non-MT-safe version. */ int -__vfwscanf(FILE * __restrict fp, const wchar_t * __restrict fmt, va_list ap) +__vfwscanf(FILE * __restrict fp, locale_t locale, + const wchar_t * __restrict fmt, va_list ap) { wint_t c; /* character from format, or conversion */ size_t width; /* field width, or 0 */ @@ -159,11 +169,11 @@ if (c == 0) return (nassigned); if (iswspace(c)) { - while ((c = __fgetwc(fp)) != WEOF && - iswspace(c)) + while ((c = __fgetwc(fp, locale)) != WEOF && + iswspace_l(c, locale)) ; if (c != WEOF) - __ungetwc(c, fp); + __ungetwc(c, fp, locale); continue; } if (c != '%') @@ -178,10 +188,10 @@ switch (c) { case '%': literal: - if ((wi = __fgetwc(fp)) == WEOF) + if ((wi = __fgetwc(fp, locale)) == WEOF) goto input_failure; if (wi != c) { - __ungetwc(wi, fp); + __ungetwc(wi, fp, locale); goto input_failure; } nread++; @@ -341,11 +351,11 @@ * that suppress this. */ if ((flags & NOSKIP) == 0) { - while ((wi = __fgetwc(fp)) != WEOF && iswspace(wi)) + while ((wi = __fgetwc(fp, locale)) != WEOF && iswspace(wi)) nread++; if (wi == WEOF) goto input_failure; - __ungetwc(wi, fp); + __ungetwc(wi, fp, locale); } /* @@ -362,7 +372,7 @@ p = va_arg(ap, wchar_t *); n = 0; while (width-- != 0 && - (wi = __fgetwc(fp)) != WEOF) { + (wi = __fgetwc(fp, locale)) != WEOF) { if (!(flags & SUPPRESS)) *p++ = (wchar_t)wi; n++; @@ -378,7 +388,7 @@ n = 0; mbs = initial_mbs; while (width != 0 && - (wi = __fgetwc(fp)) != WEOF) { + (wi = __fgetwc(fp, locale)) != WEOF) { if (width >= MB_CUR_MAX && !(flags & SUPPRESS)) { nconv = wcrtomb(mbp, wi, &mbs); @@ -390,7 +400,7 @@ if (nconv == (size_t)-1) goto input_failure; if (nconv > width) { - __ungetwc(wi, fp); + __ungetwc(wi, fp, locale); break; } if (!(flags & SUPPRESS)) @@ -418,20 +428,20 @@ /* take only those things in the class */ if ((flags & SUPPRESS) && (flags & LONG)) { n = 0; - while ((wi = __fgetwc(fp)) != WEOF && + while ((wi = __fgetwc(fp, locale)) != WEOF && width-- != 0 && INCCL(wi)) n++; if (wi != WEOF) - __ungetwc(wi, fp); + __ungetwc(wi, fp, locale); if (n == 0) goto match_failure; } else if (flags & LONG) { p0 = p = va_arg(ap, wchar_t *); - while ((wi = __fgetwc(fp)) != WEOF && + while ((wi = __fgetwc(fp, locale)) != WEOF && width-- != 0 && INCCL(wi)) *p++ = (wchar_t)wi; if (wi != WEOF) - __ungetwc(wi, fp); + __ungetwc(wi, fp, locale); n = p - p0; if (n == 0) goto match_failure; @@ -442,7 +452,7 @@ mbp = va_arg(ap, char *); n = 0; mbs = initial_mbs; - while ((wi = __fgetwc(fp)) != WEOF && + while ((wi = __fgetwc(fp, locale)) != WEOF && width != 0 && INCCL(wi)) { if (width >= MB_CUR_MAX && !(flags & SUPPRESS)) { @@ -466,7 +476,7 @@ n++; } if (wi != WEOF) - __ungetwc(wi, fp); + __ungetwc(wi, fp, locale); if (!(flags & SUPPRESS)) { *mbp = 0; nassigned++; @@ -481,29 +491,29 @@ if (width == 0) width = (size_t)~0; if ((flags & SUPPRESS) && (flags & LONG)) { - while ((wi = __fgetwc(fp)) != WEOF && + while ((wi = __fgetwc(fp, locale)) != WEOF && width-- != 0 && !iswspace(wi)) nread++; if (wi != WEOF) - __ungetwc(wi, fp); + __ungetwc(wi, fp, locale); } else if (flags & LONG) { p0 = p = va_arg(ap, wchar_t *); - while ((wi = __fgetwc(fp)) != WEOF && + while ((wi = __fgetwc(fp, locale)) != WEOF && width-- != 0 && !iswspace(wi)) { *p++ = (wchar_t)wi; nread++; } if (wi != WEOF) - __ungetwc(wi, fp); + __ungetwc(wi, fp, locale); *p = '\0'; nassigned++; } else { if (!(flags & SUPPRESS)) mbp = va_arg(ap, char *); mbs = initial_mbs; - while ((wi = __fgetwc(fp)) != WEOF && + while ((wi = __fgetwc(fp, locale)) != WEOF && width != 0 && !iswspace(wi)) { if (width >= MB_CUR_MAX && @@ -528,7 +538,7 @@ nread++; } if (wi != WEOF) - __ungetwc(wi, fp); + __ungetwc(wi, fp, locale); if (!(flags & SUPPRESS)) { *mbp = 0; nassigned++; @@ -544,7 +554,7 @@ width = sizeof(buf) / sizeof(*buf) - 1; flags |= SIGNOK | NDIGITS | NZDIGITS; for (p = buf; width; width--) { - c = __fgetwc(fp); + c = __fgetwc(fp, locale); /* * Switch on the character; `goto ok' * if we accept it as a part of number. @@ -628,7 +638,7 @@ * for a number. Stop accumulating digits. */ if (c != WEOF) - __ungetwc(c, fp); + __ungetwc(c, fp, locale); break; ok: /* @@ -644,13 +654,13 @@ */ if (flags & NDIGITS) { if (p > buf) - __ungetwc(*--p, fp); + __ungetwc(*--p, fp, locale); goto match_failure; } c = p[-1]; if (c == 'x' || c == 'X') { --p; - __ungetwc(c, fp); + __ungetwc(c, fp, locale); } if ((flags & SUPPRESS) == 0) { uintmax_t res; @@ -691,7 +701,7 @@ if (width == 0 || width > sizeof(buf) / sizeof(*buf) - 1) width = sizeof(buf) / sizeof(*buf) - 1; - if ((width = parsefloat(fp, buf, buf + width)) == 0) + if ((width = parsefloat(fp, buf, buf + width, locale)) == 0) goto match_failure; if ((flags & SUPPRESS) == 0) { if (flags & LONGDBL) { @@ -720,7 +730,7 @@ #ifndef NO_FLOATING_POINT static int -parsefloat(FILE *fp, wchar_t *buf, wchar_t *end) +parsefloat(FILE *fp, wchar_t *buf, wchar_t *end, locale_t locale) { mbstate_t mbs; size_t nconv; @@ -751,7 +761,7 @@ commit = buf - 1; c = WEOF; for (p = buf; p < end; ) { - if ((c = __fgetwc(fp)) == WEOF) + if ((c = __fgetwc(fp, locale)) == WEOF) break; reswitch: switch (state) { @@ -871,9 +881,9 @@ parsedone: if (c != WEOF) - __ungetwc(c, fp); + __ungetwc(c, fp, locale); while (commit < --p) - __ungetwc(*p, fp); + __ungetwc(*p, fp, locale); *++commit = '\0'; return (commit - buf); } Index: lib/libc/stdio/fread.c =================================================================== --- lib/libc/stdio/fread.c (revision 225653) +++ lib/libc/stdio/fread.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)fread.c 8.2 (Berkeley) 12/11/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/fread.c 201999 2010-01-10 14:30:30Z cperciva $"); #include "namespace.h" #include Index: lib/libc/stdio/xprintf_hexdump.c =================================================================== --- lib/libc/stdio/xprintf_hexdump.c (revision 225653) +++ lib/libc/stdio/xprintf_hexdump.c (working copy) @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD$ + * $FreeBSD: head/lib/libc/stdio/xprintf_hexdump.c 153486 2005-12-16 18:56:39Z phk $ */ #include Index: lib/libc/stdio/asprintf.c =================================================================== --- lib/libc/stdio/asprintf.c (revision 225653) +++ lib/libc/stdio/asprintf.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Chris Torek. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -31,10 +36,11 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/asprintf.c 199096 2009-11-09 18:50:34Z jhb $"); #include #include +#include int asprintf(char ** __restrict s, char const * __restrict fmt, ...) @@ -47,3 +53,15 @@ va_end(ap); return (ret); } +int +asprintf_l(char ** __restrict s, locale_t locale, char const * __restrict fmt, + ...) +{ + int ret; + va_list ap; + + va_start(ap, fmt); + ret = vasprintf_l(s, locale, fmt, ap); + va_end(ap); + return (ret); +} Index: lib/libc/stdio/fgetc.c =================================================================== --- lib/libc/stdio/fgetc.c (revision 225653) +++ lib/libc/stdio/fgetc.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)fgetc.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/fgetc.c 165903 2007-01-09 00:28:16Z imp $"); #include "namespace.h" #include Index: lib/libc/stdio/vswscanf.c =================================================================== --- lib/libc/stdio/vswscanf.c (revision 225653) +++ lib/libc/stdio/vswscanf.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Donn Seeley at UUNET Technologies, Inc. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -37,7 +42,7 @@ #endif /* LIBC_SCCS and not lint */ __FBSDID("FreeBSD: src/lib/libc/stdio/vsscanf.c,v 1.11 2002/08/21 16:19:57 mike Exp "); #endif -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/vswscanf.c 205021 2010-03-11 17:03:32Z jhb $"); #include #include @@ -46,6 +51,7 @@ #include #include #include "local.h" +#include "xlocale_private.h" static int eofread(void *, char *, int); @@ -57,8 +63,8 @@ } int -vswscanf(const wchar_t * __restrict str, const wchar_t * __restrict fmt, - va_list ap) +vswscanf_l(const wchar_t * __restrict str, locale_t locale, + const wchar_t * __restrict fmt, va_list ap) { static const mbstate_t initial; mbstate_t mbs; @@ -67,6 +73,7 @@ size_t mlen; int r; const wchar_t *strp; + FIX_LOCALE(locale); /* * XXX Convert the wide character string to multibyte, which @@ -76,7 +83,7 @@ return (EOF); mbs = initial; strp = str; - if ((mlen = wcsrtombs(mbstr, &strp, SIZE_T_MAX, &mbs)) == (size_t)-1) { + if ((mlen = wcsrtombs_l(mbstr, &strp, SIZE_T_MAX, &mbs, locale)) == (size_t)-1) { free(mbstr); return (EOF); } @@ -84,8 +91,14 @@ f._bf._base = f._p = (unsigned char *)mbstr; f._bf._size = f._r = mlen; f._read = eofread; - r = __vfwscanf(&f, fmt, ap); + r = __vfwscanf(&f, locale, fmt, ap); free(mbstr); return (r); } +int +vswscanf(const wchar_t * __restrict str, const wchar_t * __restrict fmt, + va_list ap) +{ + return vswscanf_l(str, __get_locale(), fmt, ap); +} Index: lib/libc/locale/collate.c =================================================================== --- lib/libc/locale/collate.c (revision 225653) +++ lib/libc/locale/collate.c (working copy) @@ -3,6 +3,16 @@ * at Electronni Visti IA, Kiev, Ukraine. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -26,7 +36,7 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/collate.c 142686 2005-02-27 20:31:13Z ru $"); #include "namespace.h" #include @@ -44,24 +54,70 @@ #include "libc_private.h" -int __collate_load_error = 1; -int __collate_substitute_nontrivial; +/* + * To avoid modifying the original (single-threaded) code too much, we'll just + * define the old globals as fields inside the table. + * + * We also modify the collation table test functions to search the thread-local + * table first and the global table second. + */ +#define __collate_load_error (table->__collate_load_error) +#define __collate_substitute_nontrivial (table->__collate_substitute_nontrivial) +#define __collate_substitute_table_ptr (table->__collate_substitute_table_ptr) +#define __collate_char_pri_table_ptr (table->__collate_char_pri_table_ptr) +#define __collate_chain_pri_table (table->__collate_chain_pri_table) -u_char __collate_substitute_table[UCHAR_MAX + 1][STR_LEN]; -struct __collate_st_char_pri __collate_char_pri_table[UCHAR_MAX + 1]; -struct __collate_st_chain_pri *__collate_chain_pri_table; +struct xlocale_collate __xlocale_global_collate = { + {{0}, "C"}, 1, 0 +}; + void __collate_err(int ex, const char *f) __dead2; int +__collate_load_tables_l(const char *encoding, struct xlocale_collate *table); + +static void +destruct_collate(void *t) +{ + struct xlocale_collate *table = t; + if (__collate_chain_pri_table) { + free(__collate_chain_pri_table); + } + free(t); +} + +void * +__collate_load(const char *encoding, locale_t unused) +{ + struct xlocale_collate *table = calloc(sizeof(struct xlocale_collate), 1); + table->header.header.destructor = destruct_collate; + // FIXME: Make sure that _LDP_CACHE is never returned. We should be doing + // the caching outside of this section + if (__collate_load_tables_l(encoding, table) != _LDP_LOADED) { + xlocale_release(table); + return NULL; + } + return table; +} + +/** + * Load the collation tables for the specified encoding into the global table. + */ +int __collate_load_tables(const char *encoding) { + return __collate_load_tables_l(encoding, &__xlocale_global_collate); +} + +int +__collate_load_tables_l(const char *encoding, struct xlocale_collate *table) +{ FILE *fp; int i, saverr, chains; uint32_t u32; char strbuf[STR_LEN], buf[PATH_MAX]; void *TMP_substitute_table, *TMP_char_pri_table, *TMP_chain_pri_table; - static char collate_encoding[ENCODING_LEN + 1]; /* 'encoding' must be already checked. */ if (strcmp(encoding, "C") == 0 || strcmp(encoding, "POSIX") == 0) { @@ -69,18 +125,6 @@ return (_LDP_CACHE); } - /* - * If the locale name is the same as our cache, use the cache. - */ - if (strcmp(encoding, collate_encoding) == 0) { - __collate_load_error = 0; - return (_LDP_CACHE); - } - - /* - * Slurp the locale file into the cache. - */ - /* 'PathLocale' must be already set & checked. */ /* Range checking not needed, encoding has fixed size */ (void)strcpy(buf, _PathLocale); @@ -165,7 +209,6 @@ sizeof(*__collate_chain_pri_table), chains, fp); (void)fclose(fp); - (void)strcpy(collate_encoding, encoding); if (__collate_substitute_table_ptr != NULL) free(__collate_substitute_table_ptr); __collate_substitute_table_ptr = TMP_substitute_table; @@ -201,7 +244,7 @@ } u_char * -__collate_substitute(const u_char *s) +__collate_substitute(struct xlocale_collate *table, const u_char *s) { int dest_len, len, nlen; int delta = strlen(s); @@ -228,7 +271,7 @@ } void -__collate_lookup(const u_char *t, int *len, int *prim, int *sec) +__collate_lookup(struct xlocale_collate *table, const u_char *t, int *len, int *prim, int *sec) { struct __collate_st_chain_pri *p2; Index: lib/libc/locale/xlocale.c =================================================================== --- lib/libc/locale/xlocale.c (revision 0) +++ lib/libc/locale/xlocale.c (revision 0) @@ -0,0 +1,312 @@ +/*- + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by David Chisnall under sponsorship from + * the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions * are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include "libc_private.h" +#include "xlocale_private.h" + +/** + * Each locale loader declares a global component. This is used by setlocale() + * and also by xlocale with LC_GLOBAL_LOCALE.. + */ +extern struct xlocale_component __xlocale_global_collate; +extern struct xlocale_component __xlocale_global_ctype; +extern struct xlocale_component __xlocale_global_monetary; +extern struct xlocale_component __xlocale_global_numeric; +extern struct xlocale_component __xlocale_global_time; +extern struct xlocale_component __xlocale_global_messages; +/* + * Private functions in setlocale.c. + */ +const char * +__get_locale_env(int category); +int +__detect_path_locale(void); + +struct _xlocale __xlocale_global_locale = { + {0}, + { + &__xlocale_global_collate, + &__xlocale_global_ctype, + &__xlocale_global_monetary, + &__xlocale_global_numeric, + &__xlocale_global_time, + &__xlocale_global_messages + }, + 1, + 0, + 1, + 0 +}; + +static void*(*constructors[])(const char*, locale_t) = +{ + __collate_load, + __ctype_load, + __monetary_load, + __numeric_load, + __time_load, + __messages_load +}; + +static pthread_key_t locale_info_key; +static int fake_tls; +static locale_t thread_local_locale; + +static void init_key(void) +{ + pthread_key_create(&locale_info_key, xlocale_release); + pthread_setspecific(locale_info_key, (void*)42); + if (pthread_getspecific(locale_info_key) == (void*)42) { + pthread_setspecific(locale_info_key, 0); + } else { + fake_tls = 1; + } + __detect_path_locale(); +} + +static pthread_once_t once_control = PTHREAD_ONCE_INIT; + +static locale_t +get_thread_locale(void) +{ + _once(&once_control, init_key); + + return fake_tls ? thread_local_locale : + pthread_getspecific(locale_info_key); +} + +locale_t +__get_locale(void) +{ + locale_t l = get_thread_locale(); + return l ? l : &__xlocale_global_locale; + +} + +static void +set_thread_locale(locale_t loc) +{ + pthread_once(&once_control, init_key); + + if (NULL != loc) { + xlocale_retain((struct xlocale_refcounted*)loc); + } + locale_t old = pthread_getspecific(locale_info_key); + if ((NULL != old) && (loc != old)) { + xlocale_release((struct xlocale_refcounted*)old); + } + if (fake_tls) { + thread_local_locale = loc; + } else { + pthread_setspecific(locale_info_key, loc); + } +} + +/** + * Clean up a locale, once its reference count reaches zero. This function is + * called by xlocale_release(), it should not be called directly. + */ +static void +destruct_locale(void *l) +{ + locale_t loc = l; + for (int type=0 ; typecomponents[type]) { + xlocale_release(loc->components[type]); + } + } + if (loc->csym) { + free(loc->csym); + } + free(l); +} + +/** + * Allocates a new, uninitialised, locale. + */ +static locale_t +alloc_locale(void) +{ + locale_t new = calloc(sizeof(struct _xlocale), 1); + new->header.destructor = destruct_locale; + new->monetary_locale_changed = 1; + new->numeric_locale_changed = 1; + return new; +} +static void +copyflags(locale_t new, locale_t old) +{ + new->using_monetary_locale = old->using_monetary_locale; + new->using_numeric_locale = old->using_numeric_locale; + new->using_time_locale = old->using_time_locale; + new->using_messages_locale = old->using_messages_locale; +} + +static int dupcomponent(int type, locale_t base, locale_t new) +{ + /* Always copy from the global locale, since it has mutable components. */ + struct xlocale_component *src = base->components[type]; + if (&__xlocale_global_locale == base) { + new->components[type] = constructors[type](src->locale, new); + if (new->components[type]) { + strncpy(new->components[type]->locale, src->locale, ENCODING_LEN); + } + } else { + new->components[type] = xlocale_retain(base->components[type]); + } + return 0 != new->components[type]; +} + +/* + * Public interfaces. These are the five public functions described by the + * xlocale interface. + */ + +locale_t newlocale(int mask, const char *locale, locale_t base) +{ + int type; + const char *realLocale = locale; + int useenv = 0; + int success = 1; + + _once(&once_control, init_key); + + locale_t new = alloc_locale(); + if (NULL == new) { + return NULL; + } + + FIX_LOCALE(base); + copyflags(new, base); + + if (NULL == locale) { + realLocale = "C"; + } else if ('\0' == locale[0]) { + useenv = 1; + } + + for (type=0 ; typecomponents[type] = constructors[type](realLocale, new); + if (new->components[type]) { + strncpy(new->components[type]->locale, realLocale, ENCODING_LEN); + } else { + success = 0; + } + } else { + if (!dupcomponent(type, base, new)) { + success = 0; + } + } + mask >>= 1; + } + if (0 == success) { + xlocale_release(new); + new = NULL; + } + + return new; +} + +locale_t duplocale(locale_t base) +{ + locale_t new = alloc_locale(); + int type; + + _once(&once_control, init_key); + + if (NULL == new) { + return NULL; + } + + FIX_LOCALE(base); + copyflags(new, base); + + for (type=0 ; typecomponents[type]->locale; + } + mask >>= 1; + } + return NULL; +} + +/* + * Installs the specified locale_t as this thread's locale. + */ +locale_t uselocale(locale_t loc) +{ + locale_t old = get_thread_locale(); + if (NULL != loc) { + if (LC_GLOBAL_LOCALE == loc) { + loc = NULL; + } + set_thread_locale(loc); + } + return old ? old : LC_GLOBAL_LOCALE; +} + Index: lib/libc/locale/ascii.c =================================================================== --- lib/libc/locale/ascii.c (revision 225653) +++ lib/libc/locale/ascii.c (working copy) @@ -6,6 +6,11 @@ * This code is derived from software contributed to Berkeley by * Paul Borman at Krystal Technologies. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -32,7 +37,7 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/ascii.c 175553 2008-01-21 23:48:12Z ache $"); #include #include @@ -56,17 +61,17 @@ size_t, size_t, mbstate_t * __restrict); int -_ascii_init(_RuneLocale *rl) +_ascii_init(struct xlocale_ctype *l,_RuneLocale *rl) { - __mbrtowc = _ascii_mbrtowc; - __mbsinit = _ascii_mbsinit; - __mbsnrtowcs = _ascii_mbsnrtowcs; - __wcrtomb = _ascii_wcrtomb; - __wcsnrtombs = _ascii_wcsnrtombs; - _CurrentRuneLocale = rl; - __mb_cur_max = 1; - __mb_sb_limit = 128; + l->__mbrtowc = _ascii_mbrtowc; + l->__mbsinit = _ascii_mbsinit; + l->__mbsnrtowcs = _ascii_mbsnrtowcs; + l->__wcrtomb = _ascii_wcrtomb; + l->__wcsnrtombs = _ascii_wcsnrtombs; + l->runes = rl; + l->__mb_cur_max = 1; + l->__mb_sb_limit = 128; return(0); } Index: lib/libc/locale/collate.h =================================================================== --- lib/libc/locale/collate.h (revision 225653) +++ lib/libc/locale/collate.h (working copy) @@ -3,6 +3,11 @@ * at Electronni Visti IA, Kiev, Ukraine. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -24,7 +29,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD$ + * $FreeBSD: head/lib/libc/locale/collate.h 142686 2005-02-27 20:31:13Z ru $ */ #ifndef _COLLATE_H_ @@ -33,6 +38,7 @@ #include #include #include +#include "xlocale_private.h" #define STR_LEN 10 #define TABLE_SIZE 100 @@ -47,20 +53,26 @@ int prim, sec; }; -extern int __collate_load_error; -extern int __collate_substitute_nontrivial; #define __collate_substitute_table (*__collate_substitute_table_ptr) -extern u_char __collate_substitute_table[UCHAR_MAX + 1][STR_LEN]; #define __collate_char_pri_table (*__collate_char_pri_table_ptr) -extern struct __collate_st_char_pri __collate_char_pri_table[UCHAR_MAX + 1]; -extern struct __collate_st_chain_pri *__collate_chain_pri_table; +struct xlocale_collate { + struct xlocale_component header; + int __collate_load_error; + int __collate_substitute_nontrivial; + + u_char (*__collate_substitute_table_ptr)[UCHAR_MAX + 1][STR_LEN]; + struct __collate_st_char_pri (*__collate_char_pri_table_ptr)[UCHAR_MAX + 1]; + struct __collate_st_chain_pri *__collate_chain_pri_table; +}; + + __BEGIN_DECLS u_char *__collate_strdup(u_char *); -u_char *__collate_substitute(const u_char *); +u_char *__collate_substitute(struct xlocale_collate *, const u_char *); int __collate_load_tables(const char *); -void __collate_lookup(const u_char *, int *, int *, int *); -int __collate_range_cmp(int, int); +void __collate_lookup(struct xlocale_collate *, const u_char *, int *, int *, int *); +int __collate_range_cmp(struct xlocale_collate *, int, int); #ifdef COLLATE_DEBUG void __collate_print_tables(void); #endif Index: lib/libc/locale/wcstoumax.c =================================================================== --- lib/libc/locale/wcstoumax.c (revision 225653) +++ lib/libc/locale/wcstoumax.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -34,26 +39,28 @@ #endif /* LIBC_SCCS and not lint */ __FBSDID("FreeBSD: src/lib/libc/stdlib/strtoumax.c,v 1.8 2002/09/06 11:23:59 tjr Exp "); #endif -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/wcstoumax.c 165903 2007-01-09 00:28:16Z imp $"); #include #include #include #include #include +#include "xlocale_private.h" /* * Convert a wide character string to a uintmax_t integer. */ uintmax_t -wcstoumax(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, - int base) +wcstoumax_l(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, + int base, locale_t locale) { const wchar_t *s; uintmax_t acc; wchar_t c; uintmax_t cutoff; int neg, any, cutlim; + FIX_LOCALE(locale); /* * See strtoimax for comments as to the logic used. @@ -61,7 +68,7 @@ s = nptr; do { c = *s++; - } while (iswspace(c)); + } while (iswspace_l(c, locale)); if (c == L'-') { neg = 1; c = *s++; @@ -86,8 +93,8 @@ cutlim = UINTMAX_MAX % base; for ( ; ; c = *s++) { #ifdef notyet - if (iswdigit(c)) - c = digittoint(c); + if (iswdigit_l(c, locale)) + c = digittoint_l(c, locale); else #endif if (c >= L'0' && c <= L'9') @@ -120,3 +127,9 @@ *endptr = (wchar_t *)(any ? s - 1 : nptr); return (acc); } +uintmax_t +wcstoumax(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, + int base) +{ + return wcstoumax_l(nptr, endptr, base, __get_locale()); +} Index: lib/libc/locale/mbtowc.c =================================================================== --- lib/libc/locale/mbtowc.c (revision 225653) +++ lib/libc/locale/mbtowc.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002-2004 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -25,26 +30,31 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/mbtowc.c 132821 2004-07-29 06:18:40Z tjr $"); #include #include #include "mblocal.h" int -mbtowc(wchar_t * __restrict pwc, const char * __restrict s, size_t n) +mbtowc_l(wchar_t * __restrict pwc, const char * __restrict s, size_t n, locale_t locale) { static const mbstate_t initial; - static mbstate_t mbs; size_t rval; + FIX_LOCALE(locale); if (s == NULL) { /* No support for state dependent encodings. */ - mbs = initial; + locale->mbtowc = initial; return (0); } - rval = __mbrtowc(pwc, s, n, &mbs); + rval = XLOCALE_CTYPE(locale)->__mbrtowc(pwc, s, n, &locale->mbtowc); if (rval == (size_t)-1 || rval == (size_t)-2) return (-1); return ((int)rval); } +int +mbtowc(wchar_t * __restrict pwc, const char * __restrict s, size_t n) +{ + return mbtowc_l(pwc, s, n, __get_locale()); +} Index: lib/libc/locale/wcstoul.c =================================================================== --- lib/libc/locale/wcstoul.c (revision 225653) +++ lib/libc/locale/wcstoul.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -28,25 +33,28 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/wcstoul.c 165903 2007-01-09 00:28:16Z imp $"); #include #include #include #include #include +#include "xlocale_private.h" /* * Convert a wide character string to an unsigned long integer. */ unsigned long -wcstoul(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, int base) +wcstoul_l(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, + int base, locale_t locale) { const wchar_t *s; unsigned long acc; wchar_t c; unsigned long cutoff; int neg, any, cutlim; + FIX_LOCALE(locale); /* * See strtol for comments as to the logic used. @@ -54,7 +62,7 @@ s = nptr; do { c = *s++; - } while (iswspace(c)); + } while (iswspace_l(c, locale)); if (c == L'-') { neg = 1; c = *s++; @@ -79,8 +87,8 @@ cutlim = ULONG_MAX % base; for ( ; ; c = *s++) { #ifdef notyet - if (iswdigit(c)) - c = digittoint(c); + if (iswdigit_l(c, locale)) + c = digittoint_l(c, locale); else #endif if (c >= L'0' && c <= L'9') @@ -113,3 +121,8 @@ *endptr = (wchar_t *)(any ? s - 1 : nptr); return (acc); } +unsigned long +wcstoul(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, int base) +{ + return wcstoul_l(nptr, endptr, base, __get_locale()); +} Index: lib/libc/locale/gb2312.c =================================================================== --- lib/libc/locale/gb2312.c (revision 225653) +++ lib/libc/locale/gb2312.c (working copy) @@ -3,6 +3,11 @@ * Copyright (c) 2003 David Xu * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -26,7 +31,7 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/gb2312.c 172619 2007-10-13 16:28:22Z ache $"); #include #include @@ -35,8 +40,6 @@ #include #include "mblocal.h" -extern int __mb_sb_limit; - static size_t _GB2312_mbrtowc(wchar_t * __restrict, const char * __restrict, size_t, mbstate_t * __restrict); static int _GB2312_mbsinit(const mbstate_t *); @@ -49,15 +52,15 @@ } _GB2312State; int -_GB2312_init(_RuneLocale *rl) +_GB2312_init(struct xlocale_ctype *l, _RuneLocale *rl) { - _CurrentRuneLocale = rl; - __mbrtowc = _GB2312_mbrtowc; - __wcrtomb = _GB2312_wcrtomb; - __mbsinit = _GB2312_mbsinit; - __mb_cur_max = 2; - __mb_sb_limit = 128; + l->runes = rl; + l->__mbrtowc = _GB2312_mbrtowc; + l->__wcrtomb = _GB2312_wcrtomb; + l->__mbsinit = _GB2312_mbsinit; + l->__mb_cur_max = 2; + l->__mb_sb_limit = 128; return (0); } Index: lib/libc/locale/Symbol.map =================================================================== --- lib/libc/locale/Symbol.map (revision 225653) +++ lib/libc/locale/Symbol.map (working copy) @@ -1,5 +1,5 @@ /* - * $FreeBSD$ + * $FreeBSD: head/lib/libc/locale/Symbol.map 172619 2007-10-13 16:28:22Z ache $ */ FBSD_1.0 { @@ -99,6 +99,96 @@ iswctype; wctype; wcwidth; + newlocale; + duplocale; + freelocale; + querylocale; + uselocale; + __getCurrentRuneLocale; + btowc_l; + localeconv_l; + mblen_l; + mbrlen_l; + mbrtowc_l; + mbsinit_l; + mbsnrtowcs_l; + mbsrtowcs_l; + mbstowcs_l; + mbtowc_l; + nl_langinfo_l; + strcoll_l; + strfmon_l; + strftime_l; + strptime_l; + strxfrm_l; + wcrtomb_l; + wcscoll_l; + wcsnrtombs_l; + wcsrtombs_l; + wcstombs_l; + wcsxfrm_l; + wctob_l; + wctomb_l; + ___tolower_l; + ___toupper_l; + ___runetype_l; + digittoint_l; + isalnum_l; + isalpha_l; + isblank_l; + iscntrl_l; + isdigit_l; + isgraph_l; + ishexnumber_l; + isideogram_l; + islower_l; + isnumber_l; + isphonogram_l; + isprint_l; + ispunct_l; + isrune_l; + isspace_l; + isspecial_l; + isupper_l; + isxdigit_l; + tolower_l; + toupper_l; + iswalnum_l; + iswalpha_l; + iswblank_l; + iswcntrl_l; + iswdigit_l; + iswgraph_l; + iswhexnumber_l; + iswideogram_l; + iswlower_l; + iswnumber_l; + iswphonogram_l; + iswprint_l; + iswpunct_l; + iswrune_l; + iswspace_l; + iswspecial_l; + iswupper_l; + iswxdigit_l; + towlower_l; + towupper_l; + iswctype_l; + wctype_l; + nextwctype_l; + ___mb_cur_max; + towctrans_l; + wctrans_l; + wcsftime_l; + wcstod_l; + wcstof_l; + wcstoimax_l; + wcstol_l; + wcstold_l; + wcstoll_l; + wcstoul_l; + wcstoull_l; + wcstoumax_l; }; FBSDprivate_1.0 { Index: lib/libc/locale/mblocal.h =================================================================== --- lib/libc/locale/mblocal.h (revision 225653) +++ lib/libc/locale/mblocal.h (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2004 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -23,42 +28,52 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD$ + * $FreeBSD: head/lib/libc/locale/mblocal.h 175553 2008-01-21 23:48:12Z ache $ */ #ifndef _MBLOCAL_H_ #define _MBLOCAL_H_ #include +#include "xlocale_private.h" + /* - * Rune initialization function prototypes. + * Conversion function pointers for current encoding. */ -int _none_init(_RuneLocale *); -int _ascii_init(_RuneLocale *); -int _UTF8_init(_RuneLocale *); -int _EUC_init(_RuneLocale *); -int _GB18030_init(_RuneLocale *); -int _GB2312_init(_RuneLocale *); -int _GBK_init(_RuneLocale *); -int _BIG5_init(_RuneLocale *); -int _MSKanji_init(_RuneLocale *); +struct xlocale_ctype { + struct xlocale_component header; + _RuneLocale *runes; + size_t (*__mbrtowc)(wchar_t * __restrict, const char * __restrict, + size_t, mbstate_t * __restrict); + int (*__mbsinit)(const mbstate_t *); + size_t (*__mbsnrtowcs)(wchar_t * __restrict, const char ** __restrict, + size_t, size_t, mbstate_t * __restrict); + size_t (*__wcrtomb)(char * __restrict, wchar_t, mbstate_t * __restrict); + size_t (*__wcsnrtombs)(char * __restrict, const wchar_t ** __restrict, + size_t, size_t, mbstate_t * __restrict); + int __mb_cur_max; + int __mb_sb_limit; +}; +#define XLOCALE_CTYPE(x) ((struct xlocale_ctype*)(x)->components[XLC_CTYPE]) +extern struct xlocale_ctype __xlocale_global_ctype; /* - * Conversion function pointers for current encoding. + * Rune initialization function prototypes. */ -extern size_t (*__mbrtowc)(wchar_t * __restrict, const char * __restrict, - size_t, mbstate_t * __restrict); -extern int (*__mbsinit)(const mbstate_t *); -extern size_t (*__mbsnrtowcs)(wchar_t * __restrict, const char ** __restrict, - size_t, size_t, mbstate_t * __restrict); -extern size_t (*__wcrtomb)(char * __restrict, wchar_t, mbstate_t * __restrict); -extern size_t (*__wcsnrtombs)(char * __restrict, const wchar_t ** __restrict, - size_t, size_t, mbstate_t * __restrict); +int _none_init(struct xlocale_ctype *, _RuneLocale *); +int _ascii_init(struct xlocale_ctype *, _RuneLocale *); +int _UTF8_init(struct xlocale_ctype *, _RuneLocale *); +int _EUC_init(struct xlocale_ctype *, _RuneLocale *); +int _GB18030_init(struct xlocale_ctype *, _RuneLocale *); +int _GB2312_init(struct xlocale_ctype *, _RuneLocale *); +int _GBK_init(struct xlocale_ctype *, _RuneLocale *); +int _BIG5_init(struct xlocale_ctype *, _RuneLocale *); +int _MSKanji_init(struct xlocale_ctype *, _RuneLocale *); extern size_t __mbsnrtowcs_std(wchar_t * __restrict, const char ** __restrict, - size_t, size_t, mbstate_t * __restrict); + size_t, size_t, mbstate_t * __restrict); extern size_t __wcsnrtombs_std(char * __restrict, const wchar_t ** __restrict, - size_t, size_t, mbstate_t * __restrict); + size_t, size_t, mbstate_t * __restrict); #endif /* _MBLOCAL_H_ */ Index: lib/libc/locale/DESIGN.xlocale =================================================================== --- lib/libc/locale/DESIGN.xlocale (revision 0) +++ lib/libc/locale/DESIGN.xlocale (revision 0) @@ -0,0 +1,157 @@ +Design of xlocale +================= + +The xlocale APIs come from Darwin, although a subset is now part of POSIX 2008. +They fall into two broad categories: + +- Manipulation of per-thread locales (POSIX) +- Locale-aware functions taking an explicit locale argument (Darwin) + +This document describes the implementation of these APIs for FreeBSD. + +Goals +----- + +The overall goal of this implementation is to be compatible with the Darwin +version. Additionally, it should include minimal changes to the existing +locale code. A lot of the existing locale code originates with 4BSD or earlier +and has had over a decade of testing. Replacing this code, unless absolutely +necessary, gives us the potential for more bugs without much benefit. + +With this in mind, various libc-private functions have been modified to take a +locale_t parameter. This causes a compiler error if they are accidentally +called without a locale. This approach was taken, rather than adding _l +variants of these functions, to make it harder for accidental uses of the +global-locale versions to slip in. + +Locale Objects +-------------- + +A locale is encapsulated in a `locale_t`, which is an opaque type: a pointer to +a `struct _xlocale`. The name `_xlocale` is unfortunate, as it does not fit +well with existing conventions, but is used because this is the name the Darwin +implementation gives to this structure and so may be used by existing (bad) code. + +This structure should include all of the information corresponding to a locale. +A locale_t is almost immutable after creation. There are no functions that modify it, +and it can therefore be used without locking. It is the responsibility of the +caller to ensure that a locale is not deallocated during a call that uses it. + +Each locale contains a number of components, one for each of the categories +supported by `setlocale()`. These are likewise immutable after creation. This +differs from the Darwin implementation, which includes a deprecated +`setinvalidrune()` function that can modify the rune locale. + +The exception to these mutability rules is a set of `mbstate_t` flags stored +with each locale. These are used by various functions that previously had a +static local `mbstate_t` variable. + +The components are reference counted, and so can be aliased between locale +objects. This makes copying locales very cheap. + +The Global Locale +----------------- + +All locales and locale components are reference counted. The global locale, +however, is special. It, and all of its components, are static and so no +malloc() memory is required when using a single locale. + +This means that threads using the global locale are subject to the same +constraints as with the pre-xlocale libc. Calls to any locale-aware functions +in threads using the global locale, while modifying the global locale, have +undefined behaviour. + +Because of this, we have to ensure that we always copy the components of the +global locale, rather than alias them. + +It would be cleaner to simply remove the special treatment of the global locale +and have a locale_t lazily allocated for the global context. This would cost a +little more `malloc()` memory, so is not done in the initial version. + +Caching +------- + +The existing locale implementation included several ad-hoc caching layers. +None of these were thread safe. Caching is only really of use for supporting +the pattern where the locale is briefly changed to something and then changed +back. + +The current xlocale implementation removes the caching entirely. This pattern +is not one that should be encouraged. If you need to make some calls with a +modified locale, then you should use the _l suffix versions of the calls, +rather than switch the global locale. If you do need to temporarily switch the +locale and then switch it back, `uselocale()` provides a way of doing this very +easily: It returns the old locale, which can then be passed to a subsequent +call to `uselocale()` to restore it, without the need to load any locale data +from the disk. + +If, in the future, it is determined that caching is beneficial, it can be added +quite easily in xlocale.c. Given, however, that any locale-aware call is going +to be a preparation for presenting data to the user, and so is invariably going +to be part of an I/O operation, this seems like a case of premature +optimisation. + +localeconv +---------- + +The `localeconv()` function is an exception to the immutable-after-creation +rule. In the classic implementation, this function returns a pointer to some +global storage, which is initialised with the data from the current locale. +This is not possible in a multithreaded environment, with multiple locales. + +Instead, each locale contains a `struct lconv` that is lazily initialised on +calls to `localeconv()`. This is not protected by any locking, however this is +still safe on any machine where word-sized stores are atomic: two concurrent +calls will write the same data into the structure. + +Explicit Locale Calls +--------------------- + +A large number of functions have been modified to take an explicit `locale_t` +parameter. The old APIs are then reimplemented with a call to `__get_locale()` +to supply the `locale_t` parameter. This is in line with the Darwin public +APIs, but also simplifies the modifications to these functions. The +`__get_locale()` function is now the only way to access the current locale +within libc. All of the old globals have gone, so there is now a linker error +if any functions attempt to use them. + +The ctype.h functions are a little different. These are not implemented in +terms of their locale-aware versions, for performance reasons. Each of these +is implemented as a short inline function. + +Differences to Darwin APIs +-------------------------- + +`strtoq_l()` and `strtouq_l() `are not provided. These are extensions to +deprecated functions - we should not be encouraging people to use deprecated +interfaces. + +Locale Placeholders +------------------- + +The pointer values 0 and -1 have special meanings as `locale_t` values. Any +public function that accepts a `locale_t` parameter must use the `FIX_LOCALE()` +macro on it before using it. For efficiency, this can be emitted in functions +which *only* use their locale parameter as an argument to another public +function, as the callee will do the `FIX_LOCALE()` itself. + +Potential Improvements +---------------------- + +Currently, the current rune set is accessed via a function call. This makes it +fairly expensive to use any of the ctype.h functions. We could improve this +quite a lot by storing the rune locale data in a __thread-qualified variable. + +Several of the existing FreeBSD locale-aware functions appear to be wrong. For +example, most of the `strto*()` family should probably use `digittoint_l()`, +but instead they assume ASCII. These will break if using a character encoding +that does not put numbers and the letters A-F in the same location as ASCII. +Some functions, like `strcoll()` only work on single-byte encodings. No +attempt has been made to fix existing limitations in the libc functions other +than to add support for xlocale. + +Intuitively, setting a thread-local locale should ensure that all locale-aware +functions can be used safely from that thread. In fact, this is not the case +in either this implementation or the Darwin one. You must call `duplocale()` +or `newlocale()` before calling `uselocale()`. This is a bit ugly, and it +would be better if libc ensure that every thread had its own locale object. Index: lib/libc/locale/mbsrtowcs.c =================================================================== --- lib/libc/locale/mbsrtowcs.c (revision 225653) +++ lib/libc/locale/mbsrtowcs.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002-2004 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -25,7 +30,7 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/mbsrtowcs.c 132497 2004-07-21 10:54:57Z tjr $"); #include #include @@ -34,12 +39,17 @@ #include "mblocal.h" size_t +mbsrtowcs_l(wchar_t * __restrict dst, const char ** __restrict src, size_t len, + mbstate_t * __restrict ps, locale_t locale) +{ + FIX_LOCALE(locale); + if (ps == NULL) + ps = &locale->mbsrtowcs; + return (XLOCALE_CTYPE(locale)->__mbsnrtowcs(dst, src, SIZE_T_MAX, len, ps)); +} +size_t mbsrtowcs(wchar_t * __restrict dst, const char ** __restrict src, size_t len, mbstate_t * __restrict ps) { - static mbstate_t mbs; - - if (ps == NULL) - ps = &mbs; - return (__mbsnrtowcs(dst, src, SIZE_T_MAX, len, ps)); + return mbsrtowcs_l(dst, src, len, ps, __get_locale()); } Index: lib/libc/locale/utf8.c =================================================================== --- lib/libc/locale/utf8.c (revision 225653) +++ lib/libc/locale/utf8.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002-2004 Tim J. Robbins * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -25,7 +30,7 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/utf8.c 172661 2007-10-15 09:51:30Z ache $"); #include #include @@ -55,22 +60,22 @@ } _UTF8State; int -_UTF8_init(_RuneLocale *rl) +_UTF8_init(struct xlocale_ctype *l, _RuneLocale *rl) { - __mbrtowc = _UTF8_mbrtowc; - __wcrtomb = _UTF8_wcrtomb; - __mbsinit = _UTF8_mbsinit; - __mbsnrtowcs = _UTF8_mbsnrtowcs; - __wcsnrtombs = _UTF8_wcsnrtombs; - _CurrentRuneLocale = rl; - __mb_cur_max = 6; + l->__mbrtowc = _UTF8_mbrtowc; + l->__wcrtomb = _UTF8_wcrtomb; + l->__mbsinit = _UTF8_mbsinit; + l->__mbsnrtowcs = _UTF8_mbsnrtowcs; + l->__wcsnrtombs = _UTF8_wcsnrtombs; + l->runes = rl; + l->__mb_cur_max = 6; /* * UCS-4 encoding used as the internal representation, so * slots 0x0080-0x00FF are occuped and must be excluded * from the single byte ctype by setting the limit. */ - __mb_sb_limit = 128; + l->__mb_sb_limit = 128; return (0); } Index: lib/libc/locale/collcmp.c =================================================================== --- lib/libc/locale/collcmp.c (revision 225653) +++ lib/libc/locale/collcmp.c (working copy) @@ -2,6 +2,11 @@ * Copyright (C) 1996 by Andrey A. Chernov, Moscow, Russia. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -25,20 +30,23 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/collcmp.c 142653 2005-02-27 14:54:23Z phantom $"); #include +#include #include "collate.h" /* * Compare two characters using collate */ -int __collate_range_cmp(int c1, int c2) +int __collate_range_cmp(struct xlocale_collate *table, int c1, int c2) { static char s1[2], s2[2]; s1[0] = c1; s2[0] = c2; - return (strcoll(s1, s2)); + struct _xlocale l = {{0}}; + l.components[XLC_COLLATE] = (struct xlocale_component *)table; + return (strcoll_l(s1, s2, &l)); } Index: lib/libc/locale/Makefile.inc =================================================================== --- lib/libc/locale/Makefile.inc (revision 225653) +++ lib/libc/locale/Makefile.inc (working copy) @@ -1,11 +1,11 @@ # from @(#)Makefile.inc 8.1 (Berkeley) 6/4/93 -# $FreeBSD$ +# $FreeBSD: head/lib/libc/locale/Makefile.inc 211774 2010-08-24 20:54:43Z imp $ # locale sources .PATH: ${.CURDIR}/${LIBC_ARCH}/locale ${.CURDIR}/locale SRCS+= ascii.c big5.c btowc.c collate.c collcmp.c euc.c fix_grouping.c \ - gb18030.c gb2312.c gbk.c isctype.c iswctype.c \ + gb18030.c gb2312.c gbk.c ctype.c isctype.c iswctype.c \ ldpart.c lmessages.c lmonetary.c lnumeric.c localeconv.c mblen.c \ mbrlen.c \ mbrtowc.c mbsinit.c mbsnrtowcs.c \ @@ -20,7 +20,8 @@ wcstoimax.c wcstol.c wcstold.c wcstoll.c \ wcstombs.c \ wcstoul.c wcstoull.c wcstoumax.c wctob.c wctomb.c wctrans.c wctype.c \ - wcwidth.c + wcwidth.c\ + xlocale.c SYM_MAPS+=${.CURDIR}/locale/Symbol.map Index: lib/libc/locale/wcstof.c =================================================================== --- lib/libc/locale/wcstof.c (revision 225653) +++ lib/libc/locale/wcstof.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002, 2003 Tim J. Robbins * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -25,17 +30,19 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/wcstof.c 127998 2004-04-07 09:47:56Z tjr $"); #include #include #include +#include "xlocale_private.h" /* * See wcstod() for comments as to the logic used. */ float -wcstof(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr) +wcstof_l(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, + locale_t locale) { static const mbstate_t initial; mbstate_t mbs; @@ -43,13 +50,14 @@ char *buf, *end; const wchar_t *wcp; size_t len; + FIX_LOCALE(locale); - while (iswspace(*nptr)) + while (iswspace_l(*nptr, locale)) nptr++; wcp = nptr; mbs = initial; - if ((len = wcsrtombs(NULL, &wcp, 0, &mbs)) == (size_t)-1) { + if ((len = wcsrtombs_l(NULL, &wcp, 0, &mbs, locale)) == (size_t)-1) { if (endptr != NULL) *endptr = (wchar_t *)nptr; return (0.0); @@ -57,9 +65,9 @@ if ((buf = malloc(len + 1)) == NULL) return (0.0); mbs = initial; - wcsrtombs(buf, &wcp, len + 1, &mbs); + wcsrtombs_l(buf, &wcp, len + 1, &mbs, locale); - val = strtof(buf, &end); + val = strtof_l(buf, &end, locale); if (endptr != NULL) *endptr = (wchar_t *)nptr + (end - buf); @@ -68,3 +76,8 @@ return (val); } +float +wcstof(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr) +{ + return wcstof_l(nptr, endptr, __get_locale()); +} Index: lib/libc/locale/localeconv.3 =================================================================== --- lib/libc/locale/localeconv.3 (revision 225653) +++ lib/libc/locale/localeconv.3 (working copy) @@ -30,7 +30,7 @@ .\" .\" From @(#)setlocale.3 8.1 (Berkeley) 6/9/93 .\" From FreeBSD: src/lib/libc/locale/setlocale.3,v 1.28 2003/11/15 02:26:04 tjr Exp -.\" $FreeBSD$ +.\" $FreeBSD: head/lib/libc/locale/localeconv.3 213573 2010-10-08 12:40:16Z uqs $ .\" .Dd November 21, 2003 .Dt LOCALECONV 3 @@ -44,6 +44,9 @@ .In locale.h .Ft struct lconv * .Fn localeconv "void" +.In xlocale.h +.Ft struct lconv * +.Fn localeconv_l "locale_t locale" .Sh DESCRIPTION The .Fn localeconv @@ -196,6 +199,11 @@ A .Dv CHAR_MAX result similarly denotes an unavailable value. +.Pp +The +.Fn localeconv_l +function takes an explicit locale parameter. For more information, see +.Xr xlocale 3 . .Sh RETURN VALUES The .Fn localeconv @@ -204,6 +212,13 @@ .Xr setlocale 3 or .Fn localeconv . +The return value for +.Fn localeconv_l +is stored with the locale. It will remain valid until a subsequent call to +.Xr freelocale 3 . +If a thread-local locale is in effect then the return value from +.Fn localeconv +will remain valid until the locale is destroyed. .Sh ERRORS No errors are defined. .Sh SEE ALSO Index: lib/libc/locale/mbsinit.c =================================================================== --- lib/libc/locale/mbsinit.c (revision 225653) +++ lib/libc/locale/mbsinit.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002-2004 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -25,14 +30,19 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/mbsinit.c 129153 2004-05-12 14:09:04Z tjr $"); #include #include "mblocal.h" int +mbsinit_l(const mbstate_t *ps, locale_t locale) +{ + FIX_LOCALE(locale); + return (XLOCALE_CTYPE(locale)->__mbsinit(ps)); +} +int mbsinit(const mbstate_t *ps) { - - return (__mbsinit(ps)); + return mbsinit_l(ps, __get_locale()); } Index: lib/libc/locale/wcwidth.c =================================================================== --- lib/libc/locale/wcwidth.c (revision 225653) +++ lib/libc/locale/wcwidth.c (working copy) @@ -10,6 +10,11 @@ * This code is derived from software contributed to Berkeley by * Paul Borman at Krystal Technologies. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -36,15 +41,21 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/wcwidth.c 165903 2007-01-09 00:28:16Z imp $"); #include +#include +#include #undef wcwidth int wcwidth(wchar_t wc) { - return (__wcwidth(wc)); } +int +wcwidth_l(wchar_t wc, locale_t locale) +{ + return (__wcwidth_l(wc, locale)); +} Index: lib/libc/locale/rune.c =================================================================== --- lib/libc/locale/rune.c (revision 225653) +++ lib/libc/locale/rune.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)rune.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/rune.c 165903 2007-01-09 00:28:16Z imp $"); #include "namespace.h" #include Index: lib/libc/locale/setlocale.c =================================================================== --- lib/libc/locale/setlocale.c (revision 225653) +++ lib/libc/locale/setlocale.c (working copy) @@ -35,7 +35,7 @@ static char sccsid[] = "@(#)setlocale.c 8.1 (Berkeley) 7/4/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/setlocale.c 165903 2007-01-09 00:28:16Z imp $"); #include #include @@ -95,7 +95,7 @@ static char *currentlocale(void); static char *loadlocale(int); -static const char *__get_locale_env(int); +const char *__get_locale_env(int); char * setlocale(category, locale) @@ -278,13 +278,14 @@ if (func(new) != _LDP_ERROR) { (void)strcpy(old, new); + (void)strcpy(__xlocale_global_locale.components[category-1]->locale, new); return (old); } return (NULL); } -static const char * +const char * __get_locale_env(category) int category; { Index: lib/libc/locale/runetype.c =================================================================== --- lib/libc/locale/runetype.c (revision 225653) +++ lib/libc/locale/runetype.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Paul Borman at Krystal Technologies. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -31,17 +36,20 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/runetype.c 165903 2007-01-09 00:28:16Z imp $"); #include #include #include +#include +#include "mblocal.h" unsigned long -___runetype(__ct_rune_t c) +___runetype_l(__ct_rune_t c, locale_t locale) { size_t lim; - _RuneRange *rr = &_CurrentRuneLocale->__runetype_ext; + FIX_LOCALE(locale); + _RuneRange *rr = &(XLOCALE_CTYPE(locale)->runes->__runetype_ext); _RuneEntry *base, *re; if (c < 0 || c == EOF) @@ -64,3 +72,18 @@ return(0L); } +unsigned long +___runetype(__ct_rune_t c) +{ + return ___runetype_l(c, __get_locale()); +} + +int ___mb_cur_max(void) +{ + return XLOCALE_CTYPE(__get_locale())->__mb_cur_max; +} +int ___mb_cur_max_l(locale_t locale) +{ + FIX_LOCALE(locale); + return XLOCALE_CTYPE(locale)->__mb_cur_max; +} Index: lib/libc/locale/btowc.c =================================================================== --- lib/libc/locale/btowc.c (revision 225653) +++ lib/libc/locale/btowc.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002, 2003 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -25,19 +30,20 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/btowc.c 129154 2004-05-12 14:26:54Z tjr $"); #include #include #include "mblocal.h" wint_t -btowc(int c) +btowc_l(int c, locale_t l) { static const mbstate_t initial; mbstate_t mbs = initial; char cc; wchar_t wc; + FIX_LOCALE(l); if (c == EOF) return (WEOF); @@ -47,7 +53,12 @@ * counts. */ cc = (char)c; - if (__mbrtowc(&wc, &cc, 1, &mbs) > 1) + if (XLOCALE_CTYPE(l)->__mbrtowc(&wc, &cc, 1, &mbs) > 1) return (WEOF); return (wc); } +wint_t +btowc(int c) +{ + return btowc_l(c, __get_locale()); +} Index: lib/libc/locale/mbrlen.c =================================================================== --- lib/libc/locale/mbrlen.c (revision 225653) +++ lib/libc/locale/mbrlen.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002-2004 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -25,17 +30,22 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/mbrlen.c 129154 2004-05-12 14:26:54Z tjr $"); #include #include "mblocal.h" size_t -mbrlen(const char * __restrict s, size_t n, mbstate_t * __restrict ps) +mbrlen_l(const char * __restrict s, size_t n, mbstate_t * __restrict ps, locale_t locale) { - static mbstate_t mbs; - + FIX_LOCALE(locale); if (ps == NULL) - ps = &mbs; - return (__mbrtowc(NULL, s, n, ps)); + ps = &locale->mbrlen; + return (XLOCALE_CTYPE(locale)->__mbrtowc(NULL, s, n, ps)); } + +size_t +mbrlen(const char * __restrict s, size_t n, mbstate_t * __restrict ps) +{ + return mbrlen_l(s, n, ps, __get_locale()); +} Index: lib/libc/locale/setlocale.h =================================================================== --- lib/libc/locale/setlocale.h (revision 225653) +++ lib/libc/locale/setlocale.h (working copy) @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD$ + * $FreeBSD: head/lib/libc/locale/setlocale.h 117270 2003-07-06 02:03:37Z ache $ */ #ifndef _SETLOCALE_H_ Index: lib/libc/locale/lmessages.c =================================================================== --- lib/libc/locale/lmessages.c (revision 225653) +++ lib/libc/locale/lmessages.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2001 Alexey Zelkin * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -25,7 +30,7 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/lmessages.c 116875 2003-06-26 10:46:16Z phantom $"); #include @@ -36,6 +41,14 @@ #define LCMESSAGES_SIZE_MIN \ (offsetof(struct lc_messages_T, yesstr) / sizeof(char *)) +struct xlocale_messages { + struct xlocale_component header; + char *buffer; + struct lc_messages_T locale; +}; + +struct xlocale_messages __xlocale_global_messages; + static char empty[] = ""; static const struct lc_messages_T _C_messages_locale = { @@ -45,33 +58,55 @@ "no" /* nostr */ }; -static struct lc_messages_T _messages_locale; -static int _messages_using_locale; -static char *_messages_locale_buf; +static void destruct_messages(void *v) +{ + struct xlocale_messages *l = v; + if (l->buffer) + free(l->buffer); + free(l); +} -int -__messages_load_locale(const char *name) +static int +messages_load_locale(struct xlocale_messages *loc, int *using_locale, const char *name) { int ret; + struct lc_messages_T *l = &loc->locale; - ret = __part_load_locale(name, &_messages_using_locale, - &_messages_locale_buf, "LC_MESSAGES", + ret = __part_load_locale(name, using_locale, + &loc->buffer, "LC_MESSAGES", LCMESSAGES_SIZE_FULL, LCMESSAGES_SIZE_MIN, - (const char **)&_messages_locale); + (const char **)l); if (ret == _LDP_LOADED) { - if (_messages_locale.yesstr == NULL) - _messages_locale.yesstr = empty; - if (_messages_locale.nostr == NULL) - _messages_locale.nostr = empty; + if (l->yesstr == NULL) + l->yesstr = empty; + if (l->nostr == NULL) + l->nostr = empty; } return (ret); } +int +__messages_load_locale(const char *name) +{ + return messages_load_locale(&__xlocale_global_messages, + &__xlocale_global_locale.using_messages_locale, name); +} +void * +__messages_load(const char *name, locale_t l) +{ + struct xlocale_messages *new = calloc(sizeof(struct xlocale_messages), 1); + new->header.header.destructor = destruct_messages; + if (messages_load_locale(new, &l->using_messages_locale, name)) { + xlocale_release(new); + return NULL; + } + return new; +} struct lc_messages_T * -__get_current_messages_locale(void) +__get_current_messages_locale(locale_t loc) { - return (_messages_using_locale - ? &_messages_locale + return (loc->using_messages_locale + ? &((struct xlocale_messages *)loc->components[XLC_MESSAGES])->locale : (struct lc_messages_T *)&_C_messages_locale); } Index: lib/libc/locale/big5.c =================================================================== --- lib/libc/locale/big5.c (revision 225653) +++ lib/libc/locale/big5.c (working copy) @@ -6,6 +6,11 @@ * This code is derived from software contributed to Berkeley by * Paul Borman at Krystal Technologies. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -39,7 +44,7 @@ static char sccsid[] = "@(#)big5.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/big5.c 172619 2007-10-13 16:28:22Z ache $"); #include #include @@ -62,15 +67,15 @@ } _BIG5State; int -_BIG5_init(_RuneLocale *rl) +_BIG5_init(struct xlocale_ctype *l, _RuneLocale *rl) { - __mbrtowc = _BIG5_mbrtowc; - __wcrtomb = _BIG5_wcrtomb; - __mbsinit = _BIG5_mbsinit; - _CurrentRuneLocale = rl; - __mb_cur_max = 2; - __mb_sb_limit = 128; + l->__mbrtowc = _BIG5_mbrtowc; + l->__wcrtomb = _BIG5_wcrtomb; + l->__mbsinit = _BIG5_mbsinit; + l->runes = rl; + l->__mb_cur_max = 2; + l->__mb_sb_limit = 128; return (0); } Index: lib/libc/locale/lmessages.h =================================================================== --- lib/libc/locale/lmessages.h (revision 225653) +++ lib/libc/locale/lmessages.h (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2000, 2001 Alexey Zelkin * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -23,12 +28,14 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD$ + * $FreeBSD: head/lib/libc/locale/lmessages.h 88309 2001-12-20 18:28:52Z phantom $ */ #ifndef _LMESSAGES_H_ #define _LMESSAGES_H_ +#include "xlocale_private.h" + struct lc_messages_T { const char *yesexpr; const char *noexpr; @@ -36,7 +43,7 @@ const char *nostr; }; -struct lc_messages_T *__get_current_messages_locale(void); +struct lc_messages_T *__get_current_messages_locale(locale_t); int __messages_load_locale(const char *); #endif /* !_LMESSAGES_H_ */ Index: lib/libc/locale/duplocale.3 =================================================================== --- lib/libc/locale/duplocale.3 (revision 0) +++ lib/libc/locale/duplocale.3 (revision 0) @@ -0,0 +1,79 @@ +.\" Copyright (c) 2011 The FreeBSD Foundation +.\" All rights reserved. +.\" +.\" This documentation was written by David Chisnall under sponsorship from +.\" the FreeBSD Foundation. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)ctype.3 8.1 (Berkeley) 6/4/93 +.\" $FreeBSD: head/lib/libc/locale/ctype.3 196820 2009-09-04 07:44:58Z des $ +.\" +.Dd September 17 2011 +.Dt DUPLOCALE 3 +.Os +.Sh NAME +.Nm duplocale +.Nd duplicate an locale +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.In xlocale.h +.Ft locale_t +.Fn duplocale "locale_t locale" +.Sh DESCRIPTION +Duplicates an existing +.Fa locale_t +returning a new +.Fa locale_t +that refers to the same locale values but has independent internal state. +Various functions, such as +.Xr mblen 3 +require presistent state. These functions formerly used static variables and +calls to them from multiple threads had undefined behavior. They now use +fields in the +.Fa locale_t +associated with the current thread by +.Xr uselocale 3 . +These calls are therefore only thread safe on threads with a unique per-thread +locale. +.Pt +The locale returned by this call must be freed with +.Xr freelocale 3 . +.Sh BUGS +Ideally, +.Xr uselocale 3 +should make a copy of the +.Fa locale_t +implicitly to ensure thread safety, and a copy of the global locale should be +installed lazily on each thread. The FreeBSD implementation does not do this, +for compatibility with Darwin. +.Sh SEE ALSO +.Xr freelocale 3 , +.Xr localeconv 3 , +.Xr newlocale 3 , +.Xr querylocale 3 , +.Xr uselocale 3 , +.Xr xlocale 3 +.Sh STANDARDS +This function, conforms to +.St -p1003.1-2008 Index: lib/libc/locale/uselocale.3 =================================================================== --- lib/libc/locale/uselocale.3 (revision 0) +++ lib/libc/locale/uselocale.3 (revision 0) @@ -0,0 +1,60 @@ +.\" Copyright (c) 2011 The FreeBSD Foundation +.\" All rights reserved. +.\" +.\" This documentation was written by David Chisnall under sponsorship from +.\" the FreeBSD Foundation. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)ctype.3 8.1 (Berkeley) 6/4/93 +.\" $FreeBSD: head/lib/libc/locale/ctype.3 196820 2009-09-04 07:44:58Z des $ +.\" +.Dd September 17 2011 +.Dt USELOCALE 3 +.Os +.Sh NAME +.Nm uselocale +.Nd Sets a thread-local locale. +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.In xlocale.h +.Ft locale_t +.Fn uselocale "locale_t locale" +.Sh DESCRIPTION +Specifies the locale for this thread to use. Specifying +.Fa LC_GLOBAL_LOCALE +disables the per-thread locale, while NULL returns the current locale without +setting a new one. +.Sh RETURN VALUES +Returns the previous locale, or LC_GLOBAL_LOCALE if this thread has no locale +associated with it. +.Sh SEE ALSO +.Xr duplocale 3 , +.Xr freelocale 3 , +.Xr localeconv 3 , +.Xr newlocale 3 , +.Xr querylocale 3 , +.Xr xlocale 3 +.Sh STANDARDS +This function, conforms to +.St -p1003.1-2008 Index: lib/libc/locale/isctype.c =================================================================== --- lib/libc/locale/isctype.c (revision 225653) +++ lib/libc/locale/isctype.c (working copy) @@ -39,7 +39,7 @@ static char sccsid[] = "@(#)isctype.c 8.3 (Berkeley) 2/24/94"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/isctype.c 172619 2007-10-13 16:28:22Z ache $"); #include Index: lib/libc/locale/freelocale.3 =================================================================== --- lib/libc/locale/freelocale.3 (revision 0) +++ lib/libc/locale/freelocale.3 (revision 0) @@ -0,0 +1,63 @@ +.\" Copyright (c) 2011 The FreeBSD Foundation +.\" All rights reserved. +.\" +.\" This documentation was written by David Chisnall under sponsorship from +.\" the FreeBSD Foundation. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)ctype.3 8.1 (Berkeley) 6/4/93 +.\" $FreeBSD: head/lib/libc/locale/ctype.3 196820 2009-09-04 07:44:58Z des $ +.\" +.Dd September 17 2011 +.Dt FREELOCALE 3 +.Os +.Sh NAME +.Nm freelocale +.Nd Frees a locale created with +.Xr duplocale 3 +or +.Xr newlocale 3 . +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.In xlocale.h +.Ft int +.Fn freelocale "locale_t locale" +.Sh DESCRIPTION +Frees a +.Fa locale_t . +This relinquishes any resources held exclusively by this locale. Note that +locales share reference-counted components, so a call to this function is not +guaranteed to free all of the components. +.Sh RETURN VALUES +Returns 0 on success or -1 on error. +.Sh SEE ALSO +.Xr duplocale 3 , +.Xr localeconv 3 , +.Xr newlocale 3 , +.Xr querylocale 3 , +.Xr uselocale 3 , +.Xr xlocale 3 +.Sh STANDARDS +This function, conforms to +.St -p1003.1-2008 . Index: lib/libc/locale/wcsrtombs.c =================================================================== --- lib/libc/locale/wcsrtombs.c (revision 225653) +++ lib/libc/locale/wcsrtombs.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002-2004 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -25,7 +30,7 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/wcsrtombs.c 132497 2004-07-21 10:54:57Z tjr $"); #include #include @@ -34,12 +39,18 @@ #include "mblocal.h" size_t +wcsrtombs_l(char * __restrict dst, const wchar_t ** __restrict src, size_t len, + mbstate_t * __restrict ps, locale_t locale) +{ + FIX_LOCALE(locale); + if (ps == NULL) + ps = &locale->wcsrtombs; + return (XLOCALE_CTYPE(locale)->__wcsnrtombs(dst, src, SIZE_T_MAX, len, ps)); +} + +size_t wcsrtombs(char * __restrict dst, const wchar_t ** __restrict src, size_t len, mbstate_t * __restrict ps) { - static mbstate_t mbs; - - if (ps == NULL) - ps = &mbs; - return (__wcsnrtombs(dst, src, SIZE_T_MAX, len, ps)); + return wcsrtombs_l(dst, src, len, ps, __get_locale()); } Index: lib/libc/locale/localeconv.c =================================================================== --- lib/libc/locale/localeconv.c (revision 225653) +++ lib/libc/locale/localeconv.c (working copy) @@ -3,6 +3,11 @@ * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -32,7 +37,7 @@ static char sccsid[] = "@(#)localeconv.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/localeconv.c 174546 2007-12-12 07:43:23Z phantom $"); #include @@ -48,25 +53,24 @@ * lconv structure are computed only when the monetary or numeric * locale has been changed. */ -int __mlocale_changed = 1; -int __nlocale_changed = 1; /* * Return the current locale conversion. */ struct lconv * -localeconv() +localeconv_l(locale_t loc) { - static struct lconv ret; + FIX_LOCALE(loc); + struct lconv *ret = &loc->lconv; - if (__mlocale_changed) { + if (loc->monetary_locale_changed) { /* LC_MONETARY part */ struct lc_monetary_T * mptr; -#define M_ASSIGN_STR(NAME) (ret.NAME = (char*)mptr->NAME) -#define M_ASSIGN_CHAR(NAME) (ret.NAME = mptr->NAME[0]) +#define M_ASSIGN_STR(NAME) (ret->NAME = (char*)mptr->NAME) +#define M_ASSIGN_CHAR(NAME) (ret->NAME = mptr->NAME[0]) - mptr = __get_current_monetary_locale(); + mptr = __get_current_monetary_locale(loc); M_ASSIGN_STR(int_curr_symbol); M_ASSIGN_STR(currency_symbol); M_ASSIGN_STR(mon_decimal_point); @@ -88,21 +92,26 @@ M_ASSIGN_CHAR(int_n_sep_by_space); M_ASSIGN_CHAR(int_p_sign_posn); M_ASSIGN_CHAR(int_n_sign_posn); - __mlocale_changed = 0; + loc->monetary_locale_changed = 0; } - if (__nlocale_changed) { + if (loc->numeric_locale_changed) { /* LC_NUMERIC part */ struct lc_numeric_T * nptr; -#define N_ASSIGN_STR(NAME) (ret.NAME = (char*)nptr->NAME) +#define N_ASSIGN_STR(NAME) (ret->NAME = (char*)nptr->NAME) - nptr = __get_current_numeric_locale(); + nptr = __get_current_numeric_locale(loc); N_ASSIGN_STR(decimal_point); N_ASSIGN_STR(thousands_sep); N_ASSIGN_STR(grouping); - __nlocale_changed = 0; + loc->numeric_locale_changed = 0; } - return (&ret); + return ret; } +struct lconv * +localeconv(void) +{ + return localeconv_l(__get_locale()); +} Index: lib/libc/locale/wcsnrtombs.c =================================================================== --- lib/libc/locale/wcsnrtombs.c (revision 225653) +++ lib/libc/locale/wcsnrtombs.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002-2004 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -25,7 +30,7 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/wcsnrtombs.c 141716 2005-02-12 08:45:12Z stefanf $"); #include #include @@ -34,16 +39,22 @@ #include "mblocal.h" size_t +wcsnrtombs_l(char * __restrict dst, const wchar_t ** __restrict src, size_t nwc, + size_t len, mbstate_t * __restrict ps, locale_t locale) +{ + FIX_LOCALE(locale); + if (ps == NULL) + ps = &locale->wcsnrtombs; + return (XLOCALE_CTYPE(locale)->__wcsnrtombs(dst, src, nwc, len, ps)); +} +size_t wcsnrtombs(char * __restrict dst, const wchar_t ** __restrict src, size_t nwc, size_t len, mbstate_t * __restrict ps) { - static mbstate_t mbs; - - if (ps == NULL) - ps = &mbs; - return (__wcsnrtombs(dst, src, nwc, len, ps)); + return wcsnrtombs_l(dst, src, nwc, len, ps, __get_locale()); } + size_t __wcsnrtombs_std(char * __restrict dst, const wchar_t ** __restrict src, size_t nwc, size_t len, mbstate_t * __restrict ps) @@ -53,13 +64,14 @@ const wchar_t *s; size_t nbytes; size_t nb; + struct xlocale_ctype *l = XLOCALE_CTYPE(__get_locale()); s = *src; nbytes = 0; if (dst == NULL) { while (nwc-- > 0) { - if ((nb = __wcrtomb(buf, *s, ps)) == (size_t)-1) + if ((nb = l->__wcrtomb(buf, *s, ps)) == (size_t)-1) /* Invalid character - wcrtomb() sets errno. */ return ((size_t)-1); else if (*s == L'\0') @@ -73,7 +85,7 @@ while (len > 0 && nwc-- > 0) { if (len > (size_t)MB_CUR_MAX) { /* Enough space to translate in-place. */ - if ((nb = __wcrtomb(dst, *s, ps)) == (size_t)-1) { + if ((nb = l->__wcrtomb(dst, *s, ps)) == (size_t)-1) { *src = s; return ((size_t)-1); } @@ -86,7 +98,7 @@ * character is too long for the buffer. */ mbsbak = *ps; - if ((nb = __wcrtomb(buf, *s, ps)) == (size_t)-1) { + if ((nb = l->__wcrtomb(buf, *s, ps)) == (size_t)-1) { *src = s; return ((size_t)-1); } Index: lib/libc/locale/gbk.c =================================================================== --- lib/libc/locale/gbk.c (revision 225653) +++ lib/libc/locale/gbk.c (working copy) @@ -6,6 +6,11 @@ * This code is derived from software contributed to Berkeley by * Paul Borman at Krystal Technologies. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -32,7 +37,7 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/gbk.c 172619 2007-10-13 16:28:22Z ache $"); #include #include @@ -55,15 +60,15 @@ } _GBKState; int -_GBK_init(_RuneLocale *rl) +_GBK_init(struct xlocale_ctype *l, _RuneLocale *rl) { - __mbrtowc = _GBK_mbrtowc; - __wcrtomb = _GBK_wcrtomb; - __mbsinit = _GBK_mbsinit; - _CurrentRuneLocale = rl; - __mb_cur_max = 2; - __mb_sb_limit = 128; + l->__mbrtowc = _GBK_mbrtowc; + l->__wcrtomb = _GBK_wcrtomb; + l->__mbsinit = _GBK_mbsinit; + l->runes = rl; + l->__mb_cur_max = 2; + l->__mb_sb_limit = 128; return (0); } Index: lib/libc/locale/querylocale.3 =================================================================== --- lib/libc/locale/querylocale.3 (revision 0) +++ lib/libc/locale/querylocale.3 (revision 0) @@ -0,0 +1,58 @@ +.\" Copyright (c) 2011 The FreeBSD Foundation +.\" All rights reserved. +.\" +.\" This documentation was written by David Chisnall under sponsorship from +.\" the FreeBSD Foundation. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)ctype.3 8.1 (Berkeley) 6/4/93 +.\" $FreeBSD: head/lib/libc/locale/ctype.3 196820 2009-09-04 07:44:58Z des $ +.\" +.Dd September 17 2011 +.Dt QUERYLOCALE 3 +.Os +.Sh NAME +.Nm querylocale +.Nd Look up the locale name for a specified category. +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.In xlocale.h +.Ft const char * +.Fn querylocale "int mask" "locale_t locale" +.Sh DESCRIPTION +Returns the name of the locale for the category specified by +.Fa mask. +This possible values for the mask are the same as those in +.Xr newlocale 3 . If more than one bit in the mask is set, the returned value +is undefined. +.Sh SEE ALSO +.Xr duplocale 3 , +.Xr freelocale 3 , +.Xr localeconv 3 , +.Xr newlocale 3 , +.Xr uselocale 3 , +.Xr xlocale 3 +.Sh STANDARDS +This function, conforms to +.St -p1003.1-2008 Index: lib/libc/locale/iswctype.c =================================================================== --- lib/libc/locale/iswctype.c (revision 225653) +++ lib/libc/locale/iswctype.c (working copy) @@ -36,7 +36,7 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/iswctype.c 172909 2007-10-23 17:39:28Z ache $"); #include Index: lib/libc/locale/wctype.c =================================================================== --- lib/libc/locale/wctype.c (revision 225653) +++ lib/libc/locale/wctype.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -25,22 +30,32 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/wctype.c 177311 2008-03-17 18:22:23Z antoine $"); #include #include #include +#include #undef iswctype int iswctype(wint_t wc, wctype_t charclass) { - return (__istype(wc, charclass)); } +int +iswctype_l(wint_t wc, wctype_t charclass, locale_t locale) +{ + return __istype_l(wc, charclass, locale); +} +/* + * IMPORTANT: The 0 in the call to this function in wctype() must be changed to + * __get_locale() if wctype_l() ie ever modified to actually use the locale + * parameter. + */ wctype_t -wctype(const char *property) +wctype_l(const char *property, locale_t locale) { static const struct { const char *name; @@ -72,3 +87,8 @@ return (props[i].mask); } + +wctype_t wctype(const char *property) +{ + return wctype_l(property, 0); +} Index: lib/libc/locale/lnumeric.c =================================================================== --- lib/libc/locale/lnumeric.c (revision 225653) +++ lib/libc/locale/lnumeric.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2000, 2001 Alexey Zelkin * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -25,14 +30,13 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/lnumeric.c 116875 2003-06-26 10:46:16Z phantom $"); #include #include "ldpart.h" #include "lnumeric.h" -extern int __nlocale_changed; extern const char *__fix_locale_grouping_str(const char *); #define LCNUMERIC_SIZE (sizeof(struct lc_numeric_T) / sizeof(char *)) @@ -45,37 +49,67 @@ numempty /* grouping */ }; -static struct lc_numeric_T _numeric_locale; -static int _numeric_using_locale; -static char *_numeric_locale_buf; +static void +destruct_numeric(void *v) +{ + struct xlocale_numeric *l = v; + if (l->buffer) + free(l->buffer); + free(l); +} -int -__numeric_load_locale(const char *name) +struct xlocale_numeric __xlocale_global_numeric; + +static int +numeric_load_locale(struct xlocale_numeric *loc, int *using_locale, int *changed, + const char *name) { int ret; + struct lc_numeric_T *l = &loc->locale; - ret = __part_load_locale(name, &_numeric_using_locale, - &_numeric_locale_buf, "LC_NUMERIC", + ret = __part_load_locale(name, using_locale, + &loc->buffer, "LC_NUMERIC", LCNUMERIC_SIZE, LCNUMERIC_SIZE, - (const char **)&_numeric_locale); + (const char**)l); if (ret != _LDP_ERROR) - __nlocale_changed = 1; + *changed= 1; if (ret == _LDP_LOADED) { /* Can't be empty according to C99 */ - if (*_numeric_locale.decimal_point == '\0') - _numeric_locale.decimal_point = + if (*l->decimal_point == '\0') + l->decimal_point = _C_numeric_locale.decimal_point; - _numeric_locale.grouping = - __fix_locale_grouping_str(_numeric_locale.grouping); + l->grouping = + __fix_locale_grouping_str(l->grouping); } return (ret); } +int +__numeric_load_locale(const char *name) +{ + return numeric_load_locale(&__xlocale_global_numeric, + &__xlocale_global_locale.using_numeric_locale, + &__xlocale_global_locale.numeric_locale_changed, name); +} +void * +__numeric_load(const char *name, locale_t l) +{ + struct xlocale_numeric *new = calloc(sizeof(struct xlocale_numeric), 1); + new->header.header.destructor = destruct_numeric; + if (numeric_load_locale(new, &l->using_numeric_locale, + &l->numeric_locale_changed, name)) + { + xlocale_release(new); + return NULL; + } + return new; +} + struct lc_numeric_T * -__get_current_numeric_locale(void) +__get_current_numeric_locale(locale_t loc) { - return (_numeric_using_locale - ? &_numeric_locale + return (loc->using_numeric_locale + ? &((struct xlocale_numeric *)loc->components[XLC_NUMERIC])->locale : (struct lc_numeric_T *)&_C_numeric_locale); } Index: lib/libc/locale/wcstoimax.c =================================================================== --- lib/libc/locale/wcstoimax.c (revision 225653) +++ lib/libc/locale/wcstoimax.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -34,26 +39,28 @@ #endif /* LIBC_SCCS and not lint */ __FBSDID("FreeBSD: src/lib/libc/stdlib/strtoimax.c,v 1.8 2002/09/06 11:23:59 tjr Exp "); #endif -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/wcstoimax.c 165903 2007-01-09 00:28:16Z imp $"); #include #include #include #include #include +#include "xlocale_private.h" /* * Convert a wide character string to an intmax_t integer. */ intmax_t -wcstoimax(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, - int base) +wcstoimax_l(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, + int base, locale_t locale) { const wchar_t *s; uintmax_t acc; wchar_t c; uintmax_t cutoff; int neg, any, cutlim; + FIX_LOCALE(locale); /* * See strtoimax for comments as to the logic used. @@ -61,7 +68,7 @@ s = nptr; do { c = *s++; - } while (iswspace(c)); + } while (iswspace_l(c, locale)); if (c == L'-') { neg = 1; c = *s++; @@ -88,8 +95,8 @@ cutoff /= base; for ( ; ; c = *s++) { #ifdef notyet - if (iswdigit(c)) - c = digittoint(c); + if (iswdigit_l(c, locale)) + c = digittoint_l(c, locale); else #endif if (c >= L'0' && c <= L'9') @@ -122,3 +129,9 @@ *endptr = (wchar_t *)(any ? s - 1 : nptr); return (acc); } +intmax_t +wcstoimax(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, + int base) +{ + return wcstoimax_l(nptr, endptr, base, __get_locale()); +} Index: lib/libc/locale/lnumeric.h =================================================================== --- lib/libc/locale/lnumeric.h (revision 225653) +++ lib/libc/locale/lnumeric.h (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2000, 2001 Alexey Zelkin * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -23,19 +28,25 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD$ + * $FreeBSD: head/lib/libc/locale/lnumeric.h 88309 2001-12-20 18:28:52Z phantom $ */ #ifndef _LNUMERIC_H_ #define _LNUMERIC_H_ +#include "xlocale_private.h" struct lc_numeric_T { const char *decimal_point; const char *thousands_sep; const char *grouping; }; +struct xlocale_numeric { + struct xlocale_component header; + char *buffer; + struct lc_numeric_T locale; +}; -struct lc_numeric_T *__get_current_numeric_locale(void); +struct lc_numeric_T *__get_current_numeric_locale(locale_t loc); int __numeric_load_locale(const char *); #endif /* !_LNUMERIC_H_ */ Index: lib/libc/locale/ldpart.c =================================================================== --- lib/libc/locale/ldpart.c (revision 225653) +++ lib/libc/locale/ldpart.c (working copy) @@ -25,7 +25,7 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/ldpart.c 128650 2004-04-25 19:56:50Z ache $"); #include "namespace.h" #include Index: lib/libc/locale/wctomb.c =================================================================== --- lib/libc/locale/wctomb.c (revision 225653) +++ lib/libc/locale/wctomb.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002-2004 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -25,25 +30,30 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/wctomb.c 132821 2004-07-29 06:18:40Z tjr $"); #include #include #include "mblocal.h" int -wctomb(char *s, wchar_t wchar) +wctomb_l(char *s, wchar_t wchar, locale_t locale) { static const mbstate_t initial; - static mbstate_t mbs; size_t rval; + FIX_LOCALE(locale); if (s == NULL) { /* No support for state dependent encodings. */ - mbs = initial; + locale->wctomb = initial; return (0); } - if ((rval = __wcrtomb(s, wchar, &mbs)) == (size_t)-1) + if ((rval = XLOCALE_CTYPE(locale)->__wcrtomb(s, wchar, &locale->wctomb)) == (size_t)-1) return (-1); return ((int)rval); } +int +wctomb(char *s, wchar_t wchar) +{ + return wctomb_l(s, wchar, __get_locale()); +} Index: lib/libc/locale/toupper.c =================================================================== --- lib/libc/locale/toupper.c (revision 225653) +++ lib/libc/locale/toupper.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Paul Borman at Krystal Technologies. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -31,18 +36,22 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/toupper.c 165903 2007-01-09 00:28:16Z imp $"); #include #include #include +#include +#include "mblocal.h" __ct_rune_t -___toupper(c) +___toupper_l(c, l) __ct_rune_t c; + locale_t l; { size_t lim; - _RuneRange *rr = &_CurrentRuneLocale->__mapupper_ext; + FIX_LOCALE(l); + _RuneRange *rr = &XLOCALE_CTYPE(l)->runes->__maplower_ext; _RuneEntry *base, *re; if (c < 0 || c == EOF) @@ -62,3 +71,9 @@ return(c); } +__ct_rune_t +___toupper(c) + __ct_rune_t c; +{ + return ___toupper_l(c, __get_locale()); +} Index: lib/libc/locale/fix_grouping.c =================================================================== --- lib/libc/locale/fix_grouping.c (revision 225653) +++ lib/libc/locale/fix_grouping.c (working copy) @@ -25,7 +25,7 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/fix_grouping.c 116875 2003-06-26 10:46:16Z phantom $"); #include #include Index: lib/libc/locale/wcstombs.c =================================================================== --- lib/libc/locale/wcstombs.c (revision 225653) +++ lib/libc/locale/wcstombs.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002-2004 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -25,7 +30,7 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/wcstombs.c 187302 2009-01-15 18:53:52Z rdivacky $"); #include #include @@ -33,13 +38,21 @@ #include "mblocal.h" size_t -wcstombs(char * __restrict s, const wchar_t * __restrict pwcs, size_t n) +wcstombs_l(char * __restrict s, const wchar_t * __restrict pwcs, size_t n, + locale_t locale) { static const mbstate_t initial; mbstate_t mbs; const wchar_t *pwcsp; + FIX_LOCALE(locale); mbs = initial; pwcsp = pwcs; - return (__wcsnrtombs(s, &pwcsp, SIZE_T_MAX, n, &mbs)); + return (XLOCALE_CTYPE(locale)->__wcsnrtombs(s, &pwcsp, SIZE_T_MAX, n, &mbs)); } +size_t +wcstombs(char * __restrict s, const wchar_t * __restrict pwcs, size_t n) +{ + return wcstombs_l(s, pwcs, n, __get_locale()); +} + Index: lib/libc/locale/wcstoull.c =================================================================== --- lib/libc/locale/wcstoull.c (revision 225653) +++ lib/libc/locale/wcstoull.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -34,26 +39,28 @@ #endif /* LIBC_SCCS and not lint */ __FBSDID("FreeBSD: src/lib/libc/stdlib/strtoull.c,v 1.18 2002/09/06 11:23:59 tjr Exp "); #endif -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/wcstoull.c 165903 2007-01-09 00:28:16Z imp $"); #include #include #include #include #include +#include "xlocale_private.h" /* * Convert a wide character string to an unsigned long long integer. */ unsigned long long -wcstoull(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, - int base) +wcstoull_l(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, + int base, locale_t locale) { const wchar_t *s; unsigned long long acc; wchar_t c; unsigned long long cutoff; int neg, any, cutlim; + FIX_LOCALE(locale); /* * See strtoull for comments as to the logic used. @@ -61,7 +68,7 @@ s = nptr; do { c = *s++; - } while (iswspace(c)); + } while (iswspace_l(c, locale)); if (c == L'-') { neg = 1; c = *s++; @@ -86,8 +93,8 @@ cutlim = ULLONG_MAX % base; for ( ; ; c = *s++) { #ifdef notyet - if (iswdigit(c)) - c = digittoint(c); + if (iswdigit_l(c, locale)) + c = digittoint_l(c, locale); else #endif if (c >= L'0' && c <= L'9') @@ -120,3 +127,9 @@ *endptr = (wchar_t *)(any ? s - 1 : nptr); return (acc); } +unsigned long long +wcstoull(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, + int base) +{ + return wcstoull_l(nptr, endptr, base, __get_locale()); +} Index: lib/libc/locale/euc.c =================================================================== --- lib/libc/locale/euc.c (revision 225653) +++ lib/libc/locale/euc.c (working copy) @@ -6,6 +6,11 @@ * This code is derived from software contributed to Berkeley by * Paul Borman at Krystal Technologies. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -39,7 +44,7 @@ static char sccsid[] = "@(#)euc.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/euc.c 172619 2007-10-13 16:28:22Z ache $"); #include #include @@ -70,7 +75,7 @@ } _EucState; int -_EUC_init(_RuneLocale *rl) +_EUC_init(struct xlocale_ctype *l, _RuneLocale *rl) { _EucInfo *ei; int x, new__mb_cur_max; @@ -113,12 +118,12 @@ } rl->__variable = ei; rl->__variable_len = sizeof(_EucInfo); - _CurrentRuneLocale = rl; - __mb_cur_max = new__mb_cur_max; - __mbrtowc = _EUC_mbrtowc; - __wcrtomb = _EUC_wcrtomb; - __mbsinit = _EUC_mbsinit; - __mb_sb_limit = 256; + l->runes = rl; + l->__mb_cur_max = new__mb_cur_max; + l->__mbrtowc = _EUC_mbrtowc; + l->__wcrtomb = _EUC_wcrtomb; + l->__mbsinit = _EUC_mbsinit; + l->__mb_sb_limit = 256; return (0); } Index: lib/libc/locale/wctob.c =================================================================== --- lib/libc/locale/wctob.c (revision 225653) +++ lib/libc/locale/wctob.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002-2004 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -25,7 +30,7 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/wctob.c 129154 2004-05-12 14:26:54Z tjr $"); #include #include @@ -33,13 +38,19 @@ #include "mblocal.h" int -wctob(wint_t c) +wctob_l(wint_t c, locale_t locale) { static const mbstate_t initial; mbstate_t mbs = initial; char buf[MB_LEN_MAX]; + FIX_LOCALE(locale); - if (c == WEOF || __wcrtomb(buf, c, &mbs) != 1) + if (c == WEOF || XLOCALE_CTYPE(locale)->__wcrtomb(buf, c, &mbs) != 1) return (EOF); return ((unsigned char)*buf); } +int +wctob(wint_t c) +{ + return wctob_l(c, __get_locale()); +} Index: lib/libc/locale/wcstold.c =================================================================== --- lib/libc/locale/wcstold.c (revision 225653) +++ lib/libc/locale/wcstold.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002, 2003 Tim J. Robbins * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -25,17 +30,19 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/wcstold.c 127998 2004-04-07 09:47:56Z tjr $"); #include #include #include +#include "xlocale_private.h" /* * See wcstod() for comments as to the logic used. */ long double -wcstold(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr) +wcstold_l(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, + locale_t locale) { static const mbstate_t initial; mbstate_t mbs; @@ -43,13 +50,14 @@ char *buf, *end; const wchar_t *wcp; size_t len; + FIX_LOCALE(locale); - while (iswspace(*nptr)) + while (iswspace_l(*nptr, locale)) nptr++; wcp = nptr; mbs = initial; - if ((len = wcsrtombs(NULL, &wcp, 0, &mbs)) == (size_t)-1) { + if ((len = wcsrtombs_l(NULL, &wcp, 0, &mbs, locale)) == (size_t)-1) { if (endptr != NULL) *endptr = (wchar_t *)nptr; return (0.0); @@ -57,9 +65,9 @@ if ((buf = malloc(len + 1)) == NULL) return (0.0); mbs = initial; - wcsrtombs(buf, &wcp, len + 1, &mbs); + wcsrtombs_l(buf, &wcp, len + 1, &mbs, locale); - val = strtold(buf, &end); + val = strtold_l(buf, &end, locale); if (endptr != NULL) *endptr = (wchar_t *)nptr + (end - buf); @@ -68,3 +76,8 @@ return (val); } +long double +wcstold(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr) +{ + return wcstold_l(nptr, endptr, __get_locale()); +} Index: lib/libc/locale/wctrans.c =================================================================== --- lib/libc/locale/wctrans.c (revision 225653) +++ lib/libc/locale/wctrans.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -25,11 +30,12 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/wctrans.c 121852 2003-11-01 08:20:58Z tjr $"); #include #include #include +#include "xlocale_private.h" enum { _WCT_ERROR = 0, @@ -38,15 +44,14 @@ }; wint_t -towctrans(wint_t wc, wctrans_t desc) +towctrans_l(wint_t wc, wctrans_t desc, locale_t locale) { - switch (desc) { case _WCT_TOLOWER: - wc = towlower(wc); + wc = towlower_l(wc, locale); break; case _WCT_TOUPPER: - wc = towupper(wc); + wc = towupper_l(wc, locale); break; case _WCT_ERROR: default: @@ -56,9 +61,18 @@ return (wc); } +wint_t +towctrans(wint_t wc, wctrans_t desc) +{ + return towctrans_l(wc, desc, __get_locale()); +} +/* + * wctrans() calls this will a 0 locale. If this is ever modified to actually + * use the locale, wctrans() must be modified to call __get_locale(). + */ wctrans_t -wctrans(const char *charclass) +wctrans_l(const char *charclass, locale_t locale) { struct { const char *name; @@ -78,3 +92,10 @@ errno = EINVAL; return (ccls[i].trans); } + +wctrans_t +wctrans(const char *charclass) +{ + return wctrans_l(charclass, 0); +} + Index: lib/libc/locale/gb18030.c =================================================================== --- lib/libc/locale/gb18030.c (revision 225653) +++ lib/libc/locale/gb18030.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002-2004 Tim J. Robbins * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -30,7 +35,7 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/gb18030.c 172619 2007-10-13 16:28:22Z ache $"); #include #include @@ -39,8 +44,6 @@ #include #include "mblocal.h" -extern int __mb_sb_limit; - static size_t _GB18030_mbrtowc(wchar_t * __restrict, const char * __restrict, size_t, mbstate_t * __restrict); static int _GB18030_mbsinit(const mbstate_t *); @@ -53,15 +56,15 @@ } _GB18030State; int -_GB18030_init(_RuneLocale *rl) +_GB18030_init(struct xlocale_ctype *l, _RuneLocale *rl) { - __mbrtowc = _GB18030_mbrtowc; - __wcrtomb = _GB18030_wcrtomb; - __mbsinit = _GB18030_mbsinit; - _CurrentRuneLocale = rl; - __mb_cur_max = 4; - __mb_sb_limit = 128; + l->__mbrtowc = _GB18030_mbrtowc; + l->__wcrtomb = _GB18030_wcrtomb; + l->__mbsinit = _GB18030_mbsinit; + l->runes = rl; + l->__mb_cur_max = 4; + l->__mb_sb_limit = 128; return (0); } Index: lib/libc/locale/nl_langinfo.c =================================================================== --- lib/libc/locale/nl_langinfo.c (revision 225653) +++ lib/libc/locale/nl_langinfo.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2001, 2003 Alexey Zelkin * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -25,7 +30,7 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/nl_langinfo.c 197765 2009-10-05 07:13:15Z edwin $"); #include #include @@ -41,15 +46,16 @@ #define _REL(BASE) ((int)item-BASE) char * -nl_langinfo(nl_item item) +nl_langinfo_l(nl_item item, locale_t loc) { - char *ret, *s, *cs; - static char *csym = NULL; + char *ret, *cs; + const char *s; + FIX_LOCALE(loc); switch (item) { case CODESET: ret = ""; - if ((s = setlocale(LC_CTYPE, NULL)) != NULL) { + if ((s = querylocale(LC_CTYPE_MASK, loc)) != NULL) { if ((cs = strchr(s, '.')) != NULL) ret = cs + 1; else if (strcmp(s, "C") == 0 || @@ -58,46 +64,46 @@ } break; case D_T_FMT: - ret = (char *) __get_current_time_locale()->c_fmt; + ret = (char *) __get_current_time_locale(loc)->c_fmt; break; case D_FMT: - ret = (char *) __get_current_time_locale()->x_fmt; + ret = (char *) __get_current_time_locale(loc)->x_fmt; break; case T_FMT: - ret = (char *) __get_current_time_locale()->X_fmt; + ret = (char *) __get_current_time_locale(loc)->X_fmt; break; case T_FMT_AMPM: - ret = (char *) __get_current_time_locale()->ampm_fmt; + ret = (char *) __get_current_time_locale(loc)->ampm_fmt; break; case AM_STR: - ret = (char *) __get_current_time_locale()->am; + ret = (char *) __get_current_time_locale(loc)->am; break; case PM_STR: - ret = (char *) __get_current_time_locale()->pm; + ret = (char *) __get_current_time_locale(loc)->pm; break; case DAY_1: case DAY_2: case DAY_3: case DAY_4: case DAY_5: case DAY_6: case DAY_7: - ret = (char*) __get_current_time_locale()->weekday[_REL(DAY_1)]; + ret = (char*) __get_current_time_locale(loc)->weekday[_REL(DAY_1)]; break; case ABDAY_1: case ABDAY_2: case ABDAY_3: case ABDAY_4: case ABDAY_5: case ABDAY_6: case ABDAY_7: - ret = (char*) __get_current_time_locale()->wday[_REL(ABDAY_1)]; + ret = (char*) __get_current_time_locale(loc)->wday[_REL(ABDAY_1)]; break; case MON_1: case MON_2: case MON_3: case MON_4: case MON_5: case MON_6: case MON_7: case MON_8: case MON_9: case MON_10: case MON_11: case MON_12: - ret = (char*) __get_current_time_locale()->month[_REL(MON_1)]; + ret = (char*) __get_current_time_locale(loc)->month[_REL(MON_1)]; break; case ABMON_1: case ABMON_2: case ABMON_3: case ABMON_4: case ABMON_5: case ABMON_6: case ABMON_7: case ABMON_8: case ABMON_9: case ABMON_10: case ABMON_11: case ABMON_12: - ret = (char*) __get_current_time_locale()->mon[_REL(ABMON_1)]; + ret = (char*) __get_current_time_locale(loc)->mon[_REL(ABMON_1)]; break; case ALTMON_1: case ALTMON_2: case ALTMON_3: case ALTMON_4: case ALTMON_5: case ALTMON_6: case ALTMON_7: case ALTMON_8: case ALTMON_9: case ALTMON_10: case ALTMON_11: case ALTMON_12: ret = (char*) - __get_current_time_locale()->alt_month[_REL(ALTMON_1)]; + __get_current_time_locale(loc)->alt_month[_REL(ALTMON_1)]; break; case ERA: /* XXX: need to be implemented */ @@ -120,16 +126,16 @@ ret = ""; break; case RADIXCHAR: - ret = (char*) __get_current_numeric_locale()->decimal_point; + ret = (char*) __get_current_numeric_locale(loc)->decimal_point; break; case THOUSEP: - ret = (char*) __get_current_numeric_locale()->thousands_sep; + ret = (char*) __get_current_numeric_locale(loc)->thousands_sep; break; case YESEXPR: - ret = (char*) __get_current_messages_locale()->yesexpr; + ret = (char*) __get_current_messages_locale(loc)->yesexpr; break; case NOEXPR: - ret = (char*) __get_current_messages_locale()->noexpr; + ret = (char*) __get_current_messages_locale(loc)->noexpr; break; /* * YESSTR and NOSTR items marked with LEGACY are available, but not @@ -137,45 +143,51 @@ * they're subject to remove in future specification editions. */ case YESSTR: /* LEGACY */ - ret = (char*) __get_current_messages_locale()->yesstr; + ret = (char*) __get_current_messages_locale(loc)->yesstr; break; case NOSTR: /* LEGACY */ - ret = (char*) __get_current_messages_locale()->nostr; + ret = (char*) __get_current_messages_locale(loc)->nostr; break; /* * SUSv2 special formatted currency string */ case CRNCYSTR: ret = ""; - cs = (char*) __get_current_monetary_locale()->currency_symbol; + cs = (char*) __get_current_monetary_locale(loc)->currency_symbol; if (*cs != '\0') { - char pos = localeconv()->p_cs_precedes; + char pos = localeconv_l(loc)->p_cs_precedes; - if (pos == localeconv()->n_cs_precedes) { + if (pos == localeconv_l(loc)->n_cs_precedes) { char psn = '\0'; if (pos == CHAR_MAX) { - if (strcmp(cs, __get_current_monetary_locale()->mon_decimal_point) == 0) + if (strcmp(cs, __get_current_monetary_locale(loc)->mon_decimal_point) == 0) psn = '.'; } else psn = pos ? '-' : '+'; if (psn != '\0') { int clen = strlen(cs); - if ((csym = reallocf(csym, clen + 2)) != NULL) { - *csym = psn; - strcpy(csym + 1, cs); - ret = csym; + if ((loc->csym = reallocf(loc->csym, clen + 2)) != NULL) { + *loc->csym = psn; + strcpy(loc->csym + 1, cs); + ret = loc->csym; } } } } break; case D_MD_ORDER: /* FreeBSD local extension */ - ret = (char *) __get_current_time_locale()->md_order; + ret = (char *) __get_current_time_locale(loc)->md_order; break; default: ret = ""; } return (ret); } + +char * +nl_langinfo(nl_item item) +{ + return nl_langinfo_l(item, __get_locale()); +} Index: lib/libc/locale/table.c =================================================================== --- lib/libc/locale/table.c (revision 225653) +++ lib/libc/locale/table.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Paul Borman at Krystal Technologies. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -34,14 +39,14 @@ static char sccsid[] = "@(#)table.c 8.1 (Berkeley) 6/27/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/table.c 165903 2007-01-09 00:28:16Z imp $"); #include #include #include #include "mblocal.h" -_RuneLocale _DefaultRuneLocale = { +const _RuneLocale _DefaultRuneLocale = { _RUNE_MAGIC_1, "NONE", NULL, @@ -245,5 +250,14 @@ }, }; -_RuneLocale *_CurrentRuneLocale = &_DefaultRuneLocale; +#undef _CurrentRuneLocale +_RuneLocale *_CurrentRuneLocale = (_RuneLocale*)&_DefaultRuneLocale; +_RuneLocale * +__runes_for_locale(locale_t locale, int *mb_sb_limit) +{ + FIX_LOCALE(locale); + struct xlocale_ctype *c = XLOCALE_CTYPE(locale); + *mb_sb_limit = c->__mb_sb_limit; + return c->runes; +} Index: lib/libc/locale/wcstoll.c =================================================================== --- lib/libc/locale/wcstoll.c (revision 225653) +++ lib/libc/locale/wcstoll.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -34,25 +39,28 @@ #endif /* LIBC_SCCS and not lint */ __FBSDID("FreeBSD: src/lib/libc/stdlib/strtoll.c,v 1.19 2002/09/06 11:23:59 tjr Exp "); #endif -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/wcstoll.c 165903 2007-01-09 00:28:16Z imp $"); #include #include #include #include #include +#include "xlocale_private.h" /* * Convert a wide character string to a long long integer. */ long long -wcstoll(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, int base) +wcstoll_l(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, + int base, locale_t locale) { const wchar_t *s; unsigned long long acc; wchar_t c; unsigned long long cutoff; int neg, any, cutlim; + FIX_LOCALE(locale); /* * See strtoll for comments as to the logic used. @@ -60,7 +68,7 @@ s = nptr; do { c = *s++; - } while (iswspace(c)); + } while (iswspace_l(c, locale)); if (c == L'-') { neg = 1; c = *s++; @@ -87,8 +95,8 @@ cutoff /= base; for ( ; ; c = *s++) { #ifdef notyet - if (iswdigit(c)) - c = digittoint(c); + if (iswdigit_l(c, locale)) + c = digittoint_l(c, locale); else #endif if (c >= L'0' && c <= L'9') @@ -121,3 +129,8 @@ *endptr = (wchar_t *)(any ? s - 1 : nptr); return (acc); } +long long +wcstoll(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, int base) +{ + return wcstoll_l(nptr, endptr, base, __get_locale()); +} Index: lib/libc/locale/tolower.c =================================================================== --- lib/libc/locale/tolower.c (revision 225653) +++ lib/libc/locale/tolower.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Paul Borman at Krystal Technologies. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -31,18 +36,22 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/tolower.c 165903 2007-01-09 00:28:16Z imp $"); #include #include #include +#include +#include "mblocal.h" __ct_rune_t -___tolower(c) +___tolower_l(c, l) __ct_rune_t c; + locale_t l; { size_t lim; - _RuneRange *rr = &_CurrentRuneLocale->__maplower_ext; + FIX_LOCALE(l); + _RuneRange *rr = &XLOCALE_CTYPE(l)->runes->__maplower_ext; _RuneEntry *base, *re; if (c < 0 || c == EOF) @@ -62,3 +71,9 @@ return(c); } +__ct_rune_t +___tolower(c) + __ct_rune_t c; +{ + return ___tolower_l(c, __get_locale()); +} Index: lib/libc/locale/mskanji.c =================================================================== --- lib/libc/locale/mskanji.c (revision 225653) +++ lib/libc/locale/mskanji.c (working copy) @@ -6,6 +6,11 @@ * (C) Sin'ichiro MIYATANI / Phase One, Inc * May 12, 1995 * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -37,7 +42,7 @@ static char sccsid[] = "@(#)mskanji.c 1.0 (Phase One) 5/5/95"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/mskanji.c 172619 2007-10-13 16:28:22Z ache $"); #include #include @@ -60,15 +65,15 @@ } _MSKanjiState; int -_MSKanji_init(_RuneLocale *rl) +_MSKanji_init(struct xlocale_ctype *l, _RuneLocale *rl) { - __mbrtowc = _MSKanji_mbrtowc; - __wcrtomb = _MSKanji_wcrtomb; - __mbsinit = _MSKanji_mbsinit; - _CurrentRuneLocale = rl; - __mb_cur_max = 2; - __mb_sb_limit = 256; + l->__mbrtowc = _MSKanji_mbrtowc; + l->__wcrtomb = _MSKanji_wcrtomb; + l->__mbsinit = _MSKanji_mbsinit; + l->runes = rl; + l->__mb_cur_max = 2; + l->__mb_sb_limit = 256; return (0); } Index: lib/libc/locale/mblen.c =================================================================== --- lib/libc/locale/mblen.c (revision 225653) +++ lib/libc/locale/mblen.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002-2004 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -25,26 +30,32 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/mblen.c 132821 2004-07-29 06:18:40Z tjr $"); #include #include #include "mblocal.h" int -mblen(const char *s, size_t n) +mblen_l(const char *s, size_t n, locale_t locale) { static const mbstate_t initial; - static mbstate_t mbs; size_t rval; + FIX_LOCALE(locale); if (s == NULL) { /* No support for state dependent encodings. */ - mbs = initial; + locale->mblen = initial; return (0); } - rval = __mbrtowc(NULL, s, n, &mbs); + rval = XLOCALE_CTYPE(locale)->__mbrtowc(NULL, s, n, &locale->mblen); if (rval == (size_t)-1 || rval == (size_t)-2) return (-1); return ((int)rval); } + +int +mblen(const char *s, size_t n) +{ + return mblen_l(s, n, __get_locale()); +} Index: lib/libc/locale/rpmatch.c =================================================================== --- lib/libc/locale/rpmatch.c (revision 225653) +++ lib/libc/locale/rpmatch.c (working copy) @@ -25,7 +25,7 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/rpmatch.c 139922 2005-01-09 03:55:13Z tjr $"); #include #include Index: lib/libc/locale/none.c =================================================================== --- lib/libc/locale/none.c (revision 225653) +++ lib/libc/locale/none.c (working copy) @@ -6,6 +6,11 @@ * This code is derived from software contributed to Berkeley by * Paul Borman at Krystal Technologies. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -35,7 +40,7 @@ static char sccsid[] = "@(#)none.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/none.c 172619 2007-10-13 16:28:22Z ache $"); #include #include @@ -64,17 +69,17 @@ int __mb_sb_limit = 256; /* Expected to be <= _CACHED_RUNES */ int -_none_init(_RuneLocale *rl) +_none_init(struct xlocale_ctype *l, _RuneLocale *rl) { - __mbrtowc = _none_mbrtowc; - __mbsinit = _none_mbsinit; - __mbsnrtowcs = _none_mbsnrtowcs; - __wcrtomb = _none_wcrtomb; - __wcsnrtombs = _none_wcsnrtombs; - _CurrentRuneLocale = rl; - __mb_cur_max = 1; - __mb_sb_limit = 256; + l->__mbrtowc = _none_mbrtowc; + l->__mbsinit = _none_mbsinit; + l->__mbsnrtowcs = _none_mbsnrtowcs; + l->__wcrtomb = _none_wcrtomb; + l->__wcsnrtombs = _none_wcsnrtombs; + l->runes = rl; + l->__mb_cur_max = 1; + l->__mb_sb_limit = 256; return(0); } @@ -192,3 +197,15 @@ size_t (*__wcsnrtombs)(char * __restrict, const wchar_t ** __restrict, size_t, size_t, mbstate_t * __restrict) = _none_wcsnrtombs; +struct xlocale_ctype __xlocale_global_ctype = { + {{0}, "C"}, + (_RuneLocale*)&_DefaultRuneLocale, + _none_mbrtowc, + _none_mbsinit, + _none_mbsnrtowcs, + _none_wcrtomb, + _none_wcsnrtombs, + 1, /* __mb_cur_max, */ + 256 /* __mb_sb_limit */ +}; + Index: lib/libc/locale/mbstowcs.c =================================================================== --- lib/libc/locale/mbstowcs.c (revision 225653) +++ lib/libc/locale/mbstowcs.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002-2004 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -25,7 +30,7 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/mbstowcs.c 187302 2009-01-15 18:53:52Z rdivacky $"); #include #include @@ -33,13 +38,19 @@ #include "mblocal.h" size_t -mbstowcs(wchar_t * __restrict pwcs, const char * __restrict s, size_t n) +mbstowcs_l(wchar_t * __restrict pwcs, const char * __restrict s, size_t n, locale_t locale) { static const mbstate_t initial; mbstate_t mbs; const char *sp; + FIX_LOCALE(locale); mbs = initial; sp = s; - return (__mbsnrtowcs(pwcs, &sp, SIZE_T_MAX, n, &mbs)); + return (XLOCALE_CTYPE(locale)->__mbsnrtowcs(pwcs, &sp, SIZE_T_MAX, n, &mbs)); } +size_t +mbstowcs(wchar_t * __restrict pwcs, const char * __restrict s, size_t n) +{ + return mbstowcs_l(pwcs, s, n, __get_locale()); +} Index: lib/libc/locale/wcstod.c =================================================================== --- lib/libc/locale/wcstod.c (revision 225653) +++ lib/libc/locale/wcstod.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002 Tim J. Robbins * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -25,11 +30,12 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/wcstod.c 127998 2004-04-07 09:47:56Z tjr $"); #include #include #include +#include "xlocale_private.h" /* * Convert a string to a double-precision number. @@ -41,7 +47,8 @@ * for at least the digits, radix character and letters. */ double -wcstod(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr) +wcstod_l(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, + locale_t locale) { static const mbstate_t initial; mbstate_t mbs; @@ -49,8 +56,9 @@ char *buf, *end; const wchar_t *wcp; size_t len; + FIX_LOCALE(locale); - while (iswspace(*nptr)) + while (iswspace_l(*nptr, locale)) nptr++; /* @@ -65,7 +73,7 @@ */ wcp = nptr; mbs = initial; - if ((len = wcsrtombs(NULL, &wcp, 0, &mbs)) == (size_t)-1) { + if ((len = wcsrtombs_l(NULL, &wcp, 0, &mbs, locale)) == (size_t)-1) { if (endptr != NULL) *endptr = (wchar_t *)nptr; return (0.0); @@ -73,10 +81,10 @@ if ((buf = malloc(len + 1)) == NULL) return (0.0); mbs = initial; - wcsrtombs(buf, &wcp, len + 1, &mbs); + wcsrtombs_l(buf, &wcp, len + 1, &mbs, locale); /* Let strtod() do most of the work for us. */ - val = strtod(buf, &end); + val = strtod_l(buf, &end, locale); /* * We only know where the number ended in the _multibyte_ @@ -92,3 +100,8 @@ return (val); } +double +wcstod(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr) +{ + return wcstod_l(nptr, endptr, __get_locale()); +} Index: lib/libc/locale/setrunelocale.c =================================================================== --- lib/libc/locale/setrunelocale.c (revision 225653) +++ lib/libc/locale/setrunelocale.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Paul Borman at Krystal Technologies. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -31,7 +36,7 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/setrunelocale.c 175586 2008-01-23 03:05:35Z ache $"); #include #include @@ -49,68 +54,46 @@ extern _RuneLocale *_Read_RuneMagi(FILE *); -static int __setrunelocale(const char *); +static int __setrunelocale(struct xlocale_ctype *l, const char *); +#define __collate_load_error (table->__collate_load_error) +#define __collate_substitute_nontrivial (table->__collate_substitute_nontrivial) +#define __collate_substitute_table_ptr (table->__collate_substitute_table_ptr) +#define __collate_char_pri_table_ptr (table->__collate_char_pri_table_ptr) +#define __collate_chain_pri_table (table->__collate_chain_pri_table) + + +static void destruct_ctype(void *v) +{ + struct xlocale_ctype *l = v; + if (strcmp(l->runes->__encoding, "EUC") == 0) + free(l->runes->__variable); + if (&_DefaultRuneLocale != l->runes) + free(l->runes); + free(l); +} +_RuneLocale *__getCurrentRuneLocale(void) +{ + return XLOCALE_CTYPE(__get_locale())->runes; +} + static int -__setrunelocale(const char *encoding) +__setrunelocale(struct xlocale_ctype *l, const char *encoding) { FILE *fp; char name[PATH_MAX]; _RuneLocale *rl; int saverr, ret; - size_t (*old__mbrtowc)(wchar_t * __restrict, - const char * __restrict, size_t, mbstate_t * __restrict); - size_t (*old__wcrtomb)(char * __restrict, wchar_t, - mbstate_t * __restrict); - int (*old__mbsinit)(const mbstate_t *); - size_t (*old__mbsnrtowcs)(wchar_t * __restrict, - const char ** __restrict, size_t, size_t, mbstate_t * __restrict); - size_t (*old__wcsnrtombs)(char * __restrict, - const wchar_t ** __restrict, size_t, size_t, - mbstate_t * __restrict); - static char ctype_encoding[ENCODING_LEN + 1]; - static _RuneLocale *CachedRuneLocale; - static int Cached__mb_cur_max; - static int Cached__mb_sb_limit; - static size_t (*Cached__mbrtowc)(wchar_t * __restrict, - const char * __restrict, size_t, mbstate_t * __restrict); - static size_t (*Cached__wcrtomb)(char * __restrict, wchar_t, - mbstate_t * __restrict); - static int (*Cached__mbsinit)(const mbstate_t *); - static size_t (*Cached__mbsnrtowcs)(wchar_t * __restrict, - const char ** __restrict, size_t, size_t, mbstate_t * __restrict); - static size_t (*Cached__wcsnrtombs)(char * __restrict, - const wchar_t ** __restrict, size_t, size_t, - mbstate_t * __restrict); + struct xlocale_ctype saved = *l; /* * The "C" and "POSIX" locale are always here. */ if (strcmp(encoding, "C") == 0 || strcmp(encoding, "POSIX") == 0) { - (void) _none_init(&_DefaultRuneLocale); + (void) _none_init(l, (_RuneLocale*)&_DefaultRuneLocale); return (0); } - /* - * If the locale name is the same as our cache, use the cache. - */ - if (CachedRuneLocale != NULL && - strcmp(encoding, ctype_encoding) == 0) { - _CurrentRuneLocale = CachedRuneLocale; - __mb_cur_max = Cached__mb_cur_max; - __mb_sb_limit = Cached__mb_sb_limit; - __mbrtowc = Cached__mbrtowc; - __mbsinit = Cached__mbsinit; - __mbsnrtowcs = Cached__mbsnrtowcs; - __wcrtomb = Cached__wcrtomb; - __wcsnrtombs = Cached__wcsnrtombs; - return (0); - } - - /* - * Slurp the locale file into the cache. - */ - /* Range checking not needed, encoding length already checked before */ (void) strcpy(name, _PathLocale); (void) strcat(name, "/"); @@ -127,63 +110,47 @@ } (void)fclose(fp); - old__mbrtowc = __mbrtowc; - old__mbsinit = __mbsinit; - old__mbsnrtowcs = __mbsnrtowcs; - old__wcrtomb = __wcrtomb; - old__wcsnrtombs = __wcsnrtombs; + l->__mbrtowc = NULL; + l->__mbsinit = NULL; + l->__mbsnrtowcs = __mbsnrtowcs_std; + l->__wcrtomb = NULL; + l->__wcsnrtombs = __wcsnrtombs_std; - __mbrtowc = NULL; - __mbsinit = NULL; - __mbsnrtowcs = __mbsnrtowcs_std; - __wcrtomb = NULL; - __wcsnrtombs = __wcsnrtombs_std; - rl->__sputrune = NULL; rl->__sgetrune = NULL; if (strcmp(rl->__encoding, "NONE") == 0) - ret = _none_init(rl); + ret = _none_init(l, rl); else if (strcmp(rl->__encoding, "ASCII") == 0) - ret = _ascii_init(rl); + ret = _ascii_init(l, rl); else if (strcmp(rl->__encoding, "UTF-8") == 0) - ret = _UTF8_init(rl); + ret = _UTF8_init(l, rl); else if (strcmp(rl->__encoding, "EUC") == 0) - ret = _EUC_init(rl); + ret = _EUC_init(l, rl); else if (strcmp(rl->__encoding, "GB18030") == 0) - ret = _GB18030_init(rl); + ret = _GB18030_init(l, rl); else if (strcmp(rl->__encoding, "GB2312") == 0) - ret = _GB2312_init(rl); + ret = _GB2312_init(l, rl); else if (strcmp(rl->__encoding, "GBK") == 0) - ret = _GBK_init(rl); + ret = _GBK_init(l, rl); else if (strcmp(rl->__encoding, "BIG5") == 0) - ret = _BIG5_init(rl); + ret = _BIG5_init(l, rl); else if (strcmp(rl->__encoding, "MSKanji") == 0) - ret = _MSKanji_init(rl); + ret = _MSKanji_init(l, rl); else ret = EFTYPE; if (ret == 0) { - if (CachedRuneLocale != NULL) { - /* See euc.c */ - if (strcmp(CachedRuneLocale->__encoding, "EUC") == 0) - free(CachedRuneLocale->__variable); - free(CachedRuneLocale); + /* Free the old runes if it exists. */ + /* FIXME: The "EUC" check here is a hideous abstraction violation. */ + if ((saved.runes != &_DefaultRuneLocale) && (saved.runes)) { + if (strcmp(saved.runes->__encoding, "EUC") == 0) { + free(saved.runes->__variable); + } + free(saved.runes); } - CachedRuneLocale = _CurrentRuneLocale; - Cached__mb_cur_max = __mb_cur_max; - Cached__mb_sb_limit = __mb_sb_limit; - Cached__mbrtowc = __mbrtowc; - Cached__mbsinit = __mbsinit; - Cached__mbsnrtowcs = __mbsnrtowcs; - Cached__wcrtomb = __wcrtomb; - Cached__wcsnrtombs = __wcsnrtombs; - (void)strcpy(ctype_encoding, encoding); } else { - __mbrtowc = old__mbrtowc; - __mbsinit = old__mbsinit; - __mbsnrtowcs = old__mbsnrtowcs; - __wcrtomb = old__wcrtomb; - __wcsnrtombs = old__wcsnrtombs; + /* Restore the saved version if this failed. */ + memcpy(l, &saved, sizeof(struct xlocale_ctype)); free(rl); } @@ -193,12 +160,24 @@ int __wrap_setrunelocale(const char *locale) { - int ret = __setrunelocale(locale); + int ret = __setrunelocale(&__xlocale_global_ctype, locale); if (ret != 0) { errno = ret; return (_LDP_ERROR); } + __mb_cur_max = __xlocale_global_ctype.__mb_cur_max; + __mb_sb_limit = __xlocale_global_ctype.__mb_sb_limit; return (_LDP_LOADED); } - +void *__ctype_load(const char *locale, locale_t unused) +{ + struct xlocale_ctype *l = calloc(sizeof(struct xlocale_ctype), 1); + l->header.header.destructor = destruct_ctype; + if (__setrunelocale(l, locale)) + { + free(l); + return NULL; + } + return l; +} Index: lib/libc/locale/lmonetary.c =================================================================== --- lib/libc/locale/lmonetary.c (revision 225653) +++ lib/libc/locale/lmonetary.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2000, 2001 Alexey Zelkin * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -25,7 +30,7 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/lmonetary.c 116875 2003-06-26 10:46:16Z phantom $"); #include #include @@ -34,7 +39,6 @@ #include "ldpart.h" #include "lmonetary.h" -extern int __mlocale_changed; extern const char * __fix_locale_grouping_str(const char *); #define LCMONETARY_SIZE_FULL (sizeof(struct lc_monetary_T) / sizeof(char *)) @@ -69,9 +73,7 @@ numempty /* int_n_sign_posn */ }; -static struct lc_monetary_T _monetary_locale; -static int _monetary_using_locale; -static char *_monetary_locale_buf; +struct xlocale_monetary __xlocale_global_monetary; static char cnv(const char *str) @@ -83,23 +85,34 @@ return ((char)i); } -int -__monetary_load_locale(const char *name) +static void +destruct_monetary(void *v) { + struct xlocale_monetary *l = v; + if (l->buffer) + free(l->buffer); + free(l); +} + +static int +monetary_load_locale_l(struct xlocale_monetary *loc, int *using_locale, + int *changed, const char *name) +{ int ret; + struct lc_monetary_T *l = &loc->locale; - ret = __part_load_locale(name, &_monetary_using_locale, - &_monetary_locale_buf, "LC_MONETARY", + ret = __part_load_locale(name, using_locale, + &loc->buffer, "LC_MONETARY", LCMONETARY_SIZE_FULL, LCMONETARY_SIZE_MIN, - (const char **)&_monetary_locale); + (const char **)l); if (ret != _LDP_ERROR) - __mlocale_changed = 1; + *changed = 1; if (ret == _LDP_LOADED) { - _monetary_locale.mon_grouping = - __fix_locale_grouping_str(_monetary_locale.mon_grouping); + l->mon_grouping = + __fix_locale_grouping_str(l->mon_grouping); -#define M_ASSIGN_CHAR(NAME) (((char *)_monetary_locale.NAME)[0] = \ - cnv(_monetary_locale.NAME)) +#define M_ASSIGN_CHAR(NAME) (((char *)l->NAME)[0] = \ + cnv(l->NAME)) M_ASSIGN_CHAR(int_frac_digits); M_ASSIGN_CHAR(frac_digits); @@ -117,9 +130,9 @@ */ #define M_ASSIGN_ICHAR(NAME) \ do { \ - if (_monetary_locale.int_##NAME == NULL) \ - _monetary_locale.int_##NAME = \ - _monetary_locale.NAME; \ + if (l->int_##NAME == NULL) \ + l->int_##NAME = \ + l->NAME; \ else \ M_ASSIGN_CHAR(int_##NAME); \ } while (0) @@ -133,12 +146,32 @@ } return (ret); } +int +__monetary_load_locale(const char *name) +{ + return monetary_load_locale_l(&__xlocale_global_monetary, + &__xlocale_global_locale.using_monetary_locale, + &__xlocale_global_locale.monetary_locale_changed, name); +} +void* __monetary_load(const char *name, locale_t l) +{ + struct xlocale_monetary *new = calloc(sizeof(struct xlocale_monetary), 1); + new->header.header.destructor = destruct_monetary; + if (monetary_load_locale_l(new, &l->using_monetary_locale, + &l->monetary_locale_changed, name) != _LDP_LOADED) + { + xlocale_release(new); + return NULL; + } + return new; +} + struct lc_monetary_T * -__get_current_monetary_locale(void) +__get_current_monetary_locale(locale_t loc) { - return (_monetary_using_locale - ? &_monetary_locale + return (loc->using_monetary_locale + ? &((struct xlocale_monetary*)loc->components[XLC_MONETARY])->locale : (struct lc_monetary_T *)&_C_monetary_locale); } Index: lib/libc/locale/nextwctype.c =================================================================== --- lib/libc/locale/nextwctype.c (revision 225653) +++ lib/libc/locale/nextwctype.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2004 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -25,17 +30,20 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/nextwctype.c 131787 2004-07-08 06:43:37Z tjr $"); #include #include #include +#include "mblocal.h" wint_t -nextwctype(wint_t wc, wctype_t wct) +nextwctype_l(wint_t wc, wctype_t wct, locale_t locale) { size_t lim; - _RuneRange *rr = &_CurrentRuneLocale->__runetype_ext; + FIX_LOCALE(locale); + _RuneLocale *runes = XLOCALE_CTYPE(locale)->runes; + _RuneRange *rr = &runes->__runetype_ext; _RuneEntry *base, *re; int noinc; @@ -43,7 +51,7 @@ if (wc < _CACHED_RUNES) { wc++; while (wc < _CACHED_RUNES) { - if (_CurrentRuneLocale->__runetype[wc] & wct) + if (runes->__runetype[wc] & wct) return (wc); wc++; } @@ -88,3 +96,8 @@ } return (-1); } +wint_t +nextwctype(wint_t wc, wctype_t wct) +{ + return nextwctype_l(wc, wct, __get_locale()); +} Index: lib/libc/locale/wcstol.c =================================================================== --- lib/libc/locale/wcstol.c (revision 225653) +++ lib/libc/locale/wcstol.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -28,25 +33,28 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/wcstol.c 165903 2007-01-09 00:28:16Z imp $"); #include #include #include #include #include +#include "xlocale_private.h" /* * Convert a string to a long integer. */ long -wcstol(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, int base) +wcstol_l(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, int + base, locale_t locale) { const wchar_t *s; unsigned long acc; wchar_t c; unsigned long cutoff; int neg, any, cutlim; + FIX_LOCALE(locale); /* * See strtol for comments as to the logic used. @@ -54,7 +62,7 @@ s = nptr; do { c = *s++; - } while (iswspace(c)); + } while (iswspace_l(c, locale)); if (c == '-') { neg = 1; c = *s++; @@ -81,8 +89,8 @@ cutoff /= base; for ( ; ; c = *s++) { #ifdef notyet - if (iswdigit(c)) - c = digittoint(c); + if (iswdigit_l(c, locale)) + c = digittoint_l(c, locale); else #endif if (c >= L'0' && c <= L'9') @@ -115,3 +123,8 @@ *endptr = (wchar_t *)(any ? s - 1 : nptr); return (acc); } +long +wcstol(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, int base) +{ + return wcstol_l(nptr, endptr, base, __get_locale()); +} Index: lib/libc/locale/wcrtomb.c =================================================================== --- lib/libc/locale/wcrtomb.c (revision 225653) +++ lib/libc/locale/wcrtomb.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002-2004 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -25,17 +30,23 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/wcrtomb.c 129153 2004-05-12 14:09:04Z tjr $"); #include #include "mblocal.h" size_t -wcrtomb(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps) +wcrtomb_l(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps, + locale_t locale) { - static mbstate_t mbs; - + FIX_LOCALE(locale); if (ps == NULL) - ps = &mbs; - return (__wcrtomb(s, wc, ps)); + ps = &locale->wcrtomb; + return (XLOCALE_CTYPE(locale)->__wcrtomb(s, wc, ps)); } + +size_t +wcrtomb(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps) +{ + return wcrtomb_l(s, wc, ps, __get_locale()); +} Index: lib/libc/locale/lmonetary.h =================================================================== --- lib/libc/locale/lmonetary.h (revision 225653) +++ lib/libc/locale/lmonetary.h (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2000, 2001 Alexey Zelkin * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -23,11 +28,12 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD$ + * $FreeBSD: head/lib/libc/locale/lmonetary.h 104711 2002-10-09 09:19:28Z tjr $ */ #ifndef _LMONETARY_H_ #define _LMONETARY_H_ +#include "xlocale_private.h" struct lc_monetary_T { const char *int_curr_symbol; @@ -52,8 +58,13 @@ const char *int_p_sign_posn; const char *int_n_sign_posn; }; +struct xlocale_monetary { + struct xlocale_component header; + char *buffer; + struct lc_monetary_T locale; +}; -struct lc_monetary_T *__get_current_monetary_locale(void); +struct lc_monetary_T *__get_current_monetary_locale(locale_t loc); int __monetary_load_locale(const char *); #endif /* !_LMONETARY_H_ */ Index: lib/libc/locale/nomacros.c =================================================================== --- lib/libc/locale/nomacros.c (revision 225653) +++ lib/libc/locale/nomacros.c (working copy) @@ -1,5 +1,5 @@ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/nomacros.c 92986 2002-03-22 21:53:29Z obrien $"); /* * Tell to generate extern versions of all its inline Index: lib/libc/locale/wcsftime.c =================================================================== --- lib/libc/locale/wcsftime.c (revision 225653) +++ lib/libc/locale/wcsftime.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002 Tim J. Robbins * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -25,13 +30,14 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/wcsftime.c 187312 2009-01-15 20:45:59Z rdivacky $"); #include #include #include #include #include +#include "xlocale_private.h" /* * Convert date and time to a wide-character string. @@ -47,8 +53,9 @@ * format specifications in the format string. */ size_t -wcsftime(wchar_t * __restrict wcs, size_t maxsize, - const wchar_t * __restrict format, const struct tm * __restrict timeptr) +wcsftime_l(wchar_t * __restrict wcs, size_t maxsize, + const wchar_t * __restrict format, const struct tm * __restrict timeptr, + locale_t locale) { static const mbstate_t initial; mbstate_t mbs; @@ -57,6 +64,7 @@ const wchar_t *formatp; size_t n, sflen; int sverrno; + FIX_LOCALE(locale); sformat = dst = NULL; @@ -66,13 +74,13 @@ */ mbs = initial; formatp = format; - sflen = wcsrtombs(NULL, &formatp, 0, &mbs); + sflen = wcsrtombs_l(NULL, &formatp, 0, &mbs, locale); if (sflen == (size_t)-1) goto error; if ((sformat = malloc(sflen + 1)) == NULL) goto error; mbs = initial; - wcsrtombs(sformat, &formatp, sflen + 1, &mbs); + wcsrtombs_l(sformat, &formatp, sflen + 1, &mbs, locale); /* * Allocate memory for longest multibyte sequence that will fit @@ -87,11 +95,11 @@ } if ((dst = malloc(maxsize * MB_CUR_MAX)) == NULL) goto error; - if (strftime(dst, maxsize, sformat, timeptr) == 0) + if (strftime_l(dst, maxsize, sformat, timeptr, locale) == 0) goto error; dstp = dst; mbs = initial; - n = mbsrtowcs(wcs, &dstp, maxsize, &mbs); + n = mbsrtowcs_l(wcs, &dstp, maxsize, &mbs, locale); if (n == (size_t)-2 || n == (size_t)-1 || dstp != NULL) goto error; @@ -106,3 +114,9 @@ errno = sverrno; return (0); } +size_t +wcsftime(wchar_t * __restrict wcs, size_t maxsize, + const wchar_t * __restrict format, const struct tm * __restrict timeptr) +{ + return wcsftime_l(wcs, maxsize, format, timeptr, __get_locale()); +} Index: lib/libc/locale/xlocale_private.h =================================================================== --- lib/libc/locale/xlocale_private.h (revision 0) +++ lib/libc/locale/xlocale_private.h (revision 0) @@ -0,0 +1,199 @@ +/*- + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by David Chisnall under sponsorship from + * the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions * are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _XLOCALE_PRIVATE__H_ +#define _XLOCALE_PRIVATE__H_ + +#include +#include +#include +#include +#include "setlocale.h" + +enum { + XLC_COLLATE = 0, + XLC_CTYPE, + XLC_MONETARY, + XLC_NUMERIC, + XLC_TIME, + XLC_MESSAGES, + XLC_LAST +}; + + +/** + * Header used for objects that are reference counted. Objects may optionally + * have a destructor associated, which is responsible for destroying the + * structure. Global / static versions of the structure should have no + * destructor set - they can then have their reference counts manipulated as + * normal, but will not do anything with them. + * + * The header stores a retain count - objects are assumed to have a reference + * count of 1 when they are created, but the retain count is 0. When the + * retain count is less than 0, they are freed. + */ +struct xlocale_refcounted { + /** Number of references to this component. */ + long retain_count; + /** Function used to destroy this component, if one is required*/ + void(*destructor)(void*); +}; +/** + * Header for a locale component. All locale components must begin with this + * header. + */ +struct xlocale_component { + struct xlocale_refcounted header; + /** Name of the locale used for this component. */ + char locale[ENCODING_LEN+1]; +}; + +/** + * xlocale structure, stores per-thread locale information. + * + * Note: We could save a few bytes by using a bitfield for the flags at the end + * of this structure. I imagine that most programs will not have more than + * half a dozen locales though, so this doesn't seem worthwhile. + */ +struct _xlocale { + struct xlocale_refcounted header; + /** Components for the locale. */ + struct xlocale_component *components[XLC_LAST]; + /** Flag indicating if components[XLC_MONETARY] has changed since the last + * call to localeconv_l() with this locale. */ + int monetary_locale_changed; + /** Flag indicating whether this locale is actually using a locale for + * LC_MONETARY (1), or if it should use the C default instead (0). */ + int using_monetary_locale; + /** Flag indicating if components[XLC_NUMERIC] has changed since the last + * call to localeconv_l() with this locale. */ + int numeric_locale_changed; + /** Flag indicating whether this locale is actually using a locale for + * LC_NUMERIC (1), or if it should use the C default instead (0). */ + int using_numeric_locale; + /** Flag indicating whether this locale is actually using a locale for + * LC_TIME (1), or if it should use the C default instead (0). */ + int using_time_locale; + /** Flag indicating whether this locale is actually using a locale for + * LC_MESSAGES (1), or if it should use the C default instead (0). */ + int using_messages_locale; + /** The structure to be returned from localeconv_l() for this locale. */ + struct lconv lconv; + /** Persistent state used by mblen() calls. */ + __mbstate_t mblen; + /** Persistent state used by mbrlen() calls. */ + __mbstate_t mbrlen; + /** Persistent state used by mbrtowc() calls. */ + __mbstate_t mbrtowc; + /** Persistent state used by mbsnrtowcs() calls. */ + __mbstate_t mbsnrtowcs; + /** Persistent state used by mbsrtowcs() calls. */ + __mbstate_t mbsrtowcs; + /** Persistent state used by mbtowc() calls. */ + __mbstate_t mbtowc; + /** Persistent state used by wcrtomb() calls. */ + __mbstate_t wcrtomb; + /** Persistent state used by wcsnrtombs() calls. */ + __mbstate_t wcsnrtombs; + /** Persistent state used by wcsrtombs() calls. */ + __mbstate_t wcsrtombs; + /** Persistent state used by wctomb() calls. */ + __mbstate_t wctomb; + /** Buffer used by nl_langinfo_l() */ + char *csym; +}; + +/** + * Increments the reference count of a reference-counted structure. + */ +__attribute__((unused)) static void* +xlocale_retain(void *val) +{ + struct xlocale_refcounted *obj = val; + __sync_fetch_and_add(&(obj->retain_count), 1); + return val; +} +/** + * Decrements the reference count of a reference-counted structure, freeing it + * if this is the last reference, calling its destructor if it has one. + */ +__attribute__((unused)) static void +xlocale_release(void *val) +{ + struct xlocale_refcounted *obj = val; + long count = __sync_sub_and_fetch(&(obj->retain_count), 1); + if (count < 0) + { + if (0 != obj->destructor) + { + obj->destructor(obj); + } + } +} + +/** + * Load functions. Each takes the name of a locale and a pointer to the data + * to be initialised as arguments. Two special values are allowed for the + */ +extern void* __collate_load(const char*, locale_t); +extern void* __ctype_load(const char*, locale_t); +extern void* __messages_load(const char*, locale_t); +extern void* __monetary_load(const char*, locale_t); +extern void* __numeric_load(const char*, locale_t); +extern void* __time_load(const char*, locale_t); + +extern struct _xlocale __xlocale_global_locale; + +/** + * Returns the current locale for this thread, or the global locale if none is + * set. The caller does not have to free the locale. The return value from + * this call is not guaranteed to remain valid after the locale changes. As + * such, this should only be called within libc functions. + */ +locale_t __get_locale(void); + +/** + * Two magic values are allowed for locale_t objects. NULL and -1. This + * function maps those to the real locales that they represent. + */ +static inline locale_t get_real_locale(locale_t locale) +{ + switch ((intptr_t)locale) + { + case 0: return &__xlocale_global_locale; + case -1: return __get_locale(); + default: return locale; + } +} + +/** + * Replace a plaecholder locale with the real global or thread-local locale_t. + */ +#define FIX_LOCALE(l) (l = get_real_locale(l)) + +#endif Index: lib/libc/locale/newlocale.3 =================================================================== --- lib/libc/locale/newlocale.3 (revision 0) +++ lib/libc/locale/newlocale.3 (revision 0) @@ -0,0 +1,111 @@ +.\" Copyright (c) 2011 The FreeBSD Foundation +.\" All rights reserved. +.\" +.\" This documentation was written by David Chisnall under sponsorship from +.\" the FreeBSD Foundation. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)ctype.3 8.1 (Berkeley) 6/4/93 +.\" $FreeBSD: head/lib/libc/locale/ctype.3 196820 2009-09-04 07:44:58Z des $ +.\" +.Dd September 17 2011 +.Dt newlocale 3 +.Os +.Sh NAME +.Nm newlocale +.Nd Creates a new locale +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.In xlocale +.Ft +.Fn newlocale "int mask" "const char * locale" "locale_t base" +.Sh DESCRIPTION +Creates a new locale, inheriting some properties from an existing locale. The +.Fa mask +defines the components that the new locale will have set to the locale with the +name specified in the +.Fa locale +parameter. Any other components will be inherited from +.Fa base . +.Pt +The +.Fa mask +is either +.Fa LC_ALL_MASK, +indicating all possible locale components, or the logical OR of some +combination of the following: +.Bl -tag -width "LC_MESSAGES_MASK" -offset indent +.It LC_COLLATE_MASK +The locale for string collation routines. This controls alphabetic ordering in +.Xr strcoll 3 + and +.Xr strxfrm 3 . +.It LC_CTYPE_MASK +The locale for the +.Xr ctype 3 +and +.Xr multibyte 3 +functions. This controls recognition of upper and lower case, alpha- betic or +non-alphabetic characters, and so on. +.It LC_MESSAGES_MASK +Set a locale for message catalogs, see +.Xr catopen 3 +function. +.It LC_MONETARY_MASK +Set a locale for formatting monetary values; this affects +the +.Xr localeconv 3 +function. +.It LC_NUMERIC_MASK +Set a locale for formatting numbers. This controls the for- +matting of decimal points in input and output of floating +point numbers in functions such as +.Xr printf 3 +and +.Xr scanf 3 , +as well as values returned by +.Xr localeconv 3 . +.It LC_TIME_MASK +Set a locale for formatting dates and times using the +.Xr strftime 3 +function. +.El + +This function uses the same rules for loading locale components as +.Xr setlocale 3 . +.Sh RETURN VALUES +Returns a new, valid, +.Fa locale_t +or NULL if an error occurs. You must free the returned locale with +.Xr freelocale 3 . +.Sh SEE ALSO +.Xr duplocale 3 , +.Xr freelocale 3 , +.Xr localeconv 3 , +.Xr querylocale 3 , +.Xr uselocale 3 , +.Xr xlocale 3 +.Sh STANDARDS +This function, conforms to +.St -p1003.1-2008 Index: lib/libc/locale/mbsnrtowcs.c =================================================================== --- lib/libc/locale/mbsnrtowcs.c (revision 225653) +++ lib/libc/locale/mbsnrtowcs.c (working copy) @@ -1,6 +1,11 @@ /*- * Copyright (c) 2002-2004 Tim J. Robbins. + * + * Copyright (c) 2011 The FreeBSD Foundation * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -25,7 +30,7 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/mbsnrtowcs.c 132497 2004-07-21 10:54:57Z tjr $"); #include #include @@ -34,14 +39,19 @@ #include "mblocal.h" size_t +mbsnrtowcs_l(wchar_t * __restrict dst, const char ** __restrict src, + size_t nms, size_t len, mbstate_t * __restrict ps, locale_t locale) +{ + FIX_LOCALE(locale); + if (ps == NULL) + ps = &locale->mbsnrtowcs; + return (XLOCALE_CTYPE(locale)->__mbsnrtowcs(dst, src, nms, len, ps)); +} +size_t mbsnrtowcs(wchar_t * __restrict dst, const char ** __restrict src, size_t nms, size_t len, mbstate_t * __restrict ps) { - static mbstate_t mbs; - - if (ps == NULL) - ps = &mbs; - return (__mbsnrtowcs(dst, src, nms, len, ps)); + return mbsnrtowcs_l(dst, src, nms, len, ps, __get_locale()); } size_t @@ -52,13 +62,14 @@ size_t nchr; wchar_t wc; size_t nb; + struct xlocale_ctype *ct = XLOCALE_CTYPE(__get_locale()); s = *src; nchr = 0; if (dst == NULL) { for (;;) { - if ((nb = __mbrtowc(&wc, s, nms, ps)) == (size_t)-1) + if ((nb = ct->__mbrtowc(&wc, s, nms, ps)) == (size_t)-1) /* Invalid sequence - mbrtowc() sets errno. */ return ((size_t)-1); else if (nb == 0 || nb == (size_t)-2) @@ -71,7 +82,7 @@ } while (len-- > 0) { - if ((nb = __mbrtowc(dst, s, nms, ps)) == (size_t)-1) { + if ((nb = ct->__mbrtowc(dst, s, nms, ps)) == (size_t)-1) { *src = s; return ((size_t)-1); } else if (nb == (size_t)-2) { Index: lib/libc/locale/xlocale.3 =================================================================== --- lib/libc/locale/xlocale.3 (revision 0) +++ lib/libc/locale/xlocale.3 (revision 0) @@ -0,0 +1,268 @@ +.\" Copyright (c) 2011 The FreeBSD Foundation +.\" All rights reserved. +.\" +.\" This documentation was written by David Chisnall under sponsorship from +.\" the FreeBSD Foundation. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)ctype.3 8.1 (Berkeley) 6/4/93 +.\" $FreeBSD: head/lib/libc/locale/ctype.3 196820 2009-09-04 07:44:58Z des $ +.\" +.Dd September 17 2011 +.Dt XLOCALE 3 +.Os +.Sh NAME +.Nm xlocale +.Nd Thread-safe extended locale support. +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.In xlocale.h +.Sh DESCRIPTION +The extended locale support includes a set of functions for setting +thread-local locales, as well convenience functions for performing locale-aware +calls with a specified locale. +.Pp +The core of the xlocale API is the +.Fa locale_t +type. This is an opqaue type encapsulating a locale. Instances of this can be +either set as the locale for a specific thread or passed directly to the +.Fa _l +suffixed variants of various standard C functions. Two special +.Fa locale_t +values are available: +.Bl -bullet -offset indent +.It +NULL refers to the current locale for the thread, or to the global locale if no +locale has been set for this thread. +.It +LC_GLOBAL_LOCALE refers to the global locale. +.El +.Pp +The global locale is the locale set with the +.Xr setlocale 3 +function. +.Sh CAVEATS +The +.Xr setlocale 3 +function, and others in the family, refer to the global locale. Other +functions that depend on the locale, however, will take the thread-local locale +if one has been set. This means that the idiom of setting the locale using +.Xr setlocale 3 , +calling a locale-dependent function, and then restoring the locale will not +have the expected behavior if the current thread has had a locale set using +.Xr uselocale 3 . +You should avoid this idiom and prefer to use the +.Fa _l +suffixed versions instead. +.Sh SEE ALSO +.Xr duplocale 3 , +.Xr freelocale 3 , +.Xr localeconv 3 , +.Xr newlocale 3 , +.Xr querylocale 3 , +.Xr uselocale 3 , +.Sh CONVENIENCE FUNCTIONS +The xlocale API includes a number of +.Fa _l +suffixed convenience functions. These are variants of standard C functions +that have been modified to take an explicit +.Fa locale_t +parameter as the final argument or, in the case of variadic functions, as an +additional argument directly before the format string. +.Pp +These functions are exposed by including +.In xlocale.h +.Em after +including the relevant headers for the standard variant. For example, the +.Xr strtol_l 3 +function is exposed by including +.In xlocale.h +after +.In stdlib.h , +which defines +.Xr strtol 3 . +.Pp +For reference, a complete list of the locale-aware functions that are available +in this form, along with the headers that expose them, is provided here: +.Pp +.Bl -tag -width " " +.It In wctype.h +.Xr iswalnum_l 3 , +.Xr iswalpha_l 3 , +.Xr iswcntrl_l 3 , +.Xr iswctype_l 3 , +.Xr iswdigit_l 3 , +.Xr iswgraph_l 3 , +.Xr iswlower_l 3 , +.Xr iswprint_l 3 , +.Xr iswpunct_l 3 , +.Xr iswspace_l 3 , +.Xr iswupper_l 3 , +.Xr iswxdigit_l 3 , +.Xr towlower_l 3 , +.Xr towupper_l 3 , +.Xr wctype_l 3 , +.It In ctype.h +.Xr digittoint_l 3 , +.Xr isalnum_l 3 , +.Xr isalpha_l 3 , +.Xr isblank_l 3 , +.Xr iscntrl_l 3 , +.Xr isdigit_l 3 , +.Xr isgraph_l 3 , +.Xr ishexnumber_l 3 , +.Xr isideogram_l 3 , +.Xr islower_l 3 , +.Xr isnumber_l 3 , +.Xr isphonogram_l 3 , +.Xr isprint_l 3 , +.Xr ispunct_l 3 , +.Xr isrune_l 3 , +.Xr isspace_l 3 , +.Xr isspecial_l 3 , +.Xr isupper_l 3 , +.Xr isxdigit_l 3 , +.Xr tolower_l 3 , +.Xr toupper_l 3 +.It In inttypes.h +.Xr strtoimax_l 3 , +.Xr strtoumax_l 3 , +.Xr wcstoimax_l 3 , +.Xr wcstoumax_l 3 +.It In langinfo.h +.Xr nl_langinfo_l 3 +.It In monetary.h +.Xr strfmon_l 3 +.It In stdio.h +.Xr asprintf_l 3 , +.Xr fprintf_l 3 , +.Xr fscanf_l 3 , +.Xr printf_l 3 , +.Xr scanf_l 3 , +.Xr snprintf_l 3 , +.Xr sprintf_l 3 , +.Xr sscanf_l 3 , +.Xr vasprintf_l 3 , +.Xr vfprintf_l 3 , +.Xr vfscanf_l 3 , +.Xr vprintf_l 3 , +.Xr vscanf_l 3 , +.Xr vsnprintf_l 3 , +.Xr vsprintf_l 3 , +.Xr vsscanf_l 3 +.It In stdlib.h +.Xr atof_l 3 , +.Xr atoi_l 3 , +.Xr atol_l 3 , +.Xr atoll_l 3 , +.Xr mblen_l 3 , +.Xr mbstowcs_l 3 , +.Xr mbtowc_l 3 , +.Xr strtod_l 3 , +.Xr strtof_l 3 , +.Xr strtol_l 3 , +.Xr strtold_l 3 , +.Xr strtoll_l 3 , +.Xr strtoq_l 3 , +.Xr strtoul_l 3 , +.Xr strtoull_l 3 , +.Xr strtouq_l 3 , +.Xr wcstombs_l 3 , +.Xr wctomb_l 3 +.It In string.h +.Xr strcoll_l 3 , +.Xr strxfrm_l 3 , +.Xr strcasecmp_l 3 , +.Xr strcasestr_l 3 , +.Xr strncasecmp_l 3 +.It In time.h +.Xr strftime_l 3 +.Xr strptime_l 3 +.It In wchar.h +.Xr btowc_l 3 , +.Xr fgetwc_l 3 , +.Xr fgetws_l 3 , +.Xr fputwc_l 3 , +.Xr fputws_l 3 , +.Xr fwprintf_l 3 , +.Xr fwscanf_l 3 , +.Xr getwc_l 3 , +.Xr getwchar_l 3 , +.Xr mbrlen_l 3 , +.Xr mbrtowc_l 3 , +.Xr mbsinit_l 3 , +.Xr mbsnrtowcs_l 3 , +.Xr mbsrtowcs_l 3 , +.Xr putwc_l 3 , +.Xr putwchar_l 3 , +.Xr swprintf_l 3 , +.Xr swscanf_l 3 , +.Xr ungetwc_l 3 , +.Xr vfwprintf_l 3 , +.Xr vfwscanf_l 3 , +.Xr vswprintf_l 3 , +.Xr vswscanf_l 3 , +.Xr vwprintf_l 3 , +.Xr vwscanf_l 3 , +.Xr wcrtomb_l 3 , +.Xr wcscoll_l 3 , +.Xr wcsftime_l 3 , +.Xr wcsnrtombs_l 3 , +.Xr wcsrtombs_l 3 , +.Xr wcstod_l 3 , +.Xr wcstof_l 3 , +.Xr wcstol_l 3 , +.Xr wcstold_l 3 , +.Xr wcstoll_l 3 , +.Xr wcstoul_l 3 , +.Xr wcstoull_l 3 , +.Xr wcswidth_l 3 , +.Xr wcsxfrm_l 3 , +.Xr wctob_l 3 , +.Xr wcwidth_l 3 , +.Xr wprintf_l 3 , +.Xr wscanf_l 3 +.It In wctype.h +.Xr iswblank_l 3 , +.Xr iswhexnumber_l 3 , +.Xr iswideogram_l 3 , +.Xr iswnumber_l 3 , +.Xr iswphonogram_l 3 , +.Xr iswrune_l 3 , +.Xr iswspecial_l 3 , +.Xr nextwctype_l 3 , +.Xr towctrans_l 3 , +.Xr wctrans_l 3 +.It In xlocale.h +.Xr localeconv_l 3 +.El +.Sh STANDARDS +The functions +conform to +.St -p1003.1-2008 . +.Sh HISTORY +The xlocale APIs first appeared in Darwin 8.0. This implementation was +written by David Chisnall, under sponsorship from the FreeBSD Foundation and +first appeared in +.Fx 9.1 . Index: lib/libc/locale/mbrtowc.c =================================================================== --- lib/libc/locale/mbrtowc.c (revision 225653) +++ lib/libc/locale/mbrtowc.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002-2004 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -25,18 +30,24 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/mbrtowc.c 129153 2004-05-12 14:09:04Z tjr $"); #include #include "mblocal.h" size_t +mbrtowc_l(wchar_t * __restrict pwc, const char * __restrict s, + size_t n, mbstate_t * __restrict ps, locale_t locale) +{ + FIX_LOCALE(locale); + if (ps == NULL) + ps = &locale->mbrtowc; + return (XLOCALE_CTYPE(locale)->__mbrtowc(pwc, s, n, ps)); +} + +size_t mbrtowc(wchar_t * __restrict pwc, const char * __restrict s, size_t n, mbstate_t * __restrict ps) { - static mbstate_t mbs; - - if (ps == NULL) - ps = &mbs; - return (__mbrtowc(pwc, s, n, ps)); + return mbrtowc_l(pwc, s, n, ps, __get_locale()); } Index: lib/libc/locale/ctype.c =================================================================== --- lib/libc/locale/ctype.c (revision 0) +++ lib/libc/locale/ctype.c (revision 0) @@ -0,0 +1,31 @@ +/*- + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by David Chisnall under sponsorship from + * the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions * are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#define _XLOCALE_INLINE +#include +#include +#include Index: lib/libc/stdtime/timelocal.h =================================================================== --- lib/libc/stdtime/timelocal.h (revision 225653) +++ lib/libc/stdtime/timelocal.h (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1997-2002 FreeBSD Project. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -23,11 +28,12 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD$ + * $FreeBSD: head/lib/libc/stdtime/timelocal.h 89736 2002-01-24 15:07:44Z phantom $ */ #ifndef _TIMELOCAL_H_ #define _TIMELOCAL_H_ +#include "xlocale_private.h" /* * Private header file for the strftime and strptime localization @@ -49,7 +55,7 @@ const char *ampm_fmt; }; -struct lc_time_T *__get_current_time_locale(void); +struct lc_time_T *__get_current_time_locale(locale_t); int __time_load_locale(const char *); #endif /* !_TIMELOCAL_H_ */ Index: lib/libc/stdtime/strptime.c =================================================================== --- lib/libc/stdtime/strptime.c (revision 225653) +++ lib/libc/stdtime/strptime.c (working copy) @@ -22,6 +22,11 @@ /* * Copyright (c) 1994 Powerdog Industries. All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -59,7 +64,7 @@ static char sccsid[] __unused = "@(#)strptime.c 0.1 (Powerdog) 94/03/27"; #endif /* !defined NOID */ #endif /* not lint */ -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdtime/strptime.c 207830 2010-05-09 22:01:35Z edwin $"); #include "namespace.h" #include @@ -72,19 +77,20 @@ #include "libc_private.h" #include "timelocal.h" -static char * _strptime(const char *, const char *, struct tm *, int *); +static char * _strptime(const char *, const char *, struct tm *, int *, locale_t); #define asizeof(a) (sizeof (a) / sizeof ((a)[0])) static char * -_strptime(const char *buf, const char *fmt, struct tm *tm, int *GMTp) +_strptime(const char *buf, const char *fmt, struct tm *tm, int *GMTp, + locale_t locale) { char c; const char *ptr; int i, len; int Ealternative, Oalternative; - struct lc_time_T *tptr = __get_current_time_locale(); + struct lc_time_T *tptr = __get_current_time_locale(locale); ptr = fmt; while (*ptr != 0) { @@ -94,8 +100,8 @@ c = *ptr++; if (c != '%') { - if (isspace((unsigned char)c)) - while (*buf != 0 && isspace((unsigned char)*buf)) + if (isspace_l((unsigned char)c, locale)) + while (*buf != 0 && isspace_l((unsigned char)*buf, locale)) buf++; else if (c != *buf++) return 0; @@ -114,18 +120,18 @@ break; case '+': - buf = _strptime(buf, tptr->date_fmt, tm, GMTp); + buf = _strptime(buf, tptr->date_fmt, tm, GMTp, locale); if (buf == 0) return 0; break; case 'C': - if (!isdigit((unsigned char)*buf)) + if (!isdigit_l((unsigned char)*buf, locale)) return 0; /* XXX This will break for 3-digit centuries. */ len = 2; - for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { + for (i = 0; len && *buf != 0 && isdigit_l((unsigned char)*buf, locale); buf++) { i *= 10; i += *buf - '0'; len--; @@ -137,13 +143,13 @@ break; case 'c': - buf = _strptime(buf, tptr->c_fmt, tm, GMTp); + buf = _strptime(buf, tptr->c_fmt, tm, GMTp, locale); if (buf == 0) return 0; break; case 'D': - buf = _strptime(buf, "%m/%d/%y", tm, GMTp); + buf = _strptime(buf, "%m/%d/%y", tm, GMTp, locale); if (buf == 0) return 0; break; @@ -161,47 +167,47 @@ goto label; case 'F': - buf = _strptime(buf, "%Y-%m-%d", tm, GMTp); + buf = _strptime(buf, "%Y-%m-%d", tm, GMTp, locale); if (buf == 0) return 0; break; case 'R': - buf = _strptime(buf, "%H:%M", tm, GMTp); + buf = _strptime(buf, "%H:%M", tm, GMTp, locale); if (buf == 0) return 0; break; case 'r': - buf = _strptime(buf, tptr->ampm_fmt, tm, GMTp); + buf = _strptime(buf, tptr->ampm_fmt, tm, GMTp, locale); if (buf == 0) return 0; break; case 'T': - buf = _strptime(buf, "%H:%M:%S", tm, GMTp); + buf = _strptime(buf, "%H:%M:%S", tm, GMTp, locale); if (buf == 0) return 0; break; case 'X': - buf = _strptime(buf, tptr->X_fmt, tm, GMTp); + buf = _strptime(buf, tptr->X_fmt, tm, GMTp, locale); if (buf == 0) return 0; break; case 'x': - buf = _strptime(buf, tptr->x_fmt, tm, GMTp); + buf = _strptime(buf, tptr->x_fmt, tm, GMTp, locale); if (buf == 0) return 0; break; case 'j': - if (!isdigit((unsigned char)*buf)) + if (!isdigit_l((unsigned char)*buf, locale)) return 0; len = 3; - for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { + for (i = 0; len && *buf != 0 && isdigit_l((unsigned char)*buf, locale); buf++) { i *= 10; i += *buf - '0'; len--; @@ -214,14 +220,14 @@ case 'M': case 'S': - if (*buf == 0 || isspace((unsigned char)*buf)) + if (*buf == 0 || isspace_l((unsigned char)*buf, locale)) break; - if (!isdigit((unsigned char)*buf)) + if (!isdigit_l((unsigned char)*buf, locale)) return 0; len = 2; - for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { + for (i = 0; len && *buf != 0 && isdigit_l((unsigned char)*buf, locale); buf++) { i *= 10; i += *buf - '0'; len--; @@ -237,8 +243,8 @@ tm->tm_sec = i; } - if (*buf != 0 && isspace((unsigned char)*buf)) - while (*ptr != 0 && !isspace((unsigned char)*ptr)) + if (*buf != 0 && isspace_l((unsigned char)*buf, locale)) + while (*ptr != 0 && !isspace_l((unsigned char)*ptr, locale)) ptr++; break; @@ -254,11 +260,11 @@ * XXX The %l specifier may gobble one too many * digits if used incorrectly. */ - if (!isdigit((unsigned char)*buf)) + if (!isdigit_l((unsigned char)*buf, locale)) return 0; len = 2; - for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { + for (i = 0; len && *buf != 0 && isdigit_l((unsigned char)*buf, locale); buf++) { i *= 10; i += *buf - '0'; len--; @@ -271,8 +277,8 @@ tm->tm_hour = i; - if (*buf != 0 && isspace((unsigned char)*buf)) - while (*ptr != 0 && !isspace((unsigned char)*ptr)) + if (*buf != 0 && isspace_l((unsigned char)*buf, locale)) + while (*ptr != 0 && !isspace_l((unsigned char)*ptr, locale)) ptr++; break; @@ -282,7 +288,7 @@ * specifiers. */ len = strlen(tptr->am); - if (strncasecmp(buf, tptr->am, len) == 0) { + if (strncasecmp_l(buf, tptr->am, len, locale) == 0) { if (tm->tm_hour > 12) return 0; if (tm->tm_hour == 12) @@ -292,7 +298,7 @@ } len = strlen(tptr->pm); - if (strncasecmp(buf, tptr->pm, len) == 0) { + if (strncasecmp_l(buf, tptr->pm, len, locale) == 0) { if (tm->tm_hour > 12) return 0; if (tm->tm_hour != 12) @@ -307,12 +313,12 @@ case 'a': for (i = 0; i < asizeof(tptr->weekday); i++) { len = strlen(tptr->weekday[i]); - if (strncasecmp(buf, tptr->weekday[i], - len) == 0) + if (strncasecmp_l(buf, tptr->weekday[i], + len, locale) == 0) break; len = strlen(tptr->wday[i]); - if (strncasecmp(buf, tptr->wday[i], - len) == 0) + if (strncasecmp_l(buf, tptr->wday[i], + len, locale) == 0) break; } if (i == asizeof(tptr->weekday)) @@ -330,11 +336,11 @@ * point to calculate a real value, so just check the * range for now. */ - if (!isdigit((unsigned char)*buf)) + if (!isdigit_l((unsigned char)*buf, locale)) return 0; len = 2; - for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { + for (i = 0; len && *buf != 0 && isdigit_l((unsigned char)*buf, locale); buf++) { i *= 10; i += *buf - '0'; len--; @@ -342,13 +348,13 @@ if (i > 53) return 0; - if (*buf != 0 && isspace((unsigned char)*buf)) - while (*ptr != 0 && !isspace((unsigned char)*ptr)) + if (*buf != 0 && isspace_l((unsigned char)*buf, locale)) + while (*ptr != 0 && !isspace_l((unsigned char)*ptr, locale)) ptr++; break; case 'w': - if (!isdigit((unsigned char)*buf)) + if (!isdigit_l((unsigned char)*buf, locale)) return 0; i = *buf - '0'; @@ -357,8 +363,8 @@ tm->tm_wday = i; - if (*buf != 0 && isspace((unsigned char)*buf)) - while (*ptr != 0 && !isspace((unsigned char)*ptr)) + if (*buf != 0 && isspace_l((unsigned char)*buf, locale)) + while (*ptr != 0 && !isspace_l((unsigned char)*ptr, locale)) ptr++; break; @@ -372,11 +378,11 @@ * XXX The %e specifier may gobble one too many * digits if used incorrectly. */ - if (!isdigit((unsigned char)*buf)) + if (!isdigit_l((unsigned char)*buf, locale)) return 0; len = 2; - for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { + for (i = 0; len && *buf != 0 && isdigit_l((unsigned char)*buf, locale); buf++) { i *= 10; i += *buf - '0'; len--; @@ -386,8 +392,8 @@ tm->tm_mday = i; - if (*buf != 0 && isspace((unsigned char)*buf)) - while (*ptr != 0 && !isspace((unsigned char)*ptr)) + if (*buf != 0 && isspace_l((unsigned char)*buf, locale)) + while (*ptr != 0 && !isspace_l((unsigned char)*ptr, locale)) ptr++; break; @@ -398,15 +404,15 @@ if (Oalternative) { if (c == 'B') { len = strlen(tptr->alt_month[i]); - if (strncasecmp(buf, + if (strncasecmp_l(buf, tptr->alt_month[i], - len) == 0) + len, locale) == 0) break; } } else { len = strlen(tptr->month[i]); - if (strncasecmp(buf, tptr->month[i], - len) == 0) + if (strncasecmp_l(buf, tptr->month[i], + len, locale) == 0) break; } } @@ -417,8 +423,8 @@ if (i == asizeof(tptr->month) && !Oalternative) { for (i = 0; i < asizeof(tptr->month); i++) { len = strlen(tptr->mon[i]); - if (strncasecmp(buf, tptr->mon[i], - len) == 0) + if (strncasecmp_l(buf, tptr->mon[i], + len, locale) == 0) break; } } @@ -430,11 +436,11 @@ break; case 'm': - if (!isdigit((unsigned char)*buf)) + if (!isdigit_l((unsigned char)*buf, locale)) return 0; len = 2; - for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { + for (i = 0; len && *buf != 0 && isdigit_l((unsigned char)*buf, locale); buf++) { i *= 10; i += *buf - '0'; len--; @@ -444,8 +450,8 @@ tm->tm_mon = i - 1; - if (*buf != 0 && isspace((unsigned char)*buf)) - while (*ptr != 0 && !isspace((unsigned char)*ptr)) + if (*buf != 0 && isspace_l((unsigned char)*buf, locale)) + while (*ptr != 0 && !isspace_l((unsigned char)*ptr, locale)) ptr++; break; @@ -458,7 +464,7 @@ sverrno = errno; errno = 0; - n = strtol(buf, &cp, 10); + n = strtol_l(buf, &cp, 10, locale); if (errno == ERANGE || (long)(t = n) != n) { errno = sverrno; return 0; @@ -472,14 +478,14 @@ case 'Y': case 'y': - if (*buf == 0 || isspace((unsigned char)*buf)) + if (*buf == 0 || isspace_l((unsigned char)*buf, locale)) break; - if (!isdigit((unsigned char)*buf)) + if (!isdigit_l((unsigned char)*buf, locale)) return 0; len = (c == 'Y') ? 4 : 2; - for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { + for (i = 0; len && *buf != 0 && isdigit_l((unsigned char)*buf, locale); buf++) { i *= 10; i += *buf - '0'; len--; @@ -493,8 +499,8 @@ tm->tm_year = i; - if (*buf != 0 && isspace((unsigned char)*buf)) - while (*ptr != 0 && !isspace((unsigned char)*ptr)) + if (*buf != 0 && isspace_l((unsigned char)*buf, locale)) + while (*ptr != 0 && !isspace_l((unsigned char)*ptr, locale)) ptr++; break; @@ -503,7 +509,7 @@ const char *cp; char *zonestr; - for (cp = buf; *cp && isupper((unsigned char)*cp); ++cp) {/*empty*/} + for (cp = buf; *cp && isupper_l((unsigned char)*cp, locale); ++cp) {/*empty*/} if (cp - buf) { zonestr = alloca(cp - buf + 1); strncpy(zonestr, buf, cp - buf); @@ -537,7 +543,7 @@ buf++; i = 0; for (len = 4; len > 0; len--) { - if (isdigit((unsigned char)*buf)) { + if (isdigit_l((unsigned char)*buf, locale)) { i *= 10; i += *buf - '0'; buf++; @@ -557,14 +563,15 @@ char * -strptime(const char * __restrict buf, const char * __restrict fmt, - struct tm * __restrict tm) +strptime_l(const char * __restrict buf, const char * __restrict fmt, + struct tm * __restrict tm, locale_t loc) { char *ret; int gmt; + FIX_LOCALE(loc); gmt = 0; - ret = _strptime(buf, fmt, tm, &gmt); + ret = _strptime(buf, fmt, tm, &gmt, loc); if (ret && gmt) { time_t t = timegm(tm); localtime_r(&t, tm); @@ -572,3 +579,9 @@ return (ret); } +char * +strptime(const char * __restrict buf, const char * __restrict fmt, + struct tm * __restrict tm) +{ + return strptime_l(buf, fmt, tm, __get_locale()); +} Index: lib/libc/stdtime/timelocal.c =================================================================== --- lib/libc/stdtime/timelocal.c (revision 225653) +++ lib/libc/stdtime/timelocal.c (working copy) @@ -3,6 +3,11 @@ * Copyright (c) 1997 FreeBSD Inc. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -26,17 +31,21 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdtime/timelocal.c 116274 2003-06-13 00:14:07Z jkh $"); #include #include "ldpart.h" #include "timelocal.h" -static struct lc_time_T _time_locale; -static int _time_using_locale; -static char *time_locale_buf; +struct xlocale_time { + struct xlocale_component header; + char *buffer; + struct lc_time_T locale; +}; +struct xlocale_time __xlocale_global_time; + #define LCTIME_SIZE (sizeof(struct lc_time_T) / sizeof(char *)) static const struct lc_time_T _C_time_locale = { @@ -99,19 +108,47 @@ "%I:%M:%S %p" }; +static void destruct_time(void *v) +{ + struct xlocale_time *l = v; + if (l->buffer) + free(l->buffer); + free(l); +} + +#include struct lc_time_T * -__get_current_time_locale(void) +__get_current_time_locale(locale_t loc) { - return (_time_using_locale - ? &_time_locale + return (loc->using_time_locale + ? &((struct xlocale_time *)loc->components[XLC_TIME])->locale : (struct lc_time_T *)&_C_time_locale); } +static int +time_load_locale(struct xlocale_time *l, int *using_locale, const char *name) +{ + struct lc_time_T *time_locale = &l->locale; + return (__part_load_locale(name, using_locale, + &l->buffer, "LC_TIME", + LCTIME_SIZE, LCTIME_SIZE, + (const char **)time_locale)); +} int __time_load_locale(const char *name) { - return (__part_load_locale(name, &_time_using_locale, - &time_locale_buf, "LC_TIME", - LCTIME_SIZE, LCTIME_SIZE, - (const char **)&_time_locale)); + return time_load_locale(&__xlocale_global_time, + &__xlocale_global_locale.using_time_locale, name); } +extern void* __time_load(const char* name, locale_t loc) +{ + struct xlocale_time *new = calloc(sizeof(struct xlocale_time), 1); + new->header.header.destructor = destruct_time; + if (time_load_locale(new, &loc->using_time_locale, name) != _LDP_LOADED) + { + xlocale_release(new); + return NULL; + } + return new; +} + Index: lib/libc/stdtime/strftime.c =================================================================== --- lib/libc/stdtime/strftime.c (revision 225653) +++ lib/libc/stdtime/strftime.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1989 The Regents of the University of California. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms are permitted * provided that the above copyright notice and this paragraph are * duplicated in all such forms and that any documentation, @@ -32,7 +37,7 @@ static const char sccsid[] = "@(#)strftime.c 5.4 (Berkeley) 3/14/89"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdtime/strftime.c 193817 2009-06-09 09:02:58Z delphij $"); #include "tzfile.h" #include @@ -43,7 +48,7 @@ static char * _add(const char *, char *, const char *); static char * _conv(int, const char *, char *, const char *); static char * _fmt(const char *, const struct tm *, char *, const char *, - int *); + int *, locale_t); static char * _yconv(int, int, int, int, char *, const char *); extern char * tzname[]; @@ -82,29 +87,30 @@ }; size_t -strftime(char * __restrict s, size_t maxsize, const char * __restrict format, - const struct tm * __restrict t) +strftime_l(char * __restrict s, size_t maxsize, const char * __restrict format, + const struct tm * __restrict t, locale_t loc) { char * p; int warn; + FIX_LOCALE(loc); tzset(); warn = IN_NONE; - p = _fmt(((format == NULL) ? "%c" : format), t, s, s + maxsize, &warn); + p = _fmt(((format == NULL) ? "%c" : format), t, s, s + maxsize, &warn, loc); #ifndef NO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU if (warn != IN_NONE && getenv(YEAR_2000_NAME) != NULL) { - (void) fprintf(stderr, "\n"); + (void) fprintf_l(stderr, loc, "\n"); if (format == NULL) - (void) fprintf(stderr, "NULL strftime format "); - else (void) fprintf(stderr, "strftime format \"%s\" ", + (void) fprintf_l(stderr, loc, "NULL strftime format "); + else (void) fprintf_l(stderr, loc, "strftime format \"%s\" ", format); - (void) fprintf(stderr, "yields only two digits of years in "); + (void) fprintf_l(stderr, loc, "yields only two digits of years in "); if (warn == IN_SOME) - (void) fprintf(stderr, "some locales"); + (void) fprintf_l(stderr, loc, "some locales"); else if (warn == IN_THIS) - (void) fprintf(stderr, "the current locale"); - else (void) fprintf(stderr, "all locales"); - (void) fprintf(stderr, "\n"); + (void) fprintf_l(stderr, loc, "the current locale"); + else (void) fprintf_l(stderr, loc, "all locales"); + (void) fprintf_l(stderr, loc, "\n"); } #endif /* !defined NO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU */ if (p == s + maxsize) @@ -113,16 +119,24 @@ return p - s; } +size_t +strftime(char * __restrict s, size_t maxsize, const char * __restrict format, + const struct tm * __restrict t) +{ + return strftime_l(s, maxsize, format, t, __get_locale()); +} + static char * -_fmt(format, t, pt, ptlim, warnp) +_fmt(format, t, pt, ptlim, warnp, loc) const char * format; const struct tm * const t; char * pt; const char * const ptlim; int * warnp; +locale_t loc; { int Ealternative, Oalternative, PadIndex; - struct lc_time_T *tptr = __get_current_time_locale(); + struct lc_time_T *tptr = __get_current_time_locale(loc); for ( ; *format; ++format) { if (*format == '%') { @@ -175,7 +189,7 @@ { int warn2 = IN_SOME; - pt = _fmt(tptr->c_fmt, t, pt, ptlim, &warn2); + pt = _fmt(tptr->c_fmt, t, pt, ptlim, &warn2, loc); if (warn2 == IN_ALL) warn2 = IN_THIS; if (warn2 > *warnp) @@ -183,7 +197,7 @@ } continue; case 'D': - pt = _fmt("%m/%d/%y", t, pt, ptlim, warnp); + pt = _fmt("%m/%d/%y", t, pt, ptlim, warnp, loc); continue; case 'd': pt = _conv(t->tm_mday, fmt_padding[PAD_FMT_DAYOFMONTH][PadIndex], @@ -216,7 +230,7 @@ fmt_padding[PAD_FMT_SDAYOFMONTH][PadIndex], pt, ptlim); continue; case 'F': - pt = _fmt("%Y-%m-%d", t, pt, ptlim, warnp); + pt = _fmt("%Y-%m-%d", t, pt, ptlim, warnp, loc); continue; case 'H': pt = _conv(t->tm_hour, fmt_padding[PAD_FMT_HMS][PadIndex], @@ -285,11 +299,11 @@ pt, ptlim); continue; case 'R': - pt = _fmt("%H:%M", t, pt, ptlim, warnp); + pt = _fmt("%H:%M", t, pt, ptlim, warnp, loc); continue; case 'r': pt = _fmt(tptr->ampm_fmt, t, pt, ptlim, - warnp); + warnp, loc); continue; case 'S': pt = _conv(t->tm_sec, fmt_padding[PAD_FMT_HMS][PadIndex], @@ -313,7 +327,7 @@ } continue; case 'T': - pt = _fmt("%H:%M:%S", t, pt, ptlim, warnp); + pt = _fmt("%H:%M:%S", t, pt, ptlim, warnp, loc); continue; case 't': pt = _add("\t", pt, ptlim); @@ -428,7 +442,7 @@ ** "date as dd-bbb-YYYY" ** (ado, 1993-05-24) */ - pt = _fmt("%e-%b-%Y", t, pt, ptlim, warnp); + pt = _fmt("%e-%b-%Y", t, pt, ptlim, warnp, loc); continue; case 'W': pt = _conv((t->tm_yday + DAYSPERWEEK - @@ -441,13 +455,13 @@ pt = _conv(t->tm_wday, "%d", pt, ptlim); continue; case 'X': - pt = _fmt(tptr->X_fmt, t, pt, ptlim, warnp); + pt = _fmt(tptr->X_fmt, t, pt, ptlim, warnp, loc); continue; case 'x': { int warn2 = IN_SOME; - pt = _fmt(tptr->x_fmt, t, pt, ptlim, &warn2); + pt = _fmt(tptr->x_fmt, t, pt, ptlim, &warn2, loc); if (warn2 == IN_ALL) warn2 = IN_THIS; if (warn2 > *warnp) @@ -534,7 +548,7 @@ continue; case '+': pt = _fmt(tptr->date_fmt, t, pt, ptlim, - warnp); + warnp, loc); continue; case '-': if (PadIndex != PAD_DEFAULT) Index: lib/libc/gen/glob.c =================================================================== --- lib/libc/gen/glob.c (revision 225653) +++ lib/libc/gen/glob.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Guido van Rossum. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -34,7 +39,7 @@ static char sccsid[] = "@(#)glob.c 8.3 (Berkeley) 10/13/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/gen/glob.c 207981 2010-05-12 17:44:00Z gordon $"); /* * glob(3) -- a superset of the one defined in POSIX 1003.2. @@ -751,6 +756,8 @@ { int ok, negate_range; Char c, k; + struct xlocale_collate *table = + (struct xlocale_collate*)__get_locale()->components[XLC_COLLATE]; while (pat < patend) { c = *pat++; @@ -775,10 +782,10 @@ ++pat; while (((c = *pat++) & M_MASK) != M_END) if ((*pat & M_MASK) == M_RNG) { - if (__collate_load_error ? + if (table->__collate_load_error ? CHAR(c) <= CHAR(k) && CHAR(k) <= CHAR(pat[1]) : - __collate_range_cmp(CHAR(c), CHAR(k)) <= 0 - && __collate_range_cmp(CHAR(k), CHAR(pat[1])) <= 0 + __collate_range_cmp(table, CHAR(c), CHAR(k)) <= 0 + && __collate_range_cmp(table, CHAR(k), CHAR(pat[1])) <= 0 ) ok = 1; pat += 2; Index: lib/libc/gen/fnmatch.c =================================================================== --- lib/libc/gen/fnmatch.c (revision 225653) +++ lib/libc/gen/fnmatch.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Guido van Rossum. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -34,7 +39,7 @@ static char sccsid[] = "@(#)fnmatch.c 8.2 (Berkeley) 4/16/94"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/gen/fnmatch.c 206711 2010-04-16 22:29:24Z jilles $"); /* * Function fnmatch() as specified in POSIX 1003.2-1992, section B.6. @@ -222,6 +227,8 @@ wchar_t c, c2; size_t pclen; const char *origpat; + struct xlocale_collate *table = + (struct xlocale_collate*)__get_locale()->components[XLC_COLLATE]; /* * A bracket expression starting with an unquoted circumflex @@ -276,10 +283,10 @@ if (flags & FNM_CASEFOLD) c2 = towlower(c2); - if (__collate_load_error ? + if (table->__collate_load_error ? c <= test && test <= c2 : - __collate_range_cmp(c, test) <= 0 - && __collate_range_cmp(test, c2) <= 0 + __collate_range_cmp(table, c, test) <= 0 + && __collate_range_cmp(table, test, c2) <= 0 ) ok = 1; } else if (c == test) Index: lib/libc/regex/regcomp.c =================================================================== --- lib/libc/regex/regcomp.c (revision 225653) +++ lib/libc/regex/regcomp.c (working copy) @@ -3,9 +3,19 @@ * Copyright (c) 1992, 1993, 1994 * The Regents of the University of California. All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * This code is derived from software contributed to Berkeley by * Henry Spencer. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -37,7 +47,7 @@ static char sccsid[] = "@(#)regcomp.c 8.5 (Berkeley) 3/20/94"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/regex/regcomp.c 170528 2007-06-11 03:05:54Z delphij $"); #include #include @@ -730,6 +740,8 @@ char c; wint_t start, finish; wint_t i; + struct xlocale_collate *table = + (struct xlocale_collate*)__get_locale()->components[XLC_COLLATE]; /* classify what we've got */ switch ((MORE()) ? PEEK() : '\0') { @@ -778,14 +790,14 @@ if (start == finish) CHadd(p, cs, start); else { - if (__collate_load_error) { + if (table->__collate_load_error) { (void)REQUIRE((uch)start <= (uch)finish, REG_ERANGE); CHaddrange(p, cs, start, finish); } else { - (void)REQUIRE(__collate_range_cmp(start, finish) <= 0, REG_ERANGE); + (void)REQUIRE(__collate_range_cmp(table, start, finish) <= 0, REG_ERANGE); for (i = 0; i <= UCHAR_MAX; i++) { - if ( __collate_range_cmp(start, i) <= 0 - && __collate_range_cmp(i, finish) <= 0 + if ( __collate_range_cmp(table, start, i) <= 0 + && __collate_range_cmp(table, i, finish) <= 0 ) CHadd(p, cs, i); } Index: lib/libc/Makefile =================================================================== --- lib/libc/Makefile (revision 225653) +++ lib/libc/Makefile (working copy) @@ -1,8 +1,11 @@ # @(#)Makefile 8.2 (Berkeley) 2/3/94 -# $FreeBSD$ +# $FreeBSD: head/lib/libc/Makefile 219019 2011-02-25 00:04:39Z gabor $ SHLIBDIR?= /lib +DEBUG_CFLAGS+=-g +CFLAGS+=-g + .include # Pick the current architecture directory for libc. In general, this is @@ -36,6 +39,7 @@ CFLAGS+=${CANCELPOINTS_CFLAGS} .endif + # # Only link with static libgcc.a (no libgcc_eh.a). # Index: lib/libc/gdtoa/machdep_ldisd.c =================================================================== --- lib/libc/gdtoa/machdep_ldisd.c (revision 225653) +++ lib/libc/gdtoa/machdep_ldisd.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2003 David Schultz * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -31,13 +36,13 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/gdtoa/machdep_ldisd.c 112163 2003-03-12 20:30:00Z das $"); #include "gdtoaimp.h" +#undef strtold_l long double -strtold(const char * __restrict s, char ** __restrict sp) +strtold_l(const char * __restrict s, char ** __restrict sp, locale_t locale) { - - return strtod(s, sp); + return __strtod_l(s, sp, locale); } Index: lib/libc/gdtoa/machdep_ldisx.c =================================================================== --- lib/libc/gdtoa/machdep_ldisx.c (revision 225653) +++ lib/libc/gdtoa/machdep_ldisx.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2003 David Schultz * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -31,17 +36,18 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/gdtoa/machdep_ldisx.c 174204 2007-12-03 07:17:33Z das $"); #include #include "gdtoaimp.h" long double -strtold(const char * __restrict s, char ** __restrict sp) +strtold_l(const char * __restrict s, char ** __restrict sp, locale_t locale) { long double result; + FIX_LOCALE(locale); - strtorx(s, sp, FLT_ROUNDS, &result); + strtorx_l(s, sp, FLT_ROUNDS, &result, locale); return result; } Index: lib/libc/gdtoa/machdep_ldisQ.c =================================================================== --- lib/libc/gdtoa/machdep_ldisQ.c (revision 225653) +++ lib/libc/gdtoa/machdep_ldisQ.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2003 David Schultz * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -31,17 +36,17 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/gdtoa/machdep_ldisQ.c 174204 2007-12-03 07:17:33Z das $"); #include #include "gdtoaimp.h" long double -strtold(const char * __restrict s, char ** __restrict sp) +strtold_l(const char * __restrict s, char ** __restrict sp, locale_t locale) { long double result; - strtorQ(s, sp, FLT_ROUNDS, &result); + strtorQ_l(s, sp, FLT_ROUNDS, &result, locale); return result; } Index: lib/libc/string/strcasecmp.c =================================================================== --- lib/libc/string/strcasecmp.c (revision 225653) +++ lib/libc/string/strcasecmp.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1987, 1993 * The Regents of the University of California. All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -31,40 +36,54 @@ static char sccsid[] = "@(#)strcasecmp.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/string/strcasecmp.c 188080 2009-02-03 17:58:20Z danger $"); #include #include +#include "xlocale_private.h" typedef unsigned char u_char; int -strcasecmp(const char *s1, const char *s2) +strcasecmp_l(const char *s1, const char *s2, locale_t locale) { const u_char *us1 = (const u_char *)s1, *us2 = (const u_char *)s2; + FIX_LOCALE(locale); - while (tolower(*us1) == tolower(*us2++)) + while (tolower_l(*us1, locale) == tolower_l(*us2++, locale)) if (*us1++ == '\0') return (0); - return (tolower(*us1) - tolower(*--us2)); + return (tolower_l(*us1, locale) - tolower_l(*--us2, locale)); } +int +strcasecmp(const char *s1, const char *s2) +{ + return strcasecmp_l(s1, s2, __get_locale()); +} int -strncasecmp(const char *s1, const char *s2, size_t n) +strncasecmp_l(const char *s1, const char *s2, size_t n, locale_t locale) { + FIX_LOCALE(locale); if (n != 0) { const u_char *us1 = (const u_char *)s1, *us2 = (const u_char *)s2; do { - if (tolower(*us1) != tolower(*us2++)) - return (tolower(*us1) - tolower(*--us2)); + if (tolower_l(*us1, locale) != tolower_l(*us2++, locale)) + return (tolower_l(*us1, locale) - tolower_l(*--us2, locale)); if (*us1++ == '\0') break; } while (--n != 0); } return (0); } + +int +strncasecmp(const char *s1, const char *s2, size_t n) +{ + return strncasecmp_l(s1, s2, n, __get_locale()); +} Index: lib/libc/string/wcscoll.c =================================================================== --- lib/libc/string/wcscoll.c (revision 225653) +++ lib/libc/string/wcscoll.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002 Tim J. Robbins * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -25,7 +30,7 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/string/wcscoll.c 127998 2004-04-07 09:47:56Z tjr $"); #include #include @@ -41,12 +46,15 @@ * with extended character sets. */ int -wcscoll(const wchar_t *ws1, const wchar_t *ws2) +wcscoll_l(const wchar_t *ws1, const wchar_t *ws2, locale_t locale) { char *mbs1, *mbs2; int diff, sverrno; + FIX_LOCALE(locale); + struct xlocale_collate *table = + (struct xlocale_collate*)locale->components[XLC_COLLATE]; - if (__collate_load_error || MB_CUR_MAX > 1) + if (table->__collate_load_error || MB_CUR_MAX > 1) /* * Locale has no special collating order, could not be * loaded, or has an extended character set; do a fast binary @@ -67,7 +75,7 @@ return (wcscmp(ws1, ws2)); } - diff = strcoll(mbs1, mbs2); + diff = strcoll_l(mbs1, mbs2, locale); sverrno = errno; free(mbs1); free(mbs2); @@ -76,6 +84,12 @@ return (diff); } +int +wcscoll(const wchar_t *ws1, const wchar_t *ws2) +{ + return wcscoll_l(ws1, ws2, __get_locale()); +} + static char * __mbsdup(const wchar_t *ws) { Index: lib/libc/string/wcswidth.c =================================================================== --- lib/libc/string/wcswidth.c (revision 225653) +++ lib/libc/string/wcswidth.c (working copy) @@ -10,6 +10,11 @@ * This code is derived from software contributed to Berkeley by * Paul Borman at Krystal Technologies. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -36,22 +41,29 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/string/wcswidth.c 165903 2007-01-09 00:28:16Z imp $"); #include +#include "xlocale_private.h" int -wcswidth(const wchar_t *pwcs, size_t n) +wcswidth_l(const wchar_t *pwcs, size_t n, locale_t locale) { wchar_t wc; int len, l; + FIX_LOCALE(locale); len = 0; while (n-- > 0 && (wc = *pwcs++) != L'\0') { - if ((l = wcwidth(wc)) < 0) + if ((l = wcwidth_l(wc, locale)) < 0) return (-1); len += l; } return (len); } +int +wcswidth(const wchar_t *pwcs, size_t n) +{ + return wcswidth_l(pwcs, n, __get_locale()); +} Index: lib/libc/string/Symbol.map =================================================================== --- lib/libc/string/Symbol.map (revision 225653) +++ lib/libc/string/Symbol.map (working copy) @@ -1,5 +1,5 @@ /* - * $FreeBSD$ + * $FreeBSD: head/lib/libc/string/Symbol.map 189361 2009-03-04 06:01:27Z das $ */ FBSD_1.0 { @@ -75,6 +75,11 @@ wmemcpy; wmemmove; wmemset; + strcasecmp_l; + strcasestr_l; + strncasecmp_l; + wcswidth_l; + wcwidth_l; }; FBSD_1.1 { Index: lib/libc/string/strcoll.c =================================================================== --- lib/libc/string/strcoll.c (revision 225653) +++ lib/libc/string/strcoll.c (working copy) @@ -3,6 +3,11 @@ * at Electronni Visti IA, Kiev, Ukraine. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -26,27 +31,32 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/string/strcoll.c 188080 2009-02-03 17:58:20Z danger $"); #include #include #include "collate.h" +#include + int -strcoll(const char *s, const char *s2) +strcoll_l(const char *s, const char *s2, locale_t locale) { int len, len2, prim, prim2, sec, sec2, ret, ret2; const char *t, *t2; char *tt, *tt2; + FIX_LOCALE(locale); + struct xlocale_collate *table = + (struct xlocale_collate*)locale->components[XLC_COLLATE]; - if (__collate_load_error) + if (table->__collate_load_error) return strcmp(s, s2); len = len2 = 1; ret = ret2 = 0; - if (__collate_substitute_nontrivial) { - t = tt = __collate_substitute(s); - t2 = tt2 = __collate_substitute(s2); + if (table->__collate_substitute_nontrivial) { + t = tt = __collate_substitute(table, s); + t2 = tt2 = __collate_substitute(table, s2); } else { tt = tt2 = NULL; t = s; @@ -55,11 +65,11 @@ while(*t && *t2) { prim = prim2 = 0; while(*t && !prim) { - __collate_lookup(t, &len, &prim, &sec); + __collate_lookup(table, t, &len, &prim, &sec); t += len; } while(*t2 && !prim2) { - __collate_lookup(t2, &len2, &prim2, &sec2); + __collate_lookup(table, t2, &len2, &prim2, &sec2); t2 += len2; } if(!prim || !prim2) @@ -83,3 +93,10 @@ return ret; } + +int +strcoll(const char *s, const char *s2) +{ + return strcoll_l(s, s2, __get_locale()); +} + Index: lib/libc/string/wcsxfrm.c =================================================================== --- lib/libc/string/wcsxfrm.c (revision 225653) +++ lib/libc/string/wcsxfrm.c (working copy) @@ -3,6 +3,11 @@ * at Electronni Visti IA, Kiev, Ukraine. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -29,7 +34,7 @@ #if 0 __FBSDID("FreeBSD: src/lib/libc/string/strxfrm.c,v 1.15 2002/09/06 11:24:06 tjr Exp "); #endif -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/string/wcsxfrm.c 127998 2004-04-07 09:47:56Z tjr $"); #include #include @@ -43,11 +48,14 @@ * the logic used. */ size_t -wcsxfrm(wchar_t * __restrict dest, const wchar_t * __restrict src, size_t len) +wcsxfrm_l(wchar_t * __restrict dest, const wchar_t * __restrict src, size_t len, locale_t locale) { int prim, sec, l; size_t slen; char *mbsrc, *s, *ss; + FIX_LOCALE(locale); + struct xlocale_collate *table = + (struct xlocale_collate*)locale->components[XLC_COLLATE]; if (*src == L'\0') { if (len != 0) @@ -55,7 +63,7 @@ return (0); } - if (__collate_load_error || MB_CUR_MAX > 1) { + if (table->__collate_load_error || MB_CUR_MAX > 1) { slen = wcslen(src); if (len > 0) { if (slen < len) @@ -71,10 +79,10 @@ mbsrc = __mbsdup(src); slen = 0; prim = sec = 0; - ss = s = __collate_substitute(mbsrc); + ss = s = __collate_substitute(table, mbsrc); while (*s != '\0') { while (*s != '\0' && prim == 0) { - __collate_lookup(s, &l, &prim, &sec); + __collate_lookup(table, s, &l, &prim, &sec); s += l; } if (prim != 0) { @@ -93,6 +101,11 @@ return (slen); } +size_t +wcsxfrm(wchar_t * __restrict dest, const wchar_t * __restrict src, size_t len) +{ + return wcsxfrm_l(dest, src, len, __get_locale()); +} static char * __mbsdup(const wchar_t *ws) Index: lib/libc/string/strcasestr.c =================================================================== --- lib/libc/string/strcasestr.c (revision 225653) +++ lib/libc/string/strcasestr.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Chris Torek. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -31,30 +36,37 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/string/strcasestr.c 188080 2009-02-03 17:58:20Z danger $"); #include #include +#include "xlocale_private.h" /* * Find the first occurrence of find in s, ignore case. */ char * -strcasestr(const char *s, const char *find) +strcasestr_l(const char *s, const char *find, locale_t locale) { char c, sc; size_t len; + FIX_LOCALE(locale); if ((c = *find++) != 0) { - c = tolower((unsigned char)c); + c = tolower_l((unsigned char)c, locale); len = strlen(find); do { do { if ((sc = *s++) == 0) return (NULL); - } while ((char)tolower((unsigned char)sc) != c); - } while (strncasecmp(s, find, len) != 0); + } while ((char)tolower_l((unsigned char)sc, locale) != c); + } while (strncasecmp_l(s, find, len, locale) != 0); s--; } return ((char *)s); } +char * +strcasestr(const char *s, const char *find) +{ + return strcasestr_l(s, find, __get_locale()); +} Index: lib/libc/string/strxfrm.c =================================================================== --- lib/libc/string/strxfrm.c (revision 225653) +++ lib/libc/string/strxfrm.c (working copy) @@ -3,6 +3,11 @@ * at Electronni Visti IA, Kiev, Ukraine. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -26,18 +31,29 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/string/strxfrm.c 184055 2008-10-19 09:10:44Z delphij $"); #include #include #include "collate.h" size_t +strxfrm_l(char * __restrict dest, const char * __restrict src, size_t len, locale_t loc); +size_t strxfrm(char * __restrict dest, const char * __restrict src, size_t len) { + return strxfrm_l(dest, src, len, __get_locale()); +} + +size_t +strxfrm_l(char * __restrict dest, const char * __restrict src, size_t len, locale_t locale) +{ int prim, sec, l; size_t slen; char *s, *ss; + FIX_LOCALE(locale); + struct xlocale_collate *table = + (struct xlocale_collate*)locale->components[XLC_COLLATE]; if (!*src) { if (len > 0) @@ -45,15 +61,15 @@ return 0; } - if (__collate_load_error) + if (table->__collate_load_error) return strlcpy(dest, src, len); slen = 0; prim = sec = 0; - ss = s = __collate_substitute(src); + ss = s = __collate_substitute(table, src); while (*s) { while (*s && !prim) { - __collate_lookup(s, &l, &prim, &sec); + __collate_lookup(table, s, &l, &prim, &sec); s += l; } if (prim) { Index: sys/sys/cdefs.h =================================================================== --- sys/sys/cdefs.h (revision 225653) +++ sys/sys/cdefs.h (working copy) @@ -30,7 +30,7 @@ * SUCH DAMAGE. * * @(#)cdefs.h 8.8 (Berkeley) 1/9/95 - * $FreeBSD$ + * $FreeBSD: head/sys/sys/cdefs.h 218824 2011-02-18 21:44:53Z nwhitehorn $ */ #ifndef _SYS_CDEFS_H_ @@ -249,7 +249,7 @@ #define __func__ NULL #endif -#if (defined(__INTEL_COMPILER) || (defined(__GNUC__) && __GNUC__ >= 2)) && !defined(__STRICT_ANSI__) || __STDC_VERSION__ >= 199901 +#if (defined(__INTEL_COMPILER) || (defined(__GNUC__) && __GNUC__ >= 2)) && !defined(__STRICT_ANSI__) || __STDC_VERSION__ >= 199901 || __cplusplus >= 201103L #define __LONG_LONG_SUPPORTED #endif @@ -407,7 +407,7 @@ * Embed the rcs id of a source file in the resulting library. Note that in * more recent ELF binutils, we use .ident allowing the ID to be stripped. * Usage: - * __FBSDID("$FreeBSD$"); + * __FBSDID("$FreeBSD: head/sys/sys/cdefs.h 218824 2011-02-18 21:44:53Z nwhitehorn $"); */ #ifndef __FBSDID #if !defined(lint) && !defined(STRIP_FBSDID) --Apple-Mail=_F55C7A91-4420-4E40-9517-BE01711EE0A4 Content-Disposition: attachment; filename=test.tbz Content-Type: application/octet-stream; x-unix-mode=0644; name="test.tbz" Content-Transfer-Encoding: base64 QlpoOTFBWSZTWReH/4cBZJ1/////////////////////////////////////////////4GuZfYOi nYB6c+dl33LbgByUlo16GhW2M0xUopSQtbGg6s2kza0tq2ptF2u5DqzSUoAAAAANzTDpqPfX2+I0 +QfemB0AMrLB3Qw9vTel593p7fTJVU7TvdrigHW68EzNTi9jCTsaj2z2FBRned9y9yp16fPtW2t7 Z2vquHzz57nwG98V8O+vt9me3zXHHfcK4aNatWzDLaoaQLs1XStEk2MkUxLYT3HVdZkwzX2Y6MpB q7Q+j2du+r7Zo1X2w7x3AProDj6AAAYK2p9Dpn11yMAaB0AOPa+333sfOs7rAH2e94KfLiGiRAgB ommmptAwhph6bU8qGim0T00amNAaBk0J6NNBoDQmAm0TajJppgU8TTTJpppinpgAhhNMQ0GmJpo0 xNGhkmyDEaNMKDRICGAA0NEmCDRMmgT0mVP009EaaMkzQk2aMiPRTyJ4mCYjU2k8mCGUzU9MmSem mp6TQyemTJDNJ6TRiNNMjT1NNNDID0T0nqaabUNGaNQSmhBAQEGkEAU8EJ4Ianqepk9JhqZTZGhk 0NR5NR4mjU8jTSbTQJjRNpMymaTCBobU0Bp6TI000M0mJpo2oD0hoaZDNTQGgGjRoJNKRCYQEBNG jCmmGhGgGmjIExT0ZqnpqfpE8mkP0SPKemKeKPCjajEek9Mo2U9MpkyDQ9QbKepoHqMnqaeU0eoP U0eU9RptNNTE9Q9Rsmk0eU09QPUESiTSaU2nqTMRKfqbRkk89U1P1T9UNlHvU1M0TPU0yCYU9NT9 DajRNkp7UynkI/aqb1Tyn6JPU/UT9GqbNJN6mUe1TynqHknppqbU8mEyR5J+onlNpPU08KeoPSeC nkmnhT2iYmTKCJJCACATRoGmk9JkaT0Mpo9CbQTCm9TRT0w1NGaJqeQTzUyjPUT9JPU9ENqDyIyB p6E9NJ6mjagZPSBoaA0AGeqaD1Mh6hpoGQaAGS5+5P8QUMpqfsj4UfRM4lrQjBpSPQwRnPi1MIMb OVc2Qv2Lc7BQdk7CClH3qaXgQrcNqLOO9iFcitN2ILzsL6ve7fy36+Yj5v1Yt3c/VicYjpx6BxdP xRit163NzjsR4ODNA0HtLIW5dFda3SnPvTnzCZ7y+z0JJxwKiOSCCveIYjF2KqEwIb5Zq80lFTC0 d6go6sbZhO5+XH1CPARKog8EZk3q/Pnp/Fn5bvPRQ1Sll9LMNy8KCl6OqJ+TyxFHooJOI5zJiLOw W8ZFfI1wg6yWX2mTy4uTxgWKZ3VEJQLqIeVZR6CHUotS0Xw213oGYol5x3hBr5yWPEXqFQEIWfIc ZmNk9WkkklGNmpAYY+PXJnrmyW6CnsmmC61TgW8qznmpxKv1LzHKO3UIXsxr2s2XpTcci3oPoutz 3sn6tkLWUzBfGDOvVE2szMQgOj+Lb+Xjjy7q+FjOuNIiNbX9tw3d99hjnu1t6PbV2yla7LqJt6nu B981jHJRv5sLWvqr10xxWfDCtpq/LB0junZgw6n3RjKx++Txr86zkbaeXywi5KSZnIYNN3ReZlac XS6wvRcZgNa6EGtdcNptdW41XrvA4CpbN78b0mVrXKTJVW23b4XF1Vqu5zpPRwj6PPG2GltK+4t4 HRsLe9TartFhx+Wz9omCqAPrbPxLqOsp9UcJJF/rmZa4u59lB49IhY56UIm/u8W9noKzO/LpYeFw Duowkzjs86lX1Fha/t6GzzA913cEbcmV5+vZtZ2c8xrd6hhv1+xuW7k4CaGwYQYCEGgzCAOvhDJ4 juXi+KrP6ea9sXyf1l4NCHqPzGKaO0f9u7e4sioIeHc1V9H+PN22DR6mnAytDWu0zrmrY8VuvmZg seTstC/Mwjgc6xd6yG7eX/Lek3pL+/a0O6aYgR10y60/NK9oINp6fOLLSN5TGnA7qeqfaaH5Li62 TkF1nTOO7Pl2zDV3gjY39Zhlz3Wlg9TlVltZDXZHWvSGei7z9BD/igX5Q3e3nZze202e70L9wOng vQ9pU+zeDNz1SGGeczZfd7v1HHaV1hazx7i0HMWXHzz2LuA0GDuIQYMzQhCEIQhDkjKG9XV5ZlTb q+Kirp2897oWrvo8GIXW0Zhs5vwHLo42Hdesu0Wdkw3qbPo+85CGLQvvt9ytrS0NjusXAZpZ12nt R/jofzFluv8SfrcnuNPg914bzvj+Lue59H6brasfiafC51V20taNtXw8/aYm9XGN7kr6/stOLN2P rt519/C4V5l5Zc+4bls4rHZn3fi+HAu5ol4KQtN1gEa236B/qPnyDk+8Rs/Z8/7t1azmffZ2SGXM z9Rl2XlcjSVNXLn1WGOua4Jzr+220F5xgzZCaH7Xri9Hx1G3l/eP4v2/Gp7hjNdnZs1rSO6+S4yb ZjfWm6cs50h8rYYXplpEVKJjzybRJDaLBHeoD7rzXpXPMuVOD4HM23JLomTdwav1/975U0kL8EzU bCKucimHEG9FDEi5tLMSpUmLE4SJaxKR5nbU3ZLvI3qibM8TgY7q903Z2dHuKD29MmGkZDkZ2SHG m5BQ3xnxqdthvLt6VDrZu89npj8jtuGfDaL6BaKKZ5aJu2tUtPv7+FNdceuaph8liI6Vjzuw1UwY MTjZ3fSIxjGMW222222222222222226zNmiulG9fF4bQODaiUbQRDuBz43A44faHPDgcvJIbzs8Q m4XuF2tdilcj1tjgUBF4PCvDmRT2c5qHOz0ce1fAT2AAQGDwEwMNQ8xb7wAJksdEb/Kj5A76hXiE gyBJrsceynavfpiyBgg0TPrDdXknrILdjwXwwc6SH6z7uPAOSRbnJX3XKvJZBvMCEIhRXOkm9Vdb 7vB9W0ACAeWaRQ9dYZIDfIIXgJrFgVwrKWxyHrdXVd1YdV+YOt0HXOr2eWWWXrlHiH1TxHhc4zd7 4/TAbuiY5ncD6NzvvTwQnI0USUvNlpObzabXsdFimjaPY70hQz5hJPCbOUmeYLBkGVskrJKVDlUp MQLZWVEUdVlbbbiDgB5T3DiJmkc4sKBgV5AkQCCCAFQkAem3POFwDIxCNJUKWcSG8kwxUMpQUlFK NVaRKkoDUVlktlgmaUZUsSraRLaxBYiMlGy0lCsS0RqFBWCV6bJdOWBGRFjBYIwWIrBZFCIxGHZC QqeHZKPOZKxQWKCk0cuwwxjIaWVIbGSQ7pR4oiFxBEk6nf4rPvYhfJFQcsUAHJERF0xEboKAccQR RFboAowAHM4Qz8x9j5ryvadz1u753Wmw2FQkKIqgjNyAU515Evo6B3vJllpM5pAAFkIAoKPxeROK eh8P4fB9Vh+p836/4Xi9HTqkASa2tk2amwduBgYX0ioIrFiwCSKqKggqRFRVYoIrFigxRFRiiRFF RJJJJIovpeldcqd1vtDky14sUyWL/X9mfAvQBQuyUYhxFurZul5fxTme7tgrhJJ8aUgwj0tVsSCr CKCAmzhKb07vmbdWoNACaQGCpeCoNfNlvFveCofBTMMXlA02xPM/M0szDMxvuxcQeHGP3NLlPFZn r9/RnJoVBEjIwioiTNlERZJGSMFQOHiMTCLJARjBNQwhWAIPcCeDiz7bXiYVh4gag+JKUSDyO9LI hZ7iVGbt/fGTm/W4CDiZv0VBISApFIsFUBQB64sOcacdv97okk0JF+l8r5HGc58UtusGDEUkUkDg CgqotGasgdHl0Mu04bMAwwIemHCevKVJAGISSM78Zz2YBYAKxQ8ONIh64tD0BSSUF5z5YwHP6eWN w0WG+JPXCYjOL0pgwrIKpJE7a9Hxpl7JMmKLCKAIgB3ZSU6JBogrIK/ZEChIeeU6NNzaOooo8giH mDAezYGB8qJVAVT7MYeXEw+aGq9uNdm2wPMDPZictJ6Q0lSMEAVTzR0elkGQqChFUGAoyQXz40FT wBlfCYBWEh5wt+pbPPFl4Zw4wfavnhK+Ce4+riePNJUUCe7IPHDqT1RG+Qj5RBPoyzR8E12seQQP BHCe3OdgDAhsved3keOy/YeCU09SnxUDSKqCyApxuprW2jiagsTAsLlzjKVsghcVGCzUEohzq90R LLjgG6WT0SHlF21hs56uThMT5Vj5ZYqEWT1KH8XpeiMZpkJXXdabeuswOG/vDgwGn+ePGDPPCZR9 8NijPejSLD2ZSWJFIsJPtyyh7sSWJIRVPKFhX3IzX3eRj0oyntiagmwJzsHpyNs+gUpIbDq61OnI 4RH+EgmzIhzBLQhFkNLu+zLAsILIrAAiEgDInKne97daH2hSAFT7Mg+iR6xqoPiEd0g+OYx+YVH9 SNUg68+bQ+iQ7Ah2JDCgdIQ+mQOqIYKkmzKJSIb7BHKiGxIfykBXqyWkdiUpm8KntRPxRnvx0SSK /dlqwYin8It++GWMO361nvRm3xdk6BpC+8GfwzFYKTyvWbj+AXLAVgqiIRQWAKAKB94Nj/IGSsCT 4BdKcidmXEb9+0qSfLICfUJWfVJ2hAT+sljlqU+sWfinqv65jdNF/sDP7In9oyJ8IcRVigisVYgS C7Y7go1iiydySgSd0YJSv1iHdkrPsFKdN3hSsCQkevIFGHYkO1K96Z6x7wh9kh/aQLQUE+EenuGQ GRUICydAZCvqC1fiCqtJ3xHXEKqOKdTRESr9Uhz9aHfkrVAPtFR70m+lgABIyDCFGQP7zsygVgbc +2aUr9wlwn+BApPAIUTwTFpVBAkBkSQRUh7sfUp3+UL8cYVkJFP840X8svP/0FD/SJcTwynfHJUO GuUYETwSf7T75D/QniGE0fukHAIcX4pX/IsokgSHG+MSoViAn3CFPHKKr/qVyvIMj84Q4xmYnzC3 88QsVnzD22DHzB+aOD5ZazQ5uFGvklAPFI9n+A66pbP+iFGLIAkgEihCDInjEfKINYovlk0fmGX4 mFnmkfNJ5xeKKhqf+RiFVVj88Q/5jhX/oMv6ZT6Bj6JgP1DBUfpCVAgfBQlT5wn6oyAH/Ucj9Ypi SvqlNwQ9YsH1ytJJtZQiesQ4PTWb98On4y1fxkr90pf0BqTRWJ7BLsfZIe0VKQIRj94hhXaKpZBN wQoe0Qoiv5CUntkKT3CUj+Uh+nK+6USi+8UFy0KkPcOtp7xYhSAoCCD7xCknuEE/+Dhn1hK/7D5X 1sLtDO3r79YcgD8xO8SCgkFZEJA6OKlZFC0Qe4gCdqB+lERJkkhEQirM0J2iB/rQIfhJDYwUARLY qhbBaMEW7EExYHjwQQC5FcUW+IYoApjiDjgDUugglQEBwJmmEkD66CJmmOD+LBAMIliCaYCnzIoe ogCYooVp05rhNEB9zANcDFL4ompnAwhFmSakk+SxZPk/FvyUhDhGRYKOxEEqA4oaY7FqEAu2aFRF 2NVABqiY4phEo1SlrCkNuKoMgen6dADm2qXJEyaaUyzDLmsoH/OLhnoWYYZLiRboJqgZIqO3DHNU Q0xQxyEBTFFMIGSCAZCK5I54jbJQ5oWvoAwIDhisas3+DaMQJqhli4z53jagNUM0iZpo4xkiVZMA SmNEDVEc0FAyZaEAxzDGUumapliZYt8HNDAxar3Xw+W6AwTNRGx3ZjFASmfXOGNUTbJtSEHdqxIb WbGSBrEUkydSsmpmlhAm7kpAUhM9uMamaM0sIOxs2bLxpmw2ojljj1aLKOnRQF2m/VcIYpigNXUr qx0ulGqZgaiAtdwAH2RDBldwMBB+ctUGldbMylOSaZsQDXFuwpc+Sh0QTTfTpihmuoUxRzkENiG9 A3IKuOISEimqKYQxwZmbXNwEpz0ga6GzvxgxTbN7s2UuzF6OD5OcyGakOxuycMjKsDYoC1phoQ04 vYUoAdGbuZx7LCBtFGBoQN9JAOqzShqz24izbaBDcMDeYb7DchM2aEzTUhUFDVFrCioElRUNEbRR csRx46RWomuA+N4GYSGCyCy2KEZWdh8HbFDDOq2cMiYoW00JkI36KANETag8iCYQFkhFTIgbnUwJ MkNWVDCGe/ngm7Kg2wtucGGaQv1Wd/boDLEckCopjhhM2SmsKKhripkgO1poAckZJA1xXTsVdFQL tFLnIJJNaThahAqBtdPHt5eUCAcaAa0dTTUsEabhwMhEV1UNKaUMsIhkhpNzsOmfY7DsREA0RAMC JGESKN8DCKraYrnCEOmLveJZBSg47uzaO7ASmJxmLIaiMI576Qwqkvi32oMWi1lS+JJIBqgIGxct m/kAphCSaUK7Wa2GvFzdaoTZpsOlcEDWWCKJgvDjNaHa6CITjZLJM0oDpZwoEmlWAqwRgGSBybKQ kyYa+CxGeOUgbqlYCKY4S2i21cGoINq5ji+1MbBM1djs2i2PrBVEVcZauCQQtHmAurJmYshIHNmp zQRLgiphDVE13FCrqgaIZsWexNKaHDpTI4bIcLJko8KGlkNiBstM2YUdV9N0HLDNFtAcsSouxFBt jpdiJMtCjhA04UiVAy2oXPG2vXZTFCRcNdBixGS2DBFBBBwi4YaLCYVptiiWkil19OR7ulZOowA5 6SCwhWSHCIT56AY9bQMyXigg9uduSlhTA7qxVPsRVTxIA5+ACbMwiqVMcUIyZSVJIKiv6MARU24y If4wUM1ANpFAA15J4BH5k1GHZsDkuibdnX8w+B+7ph8AEREBtQLKICjzKqvrIPr/W22bbNUufl4R DECReMSTPZJJnn7n3QRVAUgqrEYRZBQgopBZIltdIjcHBlq4A0oGtW0y3rNbPzC2FqTtsWEmSEIS 2VQ3kSZJlwcbWtrfYZ4mn4FqdNemPezL479H+z2vtA4UlVd9nCDCGawjXRwLVph0cNbrY27CivCZ r3o7u+zHOu3ZJhnnud5MUBo2XNt30xTcMXYwXFbDK0k2SV19ogqhKiutazWrRaY6F29TdYXDMaWw vKzUrj+3dl1BabeMqM2Rji+la1GaajjNg7gDtuYoQaIbrS5pmrWETdtRs4zXqvTXdhIkLJj2Lg0x dNigXPgxpTGrMkwWkmbA2DA0upjbq4rJzeCwIfHYQ0oaXjmdLSyQxlYBNmKE5qKFyrYWxha6au7P SQlSEqHtNK13zWAScJEU4p4KiJxNDKEaW72g023GYwyymTbjLK4sW5uQOr7/dMnmk6LIVknRZ1yS atnHu3ZGsQtFOcQbN1bI3LahoEySTpy/PMja2qQ3Hni/VQ5InBO2cUiUkkhCqhxCDOKYsc1iLNY0 aC6JJlmuLGUoUY5MbVU5KZYKpupSqOHCdFvbeyaoRzbNDlz70wjYqwF6vmWcDXhTnXZ3vruZZSh2 WDOm3sQfauANMWsRCsh2Ura4w0jynjxtTf4udod7PCjrcYtpSW1ErRBYuD7cuEnabtIOEBu0cOtm 4Jt2PWODWVQ7O7ZbGgcbab+jOM+XNpu34Le4+jJdZ6AM0jsJFujjEpXdnw3xCW7ZWy2VVx7JkIST LrsoLSxAQnKjQ9oz2zvsy2hTncOndsNul8OLRabhTZG69ktDnl87j1wZ1Bqww13mqdkmXM7oRh1V 5saZKwJkySYooVU0y6F10acqGWFDr40WwN0c/Hq1xLbrDnLnaSAV+bEsumNH30y5JhzFiwBCZmdB imAkMNw4U1clk1E7bL5wGOGWF4ekES421RQciB2tbk05c2Wyz6jGqDi3Ew2QHK99Qu1kctGAITMG 7oqUEHDNNjWS7u4S4OqnS8IQgo4Ugekcdz0ObF7OcaHOs0bAyiYC+9V50WrhOXLG0ZysiGqqO1uK xyDBF2SthBwGdbEMzGMytzuV44bK1tWLMS6hiJ2741LPZAlZlDuBD0zkzpz79gZV2G0rh0tz8K4B vQaJb8crbtmt7zWGyTyMzHBBbGR7G+CE6ZLhvyiSucBDWJQ8NyCGfe+ByedtnH0rrJ0RrlhG2jSO G/Dbnc2bsujTTIIu2U4hi9mvrlldrbON40DqUbBh0EodADoAdGGG/ZqDTx5QAYkoxqOtHTrXdvpF DbypecLCTYjzJM83DCWFjttv5VcMAQNRcOq27q1bOOK6NztlNDTKMxoIYYwQAVvEiTu7Ya9OlSg5 sixLJM8js8PyRhUmBsOGj775PqGujRsFbjhpuI3ssQ2PV2fdZbXw6DqzzbhZrZRGWY26NzMSIYYp DQtDTcWpQKsjOhjetJE8O6EszomhJ0t0M5v6GYGbBubGjOuddDbuN5003TiVwpu4huQatq4TTcF9 EU0NxnjU1eoblJzczMw2Fsb1M6Q5BomcUiaYchHMDu01oQ6ElDnDbwONadPPtDTZmPixz0CNN8A2 LjhDnPzyE4bcubDe7J6KwWVWZhp40vD2s5yiCCRK0NDEpgdDoSN5xOHEzAyzcCxwaTLfy45GWARq zg1t23kJHFRXo6KzLbeO/kb70uaDYaMMckMBljZmyRVTDid7u4JOoUavXb0tq3RQx2RwOiNldhtC kGrKy523dBy6N2wJ2ROyugJBzbMMacObHjpXtNumdLsjWm/YywcjbtAZqaz0prIIy2VJaiHTBzo0 Jfe0UaE24c4m3maNob9tYnZTIVGKAVWhiXDcaaPDVbVXGC6GAkzV0Xh3h7O7gg5nJQREEQxI7kCZ 0xCy3bc68nnQACQUA4YczoUoL0oiQgh3H1dKVBBjEUFCEGkEkUUfyQFD24im/RCQFNxERtIGzlCQ gnk+eeedHzVKSsJ/TUL7v9SYmxaZtRXuiUDAYJhvepmZhuAIAH8MVdpBsgIXCIQkimGAAeCAFBUx 4ADhQVW1ntxFPPgLiaa7VQt00aJmIB4flUWkIIj6cRQPyIJ4fjUr5EE2Ym/6cp691BUK0UiWiCYo F8E8z7flWQfHiaiJCSI5/zKC+ArfAQMXr8uLlXienBbRZAR5sBCuXhVgc5BkhERdcXNBeRIEnPYc mJYSfJZCiEwxRVWATpuSBkxa+rci5iBCSCGQIqMgCyA+3g/URbRUc8AAzxccVxEAkJJBD8SConuW 7p1PG6POdRt+97ThuuwhBb5CTiqFFBXOxUKEYSREHqQER6xuUIC/bRUMIJgRkhBBE/FXbcl0HdWq KXSMhCCgudio0IRiKrn4KG+QBqQJIQFRvRUTOxKyRhJFQNbFQURBsy+/VSkEx4CLX/t3vT3f0r04 WN1PKZPHGvQt5O1uOQ1NLdJvrjPKfR+Q7F0m5a9eR24UNGIBjxGAO25QKrwoknOQi2bvBoJg5+Bc WAAIQwALi9w8iyPDFNLT+mgg6d79ndrMjZ/d7bFKX4mg6RgKPS2Wsq9y95Wb8nn7+y0dCbTqk7Q4 jNRMdogi3Z7qdvHWPd9l8yPSxB3rs6pmNrAndgQiBIBgQz6dvzJWgwUu1UWYmRnp/I02ZstmnLhd ZHKQnm6X5fWldm5kbdvd5UfD8L6Pv/3/3v93bO37XpB5o6pQzpYjEYjEYjEYjEYjEYjEZnjxWinZ od12R5AXR3MzhF3kArA3kDp2qoIqxCKBDuUhOd2EAhXGAAU60iY5PUkxzDZDgC5GUWDKEs0SvH1N TU1NThE4TCQtTsoh8ZTduQQFNdqqglr32+xTeT/H747bvbQOH6Po0Hv+972H0Hu+57eN3m49rZ+z ZQX0GCAIdCvW3EDE0JfSYdGzO84Y2iZc72BBt2t059/ls37UaCHIAnRac2D4f/P21JS1RD+0iJcZ pTN6OHlB/0/T9zZq0bZb6WOrr8vb5W901Nf7hRUWVxedhyiop6KgwyMzRIYEagzAkDLaYOVYgzIX 8xn+70sBIe7/XubOg2GGw/rfnDxuOa11PeN/H9fTW+DEx41MwB59sNCDA9G0IIgzWkh6PFRdEH/c xQ6UUOlEAk9SAARRJETu65PX/Z5e6LXd/jOoSeXUCcMqeZVI9mHP6a/pWoO1EIMAzIAowGCdlRwV ZEvqyso6ysrKysrKysvl7evTAIrMUeEAEQmjE6ZEJEyIf4dHYrv7EdVf7ou//tZWTG+7Xsftffv7 zdz6ET4tfyrACALXGCIFZJsp+Ry/g0NeTI2uQhAVuOhOgO2soBg5QyAYMf5lUAeaYAtR26mmKq6V UTJ1UlVVVVVI1cOCKyOtXXotwV9YQBc2UDQ6dA0VL0P40vmfVznzrY5f2c10tPocju6bA3S98Lq0 W/XePy4vCzfTrH9d911tIrKu0ACpk0AAaxVNzIIJeIhyPXfg57je59O6I5CEidsUXXs77zH4GL+P lg9l39h+rpoE9Exfc2k65PRsqBUIaUia9YAtZh/Lxv28rKz+TlfBysrKws1q8Or8SJiNaECIarGo iONBX1O3127Znh9p4fQY+7aT4Xv96vgA75FSQE3ky4reCYoRSinsWAawT+QN4w8nXXhYteMIgHTA IkGB/0wQdc6x8/o2rCuyICNws/o/rv76NKKfTpsVWLcGYYMM4vOyX2uCdOgiCMnAPFarDAgAQItT nHHWOGMi/U42q99wzfsx6Pwdy4QML+fM6/1XbN3mZpdDO2qgw3W6+K862Z7KPsN90pnNv+/oRkzJ gC5mAA2YIDGa7V2PnaLYuHRQRldSF2MEEFE8kxcPUvziqeoDnChAggLYIu1vGHBUiMVd+V/e9k7b bBbdReMlHYeH+bthYywghcQ+FaH48oXwRactJ3n5etlNj7l5kQJEPL/lsfM+dcbnlrzlcfloY67q IlKefyvrPeXCeF9t7y399D4Xxfg+/tVVVZarxard15LuK3eg0Zq+3zZwc93+59G70cJHbWj4dq1h 161CjNAIMu6T+WRZQZAXYy4lNfqHA6nk9/Bb+DvuI3Xg/VfscWmrqP3p/yOf07x+na1/gseTgIIW m0oL4jKAPGNDdhme5MuGsOX3GBFW1/ufh3Xu9mT7HuX7U8jcyL0UNfAwFts8Lcb/S2q+2GlpaeTy cPKAMcmZsIwutzcdXzjiD8GUniqa0czB02k60boblj5KGObQADOcvR3CXsF53boX8O3jAuxsGReE xzbzecZkrP/C3nMvLf7aa94Tf9uMuOMzfGyV13mOX5/FmuTRdj/v8/bk/OzHV2n4arpXuoamSmjE 2YFjMhxp6LIz/BlBsngXZTd2ZI7sSNZcUBgIQAyDha/52kkPJdAnQIaY9eYEoNLYtB9GE9uO8Dq2 N6/5btDDtmALWO+AX3iMsN0u9+5Wr/Dcfzo9tzr/wn/djsvXgJmmMkEowiYQUWwzVf04DLJmSAZi Pnup5+O929+boex8k36sJbeRquHbMjuOZj+Zv9XjqW17rx/g0nD1OE5Gdt/P4Wg4t3y1X/zyvgw/ B6H15ikvfByODnARDV2xE8ZAELSYAK8AwOP45kMH7dM5cDFbtACDFTv7MAqLykGmDv9ezA+fOYgb p6P2vvWJ6cDRxOOj6/R+xsrE8iJ+5mEG/E3eLx8AAAkDBEQAFQYAII7sZlMvv6OFeP1dT6YHu+K2 4Gina3S9CN7KRqc7TmblbPfFK0lysoaSHiyz2ey6r/n0Nx22ACGWgBIikigyCEz0oVAFEkQBJBkV CRVhABAPkREQc0bRQBS6AKIUiAoSCqJGCn7UAAHC673fD0XF/pdD2+Cr3uVlOBD1uv/fBXOXos54 Mfssz0slUamyfZ8WH2+Z9H1dDyMB4bzNdDjc3f/T0vH4H+77ecT6N12sR9TkbCZA4wmkPDth2Qyx Rit9vMcTmMOMxxejWIdXIOQ7g4ZggRc/y0Cjt9piayds3fsU3GDawhRINZk9NBf901F4ujil+58X 15Dmb7G/Vh+r6F8jIw8OivEZcM5kjju3Wcl4409x1rAHZldDyPe0eQ3vj795vKva5rFfp5mR/m++ KxdDGe7P43567WT1vu+z5N09v/nqPsXUdTR47+PYyPI9DB8L4MLhsLqNhvMh0ef5/R0ncttUQIzM jM+waSTsJCCqCqxFRFkigosYRgwkCLIxgdu1xAtdFFAhFUPDpACswyRIwKIslYS22xUG1PpHvvk+ ZH1fN1Wppww1MURIDFEREIwtlRiCxgsWEo32lhCgkGMEVkhhhRhAvncSGALZKEEEwH+1AAxZ+nmN hOcTL4/Y8+9r4XyebDAB6DHvbWXRq/h8n5fs9D0729ylw6u90OsuUjFy5iYMIE2gV/O2uizOP/OC 2fD9q5IIbU/AYA7hiKMhl8ohBxRY3J9Tj/Nw/g3fb7MNyeDs93UWva4fC6O/2DQfT62w9vZ3/BSd R73Os+Dw/K0233/l9jp1Gp7ddzMrtcRO6P6OVmZ3g+L5vX9XEXTncHg3W1UJETmFBcAGDHaLYSve NkmXDVxQWXcAT5kJD5tWKeaX6vcvlbJEA10fcO/g/JvWXHfA001TFM4rw6TgAUAgHut/vNhnMwUk ikWAosYyKjIYDQlt6xXUHS3ieoVuuBJlqNAbMGmMkK1KJiwsN+cNxx0mnB+Dism81k0sN4BQWbOL BgYGaAocbpQgKEw8ACoJmZC06f6XKmpZL++DXy087SxT9ogawx0fYxRI0Hqzqw3/4KPKB3Ec+aaN j7i/kfyQw0mwbEUHTcrNbJudf1dc+efyKvmvHDz4e9THpCVECUaFGELtO3gzk/7unDFBaak8LMzc EwWAGvd27MuHYPfw3PLMGWJaDcDRSrsQx8kAObMgAaJgrec341AY6fP7cZ2JOx3ed/Le/D8UMAMf 0nrrA2nxTbvxmirGCM/h4fp9lkSBGQ9zS2D1Mu6hOFraTM4rRRXr63A7LXda0XnsXict1dHkK0wM 8YEgYGKMvbFCDNAC5kIjd/mg2Mvo7Xa9f9L0vtuAh8IDHp31yWOc1CRBBdBsR+di4uX722F02Hkj sdc64k5K9L97Pd8/ynw//X0PzGJ9jX1G2ere7bStngonhDMPGcJ9O3Xn+J+j2Hwez/B+w4t3EhrY V+B+3RQn0A/JYQfrI9Aeup+xBjWofeeh9D9QmsUSq7tkxOL8jKV6GlBJruTTYPY6irvWh85+ttg6 j9J++734/2HMUY/XDt+vAfjLPHtnfUB3F1cv6FIcW8bxJZOGYonqIJ5CB7K633OHEse8WZMWY8fj kdKZKeP52rLMQo8jhJofCSkUH+6g05yLbC0glIF2LputoG5hsfbqmKYotM1ZGIvnLLCdgw+Mw4Bk Nzu73Bg868uI4qihxId0yAefHgOAW7OXQ7HseYXEC66L7knkQymUko8+KnrZwQTqPhtc1gjztjNY dMLQPKIKCLvwPfEeKBrNZ3NVYDyfWeodTc58wlm2HMqnX54pUcFMMphrbUxcYzxUcv0MQyTabRbh 833+zB1kMvW+9rpNmdZvob7zE/WOzuo1En6Py8ezmxZ4l39SnjOfmMxJNjtnONWPJv+XpbiaaX/P 4osIBl19si0VFG0oxsA3G+LYBdBQ6JFXLESwGTisWCLv3bf0LqIB1kj5PabRciAbz0NDFCiFEp4o 7WcycHsMz2icimkE2evxe609nEfUEdo2juqqx0Nwr2Wy9N2/n3gbM94ZjMLg1+h/ROyOp5lneOGV NIdQOpYbmpUIe+3G4XPwuI49JwsjnZTqesuFnonamhuVDpC2h0mi3kamolDWW47o5/HkYwTXLiXx UZ+bmCqOdB7wMX+NlMRJ6vxvK5OJuI6c9By4rxxh5NZjMSeXYxRB7DeC4R51Lr/Mx23mKNVRMeD6 HtpmMMIC/agA7eDSxRFAA+QGZva+RAAE3WFhoUOkwkOjL673PZ91QuJJOqo5jfzlsA5TXcfU5ve3 gj523oAdz0pRJPdoFFhEg4gQQIyi7Etd8TDlgod0E/efWQhCyyyzLqCkKFjgSS9ue+HdJuAfGPPN 6RGwUOkJry0WnzMCiyTDoIMBuunBsLEecBs8ctoO5SEDEmADihhVwOb1uYwDk3wtt6QZmgx48mGf +vllUHtMbObwT4/Eq08h3GQgR8Lt19N9V4nuV+VST6h4TWrNJh6iqpnBm67AfF7NYNM8c8Es07aa SRLpVIiMLRQt6S2gZMk31jeRlTRguZt3/edtp+edPeAzB0UnAbeU7YKVgHcQu63+pp3Z3r9+Y3Bs 1Y7lMouPOoU6F54Q2a6tZvDDRsGc3HkplnN4f2oNn7yMdB+/djWKL0d88e5HYL5GWOOKLb+ljsb+ u3oj0Qlzd7fDbpHSgZ1+ajalQlD9r4ZAdgEX5giFfq344qqBikPw59fB81FcWMGQrv4o8FOp1E1M NGqka6dnzeZjsxevYBlGIN6l+jPAGr11g3M+lccJTDJb9L5T01BuOpXd3diNbcNJ1RzOuxDX2o3R 3OXDOQbajhs0gG29d2CGBcybSMuLhpFrWh7XCWBr2pBpo/N00ZjGmb1MsAbN6drTmOd7dOzEy4Ys 1sh0+MHN1p26vsXYLbjAJxU589OFD3vC3GTtjQM2aMeFiCmYNnxLRqztdptdnTOT4BUi4JZnARGC JwOgEl82oV42b4L8rCwBT/Czhg6Ae4Nkh/aqTOq2J0TwpvkpAu4EG3WevOziOC2LhRyomuazSvee Z0B6/VGiBE9hA8SB5RG7wPX1wItycRA3zzqL8DS3K8XCECbnTQzfn9XtuKlbPppOSe992GMlxn3P AvuR9SzoZnh+xo6bBDp9oJOqD3h3+Tp9BvQ65yy7ZX1zDY8DXtHNw4cKrh0PA94+MZqeU6HQ1WuS u5WZOTpdLM3Q6XS6Wq1yVzVmThXzj3autydqq4TT3N3OTvOBVV4HDN50uTXhdD3rMMldzkrqV2Nd VutzVVVVVVVVV+KzW6Vdbm62YZkww8DsdUkvmOXzHCxAcwP2T5xyA+lh4D2OD4oTpAy81BtfEyG7 6nG42RkOop/8glBCIQgEBOKCIUiISKoQGADKIl2IhjdJq8b79Oa1facpLltApGQgMynQbl0ltN16 GmJE4CZKGHHfzsMUrobSmgZmKLAQBFQFgqKyIxZHHpnvPe2ev8pYeqTZps3Pfvw3d5MdJOoRFDtW egmgrIgdmj8z4NdohqhojqkPr69GGQJgUDl5M8DtGHzfOCkvW8N1u3yOFM2HqpsIWlk8QC9n0elo OaOp9KmWBvRfZGLQg+XEXrQFywVlVaXQ3TUY0976L8TS8xvKh04moAIbGQyg7T5E7Qer+ywJ4vle dw1KtBVhvJjw/N67PlxvOBnu0WNcQG814JcYm444bvi9voAbANwfdhA8JLTuz0g/GaRt9HQhqHGt TyuSoxNX0XzCJGOCpYdDGNMMILVktXRN82DR0bHx2tVmzI124M+TPnyqmG8AgauL7b9vVQqUVW/z eXR6PnV5UPLieEYGxMs81BBqoWWmOWhEa/ToQndjOZ4TeBtwESxkSubF5YfFYYitteG94CaPjsvZ sfP8LpswbjXPuxcdVFbj7kY17yy1dkNzg2/OddzXA4G026bG2zWPlZnh7PbYlPb4rTXslCyxTwYl 073mher25BaE2TlMLFyoygp7F3wBvBzpnxVyTgLr94VNyKKfUcvkhiOZA8tHpoOfrFA0ctBAoVvM pSu3KgEBlAxOVKiN0HpNetze8sWiXvPR+m5YO1muvwujki7fIbiAKBvqKwgMnq9k9ALwbktwfwxg TxLg3Xqvabu4MPahwuDdzJWvb913Hj6WDBi7icqJh62v29A9b22ht7x98HNjTXQxevFm7w5OFcNz UTP3ppFP0PvswxGbRo0ctPpfF7a8dxz/i+RYeKHRPhI8PyXcN93ijBTv8DmFhPnyRCvGM2uEj51q OR6T5Mo5QPcX2uC7TlrZkh9Hh9QdacgUL6YLD3od7A/bU7XhnCcLNfc05NeeO9R7DrUju0VOCn0x z88jeyTKxUYRAmMI6YGCPCfw6MSxppBRiEPOyMKvVzvzzDUN0Eg7HHy1z41HFF9HzfPSckZDYYQN zc70btdRL1qVej5TvaDGTDLzvv0ByngR81Ddw+HNUzzFW17z5XMt7vp4HJqvvOYDysvIv9hHLE8Z BtNJnuQ3QtfO9I4diXo2LJcU3YYbPJNBC2acacpPSvrLhuXDj28gGK5Mi+1geri6fPrl8ug31WJ5 vap3TofsLXIAF1FC0RWpHo6nIra451V+vOP9b2LvL9Tfl1uPIfcR824WQ+myiAmTPQgJlxABwgAR VTMk13yuF0+u1VOurmdJT0rLlNhWl20n8ZcmBd1Ov/fw/fMczAHouAAPPY6vr+p2Gb2KKlEYUjrE jtCie6oytF99ofYZsaDPepE44ajFrslABDDj7AcN2RnFKJGCeKRcUA8KGOKfa+l3hbpw17m3r3d0 38eTPdJ4dE422lsa4G4G34RArumuAOIwOlivkIRJAa8kDLJOAAObzNjhg7XTWEM/CkYprpJrIeju iKDtZO9IriOX9QWACDiFuhtO0BMx8Zyds3NOU/v5PaMlxcy4bH4ZfIoqzfbIJixzcyu09RyBMm6A 8cnS78sjlTP5OOJGkc9sIdUvstWYyrgHeB2mNql7xlh2ocOSZmb5hjIgWj0mLn+QLweH4TeQj0TE iTjjM5GmcBkVLc7ZzXTuIFJBEZVeq673VByRXrR45Q7XkhUTMSmYKXiqKCQXTTF8ZIpkZ/P+f8P2 3tvC8XzXssehCSWXi79m3hetmP2egZmpx5ubGkvMZRzrNEroUK8WmJe9ajMzxLQ9BBSXRA7t0mbH oPpOU5nRVvsv3r0STZ6aRo61KPTWKdigVoSCq7Mo3SQlG+ksmYejs7uxEy6CwTRtcgswZjGQKbxC jAd4FvaLNX0TGIcKKzEdT6DZgRqATEK8WpZ3qhyHe0nGzk0clDM3MXGZqTarXKWtLvE2vQExj0+l f6n6l+pka65yS3e/zqVNc66vO1oh6ku7uV2Uy2zEXarSoulgwwddAB8zu9M3Rto6KoPJtx8j/le1 PLnYfA0h727nIzBHa4rd46K7v6O4IPkS6DDH4n7L0e/zg4SSHq82e3jd/WuL9j1A6CPQOiB4wYPx OiV6mP5cvvFc0aChIa7lsfh+P03EnP26ctlmt+SbSy0NYS2tO1y5vUTzHyPjf4fp/qfkafPsOc+O fbF6l+zIsp19CrGHV9TSZg8nK9STD4awNTMII5pAqTIGKT7kHsdNIF8YBq4UGwQ2Pq1nGDDY4dU4 LFIJUIdM0dpWEblkmYiSswKIJhw7NAzGkuk6/R1OO5yfnfPq+rYvwt+FiMAd3Mg5kcLUhhndAd1n S1oqvNczh26rLfQ1mRz3QbX8Xs+jmMaSHCzNzNPQwX6KfJKxKgwKSgG+wWkAM+sUD9HPDzHUd7p9 tcOjNx6zDiys0+azRwpAnIDp2hYzoHmMGZi7u621VVgFnpnUtacfE2WNcvH8Ejw/W18gFDGfje/Q 7XX9znwxnwJ97nMUGx40wmKeAQlM3uFvt48DwuZCTTBEomHkdOpHdESp4eziioqCFY9e8e11KWx+ dsZXZ2Em+eRFIkuQWqP9zhAYfZwK0Y/DsnvoHxyMJxBDIUZbD+fOde0N9A+SOIgSSDeBu+2gomO6 y7n00/E+F68hj778gfNB8v8DLR6OvgxIXZ6clvs8VyaL9m3KhzYJxj5qdUO94PJfC+Zd+nntvEV+ 57XZ8FcBDN92malT1HDfm5Pof5uZ8mPm3n8Xs099y+BLRkQxzdk0YaUei6pGLbUqmmXa1sQMOGYg L30HbmuCBq731vSu9V+5iftvGpPmy8yZyjl75Arc/n73VD3+XbdqCdxBPtzztTWG8HfC6waKCLK1 TpiHVDn0lL3bCVlvV+jCn5NHtLriwktAaD4Hc6Eh66g8M2V8m+4N+IEqdx0Hebr/xrHIQ3/khfSb BhyUguQiHWia6esTegQe7XBvt0hkMc3BmLl9n6HteJ9BSmgZaziOaCQC1yPnyA44La4/9XWXXiMX jIZRtsxrglnsclqPblt250MwwTgoezE1IOHcTCvQGgKCUFe8khB32UZnODvLq6poDr+LSgRHF2eq pvkmsXC+zp9ZwNHg80HwTt7dZ33V+LsnFx+bry4H1JG0j6wh17Agp211jIEava/HvdJibC78eGF5 D8hFAo0TdGAxRPGGZBh+IUIsBCwle15vi2N3FyOpu7vy+7/AyfBie86faIDY4KQoksTchdPZ3FzO swxxNNzJ5c/y+WbDggaW6IyWMIzT/D3DbDoBy/ca8NdHxmvD4wY8kwnXcVgM8fL5FkQpl+JiwtIK zmLRu5OcqaHyLfannlGVvypTTD4EBSzuTZ8sHX4YXJX4CP0ievyJfiCZ87+YeIHb7fMPS2fcY6LF jECpwnxcTDcuMvl6eC13I/HsTPwljCKyRTJADcmJe9XOTitlirrTXOCFqPNBAb1AEeXl4+pkTxS9 G51rHbbzi8LyN+TLYVuc/WVbuGkgyuboFxxV1m8K5PO8BXWKNurtBz+7aluFry0GSWJoLPfoXUu8 ugEGcW6mGHYGMx0YyHcQCEVF4u70E/agKAnBbQ6eb5fmx0rWFRljSmC6aecpuS6VYh6oytIgJp8y uFgsfCLHmrlkVy7hO7kDe2dknjh9fxmx1x9X4+YsQo1JwKCEi/VGuQPu15CAnROBlWwOcQxDLwO2 Iluexx4fO8b5uByfb06J/W7DT6xGdXZWHbng+Dwcu+4fa+Rg5L58g+YEOYUoY2WZr9HYpt4lLoiD cw2wyLq6YIeQDAtwmUAWEKSfTPZO9Srn86dnXGaNy7lz0fj09L5Fe37yj0OzQB8eKe+BHSeKP2I7 jwZPuc+v9O7yHrEfHYHRAfmoLJCae1bpYs+sOacKdY64bxhhSTteSPaNjjPvz3/m2uDLuGz6gLCG i9SL6te3ZMzB325+lHSgjhxbqNUdAE25y5ZvqOryCw+1wEPVHiI6MDXqczemLmG+kPQwexlPwew5 eY/Rc0DAwR4TNnp+Y5jL436Py2s7kxF2eMMAafaoLM5U0qIVsIxkZEQRZMi3lLhBllEONBxXLgMX yfrUDv2GSFlvYamDnu3HjOlD0tiw30CBzAEqBuPdootICk7AVparOiRjRBDFuycl1JWiZMbLGQQc YhrAadXxfp3IGaYHCDvRo2/ERv9jtFiugxMblo0DBmFxZTCKZIophKini7RRTCVFFFFFOx5+p0hB Y9gWBr8sSZ+B4Fmt8/5K+R+N7Ewc8ZDHf2gBgr2CO4l08YNmxlJBm4eHNRkFX3tQQYA8YxEDuou/ n86rF3GrHtBI4Q0AqgsXOa4Gn2U/cN1T96umNxouRx/7iPv1Y/KxyJkLsQOKEUBVbRXbhq6G//mX O6zuuaUxtFicRfHeex8DsitSwPjQ0tLxVcU6Lm1D94sCu3C41DEu0JD+qPPVoJJqSfoSnxFdbJ2S vfIc94RsnZrzcqdcD2Mn0/DjtcXH09zpvozxfbz+rMoyzelxjA+nPIbYY4+Di2HBydh6NFF8Ercc UsSKenN89wMgzN6xGZiSa8qY7fLaU6e8fk63us7XZ6/P/1NL399WqFBkUmbWmlbWshQSUmDo4mMZ s9veaRdw8R8cLSvY1/jVhM+klzJGMDN5m2FTCmFIUojZjcpebviOb8DLYr0d3Z6479975VqhQZFJ m1ppW1rIUElJg37jGM2e2/SLuG98cLSt9d9YTPpJcyRjAzb7YVMKYUhSiNmNyl5ubBb8K5PI4iEP tx377TjsqhQZlMaWqOSt2N7Qr5D0cC+687qYujcqTk+MM1kAbqzkYYVpCNZd86xe2dsN+u/W10Y4 soatKTep17e6R0Mc6bRlAaJ/Ykpy72Ax46yELaRgZWBNyBiJIILGHUi6jmCtHtDxx7A5QfikHCHy C1jWjfD+kfBHvRwx3A7UbwTiigghA+QsEhISEhISEhISEhISEhISEhISEhISEhIjvor8ymu06ZoV mKxWGRSw6ztkKDHlwWWRIQ+LBYLBYLBILBYLBYLBYLBvFBJZhoAqBj2OltvP4fqynBPMsDJ+/BOy N4YsxjvhmEIxCZoz1DPgi4WF5EHZ0QbjK8/4h/9zvsGXfBxsxvwl2wMn4O5XC/pGUdz4jy+yiDYh ccNI2RZgDdR0cXrLlXcdXIUMGOQQ3qHkaSiGPL0A6ZJ0fJ0AS/JAv6StTd4uPHaxTmNPRMtAJOti YnSfyegB/2ZXexZQ/nPH9ynRVKyvhU9DyvY9TC865bMwoL7Xu0zMPMv0MtD2L4YNcTgvkao4l58o NOv0P6+AWpzdvPgc1eEqUC5BE+OWN31Ifh5PhfWcvsdzcA5AzYw+sNonwCT0H8uXDdSKudyzOAJt c+Wzbi6Di+cqoqrrnrdhrgGwP3yqQmxr0aNAo7yr8t3qV+wzKGPFS7gAYCJo/Fdmo2K6hd0j4H17 uo9YujLNNTFYg0m72mv4ydaCN+BJOD2h05N3IPSZDfk1ENnRdrWta1u/7I6G+cZkABBnCwMnZXA9 L7dj/HL1vIwnsjXuXn6OatngOekiF+9xBQSHG3dunmnRtYWIYi+P7OFiK5laUm1Y21rNbV/Xetnr eT2EzbdbH9TowznCvwqXoscZs/0NbzhabvS/n7a1lUxvyr0lupg7P2a7oN4zSRkiioGAlAE78O9V XxgTxYTRDLxaqvutOoIS3exAJQ13rNes90BO2DaCTSP5AhC8i7KCOPCm3oTtAGhqtbd4qveU7LAy WhbOCYeddmrfOCK/q1/RglYJ/+XnvqW1NEFqmaa8Irk5S31vuvyfqvpvq/I+z9H9/zvQ/5cccccc ccccccc6d1111111111111111111111111111955555555555555111111111111111111111111 11133ED777779+/fv379/OYmK4chGQhJXdKlTNvL1rISZ7yfD1vOc74X9nl+J8rc/f5txxxxxxxx xxxxz7brrrrrrrrrrrrruN5555555555556AhCKCoi8ylFVX4//v9L6n+T6n0fcfJ/X/X/M/1fpf T7Lf39/f39/f39/f39/f3+Pi41nUtUVQUjFEX7b7r6uMkWfgfhfh/h+m/T9vqDUDuslQJ98+XT65 hmkzZD51v5rxUhVL0W/uOHh0/P5/nfKH9Huz27nPQ7rEXy8qJo+NdyX7Fo+Mmt/Hq8NgIe0QtzpP q4To80K5jhlrEFVWn2rQXtp5E4rDTEmR7pw3UmCRAtkbpJi0FSIlSXaXBOUG+XyuJdpOm9K5dwMm 9xxOPfnchTYaikXYYAEnMcn0MmxZJcZRx0s+hlLgxq/dBixINgzRFX9DMHvhSPtdKqqGcmPUe4kD LV6g0mAsLxS2gFy0npWSIIbT0wFSyH8HA/k2bU9TbOQhoGBrIyRipDfAiB7X6OjaG1tRQUtrs6GU duRmDPkcQQhrOMLBgUnK4FV05VVX8vHyE2eSZraQ4oNVQVqLq2TQDXBD0N4OQ7ADogDOaGpB5BGD EkmADnCGbznW77JrhqDLUBAmQ8hhXy/sz8qCL+J77GhCP6OH0EJCEZ7VKg3gNJIS0J1HMPLQ4BK7 aiTx2KszEJgYCJKzdwQXgQpC6SSSSSpZClvhcBo7PQAMX+iYHLq/+A3c5sGxARZhtgcgCGz6fyx3 cqqKmjoT0cYp3OrZbJhqJW27moE1gYHO2KsflB5Zeyv/KTY9ZVgw7FKdxrVoXPyUM/verzjtcoAO DMFIG7apjUi/lv3x9rWv3Clhu1s2WcjrwyrUjbjjFcqTJcvpWHd9WUuwhhkDl3hho/OmckxRdzeI cs+zA2aJM1NGjBhkWAWFGzCYcUsnwUrjeN6TtWbDXAdXBzO7U2sEOUvazu74siId3eGURKs3AaYJ hYMZwa9QQIERiJgQ4nmPRh+Gz5gWZmb7cNwGANgUZ4+6DHUJRtKA0dMmzZvs8O45sM64nSgFK2gO iSckLOq12ZyIB3prhjCKIsnIG7lm0m3hp0KbdYRlMztSLRsHHrL1MtMJcbJCDRo4zncouAwYZIju 6O0rWtqvZAbUMYyrWtqq2ta2q2pndBt3UaIKuWZdh4jqb4V7dqwdPXTDdq92OViADKAhgG4UmzwE uhyAdEBrMoaXNgNsL1AoEvDUAWe92LgbnkbhwaZsAdHl5EcrIRJ8eadgf7/LeS7GReyAOmc+wviC /jZYhKOtdaqI21FVRVbYRGZBOqeMu9NGehqqjbUVVFVtFqqjbUVVFVttsLERCtjBERBVbbN/xJ1A mmdMJw6V4SdO/SyNuJYPF8bMchjsBEUZnBry7Y93INuFlErMQ8KE6eQt1runRj34DlsME6wEX7dQ VHR4nyWvB946+sWEQ2a8muxrhrh55wiJ89hn2d+Juk5YReSxC0UTC25tBcWZJqUNfVtl9zvDvueJ USFqM3TmMFzBcQhushMB0eWSkl3CbLk1wi7JziHWKIV93i37bmbotio9/BOT49c/o/EiyxXWg8E7 ObeEOSQDMFZJEISEzdVRgaWFYQU5qUjb5UIDAZJyUAvGR/IMtpJJC5YIXI3S8TGBhZVsXZM86hCE He+ddaR6P4lHFIl3P1ve/eFnHoA6uEBdcTnmwBx4utZyAqmDi3JJJEMncarwLctSQOeyrXGLviAw 7E2yZAgH9FGgpg2gbgIavF5axAaQ5nZVQu09OvADsVsQxTQZnfXYN0yb2ubUxXUVGMUvrAOrkLfO d3bDGb21qrYq0gDRaG7eWi99DFFFISGOTT5gahrhDkJwsFFhAp0MocoIqpJxjudfm3teF8U1rWta 1vRuHDW67hxgD+gGMnJrWt2y4cNa1velw4a3mQ5oc/j6HFp1OpqKLWoooota1qLWtaii1qLWoot8 fp4pI6QcJNURgYCoKr2QEeF3TINp0vDZ6pe3Ds6a08RQot1A99q/F+d5OGIeobJHR0KQNRHiJ3Ef 9GOhvGEC9aWhFbAHfAhcIez5fx717H4EAKkjnxEDVygO0RN2+9fCV0Ew1AOJCZMKwlQJhAySvlWp CLJhKmGsghHKLqMal6QSSLeAgYkq7B9ZO1cYqlBhhxTDRlq9uz2W4dqVrXLJbhySta5ZXDklS45U dumRbdXvNGp5wHZ5QnXvNOiGQzhQxxzQRQlVUiKBFCIwCMGQNwhPFcGWWfDS1R5hh5ZhA3DyHdBs RsUStG3GQz8PJua7GH6TkrAHCcpEkssqLFEQW8UEO+GB2584RNeo1nXkpS45J3OSvQ8aTs5PlInc tGcEwiwzFQ8VYY5mEsE9aCSqqwSZKy8HR+IxFNCKv4VKdR5fT47eKrbVtrby5HkSXNsgKE4AvNDk qCUXBV7fODKHnh5vW4Pvg/l9zj/Qj7j6Ip5p0+63AsQ5ZkGOXZiimDGQN705k0Q0CmRaKUtCnX8o CdPFOz0KqqqrdIFAOw6L0doBLhxwXTs7nIph0Z6Mt6dowMs3NrWt6Vw4a3o63SEIyAQgQIBIjhmt jyl+o1B1Q08eHncIjk2gNPTD2W599sPI49mZbvqzwTMOF95t1Log46ovyw4JjAYy959DGUIig52p ZId/owW3E53OpM9BmPSC1IbNRghhFEOOI8zuO69B15jcTiDgyuoESyXIhYlguqpAsQ0uei4jFM5x NzYNAPO585+YUcDIjUGoJUBiAYgTNFzOf9BVAIbSwDhJjjinxaRAVyPRF/BGDPmOxhNI0FQRzCmC agSGUIYyGJhJAsUQQQEiAmApCQvZSWHUhMHiTq9nuMQ7vc9JrWta3bu3Em2bEy7GeJP2KdP8kQ8b oAfSQ8HvEfBPMHajU2bhv6OCk1gkJjPwrOAboHJSInlwZARZIlgODkgFO8RDqF6qqqqq4DtgkkEk T7EKgizygxAYGlgalRVFWIrJgkChqmATXa2sOHZpBp67RazeX5/Od0DEKXgnaghgCm2DlttWziXw QN6/PV9i8vjq8RQsRR4QQ1EA2dkDXADKxexj9sHknTm7k5U2sgoJAZuGeO6PjftGh5FDI7q4Yfnv ad830J3d1CeCk95m43q6tfCc780HJ7e4O/gvuLk/Jlh5oHJK2+bfqOcCGID1LV6cQPRQOdmfDnMm JPAXhXN05JJNIbSaWYJbMGcGhhmQed9SeuK3zwNEPMpI75/I68wpfxJmGlmZ0/eTMKXpMwyl6zMK XpMwyJH+OJJIRI9CSSG8HD8fxn7cOruOttxxSSWmxbU62vCeAr32XuSzr/u0HsYNoHFBJP6cAuWP heu8Szx+n0uQu7Pgcz3afi/qMu1HuQA3KHR0m1yBmOZQWHSDJGg6XbeNQlAKrhUuoTSAvARFAUt3 DY0KAmJZHkgvUAXK5Qm/gKCYQHVSVAbSFrRjSrWfEKrzECkPGgwlL2ugWA2UiBlcWQNGmCOPGZz3 K9FTCEumwFFUxx+I5XHYhpb3YnKUDbdYY2AYwYiWQR10uoM/hvT1mSDio2lAxoZcpgbO51PVgB7E 4RNxcoZ3OmgZfzorgUMQrJIM38BDMCc4PEdeqrgJyyTGFVcAcl4N3NxhV63fpuNQbqxgbj7L0nR8 6t7nueH5/sOh8zh52G8BmgABzVQCIa5g4qwZoSQz1uRWGELkA3Y7Vd31r4g0RiP11Cg8qaSM0pma PTWBpM6ldGbtjuWtoyyMnwS8A2MNX1JQkGRO2vlE7KlDpnakqMVCMlAnwCwVgzpBUGx2EbRAhsSj DWNZra1ssWasyxLNmnADuGB3eB4uWrTx7U2nfQ8KYchUh4Uw4QeeHggkgILBkGrhobIVVWO5d8Db oHuuowctgavDb18CaA0B7Gtuu9xlA0TCseX6DU6Q3GxXBrdbDHAYegbOfknXIRvDcGgOIJq3SSDw c5Va1VXOQ3bHW7WuE6MxDlA2sGgaBAdIBeuCdYCMKjFWY1AkUqIwCIhWg5Zs862w6gArTpXTb2GT P4AU8o38OQISqatg7YCZgu2ORUpz6JuSpV6m0xk5Na8YYuNBu3Aas9Do1QuHDWta1rWta1rWta1u ozYYyctUM5nBGT9xcBoCgd8oV0hBce9llTLLltV0qXS5HcgYB+bki69NjZSGbOUJYgN4NAeDwZj2 32h7n8JrlA4QKjW7cAO2IPH/Qf4c0ZLlzx66rmfcOOeY+B5SoUPj2wxlJAyu8d5PwXsDEdCHhNaK ohtYYaCgNUYp2RSwMoXgIKYUj5V7EM49MEw1wpIYLAmWOi9VV3d22qkiO/UKEntFJNQaK1ZAz4Js mRgkBEnvU4N2nUDEWbwME5Lgl0YwZFYym4wErbbZVttsq2lHQBmT0MgXBAArBpG8B2gpEO+xBlJk 0hI98Y9PILjUdZOooqsVRVGTqLe3+7+b2f6Hmur/i/Zc8+X+//e7qIKKxeD7vi+2HzeW3X/MpBb+ OyfjSEhMASaJUgCIQ0k6ADIBEUtK0j44ebRle5tnUM6l4eZdPMCB64OX5Q4XYQkJOoHdd4ZSTZgU kEiphrHVkDugipeHebEVXVbbbbbaFqqusPLGrh1b2V1atVttttVVW222223T5l8u3zOe1VVNCKKK qqqqiKqueboboz5isBUUVNCJCSU1VE6EvE61QN2eQHDViK1YYNx5kHTMhiRAA5OVrwU48qFOboh4 jcaAgb6oqiqKoqq+MDdjCqu7WfXZqOemY9HTCFTiMWKHJqhyeAeCCYv5UPYcvuOM9D4P7XHoD2n/ jadfIHSAeeB46ImCFgempzEYOAUjQEALww5PGmws7aQQhAxN4faME5G/O46fuzA9pn5x3PD3UN3H 9lVtq21tQiTmSAdOHsJ4ahZBAIIQx5Rzb3TQ4gA4QzPKJCcoA5ujp+l9Lfkwu7fb9jd86PHDaXb/ TDR1VC7/VZO+jvG7xdGdEwMm8y6+XjWjWtb1dXZ674yIbuwOlwqHYhNoTQj1QAhvG7J3DWjWjWjW jWta1rW9l9ftk5i8WgJx75PWIU6sRHyCBwOIiLERYqzm9sZYJx5Y0ze4Xh3glw4a1rWta1rWta1r Wta1rWta1rWta1rcVwnUTebYF6Uu71ShWlqXGB22AB0TALIAvcQ65VHnY55xSGWtViG793oxJ1lf tOHGFxtxhUTEJRtdqoLgUrDqtohKHdJ5iEos4GCRmZV4iKNB4Lr52+QVj/9r+LB0jIHidQ1HRuOX tPDTb6LIijDPD2DAMkLTnZUz/Kb5Pp+c6oZYyd72OYTv+eqmYeHqqtO28OdxLECCLI0zaLo7IEQr DMPEARI0sP6AImAL1Gsfdqrlmvzj+J2+jusniISuu+n9/vzFy3H0aGQsH+giO0GYLMGgyI7gdCZN CWstyowx5N9YcOr0HJPAZAPiIABpgEK4jIEVqdbrObLh5lr1/qe/ft/1w/deS102FdQUOB5dTf/j v2+3bXVutVYxcyBSyChztoEkgM/7m8DUuLhveBS+Rsu43OV1o/ag/933m+t6ux+Lr+/xXXRL4vww YkANYIEA+kcqH82Tq8rqZ3j/X7ELO0Pa0Gu713wGd4nT03yevvrCU8ZDenOHdrGEGRGLQQBoZR+9 46Oae+vgxYcJk+zeP9nr1rMTpdPp4eLICnOvPwAUqRERkAZnAgmBhhfyCCBUBB2BmNXLU+nzDM7r b88iTDs7QYc6zhbgd49Exuv1nMBbnWSMoTryKMNZRRFD20QCoL3cAUuse6h+0lxNVkaTuAsOmek9 et4nXpDvo54kvzefzvTuIelKx7+NpDD7UptYnUw46IdxEORi5fRb32HIcR1FnYYGbpKOLEz3o7Su PP8CfA+IUh/HeuYHaWzoZlAqZM4OLkT8f2/w8uTuPY6T1CZMLZTrzVD+BA1RkPw51jVn1/XZvtde zoyom5+H+f+VheoFqdILC/lqNdHR/TzDi6OzdkCBsG4uaBo7lW1Es8cOYZ25YFsPTHBQ0NzGepWR eMXXrvl5+AyyCgxRtf5dgjnQOOzuaCEC0+/e0+r0oWdLS0tLPjutWjHTzJAnBEiwl1Hn/pGZ2Ow+ 7q+k1z30J0DdOYE5Tw0NYrpLPeeJ4R8RF9WMc/0/J7R5/pN15fC5xVc/jfU7Tfdurz0X5LwuYHsB 4MwQJ5P+D0iHo8HKx9T/BC2wco6xmL0MyvdY2hCo/xI+JF4TUTjw/27uhfpeGHkoC9mAPoMp+fn5 +fn5qf3VrAgpu/XG/MgbajjGB84zQ3o+MXwDZDtBceuHIjdjxxMOV/AIo4ub7+P2YiGLqxeHrOEI REOCLr777b7iR9ATD5wfHtBzY3Y5kQB999/fj94WjpQoBttqOkA4BQBO000y98luPSnbB2xQMccc cdx7s3n5hoYYYYdsdyefLG8O15Y44z6a0UDnBiDbbdy5hVK1KLBSBSA6FC60667OxjGeN2A22222 2yJxngPAM3LlxZvGBmjPF0c2FDCM4LCoDOFAfffffyiwYhELBxhkBicRDEBnBIpHGEUUUVcdQaEo 0heAuXLlx5LCNDDsSwsADDx48eQzBggO0BAgQIECBDQHk4Bw8uX3SbgRJg9wXVdMI4e+ambQFgOk bXWG8AWNtkdAU92eeeeefpb0/tToLes+svm2qIO8Z/+K9YDLvC5aE2ECOjo6Ojo6Gewgy4wU/SnJ dTr02Q/xO1m9DM/lv6CK/s6iwiHyTssssssssbItu+eJQ7HUR0S2G9wOwxabDvkW3pG7GfAxXCNI +kRSMLM9D7P8FExwTZbLpe76fM6UunqU/D5/J5azGxs5jY1js9neRotwomFwbPEhrRuodnWPJ6Ld kGEGhhBSFCBb2EMAaky350RQGFiYsZWZYBgmh0NVyCqqqqq5sRK8Q8xTAGZOSCPxz2Bwwwwwwwwt 6p3t4NEYdMWRxBfFy4Cx81MySFhkGsOqI8iCbDY71BU0000000tjb9+aRLFl+GGh9heIv76PVhNQ qvLsLmV0CeeeeeeefYDz8E+HdxLh/wuUQOdjZpGEVHKdKyAsbYnWnnnnnnp1/T2DhKP0HOpkfNed 5cLJGPn9+/fv379+GK7tbEHZeetPl0k0y5V/v7ri0+4ieDalxdX7c7Pqr05vDyc+m8wzPnx/Ooue OB8+BwwExQ8c69CZur4FhPDPv/EtxwgGxTknY393V+86h+hIfK6nK+qdGd24hnz1cQE9P2Xm57gf FhgYqRNcWKNRlBQmE2G+3FszWcyft5TUxkZD6G4+oxGnR55AQZSJiMmp6OIwZAzZMJYooooooooT 7mmmmmzLHomBEdPp+bMxNNNNNNNNNNNNNNmyzYJuRoIb7ha4WSlKUpSlKUpSlKYkxZd9lr23JM8Q wOCL4Vrr1mQ2iFKUpVlllllllllkPCkmjXIahghOJgwGeo25EyZFyOSmmmmlKUpSlNNNOhGW7iGw Vv+Pzcutqb3Oc08uhlXIupMZ+LYDlhnMbjaZ2dnZMmZkyZMmTJnZsBegYySILTMfMEy2GuGaaZ7L PPPPPPPPPNKIz05UL54DEbUccMMMMMMcUXdQlyhxnNFFDDemiiiiiiiijphHQGAiPbHs9KaaGaaa aaWWWWWWWOQi2YAkqjjiiiiijokkkkkkk1ZOsMAQmQ1AAZY8eynXngbnnnnnnnmmmmmfAg0UD5pg QPXzafdOlnLtyQ75A7hMn7n1dO9YeRTaL5N04m8gFjwmB5pkPwn0+cgDWBkIMFzMzJszMzMGDBgw YMEUM5gWYEUn6+FEPAg8yWgXTxYJ83I1+PHHHped67SfSX9EO7DwreGeDBgwYMGDBmYNXDhw4cN8 dKOEZItMjBgwYIzAEsqDAEh8M91bUsCAyHyRipuqqqqpKU1U000vkXIGQIsJiAyoMcdyAXkOSKJ+ 2OWSSSSSSSDzhjwiUuXnRZu1tquQICwGZkRESTBDhGQ6llCzGZn4xbctpwX79+/fv379+/f3fi6+ ekvmVBA58xMY+HqDSsBmDMwCPq2NXgbBa6N7fcv379l+/bbbbbboFsCwlpka0haax37TkNfumEun 5niLrtXYF0GDAva/B8HEHgYMMqgUpVdastlkctlmWGEiIuXOg9dO0WHQ9r7Gn9fnPQ/N6Zpv5vDk b/xi7px7qPveQ95fpYTc33+4r15S6N0/F4LrcVWAumQsdgrfK+zf3zpcGnq8tuPc1W7a9DYcKe+z Xaajuf6f5oeDdLp+fBnbjoNJXav2sFsvSrtVA0HL6nIouv5na4H7eCr9q9ca+a6XvViub2vxtoSV tGwAxlOURUPccwirlparq6Srq6urfT2ExNW9xGcQWeMXz/YvmZ71o3o+nolUMPB2Sc7UJHAc9wrv vhBxl0twPG0EwLttmc+vP2YOz2KUzEFDp4iJmiLJmZ6FBBB2Eww6NAzRkJ49H5gCHiUCurYOyvnz 6Ml3z6QfPplqtiahC6zXVyMr/ywPAZgfJDfx/Px9drp8r8Ze3TEdwqjR+vguRvcxoM9kNhkeLK7H Ecfja/k8jXaHc7Gf1t/wNbx63l1PNlJiYmJjX8mZmZl5MzMzMzMzM4tpppppppppppppprIPnz77 222222222222221SyQlKU76nWtcEta1rWta1rWta1rWta1rWta1rWta1rWta1rWta5hha1rWta3i 1rWta1KUpSlKUpSlKU/fv379KUpSlKUpSlKXyU5xSlKUpSlKUpSlKUpSlKUpSlKUpSlKfv379+/f v379+/fv379+/f9yzJSlKUtvnz58+fPptuIbbbbbbbbbbbbbm0pSlb9+/fv379+/fv0pSlLbbbbb bbbbbbbbbbbbbbbbbbbbbbbbbbbc2lKUpSlKUpSlKUpSmZVF2Z+/fv3T+aVNLUpSn79KYpKUpSlK UpSlKUpSlKUpSlKUpS23YZJpppppppppppqEaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabfPnz6Kl WmmmmmnLTTS30ytppb58+fPnz58+fPnz58+sam2222222222222221pTJtttttttttttttwrbbbb ba0pSlKUpSlKUpSlKUpSlKUpSlKUpSlKUpSlKUrWpSlKUpSlKUpSlKUpSlKUpSlKUpSlKUpSlKVZ 4ha1rWta1rWta1xC1rWtSlKUpSlKUpSlKUqUUpSlKUpSlKUpU5MRy1rWta1vFrWta1rWta1rWta1 rWuxLWta1rWta1rWta1rWta3tlaWta1rcrWta1rWta1qi5pa1rWta1rWta5Fa1rWta1rWta1rWtc 01NTU1NTU1NOppa1rWta1rUpSlKUpSlKUpT9+/SlKUpSlKUpSlMAvJ9mP0Z+Qfs5/2noFJSUlJSU kNSUlJQKtMhSUkZTY26x4ypcmIG17ms3aGGGGD5Pz6E7hIuIIwZH5wWu/XJwgOg4pEg8AHDw4cOH Dhcw4cGDBgwYIo8RIBfH8rL8Dk/haRFo51zjNreRYpSlKUpSthZZZZZZJ02ZOXA4Pl9UuJjMwMKk rpSlKUpSlKUpTTFHDWgeiYHlVfHnannnnnnnnnnnnnn/PqlooQMoZ9/+NH1fKMfSa7EwB+LHqZ5W 222222222222220ZxW6NtHVGPFlw+p6ku6Z0GGW9H7LHHsfLX+5yIvZLpFd3+8W8E8cePHjlx48e PHjkpKSkoiMsoQQkqK0e+PUABjkgCj/xAbOP3QrUMmGTxEPB/ty+bBOPm/9Bb5XgWo8fzgh8B/+7 2N74q7n7AweB6PQw9f9OvkVXqpLzpIhQOwcF39t7Xdv3Ww+AfUhtZnexpo9AFNFTe60qUB4iKC94 3pZUJFKA0hwd6xM+BcAgX8GHDk84ZCFNgxB+ogMmBs3VpiqCIoKCgTQZGR8HIyMjIxc1uKL1hVN3 gHEwT82AZ2ZOdoFu2o3GcBC2PqlD7TFXDc7HPPcQO9nidgv3MnkMWZAdkgr2Y5YMGJWVlZWVlZWV lZWVlZWVlZXLFLzk3GShhovXyH9ARpezIA+1keice1dw1teWOj8u3eQUHB5ZZZZZZZYYWpT+e3X9 js9u3APwm9UhwXMzh7vBuf0R7s67N2EA0VjWBlgGSIC5O0c8w23ENx7bbbbbbbdjbbiAAA+MZk7k YFpEjZfO/bFX2f25XKPGf0WNM+fOJff1wGXDhw4cMsseSXxlBvh1ocsuOsHJM6cZSWVIeUdxMhix TuJKlHmgGHL+Cettttttttv0pTdIh+/rzA0AD6yWaixXx5/qfvonnU8yErQYDEKgAOtighL/KggI kZ06G+SwlgEhAMZdDQ0MHJZcuXLly5cuXLl32/A5XleHMusS5TAbFNWmoe9+t1qayvf1porZXm+X LeYzantqt1m9tlctue7lnV8sFbxUFcRZhYtaz/hvPklGB7KBdAIIC6hgGIECBAgWeBAgQJWBAgQI EVGAZ/FVeWCMnjSIag+Y5yLDvuXUdHt38YK30+eTNe3yNJq3D3lKUZPRk6KM46FGkEaxB/kd2Som ecHjKhgHj60ov4X37lsXDhueEylxsncx7wOBlTtH1qaU+WPDwH/3H43JSb7mOwyGzh9ZdZ8Tj9Pp ia71vk+x9t2d/HLQHRvE3aV+Hyv41sPusYI4Pt2voJMf8QpBwsaTyHDYKiZa8eFZHM3gFveXr7Jw WXHCuFHdWNy5e6O3nIqb1mtc9G0CfVp7bXa2GtKpLCpljNOthBbv/JEN8kL8KYcsDTClBimAv4ZD IQJ+fn5+12uyT8/Pz8/Pzs/i5qvPY8RUYNJ1zBYvdseKpIiLiuSyBlyXHUQPxhEBgcHYatzXMfWb kRkFs/newjn7jRCHwOzkvc+0nuPX+r4f7Xa/6cwU/+OOQ3D2Ge38+9ItbLLLWTeYbMK2wwcRBDYX t7/+H/E5/cdOt6dk7jh7Gn4evFLZIoy63/GlNsxn6mKfo3H09VZ/8v479ddp7n8F8+KpgiMx/xUT /2Z9sbL+Aopu6jPhypoIa7Fu7o8m2upMjf9DF6KFDu/fC0Zw4E/yMfj55Ee2GTZKhuQWwDRUAxDx zMbNjYrwiiJl6epiC4GYA7m3b+2sX1cw0m5jdFdHmPMaOY2qS6K6JZWKLmkSUiOFToWa5gXVSW9/ J9/x3I81L9T7A/y2lCxX5Larsy7U6DqYiEDrEtLN2WFmihl1++iyO4LjTFczC7DhxpoS+0nKm29a HRgQTc1GrRWGIVYZJ4wzGUp61Ut8d9PGlFF6FuKWSJ+K4gpjMzwmWtJK863BHBt4UMNPT5YBrQEL yy+Q4J4ZV35rMItTW1Q5KnOYl04YhKJZcopuNLpsXqBp0rMAXbj2Zbma7ZZU3D9yxxe6hNdbrlDU EVzaZ1Gou3DRAP2jGziQ9K/SyihyteW4xGtUVLbAan03nnXAzEgr/aXoHM+ua7K1efckZC5MGhLS yNsa07UmZGY8mGvQvYMGPIc0lJd8per1SWCkpKS80lJD7TwV4RR2JCJAC/ZdgCymLAjchjokMAd6 AgMmQH2l+JeUpSlK4lllllirO5ii+92xgu+Mgsf1jRT1aBSDIDo80CqqqqmmmmmmmmmmnjFEXGg3 aPZ+2AkYkkvyyyyyyyyyyyyAPmD80DSopJeOOOOOOOOOOCOOPtxTozEB9Puezpmmmmmmmmmmmlll m1VfP+l1up3YpsMF84GAwlKUpSlKUpSlKU53je+1fyzEKDLfaCJzqx8f5HvGFNKUpSlKUpSlKVH0 HFjIhyZlqJ89aqiiiiiiiiiiiiiiijTHiahokAR529WIclLrhdchNiCC+iY7B9c6UUNSHRQOwTVO +8145ve5h2adb/KtPH+c1ew62YFKfrYeE6glyGgijQ0NDQ0NDQ0NDQ0NDQgAG+MAerPR/zRfPZGA MXyEF7UwS3a+3WCxgrmarH06N+zuse2A57FixYsWLFixYsWLFixYtqJ5qzLdx7QLEXiq3OnZ595o AgsdV2qqqqqqqqqqqqqqAgNQwQKraoLowY+F7IfwsKUqrabp0D4l4vJYFtttttttttttttttqvQ5 hAEOMuTssss+ZuhsBpIHNALA1OKUpSlKUpSlKV1YEJRjPCuUMpDMxNXXXXl7nrNq5Y5ZZZZXXXXX XXXUOSweHXHxEYTLyTLb2222saB3T1lKUpSs3NttttttttgxREOYMRH283xqqqqltwqu9XXXXXXX XXXXXXXhGnVbyyCjMhtTXMhRVVUvl2KFkVXap6qqqqaaaaaaf6ohOlA5qJFzmaaaU3VJupooooTZ TTTHTTTjo+Db7HoFxuDKU66668G03SrilKUpSlKUpSlZdXM72qOYtQbM2z6RYIzmiM2jtttt7Tvq 7Dxe3SXhEh8FDH44Z555+H76zek2b9OERCVF5fjBxTC11114FW9d4vw4JWjHVsHPjXyjGrN7HSml Ds+ka9/lFZMytbT6L4VSPJ9LosqH6SP4P2Th5xMcsXPaogF1k29Zrd+M4h2cQ7snKw4gwu0wrNZL Ijl4JZ8ai5ETGgmqgsGQM9WjO59cFJJ22Pgb/ZXtpk5z7vB4zute1H1iRtO+eiAydWgF0mc5e5su lqIb+EROfhUnmGjx9z4M8Oy0/YjhYWD8IMULwaQrevx13MaByZO373V+WbcWBAD3ED2cTzNgMwaA ZOOIHYdM4W86j86jYb1nUaTgqXdAgMoIOfGnWrHAFr0TLyxZrgL1lIhoZFD7jG35riGOgQiIMTCA cohhiEQbGAYL+TjnfabZnng/swaYEqKKfaophKiiiilSoopIZulCQkK3o5EcXDpwfDZeBIhwnzLN 14fQOBhdB/RtP/vO8rAdK66zIe7vZWHjTsZxJlY5fPMByYsQshPzIMB7nnTgvnxGBBsdXbjycSiE +nJ9UdZyGUYv6jB+7q/wo8hioz4+qQYr+IYcGbN54zLm6oFuprswJ2y3Qy8diTwkMWmw/f0uXebW XzX5zXzXTbcrbRYmrhxIvLIQ8BhyObvuLEI5KAZmJR9zPzc/E7o/F91+D7LJ/kK+nypST6TVrTW0 lrHkP7iXZiUwGt1jlSlTk8GH0+3D0LPtwtfH5rbTBFY+n6PLobu/Lv7ryv2/zt/3n4mnSvV8D0lw fXtXGZ8vzz2Xmffnzcu6LjFa1N7+ZjP41zHRlDPD+s+liZeYgSrI+Zy9U57nm63WnyeXwYj9ZzFN 3N7/R+b+u61kho/MedmvBBPctEQsJOI8u5OK8Yjjr09Xq85iKESsOWQo/z9Wx1PL5nHrvwpowhnj FzMoyMlPPNuvyNldsB6822x436cvLcSa30ICcls3rAh73GsS9n5/UioxyQ200MCsLtKJCCPREXUw NjDjO23e6AWIbKbKXn/ihDxrvqzTHOM3MDyCfyUx5XwPPc/5Xa911PV+A3GWO79LeZodTfRvzPUp vPA7CoryBBXORc1p+HxfVyeszmAGXg3tdat76fQz0hzIopYgfjRtHHw5CKieVHl42hvHC0vHu238 rHSUl1fK8iHEoOuJe2qsMcBXzMHCwT6/Rmo72piPq0uKnZKIp3sT4TInpzdr2e+m/h96BDWXV0EI UwYHtw4YYgMMMDfRlvYsXWR2K2M5e35sC+4bzfQuuzhRcOhemKE8iiTtHdeDuZSkgcdxeXjgUsLD HWmIayaZhFlQAgyGrYzvfy/i0flVGx+aRhYXV29D4sPM/7R1vIvvh3MzfexqPZxGL2vCXGx1lp6H GYOP317+RgoEHcGAkwL9Md2Tb+ynzc7kIICmFtlrqyByomvsaPf4FhMVXX9l5HBBQkIAaAQsin3E rItzzqYYkUUV8MufXmxnBDhrOuN3Qw8b6SCHLyyIElIhggI2cAqSs4DBIg2Spb3icGxvvM+x7zKv sZeMxknmsvtMffMlx8Rzudqq6iz+Y3kCSLDBBizXZCPmcMaraHNo5ts6Gk7gqPqQiHrMRmmIcC3u EEXK6bql9Gqzmy3Xdz/ZykKM5bqBDA6GOP9TpWZKxITbiWlSoP48Dghx/e9myOBEh1OtZPlQMIN8 C9NPtaJZNBvFCu80Pz7LA5eZouB8+Vmiyc6vKljgxfbifNyb9uDcBdKsEdVCsSTX3DcuVsDMwtzN Evwtt+Xza1GLodeo6HYlSuanHbIddM1a88H6KOhH4fY0jsC4noMzJH6r9+RXqarr6XosdL6VNfek 9eyY+F31QFgx5gzEbiBpmCDKcMx+8Tj/T8VXp+rA9Ly/7l+xsJTB67w6Xs1NDhOPkZTK+14/P8zZ y/c+35tp0NJ8O26XclNtN0r9u9G+BGc8BM3KBPFVOQGgBRgCopMNTzX28Bq39jFcPvaCY6H1/PL5 XrZ/sczMbz8b5IShkQIgCAIAjqLH5f65iyyWCvVk3nqa/gWnPff6ltr87yM3G7SOmjGJMi9DHIoj DojIOTAx52CanXAcnjmDrcltoSzRkd5bzJW1iIiaT36GJDnDugQenB23s6tw87TosoQA/lHNg0M5 40IiBWQKu/ZAog/m0+chA6owJkgDBgAiAMSWdu+S3/Uz/O/Dh6BrAQxDaGBl7hqc3wMtudxjO04g gCw9g+9gEM0ZEPlMCRHIQ5j0AD8cfF/GyAWcc/swKS72zo8b/NP8DN+z1LLH5o61Dnue89Stt1pY RQPsIEHeL2zrtFYW4/CfyXOSCDQhC0b8HgXQQF0yAAIfBE/v8i/m/k3/RrZPwMj9w3b+TwqGfsY2 xhqRHmeJEuCEhnb7fmnAIhT2C7UdrkvQ6G49X0mTgfgN1SDEuLXBHa8obxmCuWjdQbthw5g3G2Hf 8iarTLD19c7Wo+7JUTvjhpW+6miJj0G988Xj1un4OdcM1+237d27OYLYLClJ1txKbsMynDCvtJyz /154c6Zc9I2bNmmm26mdtbThYvfTCduGwwyMM8SMKFOiMaROzC3rP83Z/A8b0H3/cgRO2eR+ZcAX isr+LcvhJnU0sJ5ELX8+jl4b/4u5IpwoSAvD/8OA --Apple-Mail=_F55C7A91-4420-4E40-9517-BE01711EE0A4-- From owner-freebsd-hackers@FreeBSD.ORG Mon Sep 19 16:17:09 2011 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id F215F1065676 for ; Mon, 19 Sep 2011 16:17:09 +0000 (UTC) (envelope-from crmartin@sgi.com) Received: from relay.sgi.com (relay3.sgi.com [192.48.152.1]) by mx1.freebsd.org (Postfix) with ESMTP id DD54C8FC16 for ; Mon, 19 Sep 2011 16:17:09 +0000 (UTC) Received: from xmail.sgi.com (pv-excas3-dc21.corp.sgi.com [137.38.102.206]) by relay3.corp.sgi.com (Postfix) with ESMTP id 6768BAC003 for ; Mon, 19 Sep 2011 09:17:09 -0700 (PDT) Received: from [10.3.0.220] (10.3.0.220) by xmail.sgi.com (137.38.102.30) with Microsoft SMTP Server (TLS) id 14.1.289.1; Mon, 19 Sep 2011 11:17:08 -0500 Message-ID: <4E776B03.7030100@sgi.com> Date: Mon, 19 Sep 2011 10:17:07 -0600 From: Charlie Martin User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.21) Gecko/20110831 Lightning/1.0b2 Thunderbird/3.1.13 MIME-Version: 1.0 To: References: <4E73B1E1.6020306@sgi.com> <1316220398.47177.1.camel@rho.emma.line.org> In-Reply-To: <1316220398.47177.1.camel@rho.emma.line.org> Content-Type: text/plain; charset="UTF-8"; format=flowed Content-Transfer-Encoding: 7bit X-Originating-IP: [10.3.0.220] Subject: Re: dtrace in FreeBSD 7.2 X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 19 Sep 2011 16:17:10 -0000 Dude, you say that like it was an option. On 2011-09-16 18:46, Matthias Andree wrote: > Am Freitag, den 16.09.2011, 14:30 -0600 schrieb Charlie Martin: >> I need to add some custom static dtrace probes in 7.2 apps; the online >> documentation refers only to 9 however. Can someone tell me how to >> replace what's done in bsd.dtrace.mk for 7.2? > FreeBSD 7.2 is quite old and wasn't under extended support, hence it is > no longer supported. Consider upgrading. > -- Charles R. (Charlie) Martin Senior Software Engineer SGI logo 1900 Pike Road Longmont, CO 80501 Phone: 303-532-0209 E-Mail: CRMartin@sgi.com Website: www.sgi.com From owner-freebsd-hackers@FreeBSD.ORG Mon Sep 19 16:18:09 2011 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 21D71106564A for ; Mon, 19 Sep 2011 16:18:09 +0000 (UTC) (envelope-from crmartin@sgi.com) Received: from relay.sgi.com (relay1.sgi.com [192.48.179.29]) by mx1.freebsd.org (Postfix) with ESMTP id F36FC8FC16 for ; Mon, 19 Sep 2011 16:18:08 +0000 (UTC) Received: from xmail.sgi.com (pv-excas3-dc21-nlb.corp.sgi.com [137.38.102.207]) by relay1.corp.sgi.com (Postfix) with ESMTP id 7B6B38F8040; Mon, 19 Sep 2011 09:18:08 -0700 (PDT) Received: from [10.3.0.220] (10.3.0.220) by xmail.sgi.com (137.38.102.30) with Microsoft SMTP Server (TLS) id 14.1.289.1; Mon, 19 Sep 2011 11:18:08 -0500 Message-ID: <4E776B3F.4060902@sgi.com> Date: Mon, 19 Sep 2011 10:18:07 -0600 From: Charlie Martin User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.21) Gecko/20110831 Lightning/1.0b2 Thunderbird/3.1.13 MIME-Version: 1.0 To: Julian Elischer References: <4E73B1E1.6020306@sgi.com> <4E742CC8.1070900@freebsd.org> In-Reply-To: <4E742CC8.1070900@freebsd.org> Content-Type: text/plain; charset="ISO-8859-1"; format=flowed Content-Transfer-Encoding: 7bit X-Originating-IP: [10.3.0.220] Cc: freebsd-hackers@freebsd.org Subject: Re: dtrace in FreeBSD 7.2 X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 19 Sep 2011 16:18:09 -0000 Thanks On 2011-09-16 23:14, Julian Elischer wrote: > On 9/16/11 1:30 PM, Charlie Martin wrote: >> I need to add some custom static dtrace probes in 7.2 apps; the >> online documentation refers only to 9 however. Can someone tell me >> how to replace what's done in bsd.dtrace.mk for 7.2? > > I' am not sure that user space dtrace suport was available in 7.2.. My > memory is that it came in 8.x but I'm not certain. > >> >> Thanks >> >> Charlie > > -- Charles R. (Charlie) Martin Senior Software Engineer SGI logo 1900 Pike Road Longmont, CO 80501 Phone: 303-532-0209 E-Mail: CRMartin@sgi.com Website: www.sgi.com From owner-freebsd-hackers@FreeBSD.ORG Mon Sep 19 16:32:20 2011 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 47D911065673 for ; Mon, 19 Sep 2011 16:32:20 +0000 (UTC) (envelope-from dieterbsd@engineer.com) Received: from mailout-us.gmx.com (mailout-us.gmx.com [74.208.5.67]) by mx1.freebsd.org (Postfix) with SMTP id E35908FC13 for ; Mon, 19 Sep 2011 16:32:19 +0000 (UTC) Received: (qmail 23976 invoked by uid 0); 19 Sep 2011 16:32:18 -0000 Received: from 67.206.187.119 by rms-us018 with HTTP Content-Type: text/plain; charset="utf-8" Date: Mon, 19 Sep 2011 12:32:14 -0400 From: "Dieter BSD" Message-ID: <20110919163215.212610@gmx.com> MIME-Version: 1.0 To: freebsd-hackers@freebsd.org X-Authenticated: #74169980 X-Flags: 0001 X-Mailer: GMX.com Web Mailer x-registered: 0 Content-Transfer-Encoding: 8bit X-GMX-UID: vVdPezEgyH6nIQ7MAzNLbxBPUzc4chEg Subject: Re: checksum offload X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 19 Sep 2011 16:32:20 -0000 >>> The data sheet for intel 82576 advertises IP TX/RX checksum offload >>> but the driver does not set CSUM_IP in ifp->if_hwassist. Does this mean >>> that driver (and chip) do not support IP TX checksum offload or the >>> support for TX is not yet included in the driver? >> >> The first question is "is checksum offload a good idea?" >> There is less protection against errors. > > This assumes firmware flaws, right? Albeit, it also does confuse some > software like tcpdump. "Unfortunately lots of high performance people use checksum offload which removes much of the end to end protection"      Alan Cox http://kerneltrap.org/Linux/Data_Errors_During_Drive_Communication Bugs in the hardware/firmware/software are not required to have a problem, but if present would make things even worse. From owner-freebsd-hackers@FreeBSD.ORG Mon Sep 19 16:37:54 2011 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id BC8241065673 for ; Mon, 19 Sep 2011 16:37:54 +0000 (UTC) (envelope-from julian@freebsd.org) Received: from vps1.elischer.org (vps1.elischer.org [204.109.63.16]) by mx1.freebsd.org (Postfix) with ESMTP id 90ECE8FC13 for ; Mon, 19 Sep 2011 16:37:54 +0000 (UTC) Received: from julian-mac.elischer.org (home-nat.elischer.org [67.100.89.137]) (authenticated bits=0) by vps1.elischer.org (8.14.4/8.14.4) with ESMTP id p8JGboGU068140 (version=TLSv1/SSLv3 cipher=DHE-RSA-CAMELLIA256-SHA bits=256 verify=NO); Mon, 19 Sep 2011 09:37:53 -0700 (PDT) (envelope-from julian@freebsd.org) Message-ID: <4E777006.8040907@freebsd.org> Date: Mon, 19 Sep 2011 09:38:30 -0700 From: Julian Elischer User-Agent: Mozilla/5.0 (Macintosh; U; PPC Mac OS X 10.4; en-US; rv:1.9.2.22) Gecko/20110902 Thunderbird/3.1.14 MIME-Version: 1.0 To: Charlie Martin References: <4E73B1E1.6020306@sgi.com> <1316220398.47177.1.camel@rho.emma.line.org> <4E776B03.7030100@sgi.com> In-Reply-To: <4E776B03.7030100@sgi.com> Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit Cc: freebsd-hackers@freebsd.org Subject: Re: dtrace in FreeBSD 7.2 X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 19 Sep 2011 16:37:54 -0000 On 9/19/11 9:17 AM, Charlie Martin wrote: > Dude, you say that like it was an option. It's understood about the realities of commercial decisions, however, if you really want to trace APPS that means user space dtrace and 7.2 just doesn't have the hooks to do non-kernel dtrace. As a side note, realize that Dtrace support in FreeBSD had a serious problem a couple of years ago when the lead developer suddenly dropped dead (Very literally, to out great sadness), and it took a while for alternative resources to fill the gap. > > On 2011-09-16 18:46, Matthias Andree wrote: >> Am Freitag, den 16.09.2011, 14:30 -0600 schrieb Charlie Martin: >>> I need to add some custom static dtrace probes in 7.2 apps; the >>> online >>> documentation refers only to 9 however. Can someone tell me how to >>> replace what's done in bsd.dtrace.mk for 7.2? >> FreeBSD 7.2 is quite old and wasn't under extended support, hence >> it is >> no longer supported. Consider upgrading. >> From owner-freebsd-hackers@FreeBSD.ORG Mon Sep 19 16:48:09 2011 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 6B24E106566B; Mon, 19 Sep 2011 16:48:09 +0000 (UTC) (envelope-from crmartin@sgi.com) Received: from relay.sgi.com (relay2.sgi.com [192.48.179.30]) by mx1.freebsd.org (Postfix) with ESMTP id 485668FC18; Mon, 19 Sep 2011 16:48:09 +0000 (UTC) Received: from xmail.sgi.com (pv-excas3-dc21-nlb.corp.sgi.com [137.38.102.207]) by relay2.corp.sgi.com (Postfix) with ESMTP id 97502304039; Mon, 19 Sep 2011 09:48:08 -0700 (PDT) Received: from [10.3.0.220] (10.3.0.220) by xmail.sgi.com (137.38.102.30) with Microsoft SMTP Server (TLS) id 14.1.289.1; Mon, 19 Sep 2011 11:48:08 -0500 Message-ID: <4E777247.3090904@sgi.com> Date: Mon, 19 Sep 2011 10:48:07 -0600 From: Charlie Martin User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.21) Gecko/20110831 Lightning/1.0b2 Thunderbird/3.1.13 MIME-Version: 1.0 To: Julian Elischer References: <4E73B1E1.6020306@sgi.com> <1316220398.47177.1.camel@rho.emma.line.org> <4E776B03.7030100@sgi.com> <4E777006.8040907@freebsd.org> In-Reply-To: <4E777006.8040907@freebsd.org> Content-Type: text/plain; charset="UTF-8"; format=flowed Content-Transfer-Encoding: 7bit X-Originating-IP: [10.3.0.220] Cc: freebsd-hackers@freebsd.org Subject: Re: dtrace in FreeBSD 7.2 X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 19 Sep 2011 16:48:09 -0000 On 2011-09-19 10:38, Julian Elischer wrote: > On 9/19/11 9:17 AM, Charlie Martin wrote: >> Dude, you say that like it was an option. > > It's understood about the realities of commercial decisions, however, > if you really want to trace APPS > that means user space dtrace and 7.2 just doesn't have the hooks to > do non-kernel dtrace. I think in fact I want to add probes in kernel space; I was trying to play with it in user space just to avoid a lot of test kernels. > > As a side note, realize that Dtrace support in FreeBSD had a serious > problem a couple of years ago > when the lead developer suddenly dropped dead (Very literally, to out > great sadness), and it took > a while for alternative resources to fill the gap. I bet. I'd kind of gotten that idea but don't know the history; I was working in Solaris until recently. > >> >> On 2011-09-16 18:46, Matthias Andree wrote: >>> Am Freitag, den 16.09.2011, 14:30 -0600 schrieb Charlie Martin: >>>> I need to add some custom static dtrace probes in 7.2 apps; the online >>>> documentation refers only to 9 however. Can someone tell me how to >>>> replace what's done in bsd.dtrace.mk for 7.2? >>> FreeBSD 7.2 is quite old and wasn't under extended support, hence it is >>> no longer supported. Consider upgrading. >>> > > -- Charles R. (Charlie) Martin Senior Software Engineer SGI logo 1900 Pike Road Longmont, CO 80501 Phone: 303-532-0209 E-Mail: CRMartin@sgi.com Website: www.sgi.com From owner-freebsd-hackers@FreeBSD.ORG Mon Sep 19 16:59:21 2011 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 7FF09106564A; Mon, 19 Sep 2011 16:59:21 +0000 (UTC) (envelope-from pyunyh@gmail.com) Received: from mail-iy0-f182.google.com (mail-iy0-f182.google.com [209.85.210.182]) by mx1.freebsd.org (Postfix) with ESMTP id 21C5C8FC13; Mon, 19 Sep 2011 16:59:21 +0000 (UTC) Received: by iadk27 with SMTP id k27so8665010iad.13 for ; Mon, 19 Sep 2011 09:59:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=from:date:to:cc:subject:message-id:reply-to:references:mime-version :content-type:content-disposition:in-reply-to:user-agent; bh=jT1fcJroGTrjUuPTrNeGabuPhWmjhOVx59dpaVyhEJg=; b=UNj5qqOYwwwWjLhYA88rS8/TuU34a/BtdMoLlpx2D1DiU9JjYl0JZ7xQe5NzM9jW8i 0C0s72DLP9geCq00Gj9RSYhTcuUySacRN4Ltb6GDv2vxavd8B4DlwOEXboxCF5+pstXn kcbL/d1PMxngaFqfo085ggrSYDbvH3CH5RIes= Received: by 10.231.63.136 with SMTP id b8mr4498229ibi.43.1316451560571; Mon, 19 Sep 2011 09:59:20 -0700 (PDT) Received: from pyunyh@gmail.com ([174.35.1.224]) by mx.google.com with ESMTPS id z11sm26459737iba.6.2011.09.19.09.59.16 (version=TLSv1/SSLv3 cipher=OTHER); Mon, 19 Sep 2011 09:59:18 -0700 (PDT) Received: by pyunyh@gmail.com (sSMTP sendmail emulation); Mon, 19 Sep 2011 09:59:20 -0700 From: YongHyeon PYUN Date: Mon, 19 Sep 2011 09:59:20 -0700 To: Arnaud Lacombe Message-ID: <20110919165920.GA4202@michelle.cdnetworks.com> References: <20110917203218.GC13993@michelle.cdnetworks.com> <20110918210647.GA8930@onelab2.iet.unipi.it> <20110919020131.GA11657@onelab2.iet.unipi.it> <4E76E5B9.9080301@sepehrs.com> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.4.2.3i Cc: Adrian Chadd , freebsd-hackers@freebsd.org, Hooman Fazaeli , Jack Vogel , jfv@freebsd.org, Luigi Rizzo Subject: Re: intel checksum offload X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list Reply-To: pyunyh@gmail.com List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 19 Sep 2011 16:59:21 -0000 On Mon, Sep 19, 2011 at 10:17:22AM -0400, Arnaud Lacombe wrote: > Hi, > > On Mon, Sep 19, 2011 at 5:28 AM, Adrian Chadd wrote: > > Arnaud (and others), > > > > Liaising with vendors is not an easy task. The reason why Intel (and > > other vendors) don't supply detailed history and reasoning for their > > development efforts is that their engineers are likely tasked with > > "making it work" versus "writing lots of stuff down for public > > release." In some instances, the vendor support of FreeBSD (and "free" > > open source in general) is done as a side-project by some of the > > engineers inside the company. > > > > So in this case, you may find that Jack and the other engineers at > > Intel just don't have the time or resources to dedicate the kinds of > > feedback and support you seem to be after. He and others likely have a > > huge set of tasks to do at work and none of them officially include > > "support FreeBSD/Linux developers by providing detailed feedback and > > assistance." So whenever Jack pops up to help out, he's likely doing > > it in his spare time. :-) > > > Yes, and he seems to really like to waste his spare time by repeating > me for two months to increase `kern.ipc.nmbclusters' to fix issue I > was seeing, when the code was clearly buggy, even when I sent him > patchs fixing issues. > If you think you encountered a driver bug, could you share it with us? I didn't closely follow em(4)/lem(4)/igb(4) changes for a long time so I'm not sure whether I can come up with reasonable fix for the issue but I may be able to help you. > That's sure a very efficient way of managing time. > > - Arnaud > > > Developers can and will disable or remove functionality which is > > problematic because they don't have the time or resources to support > > it. Users may wish to turn on unsupported features and then will > > complain loudly when they don't work; even giving up and moving to > > another piece of equipment because of perceived issues. I agree that > > it would be nice if the developers included _all_ features, > > unsupported or not, so that developers can choose to work on them if > > they wish. It however is a trade-off between trying to provide > > developers with more useful things to tinker with and not increasing > > support load from users (and other developers) who seek to use > > incomplete features. > > > > I hope this helps. > > > > > > Adrian > > From owner-freebsd-hackers@FreeBSD.ORG Mon Sep 19 17:47:31 2011 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 9008B106564A; Mon, 19 Sep 2011 17:47:31 +0000 (UTC) (envelope-from lacombar@gmail.com) Received: from mail-ww0-f50.google.com (mail-ww0-f50.google.com [74.125.82.50]) by mx1.freebsd.org (Postfix) with ESMTP id BCFA18FC16; Mon, 19 Sep 2011 17:47:30 +0000 (UTC) Received: by wwe3 with SMTP id 3so7793997wwe.31 for ; Mon, 19 Sep 2011 10:47:29 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=mime-version:in-reply-to:references:date:message-id:subject:from:to :cc:content-type; bh=CMiY0Iolp27w33Kbt/bAJuZgPdM87SgugvCEYZJUE44=; b=p/I+LH5yXlS8Bty1mags0kzQ76dwtfkeKYK7lB+vqL1AfkoZcR4mFuoN1CDMClwSMH jv6yTG55CljrSiMY1BhUxc41ONDLjYiab7EGe4+s3+7T1EIi5hWPXrZmItSUkJ2bprLH oWzPCqJ7QP6ggnyJHSC4f5jdRZrVW+v8awg+M= MIME-Version: 1.0 Received: by 10.216.172.75 with SMTP id s53mr3024029wel.38.1316454449053; Mon, 19 Sep 2011 10:47:29 -0700 (PDT) Received: by 10.180.95.169 with HTTP; Mon, 19 Sep 2011 10:47:29 -0700 (PDT) In-Reply-To: <20110919165920.GA4202@michelle.cdnetworks.com> References: <20110917203218.GC13993@michelle.cdnetworks.com> <20110918210647.GA8930@onelab2.iet.unipi.it> <20110919020131.GA11657@onelab2.iet.unipi.it> <4E76E5B9.9080301@sepehrs.com> <20110919165920.GA4202@michelle.cdnetworks.com> Date: Mon, 19 Sep 2011 13:47:29 -0400 Message-ID: From: Arnaud Lacombe To: pyunyh@gmail.com Content-Type: text/plain; charset=ISO-8859-1 Cc: Adrian Chadd , freebsd-hackers@freebsd.org, Hooman Fazaeli , Jack Vogel , jfv@freebsd.org, Luigi Rizzo Subject: Re: intel checksum offload X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 19 Sep 2011 17:47:31 -0000 Hi, On Mon, Sep 19, 2011 at 12:59 PM, YongHyeon PYUN wrote: > On Mon, Sep 19, 2011 at 10:17:22AM -0400, Arnaud Lacombe wrote: >> Hi, >> >> On Mon, Sep 19, 2011 at 5:28 AM, Adrian Chadd wrote: >> > Arnaud (and others), >> > >> > Liaising with vendors is not an easy task. The reason why Intel (and >> > other vendors) don't supply detailed history and reasoning for their >> > development efforts is that their engineers are likely tasked with >> > "making it work" versus "writing lots of stuff down for public >> > release." In some instances, the vendor support of FreeBSD (and "free" >> > open source in general) is done as a side-project by some of the >> > engineers inside the company. >> > >> > So in this case, you may find that Jack and the other engineers at >> > Intel just don't have the time or resources to dedicate the kinds of >> > feedback and support you seem to be after. He and others likely have a >> > huge set of tasks to do at work and none of them officially include >> > "support FreeBSD/Linux developers by providing detailed feedback and >> > assistance." So whenever Jack pops up to help out, he's likely doing >> > it in his spare time. :-) >> > >> Yes, and he seems to really like to waste his spare time by repeating >> me for two months to increase `kern.ipc.nmbclusters' to fix issue I >> was seeing, when the code was clearly buggy, even when I sent him >> patchs fixing issues. >> > > If you think you encountered a driver bug, could you share it with > us? I didn't closely follow em(4)/lem(4)/igb(4) changes for a long > time so I'm not sure whether I can come up with reasonable fix for > the issue but I may be able to help you. > They ended up being fixed, thanks :-) Now, up until next week, we were struggle on the mbuf corruption I reported on freebsd-net@, but I do not think it is a driver issue per-se. - Arnaud From owner-freebsd-hackers@FreeBSD.ORG Tue Sep 20 05:26:15 2011 Return-Path: Delivered-To: hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 9B5EF1065672; Tue, 20 Sep 2011 05:26:15 +0000 (UTC) (envelope-from lacombar@gmail.com) Received: from mail-wy0-f182.google.com (mail-wy0-f182.google.com [74.125.82.182]) by mx1.freebsd.org (Postfix) with ESMTP id 10D328FC13; Tue, 20 Sep 2011 05:26:14 +0000 (UTC) Received: by wyh15 with SMTP id 15so180078wyh.13 for ; Mon, 19 Sep 2011 22:26:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=mime-version:in-reply-to:references:date:message-id:subject:from:to :cc:content-type:content-transfer-encoding; bh=BU723t4KWqVgpnKQDdl4Fzz6z4uHK+UexplzlfGp2PI=; b=oUdpgY9L9ZKmkTQ+AF/1YO8r0PQNEtZmbfWX8vPFW70Hx8JGGhOpMDyDTXDpIB2MEy fQ4AR3XFi/55Bp0hqtIqhtBol2+MAvRte2uKFR3F4ugXEM5PJXkqwWEunUdj3By7A/6O M957sACsSwgLxROqSUeoalwPiLAWBDQMj8Y+g= MIME-Version: 1.0 Received: by 10.227.175.77 with SMTP id w13mr338936wbz.53.1316494689846; Mon, 19 Sep 2011 21:58:09 -0700 (PDT) Received: by 10.180.95.169 with HTTP; Mon, 19 Sep 2011 21:58:09 -0700 (PDT) In-Reply-To: <4E75B67E.1000802@FreeBSD.org> References: <4E712D11.7040202@FreeBSD.org> <4E75B67E.1000802@FreeBSD.org> Date: Tue, 20 Sep 2011 00:58:09 -0400 Message-ID: From: Arnaud Lacombe To: Andriy Gapon Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable Cc: hackers@freebsd.org, Fabien Thomas Subject: Re: my git development snapshot(s) X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 20 Sep 2011 05:26:15 -0000 Hi, [adding Fabien Thomas to the CC: list] On Sun, Sep 18, 2011 at 5:14 AM, Andriy Gapon wrote: > > Just decided to follow the global trends and trying to throw all of my > local/private changes at you in hope that the "crowd-sourcing magic" migh= t > somehow happen :-) =A0This seems definitely easier than carefully produci= ng the > patch files and keeping them up-to-date. > > So, my newly cloned gitorious repository: > https://gitorious.org/~avg/freebsd/avgbsd > I see that this tree is a clone of: https://gitorious.org/freebsd/freebsd One issue I've got with that tree, is that it is not usable for any serious work because of the following: % git merge-base origin/master origin/svn_stable_8 % echo $? 1 The whole FreeBSD 8.x branch is on its own. However: % git merge-base origin/master origin/svn_stable_7 bdad8b50a25980737a8e00047f41fc1e588fc9e5 % git show bdad8b50a25980737a8e00047f41fc1e588fc9e5 commit bdad8b50a25980737a8e00047f41fc1e588fc9e5 Author: obrien Date: Wed Oct 10 16:59:14 2007 +0000 For 7.0 make the shared lib "version" '3'. Approved by: re(kensmith) git-svn-id: svn://svn.freebsd.org/base/head@172505 ccf9f872-aa2e-dd11-9fc8-001c23d0bc1f So something should have gone wrong when the mirror was created with the 8-STABLE branch as its root commit is: commit 47c9e1cbe6e19ab62a112f67fa4baf081aa213be Author: jfv Date: Fri Sep 4 22:37:03 2009 +0000 This patch seperates the control of header split from LRO (which it was previously dependent on), LRO gets turned off when bridging but its been found that header split is still a performance win in that cas= e. Secondly, there was some interface specific control in stats code that has been missing, and a logic error that resulted in bogus reporting. Thanks to Manish and John of LineRateSystems for the report and help in this code. Approved by: re git-svn-id: http://svn.freebsd.org/base/stable/8@196843 ccf9f872-aa2e-dd11-9fc8-001c23d0bc1f which should rather be: commit d4a6bb6e18d2601fe08d76be4610ae4a303574b2 Author: ache Date: Fri Jan 21 13:31:02 2005 +0000 Whitespace/style tweaking of prev. commit. Noted by: bde git-svn-id: svn://svn.freebsd.org/base/head@140577 ccf9f872-aa2e-dd11-9fc8-001c23d0bc1f Regards, - Arnaud > And the first branch of interest: > https://gitorious.org/~avg/freebsd/avgbsd/commits/devel-20110915 > > This is a snapshot of almost all of my local changes to the FreeBSD src t= ree. > Please note that the branch is not intended to be public in the git sense= . =A0That > is, there will be no linear history - I periodically rebase my changes on= top of > the svn head and also frequently reshuffle/merge/split commits. > The snapshot is not tidied up, there are quite a few commits that should = be > merged into other commits, some commit messages are not accurate/pretty, = etc. > The older the commits, the more mature they are supposed to be. > > Based on the above, no new commits are expected to this snapshot branch. > I will produce new snapshot branches from time to time. > > I am posting this information to this list initially, later I plan to sha= re the > code with the wider audience e.g. via hackers@. > > P.S. This code sharing is made easier for me by git, Gitorious and "git r= ebase > --onto" in particular. =A0Thanks to Fabien Thomas for the initial FreeBSD= clone > repository at Gitorious! > > -- > Andriy Gapon > _______________________________________________ > freebsd-hackers@freebsd.org mailing list > http://lists.freebsd.org/mailman/listinfo/freebsd-hackers > To unsubscribe, send any mail to "freebsd-hackers-unsubscribe@freebsd.org= " > From owner-freebsd-hackers@FreeBSD.ORG Tue Sep 20 09:32:48 2011 Return-Path: Delivered-To: hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id A82A51065675; Tue, 20 Sep 2011 09:32:48 +0000 (UTC) (envelope-from fabien.thomas@netasq.com) Received: from work.netasq.com (mars.netasq.com [91.212.116.3]) by mx1.freebsd.org (Postfix) with ESMTP id EBF4F8FC14; Tue, 20 Sep 2011 09:32:47 +0000 (UTC) Received: from [10.2.1.1] (unknown [10.2.1.1]) by work.netasq.com (Postfix) with ESMTPSA id 9A72674002C; Tue, 20 Sep 2011 11:32:02 +0200 (CEST) Mime-Version: 1.0 (Apple Message framework v1084) Content-Type: text/plain; charset=us-ascii From: Fabien Thomas In-Reply-To: Date: Tue, 20 Sep 2011 11:32:46 +0200 Content-Transfer-Encoding: quoted-printable Message-Id: <93879B90-3D40-4D88-B13C-921F2C5BB135@netasq.com> References: <4E712D11.7040202@FreeBSD.org> <4E75B67E.1000802@FreeBSD.org> To: Arnaud Lacombe X-Mailer: Apple Mail (2.1084) Cc: hackers@freebsd.org, Andriy Gapon Subject: Re: my git development snapshot(s) X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list Reply-To: Fabien Thomas List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 20 Sep 2011 09:32:48 -0000 On Sep 20, 2011, at 6:58 AM, Arnaud Lacombe wrote: > Hi, >=20 > [adding Fabien Thomas to the CC: list] >=20 > On Sun, Sep 18, 2011 at 5:14 AM, Andriy Gapon wrote: >>=20 >> Just decided to follow the global trends and trying to throw all of = my >> local/private changes at you in hope that the "crowd-sourcing magic" = might >> somehow happen :-) This seems definitely easier than carefully = producing the >> patch files and keeping them up-to-date. >>=20 >> So, my newly cloned gitorious repository: >> https://gitorious.org/~avg/freebsd/avgbsd >>=20 > I see that this tree is a clone of: >=20 > https://gitorious.org/freebsd/freebsd >=20 > One issue I've got with that tree, is that it is not usable for any > serious work because of the following: I'm working seriously with it :D >=20 > % git merge-base origin/master origin/svn_stable_8 > % echo $? > 1 >=20 That's strange: # git merge-base origin/master origin/svn_stable_8 08b4e774d45547b6476807eacbfc1d2b5aab02e2 I've tried from fresh fresh clone with same result. > The whole FreeBSD 8.x branch is on its own. However: >=20 > % git merge-base origin/master origin/svn_stable_7 > bdad8b50a25980737a8e00047f41fc1e588fc9e5 >=20 > % git show bdad8b50a25980737a8e00047f41fc1e588fc9e5 > commit bdad8b50a25980737a8e00047f41fc1e588fc9e5 > Author: obrien > Date: Wed Oct 10 16:59:14 2007 +0000 >=20 > For 7.0 make the shared lib "version" '3'. > Approved by: re(kensmith) >=20 > git-svn-id: svn://svn.freebsd.org/base/head@172505 > ccf9f872-aa2e-dd11-9fc8-001c23d0bc1f >=20 > So something should have gone wrong when the mirror was created with > the 8-STABLE branch as its root commit is: # git log origin/svn_stable_8 commit 46c8a8db6dae5c885c7c1de5d39904566cc19685 Author: ume Date: Sun Sep 13 11:34:33 2009 +0000 MFC r196475: - Add AS lookup functionality to traceroute6(8) as well. - Support for IPv6 transport for AS lookup. - Introduce $RA_SERVER to set whois server. - Support for 4 byte ASN. - ANSIfy function declaration in as.c. Approved by: re (kib) git-svn-id: http://svn.freebsd.org/base/stable/8@197158 = ccf9f872-aa2e-dd11-9fc8-001c23d0bc1f >=20 > commit 47c9e1cbe6e19ab62a112f67fa4baf081aa213be > Author: jfv > Date: Fri Sep 4 22:37:03 2009 +0000 >=20 > This patch seperates the control of header split from LRO (which it > was previously dependent on), LRO gets turned off when bridging but > its been found that header split is still a performance win in that = case. >=20 > Secondly, there was some interface specific control in stats code = that > has been missing, and a logic error that resulted in bogus = reporting. > Thanks to Manish and John of LineRateSystems for the report and help = in > this code. >=20 > Approved by: re >=20 > git-svn-id: http://svn.freebsd.org/base/stable/8@196843 > ccf9f872-aa2e-dd11-9fc8-001c23d0bc1f >=20 > which should rather be: >=20 > commit d4a6bb6e18d2601fe08d76be4610ae4a303574b2 > Author: ache > Date: Fri Jan 21 13:31:02 2005 +0000 >=20 > Whitespace/style tweaking of prev. commit. >=20 > Noted by: bde >=20 > git-svn-id: svn://svn.freebsd.org/base/head@140577 > ccf9f872-aa2e-dd11-9fc8-001c23d0bc1f >=20 >=20 > Regards, > - Arnaud >=20 >> And the first branch of interest: >> https://gitorious.org/~avg/freebsd/avgbsd/commits/devel-20110915 >>=20 >> This is a snapshot of almost all of my local changes to the FreeBSD = src tree. >> Please note that the branch is not intended to be public in the git = sense. That >> is, there will be no linear history - I periodically rebase my = changes on top of >> the svn head and also frequently reshuffle/merge/split commits. >> The snapshot is not tidied up, there are quite a few commits that = should be >> merged into other commits, some commit messages are not = accurate/pretty, etc. >> The older the commits, the more mature they are supposed to be. >>=20 >> Based on the above, no new commits are expected to this snapshot = branch. >> I will produce new snapshot branches from time to time. >>=20 >> I am posting this information to this list initially, later I plan to = share the >> code with the wider audience e.g. via hackers@. >>=20 >> P.S. This code sharing is made easier for me by git, Gitorious and = "git rebase >> --onto" in particular. Thanks to Fabien Thomas for the initial = FreeBSD clone >> repository at Gitorious! >>=20 >> -- >> Andriy Gapon >> _______________________________________________ >> freebsd-hackers@freebsd.org mailing list >> http://lists.freebsd.org/mailman/listinfo/freebsd-hackers >> To unsubscribe, send any mail to = "freebsd-hackers-unsubscribe@freebsd.org" >>=20 -- Fabien Thomas From owner-freebsd-hackers@FreeBSD.ORG Tue Sep 20 13:34:32 2011 Return-Path: Delivered-To: hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 73408106566B; Tue, 20 Sep 2011 13:34:32 +0000 (UTC) (envelope-from fabien.thomas@netasq.com) Received: from work.netasq.com (mars.netasq.com [91.212.116.3]) by mx1.freebsd.org (Postfix) with ESMTP id D9F2B8FC08; Tue, 20 Sep 2011 13:34:31 +0000 (UTC) Received: from [10.2.1.1] (unknown [10.2.1.1]) by work.netasq.com (Postfix) with ESMTPSA id F3B18740021; Tue, 20 Sep 2011 15:33:45 +0200 (CEST) Mime-Version: 1.0 (Apple Message framework v1084) Content-Type: text/plain; charset=us-ascii From: Fabien Thomas In-Reply-To: Date: Tue, 20 Sep 2011 15:34:29 +0200 Content-Transfer-Encoding: 7bit Message-Id: References: <4E712D11.7040202@FreeBSD.org> <4E75B67E.1000802@FreeBSD.org> To: Arnaud Lacombe X-Mailer: Apple Mail (2.1084) Cc: hackers@freebsd.org, Andriy Gapon Subject: Re: my git development snapshot(s) X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list Reply-To: Fabien Thomas List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 20 Sep 2011 13:34:32 -0000 git merge-base upstream/svn_trunk upstream/svn_stable_8 does not work. it seems that at some point in time it was working. (upstream = live tree, origin = my sandbox) I will need to dig a little more to understand the problem. Regards, Fabien From owner-freebsd-hackers@FreeBSD.ORG Tue Sep 20 14:11:37 2011 Return-Path: Delivered-To: hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 19BD41065792; Tue, 20 Sep 2011 14:11:37 +0000 (UTC) (envelope-from lacombar@gmail.com) Received: from mail-ww0-f50.google.com (mail-ww0-f50.google.com [74.125.82.50]) by mx1.freebsd.org (Postfix) with ESMTP id 3F8298FC17; Tue, 20 Sep 2011 14:11:35 +0000 (UTC) Received: by wwe3 with SMTP id 3so778525wwe.31 for ; Tue, 20 Sep 2011 07:11:35 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=mime-version:in-reply-to:references:date:message-id:subject:from:to :cc:content-type:content-transfer-encoding; bh=Se4ZEbU5oMs6TgbrZjJQ4h8nORBFZHwiS9V1MWQ1Mps=; b=gKeKVbZzToSvv9EJpMWnJSlTOC9iekXiV2VlXiC8gHqTvopUakUXTfEC7iqmQoC3BF Efro1C8wityiODaME9pw09fGuV13qCLMStFzFEKKmzJdTqPv0cpJuhWWgngE0hcSzdpN unS70nL89nlj967pzQYCXjoKjYwIfTSL0MCHQ= MIME-Version: 1.0 Received: by 10.216.172.75 with SMTP id s53mr906690wel.38.1316527894900; Tue, 20 Sep 2011 07:11:34 -0700 (PDT) Received: by 10.180.95.169 with HTTP; Tue, 20 Sep 2011 07:11:34 -0700 (PDT) In-Reply-To: <3C53D349-6629-48FC-A8EF-84C3B2C13617@netasq.com> References: <4E712D11.7040202@FreeBSD.org> <4E75B67E.1000802@FreeBSD.org> <3C53D349-6629-48FC-A8EF-84C3B2C13617@netasq.com> Date: Tue, 20 Sep 2011 10:11:34 -0400 Message-ID: From: Arnaud Lacombe To: Fabien Thomas Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable Cc: hackers@freebsd.org, Fabien Thomas , Andriy Gapon Subject: Re: my git development snapshot(s) X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 20 Sep 2011 14:11:37 -0000 Hi, On Tue, Sep 20, 2011 at 4:58 AM, Fabien Thomas w= rote: > > On Sep 20, 2011, at 6:58 AM, Arnaud Lacombe wrote: > >> Hi, >> >> [adding Fabien Thomas to the CC: list] >> >> On Sun, Sep 18, 2011 at 5:14 AM, Andriy Gapon wrote: >>> >>> Just decided to follow the global trends and trying to throw all of my >>> local/private changes at you in hope that the "crowd-sourcing magic" mi= ght >>> somehow happen :-) =A0This seems definitely easier than carefully produ= cing the >>> patch files and keeping them up-to-date. >>> >>> So, my newly cloned gitorious repository: >>> https://gitorious.org/~avg/freebsd/avgbsd >>> >> I see that this tree is a clone of: >> >> https://gitorious.org/freebsd/freebsd >> >> One issue I've got with that tree, is that it is not usable for any >> serious work because of the following: > > I'm working seriously with it :D > he, I guess we do not have the same kind of workflow :) In my case, I was trying a tree from 7-STABLE into 8-STABLE. >> >> % git merge-base origin/master origin/svn_stable_8 >> % echo $? >> 1 >> > That's strange: > # git merge-base origin/master origin/svn_stable_8 > 08b4e774d45547b6476807eacbfc1d2b5aab02e2 > > I've tried from fresh fresh clone with same result. > You will see this issue online too: https://gitorious.org/freebsd/freebsd/commits/svn_release_8_0_0?page=3D8 https://gitorious.org/freebsd/freebsd/commits/svn_release_8_1_0?page=3D82 https://gitorious.org/freebsd/freebsd/commits/svn_releng_8_0?page=3D8 https://gitorious.org/freebsd/freebsd/commits/svn_releng_8_1?page=3D82 There is no history before commit 47c9e1c. https://gitorious.org/freebsd/freebsd/commits/svn_releng_8_2?page=3D3 There is no history before commit aca2adc. Now, compare with 7.x branches: https://gitorious.org/freebsd/freebsd/commits/svn_releng_7_0?page=3D776 https://gitorious.org/freebsd/freebsd/commits/svn_releng_7_1?page=3D858 https://gitorious.org/freebsd/freebsd/commits/svn_releng_7_3?page=3D928 https://gitorious.org/freebsd/freebsd/commits/svn_releng_7_4?page=3D963 All have exactly the same root commit: d4a6bb6. I'm trying a new clone now, I'll let you know the result... - Arnaud >> The whole FreeBSD 8.x branch is on its own. However: >> >> % git merge-base origin/master origin/svn_stable_7 >> bdad8b50a25980737a8e00047f41fc1e588fc9e5 >> >> % git show bdad8b50a25980737a8e00047f41fc1e588fc9e5 >> commit bdad8b50a25980737a8e00047f41fc1e588fc9e5 >> Author: obrien >> Date: =A0 Wed Oct 10 16:59:14 2007 +0000 >> >> =A0 =A0For 7.0 make the shared lib "version" '3'. >> =A0 =A0Approved by: =A0 =A0 =A0 =A0re(kensmith) >> >> =A0 =A0git-svn-id: svn://svn.freebsd.org/base/head@172505 >> ccf9f872-aa2e-dd11-9fc8-001c23d0bc1f >> >> So something should have gone wrong when the mirror was created with >> the 8-STABLE branch as its root commit is: > > # git log origin/svn_stable_8 > commit 46c8a8db6dae5c885c7c1de5d39904566cc19685 > Author: ume > Date: =A0 Sun Sep 13 11:34:33 2009 +0000 > > =A0 =A0MFC r196475: > =A0 =A0 - Add AS lookup functionality to traceroute6(8) as well. > =A0 =A0 - Support for IPv6 transport for AS lookup. > =A0 =A0 - Introduce $RA_SERVER to set whois server. > =A0 =A0 - Support for 4 byte ASN. > =A0 =A0 - ANSIfy function declaration in as.c. > > =A0 =A0Approved by: =A0 =A0 =A0 =A0re (kib) > > > =A0 =A0git-svn-id: http://svn.freebsd.org/base/stable/8@197158 ccf9f872-a= a2e-dd11-9fc8-001c23d0bc1f > >> >> commit 47c9e1cbe6e19ab62a112f67fa4baf081aa213be >> Author: jfv >> Date: =A0 Fri Sep 4 22:37:03 2009 +0000 >> >> =A0 =A0This patch seperates the control of header split from LRO (which = it >> =A0 =A0was previously dependent on), LRO gets turned off when bridging b= ut >> =A0 =A0its been found that header split is still a performance win in th= at case. >> >> =A0 =A0Secondly, there was some interface specific control in stats code= that >> =A0 =A0has been missing, and a logic error that resulted in bogus report= ing. >> =A0 =A0Thanks to Manish and John of LineRateSystems for the report and h= elp in >> =A0 =A0this code. >> >> =A0 =A0Approved by: re >> >> =A0 =A0git-svn-id: http://svn.freebsd.org/base/stable/8@196843 >> ccf9f872-aa2e-dd11-9fc8-001c23d0bc1f >> >> which should rather be: >> >> commit d4a6bb6e18d2601fe08d76be4610ae4a303574b2 >> Author: ache >> Date: =A0 Fri Jan 21 13:31:02 2005 +0000 >> >> =A0 =A0Whitespace/style tweaking of prev. commit. >> >> =A0 =A0Noted by: =A0 =A0 =A0 bde >> >> =A0 =A0git-svn-id: svn://svn.freebsd.org/base/head@140577 >> ccf9f872-aa2e-dd11-9fc8-001c23d0bc1f >> >> >> Regards, >> - Arnaud >> >>> And the first branch of interest: >>> https://gitorious.org/~avg/freebsd/avgbsd/commits/devel-20110915 >>> >>> This is a snapshot of almost all of my local changes to the FreeBSD src= tree. >>> Please note that the branch is not intended to be public in the git sen= se. =A0That >>> is, there will be no linear history - I periodically rebase my changes = on top of >>> the svn head and also frequently reshuffle/merge/split commits. >>> The snapshot is not tidied up, there are quite a few commits that shoul= d be >>> merged into other commits, some commit messages are not accurate/pretty= , etc. >>> The older the commits, the more mature they are supposed to be. >>> >>> Based on the above, no new commits are expected to this snapshot branch= . >>> I will produce new snapshot branches from time to time. >>> >>> I am posting this information to this list initially, later I plan to s= hare the >>> code with the wider audience e.g. via hackers@. >>> >>> P.S. This code sharing is made easier for me by git, Gitorious and "git= rebase >>> --onto" in particular. =A0Thanks to Fabien Thomas for the initial FreeB= SD clone >>> repository at Gitorious! >>> >>> -- >>> Andriy Gapon >>> _______________________________________________ >>> freebsd-hackers@freebsd.org mailing list >>> http://lists.freebsd.org/mailman/listinfo/freebsd-hackers >>> To unsubscribe, send any mail to "freebsd-hackers-unsubscribe@freebsd.o= rg" >>> > > -- > Fabien Thomas > > > > > From owner-freebsd-hackers@FreeBSD.ORG Tue Sep 20 14:26:10 2011 Return-Path: Delivered-To: hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 68DF61065740; Tue, 20 Sep 2011 14:26:10 +0000 (UTC) (envelope-from lacombar@gmail.com) Received: from mail-wy0-f182.google.com (mail-wy0-f182.google.com [74.125.82.182]) by mx1.freebsd.org (Postfix) with ESMTP id 8193A8FC12; Tue, 20 Sep 2011 14:26:09 +0000 (UTC) Received: by wyh15 with SMTP id 15so755294wyh.13 for ; Tue, 20 Sep 2011 07:26:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=mime-version:in-reply-to:references:date:message-id:subject:from:to :cc:content-type:content-transfer-encoding; bh=Wrpu84hvnpYUtbFaTrR58PUZDBdUa2U9WsJZ5v+fxqA=; b=PnAyNFP+4jclZwtcXTsj+2TZjIaTn4Sxgs6912027hQVoibIauoD4UWC7yDJhyipeJ z29eqdbmyS8oRSN81jm/1htTw7p+WsOkMOM4diK/cJuaI/esmAMt9kRBJZEs4ZKrfmqr THwDXPB6N6kHVtfVRxsCDa1+nrZ/vvsvBn5og= MIME-Version: 1.0 Received: by 10.216.172.75 with SMTP id s53mr923693wel.38.1316528768455; Tue, 20 Sep 2011 07:26:08 -0700 (PDT) Received: by 10.180.95.169 with HTTP; Tue, 20 Sep 2011 07:26:08 -0700 (PDT) In-Reply-To: References: <4E712D11.7040202@FreeBSD.org> <4E75B67E.1000802@FreeBSD.org> <3C53D349-6629-48FC-A8EF-84C3B2C13617@netasq.com> Date: Tue, 20 Sep 2011 10:26:08 -0400 Message-ID: From: Arnaud Lacombe To: Fabien Thomas Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable Cc: hackers@freebsd.org, Fabien Thomas , Andriy Gapon Subject: Re: my git development snapshot(s) X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 20 Sep 2011 14:26:10 -0000 Hi, On Tue, Sep 20, 2011 at 10:11 AM, Arnaud Lacombe wrote= : > Hi, > > On Tue, Sep 20, 2011 at 4:58 AM, Fabien Thomas = wrote: >> >> On Sep 20, 2011, at 6:58 AM, Arnaud Lacombe wrote: >> >>> Hi, >>> >>> [adding Fabien Thomas to the CC: list] >>> >>> On Sun, Sep 18, 2011 at 5:14 AM, Andriy Gapon wrote: >>>> >>>> Just decided to follow the global trends and trying to throw all of my >>>> local/private changes at you in hope that the "crowd-sourcing magic" m= ight >>>> somehow happen :-) =A0This seems definitely easier than carefully prod= ucing the >>>> patch files and keeping them up-to-date. >>>> >>>> So, my newly cloned gitorious repository: >>>> https://gitorious.org/~avg/freebsd/avgbsd >>>> >>> I see that this tree is a clone of: >>> >>> https://gitorious.org/freebsd/freebsd >>> >>> One issue I've got with that tree, is that it is not usable for any >>> serious work because of the following: >> >> I'm working seriously with it :D >> > he, I guess we do not have the same kind of workflow :) In my case, I > was trying a tree from 7-STABLE into 8-STABLE. > >>> >>> % git merge-base origin/master origin/svn_stable_8 >>> % echo $? >>> 1 >>> >> That's strange: >> # git merge-base origin/master origin/svn_stable_8 >> 08b4e774d45547b6476807eacbfc1d2b5aab02e2 >> >> I've tried from fresh fresh clone with same result. >> > You will see this issue online too: > > https://gitorious.org/freebsd/freebsd/commits/svn_release_8_0_0?page=3D8 > https://gitorious.org/freebsd/freebsd/commits/svn_release_8_1_0?page=3D82 > https://gitorious.org/freebsd/freebsd/commits/svn_releng_8_0?page=3D8 > https://gitorious.org/freebsd/freebsd/commits/svn_releng_8_1?page=3D82 > > There is no history before commit 47c9e1c. > > https://gitorious.org/freebsd/freebsd/commits/svn_releng_8_2?page=3D3 > > There is no history before commit aca2adc. > > Now, compare with 7.x branches: > > https://gitorious.org/freebsd/freebsd/commits/svn_releng_7_0?page=3D776 > https://gitorious.org/freebsd/freebsd/commits/svn_releng_7_1?page=3D858 > https://gitorious.org/freebsd/freebsd/commits/svn_releng_7_3?page=3D928 > https://gitorious.org/freebsd/freebsd/commits/svn_releng_7_4?page=3D963 > > All have exactly the same root commit: d4a6bb6. > > I'm trying a new clone now, I'll let you know the result... > Still the same issue: % git clone git://gitorious.org/freebsd/freebsd.git Cloning into freebsd... remote: Counting objects: 639377, done. remote: Compressing objects: 100% (159732/159732), done. remote: Total 639377 (delta 489007), reused 619601 (delta 470781) Receiving objects: 100% (639377/639377), 339.01 MiB | 382 KiB/s, done. Resolving deltas: 100% (489007/489007), done. % cd freebsd freebsd/% git merge-base origin/master origin/svn_stable_8 freebsd/% echo $? 1 freebsd/% git --version git version 1.7.4.1 freebsd/% git log --pretty=3Doneline origin/svn_releng_7_0 | wc -l 23276 freebsd/% git log --pretty=3Doneline origin/svn_releng_7_1 | wc -l 25731 freebsd/% git log --pretty=3Doneline origin/svn_releng_7_2 | wc -l 26620 freebsd/% git log --pretty=3Doneline origin/svn_releng_7_3 | wc -l 27826 freebsd/% git log --pretty=3Doneline origin/svn_releng_7_4 | wc -l 28872 freebsd/% git log --pretty=3Doneline origin/svn_releng_8_0 | wc -l 238 freebsd/% git log --pretty=3Doneline origin/svn_releng_8_1 | wc -l 2446 freebsd/% git log --pretty=3Doneline origin/svn_releng_8_2 | wc -l 77 freebsd/% git log --pretty=3Doneline origin/master | wc -l 52252 Beside that, this repository is the only one with which I've got problem. =A0- Arnaud > >>> The whole FreeBSD 8.x branch is on its own. However: >>> >>> % git merge-base origin/master origin/svn_stable_7 >>> bdad8b50a25980737a8e00047f41fc1e588fc9e5 >>> >>> % git show bdad8b50a25980737a8e00047f41fc1e588fc9e5 >>> commit bdad8b50a25980737a8e00047f41fc1e588fc9e5 >>> Author: obrien >>> Date: =A0 Wed Oct 10 16:59:14 2007 +0000 >>> >>> =A0 =A0For 7.0 make the shared lib "version" '3'. >>> =A0 =A0Approved by: =A0 =A0 =A0 =A0re(kensmith) >>> >>> =A0 =A0git-svn-id: svn://svn.freebsd.org/base/head@172505 >>> ccf9f872-aa2e-dd11-9fc8-001c23d0bc1f >>> >>> So something should have gone wrong when the mirror was created with >>> the 8-STABLE branch as its root commit is: >> >> # git log origin/svn_stable_8 >> commit 46c8a8db6dae5c885c7c1de5d39904566cc19685 >> Author: ume >> Date: =A0 Sun Sep 13 11:34:33 2009 +0000 >> >> =A0 =A0MFC r196475: >> =A0 =A0 - Add AS lookup functionality to traceroute6(8) as well. >> =A0 =A0 - Support for IPv6 transport for AS lookup. >> =A0 =A0 - Introduce $RA_SERVER to set whois server. >> =A0 =A0 - Support for 4 byte ASN. >> =A0 =A0 - ANSIfy function declaration in as.c. >> >> =A0 =A0Approved by: =A0 =A0 =A0 =A0re (kib) >> >> >> =A0 =A0git-svn-id: http://svn.freebsd.org/base/stable/8@197158 ccf9f872-= aa2e-dd11-9fc8-001c23d0bc1f >> >>> >>> commit 47c9e1cbe6e19ab62a112f67fa4baf081aa213be >>> Author: jfv >>> Date: =A0 Fri Sep 4 22:37:03 2009 +0000 >>> >>> =A0 =A0This patch seperates the control of header split from LRO (which= it >>> =A0 =A0was previously dependent on), LRO gets turned off when bridging = but >>> =A0 =A0its been found that header split is still a performance win in t= hat case. >>> >>> =A0 =A0Secondly, there was some interface specific control in stats cod= e that >>> =A0 =A0has been missing, and a logic error that resulted in bogus repor= ting. >>> =A0 =A0Thanks to Manish and John of LineRateSystems for the report and = help in >>> =A0 =A0this code. >>> >>> =A0 =A0Approved by: re >>> >>> =A0 =A0git-svn-id: http://svn.freebsd.org/base/stable/8@196843 >>> ccf9f872-aa2e-dd11-9fc8-001c23d0bc1f >>> >>> which should rather be: >>> >>> commit d4a6bb6e18d2601fe08d76be4610ae4a303574b2 >>> Author: ache >>> Date: =A0 Fri Jan 21 13:31:02 2005 +0000 >>> >>> =A0 =A0Whitespace/style tweaking of prev. commit. >>> >>> =A0 =A0Noted by: =A0 =A0 =A0 bde >>> >>> =A0 =A0git-svn-id: svn://svn.freebsd.org/base/head@140577 >>> ccf9f872-aa2e-dd11-9fc8-001c23d0bc1f >>> >>> >>> Regards, >>> - Arnaud >>> >>>> And the first branch of interest: >>>> https://gitorious.org/~avg/freebsd/avgbsd/commits/devel-20110915 >>>> >>>> This is a snapshot of almost all of my local changes to the FreeBSD sr= c tree. >>>> Please note that the branch is not intended to be public in the git se= nse. =A0That >>>> is, there will be no linear history - I periodically rebase my changes= on top of >>>> the svn head and also frequently reshuffle/merge/split commits. >>>> The snapshot is not tidied up, there are quite a few commits that shou= ld be >>>> merged into other commits, some commit messages are not accurate/prett= y, etc. >>>> The older the commits, the more mature they are supposed to be. >>>> >>>> Based on the above, no new commits are expected to this snapshot branc= h. >>>> I will produce new snapshot branches from time to time. >>>> >>>> I am posting this information to this list initially, later I plan to = share the >>>> code with the wider audience e.g. via hackers@. >>>> >>>> P.S. This code sharing is made easier for me by git, Gitorious and "gi= t rebase >>>> --onto" in particular. =A0Thanks to Fabien Thomas for the initial Free= BSD clone >>>> repository at Gitorious! >>>> >>>> -- >>>> Andriy Gapon >>>> _______________________________________________ >>>> freebsd-hackers@freebsd.org mailing list >>>> http://lists.freebsd.org/mailman/listinfo/freebsd-hackers >>>> To unsubscribe, send any mail to "freebsd-hackers-unsubscribe@freebsd.= org" >>>> >> >> -- >> Fabien Thomas >> >> >> >> >> > From owner-freebsd-hackers@FreeBSD.ORG Tue Sep 20 15:10:48 2011 Return-Path: Delivered-To: hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 696E7106564A; Tue, 20 Sep 2011 15:10:48 +0000 (UTC) (envelope-from fabien.thomas@netasq.com) Received: from work.netasq.com (mars.netasq.com [91.212.116.3]) by mx1.freebsd.org (Postfix) with ESMTP id C194D8FC1D; Tue, 20 Sep 2011 15:10:46 +0000 (UTC) Received: from [10.2.1.1] (unknown [10.2.1.1]) by work.netasq.com (Postfix) with ESMTPSA id 3512B740021; Tue, 20 Sep 2011 17:10:01 +0200 (CEST) Mime-Version: 1.0 (Apple Message framework v1084) Content-Type: text/plain; charset=us-ascii From: Fabien Thomas In-Reply-To: Date: Tue, 20 Sep 2011 17:10:45 +0200 Content-Transfer-Encoding: quoted-printable Message-Id: References: <4E712D11.7040202@FreeBSD.org> <4E75B67E.1000802@FreeBSD.org> <3C53D349-6629-48FC-A8EF-84C3B2C13617@netasq.com> To: Arnaud Lacombe X-Mailer: Apple Mail (2.1084) Cc: hackers@freebsd.org, Andriy Gapon Subject: Re: my git development snapshot(s) X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list Reply-To: Fabien Thomas List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 20 Sep 2011 15:10:48 -0000 At some point in time (when i've migrated my server from i386 to amd64) = the git-svn metadata was corrupted (perl problem). Maybe this problem is related as my original clone does not have the = problem. I will try to restore and force push a new repo. Fabien From owner-freebsd-hackers@FreeBSD.ORG Tue Sep 20 15:34:06 2011 Return-Path: Delivered-To: hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 459AC1065670 for ; Tue, 20 Sep 2011 15:34:06 +0000 (UTC) (envelope-from artemb@gmail.com) Received: from mail-gy0-f182.google.com (mail-gy0-f182.google.com [209.85.160.182]) by mx1.freebsd.org (Postfix) with ESMTP id 06A208FC08 for ; Tue, 20 Sep 2011 15:34:05 +0000 (UTC) Received: by gyf2 with SMTP id 2so555960gyf.13 for ; Tue, 20 Sep 2011 08:34:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=mime-version:sender:in-reply-to:references:date :x-google-sender-auth:message-id:subject:from:to:cc:content-type; bh=ZEbJkvcDE7cZphV/JNfw8wqA6lEQblr6448rdcD/krI=; b=skTRoohpy1sj/urpJCOEvfRRsEHdGNC8TorpOjbpXIgAKzZ9pv/4orrW3V/F81pUMZ s2YV+W0Lx6I32wi5iiUVCOilnvHhunUete70NUNoKERsEjHlv8O3POxAkgNkAMv7/cta SgnbOpOoZkJz9oPj5qm7IbfSnCfndQ/zlxfwg= MIME-Version: 1.0 Received: by 10.236.187.36 with SMTP id x24mr5384828yhm.74.1316531129048; Tue, 20 Sep 2011 08:05:29 -0700 (PDT) Sender: artemb@gmail.com Received: by 10.236.102.147 with HTTP; Tue, 20 Sep 2011 08:05:28 -0700 (PDT) In-Reply-To: References: <4E712D11.7040202@FreeBSD.org> <4E75B67E.1000802@FreeBSD.org> Date: Tue, 20 Sep 2011 08:05:28 -0700 X-Google-Sender-Auth: C_EKBBqqVH26igoLeM_XE-YA8X8 Message-ID: From: Artem Belevich To: Fabien Thomas Content-Type: text/plain; charset=ISO-8859-1 Cc: hackers@freebsd.org, Andriy Gapon , Arnaud Lacombe Subject: Re: my git development snapshot(s) X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 20 Sep 2011 15:34:06 -0000 On Tue, Sep 20, 2011 at 6:34 AM, Fabien Thomas wrote: > git merge-base upstream/svn_trunk upstream/svn_stable_8 > does not work. Ditto here. > > it seems that at some point in time it was working. > (upstream = live tree, origin = my sandbox) > I will need to dig a little more to understand the problem. Here's an observation that may be relevant. Some time back repository had much deeper history. Then at one point remote branches got forcefully updated during 'git fetch origin'. Once that happened, new svn_stable_8 branch had completely separate one from the one that was in the clone before the fetch. History also got trimmed and would only go as deep as ~2009. I suspected that history depth was trimmed in the original repository. The same trim could've 'disconnected' branches from the trunk, too. --Artem From owner-freebsd-hackers@FreeBSD.ORG Tue Sep 20 18:53:39 2011 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 71C12106566B for ; Tue, 20 Sep 2011 18:53:39 +0000 (UTC) (envelope-from geoffrey.levand@mail.ru) Received: from fallback4.mail.ru (fallback4.mail.ru [94.100.176.42]) by mx1.freebsd.org (Postfix) with ESMTP id DE31E8FC15 for ; Tue, 20 Sep 2011 18:53:38 +0000 (UTC) Received: from f57.mail.ru (f57.mail.ru [217.69.129.104]) by fallback4.mail.ru (mPOP.Fallback_MX) with ESMTP id 5C38149D3E3F for ; Tue, 20 Sep 2011 22:36:00 +0400 (MSD) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=mail.ru; s=mail; h=Message-Id:Content-Type:Reply-To:Date:Mime-Version:Subject:To:From; bh=9AnRNWtZFGSadmCPUW7yIOytGyCSAPiiESmlBuAP6fs=; b=kd5so0BjZbYFcvhbz+QrzPyO8kquwONfW3oYikbcAHWzIe5pk88pRow/POF/l0lOjEAIjnS2AcbMPt4sVrEiLMSihIV+tQC8GinmeILbLTvGK10ilOXWjnLuuL9RPVlT; Received: from mail by f57.mail.ru with local id 1R65Aj-0003Fj-00 for freebsd-hackers@freebsd.org; Tue, 20 Sep 2011 22:35:57 +0400 Received: from [85.216.79.15] by e.mail.ru with HTTP; Tue, 20 Sep 2011 22:35:57 +0400 From: =?UTF-8?B?Z2VvZmZyZXkgbGV2YW5k?= To: freebsd-hackers@freebsd.org Mime-Version: 1.0 X-Mailer: mPOP Web-Mail 2.19 X-Originating-IP: [85.216.79.15] Date: Tue, 20 Sep 2011 22:35:57 +0400 Message-Id: X-Spam: Not detected X-Mras: Ok X-Mras: Ok Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: base64 X-Content-Filtered-By: Mailman/MimeDel 2.1.5 Subject: Sharing device driver between kernel and user space X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list Reply-To: =?UTF-8?B?Z2VvZmZyZXkgbGV2YW5k?= List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 20 Sep 2011 18:53:39 -0000 Q3VycmVudGx5IGknbSBkZXZlbG9waW5nIFZVQVJUIGRldmljZSBkcml2ZXJzIGZvciBQUzMgYXJj aGl0ZWN0dXJlLiBWVUFSVCBpcyBiaS1kaXJlY3Rpb25hbCBGSUZPIHF1ZXVlIGJldHdlZW4gMiBs b2dpY2FsIHBhcnRpdGlvbnMgb24gUFMzLiBJIHdhbnQgdG8gdXNlIHRoZSBkZXZpY2UgaW4gdGhl IGtlcm5lbCBhbmQgdXNlciBzcGFjZS4gRHVyaW5nIHN5c3RlbSBib290IFBTMyBzeXN0ZW0gaGFz IHRvIHJlYWQvd3JpdGUgc29tZSBkYXRhIGZyb20vdG8gdGhlIFZVQVJUIGRldmljZXMgYW5kIHNv bWV0aW1lcyBpIHdhbnQgdG8gYWNjZXNzIHRoZSBkZXZpY2UgZnJvbSB1c2VyIHNwYWNlICwgZS5n LiB3aXRoIGNoYXJhY3RlciBkZXZpY2UgZHJpdmVyIGJ5IHVzaW5nIHJlYWQvd3JpdGUgc3lzY2Fs bHMuIFRoZSBxdXVlc3Rpb24gaXMgd2hhdCBpcyB0aGUgYmVzdCBzb2x1dGlvbiB0byBzaGFyZSB0 aGUgZGV2aWNlIGJldHdlZW4ga2VybmVsIGFuZCB1c2VyIGxhbmRzLiBPbmUgc29sdXRpb24gaSBm b3VuZCB3b3VsZCBiZSB0byBwb3JvaGliaXQga2VybmVsIGFjY2VzcyB0byB0aGUgZGV2aWNlIGFz IHNvb24gYXMgYSB1c2VyIGFwcGxpY2F0aW9uIG9wZW5zIHRoZSBjb3JyZXNwb25kaW5nIGNoYXJh Y3RlciBkZXZpY2UuIEFuZCBhbGxvdyBpdCBhZ2FpbiB3aGVuIHRoZSBhcHBsaWNhdGlvbiBjYWxs cyBjbG9zZSBzeXNjYWxsLiBUaGUgdXNlciBzcGFjZSBzaG91bGQgaGF2ZSBoaWdoZXIgcHJpb3Jp dHkgdGhlbiB0aGUga2VybmVsLiBBcmUgdGhlcmUgYW55IGJldHRlciBzb2x1dGlvbnMgZm9yIHRo aXMgcHJvYmxlbSA/IEZvcmdvdCB0byBtZW50aW9uIHRoYXQgYSBWVUFSVCBkZXZpY2UgY2Fubm90 IGJlIGFjY2Vzc2VkIHNpbXVsdGFuZW91c2x5IGJ5IHVzZXIgbGFuZCBhbmQgdGhlIGtlcm5lbC4g VGhlIFZVQVJUIGRldmljZXMgYXJlIHVzZWQgYnkgUFMzIG1hbmFnZW1lbnQgbG9naWNhbCBwYXJ0 aXRpb24gdG8gcHJvdmlkZSBkaWZmZXJlbnQgcmVxdWVzdC9yZXNwb25zZSBzZXJ2aWNlcyBhbmQg ZXZlbnQgbm90aWZpY2F0aW9uIHRvIG90aGVyIGxvZ2ljYWwgcGFydGl0aW9ucy4gRS5nLiBzZXR0 aW5nIHZpZGVvIG1vZGUgb3IgY29uZmlndXJpbmcgYXVkaW8gb3V0cHV0cy4KClRoYW5rcy4KCgot LQrQktGB0LUg0LLQvtC30LzQvtC20L3QvtGB0YLQuCBATWFpbC5SdSDQsiDRgtCy0L7QtdC8INC8 0L7QsdC40LvRjNC90L7QvC4K0J/RgNC+0YHRgtC+INC30LDQudC00Lgg0YEg0YLQtdC70LXRhNC+ 0L3QsCDQvdCwIG0ubWFpbC5ydQ== From owner-freebsd-hackers@FreeBSD.ORG Tue Sep 20 19:19:52 2011 Return-Path: Delivered-To: hackers@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 5C0FA1065673; Tue, 20 Sep 2011 19:19:52 +0000 (UTC) (envelope-from avg@FreeBSD.org) Received: from citadel.icyb.net.ua (citadel.icyb.net.ua [212.40.38.140]) by mx1.freebsd.org (Postfix) with ESMTP id 65E268FC1C; Tue, 20 Sep 2011 19:19:50 +0000 (UTC) Received: from porto.starpoint.kiev.ua (porto-e.starpoint.kiev.ua [212.40.38.100]) by citadel.icyb.net.ua (8.8.8p3/ICyb-2.3exp) with ESMTP id WAA08514; Tue, 20 Sep 2011 22:19:49 +0300 (EEST) (envelope-from avg@FreeBSD.org) Received: from localhost ([127.0.0.1]) by porto.starpoint.kiev.ua with esmtp (Exim 4.34 (FreeBSD)) id 1R65rB-000LC8-Ha; Tue, 20 Sep 2011 22:19:49 +0300 Message-ID: <4E78E755.8050404@FreeBSD.org> Date: Tue, 20 Sep 2011 22:19:49 +0300 From: Andriy Gapon User-Agent: Mozilla/5.0 (X11; FreeBSD amd64; rv:6.0.2) Gecko/20110907 Thunderbird/6.0.2 MIME-Version: 1.0 To: Alexander Motin X-Enigmail-Version: undefined Content-Type: text/plain; charset=X-VIET-VPS Content-Transfer-Encoding: 7bit Cc: hackers@FreeBSD.org Subject: SW_WATCHDOG vs new eventtimer code X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 20 Sep 2011 19:19:52 -0000 Alexander, just want to check with you first if the following makes sense. I use SW_WATCHDOG on one of the test machines, which was recently updated to from stable/8 to head. Now it seems to get seemingly random watchdog events. My theory is that this is because of the eventtimer logic. If during idle period we accumulate enough timer ticks and then run all those ticks very rapidly, then the SW_WATCHDOG code may get an impression that it was not patted for many real ticks. Not sure what would be the best way to make SW_WATCHDOG happier/smarter. -- Andriy Gapon From owner-freebsd-hackers@FreeBSD.ORG Tue Sep 20 19:17:43 2011 Return-Path: Delivered-To: hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id AC286106564A for ; Tue, 20 Sep 2011 19:17:43 +0000 (UTC) (envelope-from theraven@theravensnest.org) Received: from theravensnest.org (theravensnest.org [109.169.23.128]) by mx1.freebsd.org (Postfix) with ESMTP id 2FFF18FC14 for ; Tue, 20 Sep 2011 19:17:41 +0000 (UTC) Received: from [192.168.0.128] (cpc1-cwma5-0-0-cust192.7-3.cable.virginmedia.com [80.4.12.193]) (authenticated bits=0) by theravensnest.org (8.14.4/8.14.4) with ESMTP id p8KKETcX054729 (version=TLSv1/SSLv3 cipher=DHE-DSS-AES128-SHA bits=128 verify=NO); Tue, 20 Sep 2011 21:14:29 +0100 (BST) (envelope-from theraven@theravensnest.org) Mime-Version: 1.0 (Apple Message framework v1244.3) Content-Type: multipart/mixed; boundary="Apple-Mail=_42B7C1B0-E4C4-4143-8596-7785C86E8855" From: David Chisnall In-Reply-To: <20110919172214.GJ33993@hoeg.nl> Date: Tue, 20 Sep 2011 20:17:28 +0100 Message-Id: <3A86EAEA-1861-43A6-95DC-FC700BE0E507@theravensnest.org> References: <20110919172214.GJ33993@hoeg.nl> To: Ed Schouten X-Mailer: Apple Mail (2.1244.3) X-Mailman-Approved-At: Tue, 20 Sep 2011 19:21:30 +0000 Cc: hackers@freebsd.org Subject: Re: xlocale patch X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 20 Sep 2011 19:17:43 -0000 --Apple-Mail=_42B7C1B0-E4C4-4143-8596-7785C86E8855 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=us-ascii Ooops, I forgot I uninstalled the subversion-freebsd package and = installed subversion to work on libc++ (it would be really nice if these = two could coexist, by the way...). The updated version of the diff now passes all of the libc++ locale = tests (309 files, multiple tests in each), with my copy of libc++. I've = just pushed the exception handling bits required to support = std::exception_ptr to libcxxrt, so we can now build a mostly-working BSD = licensed C++ stack. For anyone that's interested, the full results of the libc++ test suite = are here: http://pastebin.com/UCskvjCv For those two lazy to click on a link, here's the summary: **************************************************** Results for /root/libcxx/test: using FreeBSD clang version 3.0 (trunk 135360) 20110717 Target: x86_64-unknown-freebsd9.0 Thread model: posix with -std=3Dc++0x -stdlib=3Dlibc++ -I/root/libcxx/include = -L/root/libcxx/build/lib ---------------------------------------------------- sections without tests : 1 sections with failures : 48 sections without failures: 1015 + ---- total number of sections : 1064 ---------------------------------------------------- number of tests failed : 145 number of tests passed : 4179 + ---- total number of tests : 4324 **************************************************** The tests all fail because the version of clang in the base = system doesn't support the cxx_atomic builtins. Not sure when these = were added, but a lot of those failures should go away with a newer = clang. =20 Quite a few of the remaining failures are due to system headers not = being C++11-aware (i.e. most of the c99 stuff should be exposed in c++11 = mode). A few tests fail when creating locales because FreeBSD doesn't have = locales like en_US or fr_FR (with no encoding specified), while Darwin = does (and also has locales like fr and en). I've fixed all of the tests = in the localization part of the test suite to fully specify the locale. =20= David On 19 Sep 2011, at 18:22, Ed Schouten wrote: > Hi David, >=20 > Can you please regenerate the patch using `diff -I '$FreeBSD'` or > something? There are a lot of changes to $FreeBSD$ lines that will > likely make it hard to apply the patch to most checkouts. >=20 > Thanks, > --=20 > Ed Schouten > WWW: http://80386.nl/ --Apple-Mail=_42B7C1B0-E4C4-4143-8596-7785C86E8855 Content-Disposition: attachment; filename=xlocale.diff Content-Type: application/octet-stream; x-unix-mode=0644; name="xlocale.diff" Content-Transfer-Encoding: 7bit Index: include/Makefile =================================================================== --- include/Makefile (revision 225653) +++ include/Makefile (working copy) @@ -24,7 +24,7 @@ strings.h sysexits.h tar.h termios.h tgmath.h \ time.h timeconv.h timers.h ttyent.h \ ulimit.h unistd.h utime.h utmpx.h uuid.h varargs.h vis.h \ - wchar.h wctype.h wordexp.h + wchar.h wctype.h wordexp.h xlocale.h _xlocale_ctype.h MHDRS= float.h floatingpoint.h stdarg.h Index: include/xlocale.h =================================================================== --- include/xlocale.h (revision 0) +++ include/xlocale.h (revision 0) @@ -0,0 +1,256 @@ +/*- + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by David Chisnall under sponsorship from + * the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions * are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _XLOCALE_H_ +#define _XLOCALE_H_ + +#include + +__BEGIN_DECLS + +/* + * Extended locale versions of the locale-aware functions from string.h. + * + * Include before to expose these. + */ +#ifdef _STRING_H_ +int strcoll_l(const char *, const char *, locale_t); +size_t strxfrm_l(char *, const char *, size_t, locale_t); +int strcasecmp_l(const char *, const char *, locale_t); +char *strcasestr_l(const char *, const char *, locale_t); +int strncasecmp_l(const char *, const char *, size_t, locale_t); +#endif +/* + * Extended locale versions of the locale-aware functions from inttypes.h. + * + * Include before to expose these. + */ +#ifdef _INTTYPES_H_ +intmax_t +strtoimax_l(const char * __restrict, char ** __restrict, int, locale_t); +uintmax_t +strtoumax_l(const char * __restrict, char ** __restrict, int, locale_t); +intmax_t +wcstoimax_l(const wchar_t * __restrict, wchar_t ** __restrict, int , locale_t); +uintmax_t +wcstoumax_l(const wchar_t * __restrict, wchar_t ** __restrict, int, locale_t); +#endif +/* + * Extended locale versions of the locale-aware functions from monetary.h. + * + * Include before to expose these. + */ +#ifdef _MONETARY_H_ +ssize_t strfmon_l(char *, size_t, locale_t, const char *, ...) +# if __GNUC__ > 2 || __GNUC__ == 2 && __GNUC_MINOR__ >= 7 + __attribute__((__format__ (__strfmon__, 4, 5))) +# endif + ; +#endif + +/* + * Extended locale versions of the locale-aware functions from stdlib.h. + * + * Include before to expose these. + */ +#ifdef _STDLIB_H_ +double atof_l(const char *, locale_t); +int atoi_l(const char *, locale_t); +long atol_l(const char *, locale_t); +long long atoll_l(const char *, locale_t); +int mblen_l(const char *, size_t, locale_t); +size_t +mbstowcs_l(wchar_t * __restrict, const char * __restrict, size_t, locale_t); +int +mbtowc_l(wchar_t * __restrict, const char * __restrict, size_t, locale_t); +double strtod_l(const char *, char **, locale_t); +float strtof_l(const char *, char **, locale_t); +long strtol_l(const char *, char **, int, locale_t); +long double strtold_l(const char *, char **, locale_t); +long long strtoll_l(const char *, char **, int, locale_t); +unsigned long strtoul_l(const char *, char **, int, locale_t); +unsigned long long strtoull_l(const char *, char **, int, locale_t); +size_t +wcstombs_l(char * __restrict, const wchar_t * __restrict, size_t, locale_t); +int wctomb_l(char *, wchar_t, locale_t); + +int ___mb_cur_max_l(locale_t); +#define MB_CUR_MAX_L(x) (___mb_cur_max_l(x)) + +#endif +/* + * Extended locale versions of the locale-aware functions from time.h. + * + * Include before to expose these. + */ +#ifdef _TIME_H_ +size_t +strftime_l(char * __restrict, size_t, const char * __restrict, const + struct tm * __restrict, locale_t) +# if __GNUC__ > 2 || __GNUC__ == 2 && __GNUC_MINOR__ >= 7 + __attribute__((__format__ (__strftime__, 3, 0))) +# endif + ; +char * +strptime_l(const char * __restrict, const char * __restrict, + struct tm * __restrict, locale_t); +#endif +#ifdef _LANGINFO_H_ +char *nl_langinfo_l(nl_item, locale_t); +#endif +#ifdef _CTYPE_H_ +#include <_xlocale_ctype.h> +#endif +#ifdef _WCTYPE_H_ +#define XLOCALE_WCTYPES 1 +#include <_xlocale_ctype.h> +#endif + +#ifdef _STDIO_H_ +int fprintf_l(FILE * __restrict, locale_t, const char * __restrict, ...) + __printflike(3, 4); +int fscanf_l(FILE * __restrict, locale_t, const char * __restrict, ...) + __scanflike(3, 4); +int printf_l(locale_t, const char * __restrict, ...) __printflike(2, 3); +int scanf_l(locale_t, const char * __restrict, ...) __scanflike(2, 3); +int sprintf_l(char * __restrict, locale_t, const char * __restrict, ...) + __printflike(3, 4); +int sscanf_l(const char * __restrict, locale_t, const char * __restrict, ...) + __scanflike(3, 4); +int vfprintf_l(FILE * __restrict, locale_t, const char * __restrict, __va_list) + __printflike(3, 0); +int vprintf_l(locale_t, const char * __restrict, __va_list) __printflike(2, 0); +int vsprintf_l(char * __restrict, locale_t, const char * __restrict, __va_list) + __printflike(3, 0); + +int snprintf_l(char * __restrict, size_t, locale_t, const char * __restrict, + ...) __printflike(4, 5); +int vfscanf_l(FILE * __restrict, locale_t, const char * __restrict, __va_list) + __scanflike(3, 0); +int vscanf_l(locale_t, const char * __restrict, __va_list) __scanflike(2, 0); +int vsnprintf_l(char * __restrict, size_t, locale_t, const char * __restrict, + va_list) __printflike(4, 0); +int vsscanf_l(const char * __restrict, locale_t, const char * __restrict, + va_list) __scanflike(3, 0); +int dprintf_l(int, locale_t, const char * __restrict, ...) __printflike(3, 4); +int vdprintf_l(int, locale_t, const char * __restrict, __va_list) + __printflike(3, 0); +int asprintf_l(char **, locale_t, const char *, ...) __printflike(3, 4); +int vasprintf_l(char **, locale_t, const char *, __va_list) __printflike(3, 0); +#endif +#ifdef _WCHAR_H_ +wint_t btowc_l(int, locale_t); +wint_t fgetwc_l(struct __sFILE *, locale_t); +wchar_t * +fgetws_l(wchar_t * __restrict, int, struct __sFILE * __restrict, locale_t); +wint_t fputwc_l(wchar_t, struct __sFILE *, locale_t); +int +fputws_l(const wchar_t * __restrict, struct __sFILE * __restrict, locale_t); +int +fwprintf_l(struct __sFILE * __restrict, locale_t, const wchar_t * __restrict, + ...); +int +fwscanf_l(struct __sFILE * __restrict, locale_t, const wchar_t * __restrict, ...); +wint_t getwc_l(struct __sFILE *, locale_t); +wint_t getwchar_l(locale_t); +size_t +mbrlen_l(const char * __restrict, size_t, mbstate_t * __restrict, locale_t); +size_t +mbrtowc_l(wchar_t * __restrict, const char * __restrict, size_t, + mbstate_t * __restrict, locale_t); +int mbsinit_l(const mbstate_t *, locale_t); +size_t +mbsrtowcs_l(wchar_t * __restrict, const char ** __restrict, size_t, + mbstate_t * __restrict, locale_t); +wint_t putwc_l(wchar_t, struct __sFILE *, locale_t); +wint_t putwchar_l(wchar_t, locale_t); +int +swprintf_l(wchar_t * __restrict, size_t n, locale_t, + const wchar_t * __restrict, ...); +int +swscanf_l(const wchar_t * __restrict, locale_t, const wchar_t * __restrict, + ...); +wint_t ungetwc_l(wint_t, struct __sFILE *, locale_t); +int +vfwprintf_l(struct __sFILE * __restrict, locale_t, const wchar_t * __restrict, + __va_list); +int +vswprintf_l(wchar_t * __restrict, size_t n, locale_t, + const wchar_t * __restrict, __va_list); +int vwprintf_l(locale_t, const wchar_t * __restrict, __va_list); +size_t +wcrtomb_l(char * __restrict, wchar_t, mbstate_t * __restrict, locale_t); +int wcscoll_l(const wchar_t *, const wchar_t *, locale_t); +size_t +wcsftime_l(wchar_t * __restrict, size_t, const wchar_t * __restrict, + const struct tm * __restrict, locale_t); +size_t +wcsrtombs_l(char * __restrict, const wchar_t ** __restrict, size_t, + mbstate_t * __restrict, locale_t); +double wcstod_l(const wchar_t * __restrict, wchar_t ** __restrict, locale_t); +long +wcstol_l(const wchar_t * __restrict, wchar_t ** __restrict, int, locale_t); +unsigned long +wcstoul_l(const wchar_t * __restrict, wchar_t ** __restrict, int, locale_t); +int wcswidth_l(const wchar_t *, size_t, locale_t); +size_t +wcsxfrm_l(wchar_t * __restrict, const wchar_t * __restrict, size_t, locale_t); +int wctob_l(wint_t, locale_t); +int wcwidth_l(wchar_t, locale_t); +int wprintf_l(locale_t, const wchar_t * __restrict, ...); +int wscanf_l(locale_t, const wchar_t * __restrict, ...); + +int +vfwscanf_l(struct __sFILE * __restrict, locale_t, const wchar_t * __restrict, + __va_list); +int vswscanf_l(const wchar_t * __restrict, locale_t, +const wchar_t * __restrict, __va_list); +int vwscanf_l(locale_t, const wchar_t * __restrict, __va_list); +float wcstof_l(const wchar_t * __restrict, wchar_t ** __restrict, locale_t); +long double +wcstold_l(const wchar_t * __restrict, wchar_t ** __restrict, locale_t); +long long +wcstoll_l(const wchar_t * __restrict, wchar_t ** __restrict, int, locale_t); +unsigned long long +wcstoull_l(const wchar_t * __restrict, wchar_t ** __restrict, int, locale_t); +size_t +mbsnrtowcs_l(wchar_t * __restrict, const char ** __restrict, size_t, size_t, + mbstate_t * __restrict, locale_t); +int wcscasecmp_l(const wchar_t *, const wchar_t *, locale_t); +int wcsncasecmp_l(const wchar_t *, const wchar_t *, size_t n, locale_t); +size_t +wcsnrtombs_l(char * __restrict, const wchar_t ** __restrict, size_t, size_t, + mbstate_t * __restrict, locale_t); + +#endif + +struct lconv * +localeconv_l(locale_t loc); +__END_DECLS + +#endif Index: include/locale.h =================================================================== --- include/locale.h (revision 225653) +++ include/locale.h (working copy) @@ -79,4 +79,48 @@ char *setlocale(int, const char *); __END_DECLS +#if __POSIX_VISIBLE >= 200809 + +#define LC_COLLATE_MASK (1<<0) +#define LC_CTYPE_MASK (1<<1) +#define LC_MESSAGES_MASK (1<<2) +#define LC_MONETARY_MASK (1<<3) +#define LC_NUMERIC_MASK (1<<4) +#define LC_TIME_MASK (1<<5) +#define LC_ALL_MASK (LC_COLLATE_MASK | LC_CTYPE_MASK | LC_MESSAGES_MASK | \ + LC_MONETARY_MASK | LC_NUMERIC_MASK | LC_TIME_MASK) + +#define LC_GLOBAL_LOCALE ((locale_t)-1) + +__BEGIN_DECLS + +typedef struct _xlocale *locale_t; +/** + * Creates a new locale. + */ +locale_t newlocale(int mask, const char *locale, locale_t base); + +locale_t duplocale(locale_t base); +/* + * Free a locale_t. This is quite a poorly named function. It actually + * disclaims a reference to a locale_t, rather than freeing it. + */ +int +freelocale(locale_t loc); + +/* + * Returns the name of the locale for a particular component of a locale_t. + */ +const char *querylocale(int mask, locale_t loc); + +/* + * Installs the specified locale_t as this thread's locale. + */ +locale_t uselocale(locale_t loc); + +__END_DECLS + +#endif /* __POSIX_VISIBLE >= 200809 */ + + #endif /* _LOCALE_H_ */ Index: include/_xlocale_ctype.h =================================================================== --- include/_xlocale_ctype.h (revision 0) +++ include/_xlocale_ctype.h (revision 0) @@ -0,0 +1,160 @@ +/*- + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by David Chisnall under sponsorship from + * the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions * are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef _XLOCALE_H_ +#error This header should only be included by , never directly. +#endif + +#ifndef _XLOCALE_CTYPE_H_ +__BEGIN_DECLS +unsigned long ___runetype_l(__ct_rune_t, locale_t) __pure; +__ct_rune_t ___tolower_l(__ct_rune_t, locale_t) __pure; +__ct_rune_t ___toupper_l(__ct_rune_t, locale_t) __pure; +_RuneLocale *__runes_for_locale(locale_t, int*); +__END_DECLS +#endif + +#ifndef _XLOCALE_INLINE +# if __GNUC__ && !__GNUC_STDC_INLINE__ +# define _XLOCALE_INLINE extern inline +# else +# define _XLOCALE_INLINE inline +# endif +#endif + +#ifdef XLOCALE_WCTYPES +static __inline int +__maskrune_l(__ct_rune_t _c, unsigned long _f, locale_t locale) +{ + int mb_sb_limit; + _RuneLocale *runes = __runes_for_locale(locale, &mb_sb_limit); + return (_c < 0 || _c >= _CACHED_RUNES) ? ___runetype_l(_c, locale) : + runes->__runetype[_c] & _f; +} + +static __inline int +__istype_l(__ct_rune_t _c, unsigned long _f, locale_t locale) +{ + return (!!__maskrune_l(_c, _f, locale)); +} + +# define XLOCALE_ISCTYPE(fname, cat) \ + _XLOCALE_INLINE int isw##fname##_l(int c, locale_t l)\ + { return __istype_l(c, cat, l); } +#else +static __inline int +__sbmaskrune_l(__ct_rune_t _c, unsigned long _f, locale_t locale) +{ + int mb_sb_limit; + _RuneLocale *runes = __runes_for_locale(locale, &mb_sb_limit); + return (_c < 0 || _c >= mb_sb_limit) ? 0 : + runes->__runetype[_c] & _f; +} + +static __inline int +__sbistype_l(__ct_rune_t _c, unsigned long _f, locale_t locale) +{ + return (!!__sbmaskrune_l(_c, _f, locale)); +} + +# define XLOCALE_ISCTYPE(fname, cat) \ + _XLOCALE_INLINE int is##fname##_l(int c, locale_t l)\ + { return __sbistype_l(c, cat, l); } +#endif + +XLOCALE_ISCTYPE(alnum, _CTYPE_A|_CTYPE_D) +XLOCALE_ISCTYPE(alpha, _CTYPE_A) +XLOCALE_ISCTYPE(blank, _CTYPE_B) +XLOCALE_ISCTYPE(cntrl, _CTYPE_C) +XLOCALE_ISCTYPE(digit, _CTYPE_D) +XLOCALE_ISCTYPE(graph, _CTYPE_G) +XLOCALE_ISCTYPE(hexnumber, _CTYPE_X) +XLOCALE_ISCTYPE(ideogram, _CTYPE_I) +XLOCALE_ISCTYPE(lower, _CTYPE_L) +XLOCALE_ISCTYPE(number, _CTYPE_D) +XLOCALE_ISCTYPE(phonogram, _CTYPE_Q) +XLOCALE_ISCTYPE(print, _CTYPE_R) +XLOCALE_ISCTYPE(punct, _CTYPE_P) +XLOCALE_ISCTYPE(rune, 0xFFFFFF00L) +XLOCALE_ISCTYPE(space, _CTYPE_S) +XLOCALE_ISCTYPE(special, _CTYPE_T) +XLOCALE_ISCTYPE(upper, _CTYPE_U) +XLOCALE_ISCTYPE(xdigit, _CTYPE_X) +#undef XLOCALE_ISCTYPE + +#ifdef XLOCALE_WCTYPES +_XLOCALE_INLINE int towlower_l(int c, locale_t locale) +{ + int mb_sb_limit; + _RuneLocale *runes = __runes_for_locale(locale, &mb_sb_limit); + return (c < 0 || c >= _CACHED_RUNES) ? ___tolower_l(c, locale) : + runes->__maplower[c]; +} +_XLOCALE_INLINE int towupper_l(int c, locale_t locale) +{ + int mb_sb_limit; + _RuneLocale *runes = __runes_for_locale(locale, &mb_sb_limit); + return (c < 0 || c >= _CACHED_RUNES) ? ___toupper_l(c, locale) : + runes->__mapupper[c]; +} +_XLOCALE_INLINE int +__wcwidth_l(__ct_rune_t _c, locale_t locale) +{ + unsigned int _x; + + if (_c == 0) + return (0); + _x = (unsigned int)__maskrune_l(_c, _CTYPE_SWM|_CTYPE_R, locale); + if ((_x & _CTYPE_SWM) != 0) + return ((_x & _CTYPE_SWM) >> _CTYPE_SWS); + return ((_x & _CTYPE_R) != 0 ? 1 : -1); +} +int iswctype_l(wint_t wc, wctype_t charclass, locale_t locale); +wctype_t wctype_l(const char *property, locale_t locale); +wint_t towctrans_l(wint_t wc, wctrans_t desc, locale_t locale); +wint_t nextwctype_l(wint_t wc, wctype_t wct, locale_t locale); +wctrans_t wctrans_l(const char *charclass, locale_t locale); +#undef XLOCALE_WCTYPES +#else +_XLOCALE_INLINE int digittoint_l(int c, locale_t locale) +{ return __sbmaskrune_l((c), 0xFF, locale); } + +_XLOCALE_INLINE int tolower_l(int c, locale_t locale) +{ + int mb_sb_limit; + _RuneLocale *runes = __runes_for_locale(locale, &mb_sb_limit); + return (c < 0 || c >= mb_sb_limit) ? c : + runes->__maplower[c]; +} +_XLOCALE_INLINE int toupper_l(int c, locale_t locale) +{ + int mb_sb_limit; + _RuneLocale *runes = __runes_for_locale(locale, &mb_sb_limit); + return (c < 0 || c >= mb_sb_limit) ? c : + runes->__mapupper[c]; +} +#endif Index: include/runetype.h =================================================================== --- include/runetype.h (revision 225653) +++ include/runetype.h (working copy) @@ -83,8 +83,14 @@ } _RuneLocale; #define _RUNE_MAGIC_1 "RuneMagi" /* Indicates version 0 of RuneLocale */ - -extern _RuneLocale _DefaultRuneLocale; +__BEGIN_DECLS +extern const _RuneLocale _DefaultRuneLocale; +__attribute__((deprecated)) extern _RuneLocale *_CurrentRuneLocale; +/* TODO: This is called quite a lot, so we should use a __thread variable when + * it's available. */ +extern _RuneLocale *__getCurrentRuneLocale(void); +#define _CurrentRuneLocale (__getCurrentRuneLocale()) +__END_DECLS #endif /* !_RUNETYPE_H_ */ Index: include/stdlib.h =================================================================== --- include/stdlib.h (revision 225653) +++ include/stdlib.h (working copy) @@ -71,10 +71,11 @@ #define RAND_MAX 0x7fffffff +__BEGIN_DECLS extern int __mb_cur_max; -#define MB_CUR_MAX __mb_cur_max +extern int ___mb_cur_max(void); +#define MB_CUR_MAX (___mb_cur_max()) -__BEGIN_DECLS void abort(void) __dead2; int abs(int) __pure2; int atexit(void (*)(void)); Index: contrib/gdtoa/gdtoaimp.h =================================================================== --- contrib/gdtoa/gdtoaimp.h (revision 225653) +++ contrib/gdtoa/gdtoaimp.h (working copy) @@ -201,6 +201,7 @@ #include "namespace.h" #include #include "un-namespace.h" +#include "xlocale_private.h" #ifdef KR_headers #define Char char @@ -526,10 +527,13 @@ #define strtoIx __strtoIx #define strtoIxL __strtoIxL #define strtord __strtord +#define strtord_l __strtord_l #define strtordd __strtordd #define strtorf __strtorf #define strtorQ __strtorQ +#define strtorQ_l __strtorQ_l #define strtorx __strtorx +#define strtorx_l __strtorx_l #define strtorxL __strtorxL #define strtodI __strtodI #define strtopd __strtopd @@ -635,6 +639,7 @@ extern Bigint *set_ones ANSI((Bigint*, int)); extern char *strcp ANSI((char*, const char*)); extern int strtodg ANSI((CONST char*, char**, FPI*, Long*, ULong*)); + extern int strtodg_l ANSI((CONST char*, char**, FPI*, Long*, ULong*, locale_t)); extern int strtoId ANSI((CONST char *, char **, double *, double *)); extern int strtoIdd ANSI((CONST char *, char **, double *, double *)); @@ -644,6 +649,7 @@ extern int strtoIx ANSI((CONST char *, char **, void *, void *)); extern int strtoIxL ANSI((CONST char *, char **, void *, void *)); extern double strtod ANSI((const char *s00, char **se)); + extern double strtod_l ANSI((const char *s00, char **se, locale_t)); extern int strtopQ ANSI((CONST char *, char **, Void *)); extern int strtopf ANSI((CONST char *, char **, float *)); extern int strtopd ANSI((CONST char *, char **, double *)); @@ -651,10 +657,13 @@ extern int strtopx ANSI((CONST char *, char **, Void *)); extern int strtopxL ANSI((CONST char *, char **, Void *)); extern int strtord ANSI((CONST char *, char **, int, double *)); + extern int strtord_l ANSI((CONST char *, char **, int, double *, locale_t)); extern int strtordd ANSI((CONST char *, char **, int, double *)); extern int strtorf ANSI((CONST char *, char **, int, float *)); extern int strtorQ ANSI((CONST char *, char **, int, void *)); + extern int strtorQ_l ANSI((CONST char *, char **, int, void *, locale_t)); extern int strtorx ANSI((CONST char *, char **, int, void *)); + extern int strtorx_l ANSI((CONST char *, char **, int, void *, locale_t)); extern int strtorxL ANSI((CONST char *, char **, int, void *)); extern Bigint *sum ANSI((Bigint*, Bigint*)); extern int trailz ANSI((Bigint*)); Index: contrib/gdtoa/strtopQ.c =================================================================== --- contrib/gdtoa/strtopQ.c (revision 225653) +++ contrib/gdtoa/strtopQ.c (working copy) @@ -56,7 +56,7 @@ strtopQ(CONST char *s, char **sp, void *V) #endif { - static FPI fpi0 = { 113, 1-16383-113+1, 32766 - 16383 - 113 + 1, 1, SI }; + static const FPI fpi0 = { 113, 1-16383-113+1, 32766 - 16383 - 113 + 1, 1, SI }; ULong bits[4]; Long exp; int k; Index: contrib/gdtoa/strtorQ.c =================================================================== --- contrib/gdtoa/strtorQ.c (revision 225653) +++ contrib/gdtoa/strtorQ.c (working copy) @@ -103,9 +103,10 @@ int #ifdef KR_headers -strtorQ(s, sp, rounding, L) CONST char *s; char **sp; int rounding; void *L; +strtorQ_l(s, sp, rounding, L, locale) CONST char *s; char **sp; int rounding; +void *L; locale_t locale; #else -strtorQ(CONST char *s, char **sp, int rounding, void *L) +strtorQ_l(CONST char *s, char **sp, int rounding, void *L, locale_t locale) #endif { static FPI fpi0 = { 113, 1-16383-113+1, 32766-16383-113+1, 1, SI }; @@ -120,7 +121,17 @@ fpi1.rounding = rounding; fpi = &fpi1; } - k = strtodg(s, sp, fpi, &exp, bits); + k = strtodg_l(s, sp, fpi, &exp, bits, locale); ULtoQ((ULong*)L, bits, exp, k); return k; } + + int +#ifdef KR_headers +strtorQ(s, sp, rounding, L) CONST char *s; char **sp; int rounding; void *L; +#else +strtorQ(CONST char *s, char **sp, int rounding, void *L) +#endif +{ + return strtorQ_l(s, sp, rounding, L, __get_locale()); +} Index: contrib/gdtoa/strtodg.c =================================================================== --- contrib/gdtoa/strtodg.c (revision 225653) +++ contrib/gdtoa/strtodg.c (working copy) @@ -34,6 +34,7 @@ #ifdef USE_LOCALE #include "locale.h" #endif +#include "xlocale_private.h" static CONST int fivesbits[] = { 0, 3, 5, 7, 10, 12, 14, 17, 19, 21, @@ -313,12 +314,12 @@ } int -strtodg +strtodg_l #ifdef KR_headers - (s00, se, fpi, exp, bits) - CONST char *s00; char **se; FPI *fpi; Long *exp; ULong *bits; + (s00, se, fpi, exp, bits, l) + CONST char *s00; char **se; FPI *fpi; Long *exp; ULong *bits; locale_t l; #else - (CONST char *s00, char **se, FPI *fpi, Long *exp, ULong *bits) + (CONST char *s00, char **se, FPI *fpi, Long *exp, ULong *bits, locale_t l) #endif { int abe, abits, asub; @@ -334,14 +335,14 @@ Bigint *ab, *bb, *bb1, *bd, *bd0, *bs, *delta, *rvb, *rvb0; #ifdef USE_LOCALE /*{{*/ #ifdef NO_LOCALE_CACHE - char *decimalpoint = localeconv()->decimal_point; + char *decimalpoint = localeconv_l(l)->decimal_point; int dplen = strlen(decimalpoint); #else char *decimalpoint; static char *decimalpoint_cache; static int dplen; if (!(s0 = decimalpoint_cache)) { - s0 = localeconv()->decimal_point; + s0 = localeconv_l(l)->decimal_point; if ((decimalpoint_cache = (char*)MALLOC(strlen(s0) + 1))) { strcpy(decimalpoint_cache, s0); s0 = decimalpoint_cache; @@ -1063,3 +1064,15 @@ } return irv; } + + int +strtodg +#ifdef KR_headers + (s00, se, fpi, exp, bits) + CONST char *s00; char **se; FPI *fpi; Long *exp; ULong *bits; +#else + (CONST char *s00, char **se, FPI *fpi, Long *exp, ULong *bits) +#endif +{ + return strtodg_l(s00, se, fpi, exp, bits, __get_locale()); +} Index: contrib/gdtoa/strtord.c =================================================================== --- contrib/gdtoa/strtord.c (revision 225653) +++ contrib/gdtoa/strtord.c (working copy) @@ -70,9 +70,10 @@ int #ifdef KR_headers -strtord(s, sp, rounding, d) CONST char *s; char **sp; int rounding; double *d; +strtord_l(s, sp, rounding, d, locale) CONST char *s; char **sp; int rounding; +double *d; locale_t locale; #else -strtord(CONST char *s, char **sp, int rounding, double *d) +strtord_l(CONST char *s, char **sp, int rounding, double *d, locale_t locale) #endif { static FPI fpi0 = { 53, 1-1023-53+1, 2046-1023-53+1, 1, SI }; @@ -87,7 +88,17 @@ fpi1.rounding = rounding; fpi = &fpi1; } - k = strtodg(s, sp, fpi, &exp, bits); + k = strtodg_l(s, sp, fpi, &exp, bits, locale); ULtod((ULong*)d, bits, exp, k); return k; } + int +#ifdef KR_headers +strtord(s, sp, rounding, L, locale) CONST char *s; char **sp; int rounding; +void *L; +#else +strtord(CONST char *s, char **sp, int rounding, double *d) +#endif +{ + return strtord_l(s, sp, rounding, d, __get_locale()); +} Index: contrib/gdtoa/strtod.c =================================================================== --- contrib/gdtoa/strtod.c (revision 225653) +++ contrib/gdtoa/strtod.c (working copy) @@ -39,6 +39,7 @@ #ifdef USE_LOCALE #include "locale.h" #endif +#include "xlocale_private.h" #ifdef IEEE_Arith #ifndef NO_IEEE_Scale @@ -82,11 +83,11 @@ #endif /*}*/ double -strtod +strtod_l #ifdef KR_headers - (s00, se) CONST char *s00; char **se; + (s00, se, l) CONST char *s00; char **se; locale_t l #else - (CONST char *s00, char **se) + (CONST char *s00, char **se, locale_t l) #endif { #ifdef Avoid_Underflow @@ -108,14 +109,14 @@ #endif #ifdef USE_LOCALE /*{{*/ #ifdef NO_LOCALE_CACHE - char *decimalpoint = localeconv()->decimal_point; + char *decimalpoint = localeconv_l(l)->decimal_point; int dplen = strlen(decimalpoint); #else char *decimalpoint; static char *decimalpoint_cache; static int dplen; if (!(s0 = decimalpoint_cache)) { - s0 = localeconv()->decimal_point; + s0 = localeconv_l(l)->decimal_point; if ((decimalpoint_cache = (char*)MALLOC(strlen(s0) + 1))) { strcpy(decimalpoint_cache, s0); s0 = decimalpoint_cache; @@ -168,7 +169,7 @@ if (*s == '0') { #ifndef NO_HEX_FP /*{*/ { - static FPI fpi = { 53, 1-1023-53+1, 2046-1023-53+1, 1, SI }; + static const FPI fpi = { 53, 1-1023-53+1, 2046-1023-53+1, 1, SI }; Long exp; ULong bits[2]; switch(s[1]) { @@ -295,7 +296,7 @@ #ifdef INFNAN_CHECK /* Check for Nan and Infinity */ ULong bits[2]; - static FPI fpinan = /* only 52 explicit bits */ + static const FPI fpinan = /* only 52 explicit bits */ { 52, 1-1023-53+1, 2046-1023-53+1, 1, SI }; if (!decpt) switch(c) { @@ -1074,3 +1075,13 @@ return sign ? -dval(&rv) : dval(&rv); } + double +strtod +#ifdef KR_headers + (s00, se, l) CONST char *s00; char **se; locale_t +#else + (CONST char *s00, char **se) +#endif +{ + return strtod_l(s00, se, __get_locale()); +} Index: contrib/gdtoa/strtof.c =================================================================== --- contrib/gdtoa/strtof.c (revision 225653) +++ contrib/gdtoa/strtof.c (working copy) @@ -32,15 +32,16 @@ /* $FreeBSD$ */ #include "gdtoaimp.h" +#include "xlocale_private.h" float #ifdef KR_headers -strtof(s, sp) CONST char *s; char **sp; +strtof_l(s, sp, l) CONST char *s; char **sp; locale_t l; #else -strtof(CONST char *s, char **sp) +strtof_l(CONST char *s, char **sp, locale_t l) #endif { - static FPI fpi0 = { 24, 1-127-24+1, 254-127-24+1, 1, SI }; + static const FPI fpi0 = { 24, 1-127-24+1, 254-127-24+1, 1, SI }; ULong bits[1]; Long exp; int k; @@ -51,7 +52,7 @@ #define fpi &fpi0 #endif - k = strtodg(s, sp, fpi, &exp, bits); + k = strtodg_l(s, sp, fpi, &exp, bits, l); switch(k & STRTOG_Retmask) { case STRTOG_NoNumber: case STRTOG_Zero: @@ -82,3 +83,13 @@ u.L[0] |= 0x80000000L; return u.f; } + + float +#ifdef KR_headers +strtof(s, sp) CONST char *s; char **sp; +#else +strtof(CONST char *s, char **sp) +#endif +{ + return strtof_l(s, sp, __get_locale()); +} Index: contrib/gdtoa/strtorx.c =================================================================== --- contrib/gdtoa/strtorx.c (revision 225653) +++ contrib/gdtoa/strtorx.c (working copy) @@ -106,9 +106,10 @@ int #ifdef KR_headers -strtorx(s, sp, rounding, L) CONST char *s; char **sp; int rounding; void *L; +strtorx_l(s, sp, rounding, L, locale) CONST char *s; char **sp; int rounding; +void *L; locale_t locale; #else -strtorx(CONST char *s, char **sp, int rounding, void *L) +strtorx_l(CONST char *s, char **sp, int rounding, void *L, locale_t locale) #endif { static FPI fpi0 = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, SI }; @@ -123,7 +124,16 @@ fpi1.rounding = rounding; fpi = &fpi1; } - k = strtodg(s, sp, fpi, &exp, bits); + k = strtodg_l(s, sp, fpi, &exp, bits, locale); ULtox((UShort*)L, bits, exp, k); return k; } + int +#ifdef KR_headers +strtorx(s, sp, rounding, L) CONST char *s; char **sp; int rounding; void *L; +#else +strtorx(CONST char *s, char **sp, int rounding, void *L) +#endif +{ + return strtorx_l(s, sp, rounding, L, __get_locale()); +} Index: share/monetdef/zh_CN.UTF-8.src =================================================================== --- share/monetdef/zh_CN.UTF-8.src (revision 225653) +++ share/monetdef/zh_CN.UTF-8.src (working copy) @@ -18,9 +18,9 @@ # negative_sign - # int_frac_digits -0 +2 # frac_digits -0 +2 # p_cs_precedes 1 # p_sep_by_space Index: lib/msun/src/math.h =================================================================== --- lib/msun/src/math.h (revision 225653) +++ lib/msun/src/math.h (working copy) @@ -398,32 +398,32 @@ * long double versions of ISO/POSIX math functions */ #if __ISO_C_VISIBLE >= 1999 -#if 0 +#if !__NO_IMPRECISE_LIBM_FUNCTIONS long double acoshl(long double); #endif long double acosl(long double); -#if 0 +#if !__NO_IMPRECISE_LIBM_FUNCTIONS long double asinhl(long double); #endif long double asinl(long double); long double atan2l(long double, long double); -#if 0 +#if !__NO_IMPRECISE_LIBM_FUNCTIONS long double atanhl(long double); #endif long double atanl(long double); long double cbrtl(long double); long double ceill(long double); long double copysignl(long double, long double) __pure2; -#if 0 +#if !__NO_IMPRECISE_LIBM_FUNCTIONS long double coshl(long double); #endif long double cosl(long double); -#if 0 +#if !__NO_IMPRECISE_LIBM_FUNCTIONS long double erfcl(long double); long double erfl(long double); #endif long double exp2l(long double); -#if 0 +#if !__NO_IMPRECISE_LIBM_FUNCTIONS long double expl(long double); long double expm1l(long double); #endif @@ -438,18 +438,18 @@ long double hypotl(long double, long double); int ilogbl(long double) __pure2; long double ldexpl(long double, int); -#if 0 +#if !__NO_IMPRECISE_LIBM_FUNCTIONS long double lgammal(long double); #endif long long llrintl(long double); long long llroundl(long double); -#if 0 +#if !__NO_IMPRECISE_LIBM_FUNCTIONS long double log10l(long double); long double log1pl(long double); long double log2l(long double); #endif long double logbl(long double); -#if 0 +#if !__NO_IMPRECISE_LIBM_FUNCTIONS long double logl(long double); #endif long lrintl(long double); @@ -461,7 +461,7 @@ double nexttoward(double, long double); float nexttowardf(float, long double); long double nexttowardl(long double, long double); -#if 0 +#if !__NO_IMPRECISE_LIBM_FUNCTIONS long double powl(long double, long double); #endif long double remainderl(long double, long double); @@ -470,16 +470,16 @@ long double roundl(long double); long double scalblnl(long double, long); long double scalbnl(long double, int); -#if 0 +#if !__NO_IMPRECISE_LIBM_FUNCTIONS long double sinhl(long double); #endif long double sinl(long double); long double sqrtl(long double); -#if 0 +#if !__NO_IMPRECISE_LIBM_FUNCTIONS long double tanhl(long double); #endif long double tanl(long double); -#if 0 +#if !__NO_IMPRECISE_LIBM_FUNCTIONS long double tgammal(long double); #endif long double truncl(long double); Index: lib/msun/src/stubs.c =================================================================== --- lib/msun/src/stubs.c (revision 0) +++ lib/msun/src/stubs.c (revision 0) @@ -0,0 +1,22 @@ +#include + +#define LIBCXX_LONG_DOUBLE_STUB(fn) __attribute__((weak)) long double fn ## l(long double x) { return fn(x); } +#define LIBCXX_LONG_DOUBLE_STUB2(fn) __attribute__((weak)) long double fn ## l(long double x, long double y) { return fn(x, y); } + +LIBCXX_LONG_DOUBLE_STUB(cosh) +LIBCXX_LONG_DOUBLE_STUB(asinh) +LIBCXX_LONG_DOUBLE_STUB(atanh) +LIBCXX_LONG_DOUBLE_STUB(acosh) +LIBCXX_LONG_DOUBLE_STUB(erfc) +LIBCXX_LONG_DOUBLE_STUB(erf) +LIBCXX_LONG_DOUBLE_STUB(exp) +LIBCXX_LONG_DOUBLE_STUB(expm1) +LIBCXX_LONG_DOUBLE_STUB(lgamma) +LIBCXX_LONG_DOUBLE_STUB(log10) +LIBCXX_LONG_DOUBLE_STUB(log1p) +LIBCXX_LONG_DOUBLE_STUB(log2) +LIBCXX_LONG_DOUBLE_STUB(log) +LIBCXX_LONG_DOUBLE_STUB(tanh) +LIBCXX_LONG_DOUBLE_STUB(sinh) +LIBCXX_LONG_DOUBLE_STUB(tgamma) +LIBCXX_LONG_DOUBLE_STUB2(pow) Index: lib/msun/Makefile =================================================================== --- lib/msun/Makefile (revision 225653) +++ lib/msun/Makefile (working copy) @@ -70,7 +70,7 @@ s_scalbln.c s_scalbn.c s_scalbnf.c s_signbit.c \ s_signgam.c s_significand.c s_significandf.c s_sin.c s_sinf.c \ s_tan.c s_tanf.c s_tanh.c s_tanhf.c s_tgammaf.c s_trunc.c s_truncf.c \ - w_cabs.c w_cabsf.c w_drem.c w_dremf.c + w_cabs.c w_cabsf.c w_drem.c w_dremf.c stubs.c # Location of fpmath.h and _fpmath.h LIBCDIR= ${.CURDIR}/../libc Index: lib/libc/stdlib/Symbol.map =================================================================== --- lib/libc/stdlib/Symbol.map (revision 225653) +++ lib/libc/stdlib/Symbol.map (working copy) @@ -90,6 +90,21 @@ tfind; tsearch; twalk; + atof_l; + atoi_l; + atol_l; + atoll_l; + strtod_l; + strtol_l; + strtoll_l; + strtof_l; + strtoimax_l; + strtold_l; + strtoq_l; + strtoul_l; + strtoull_l; + strtoumax_l; + strtouq_l; }; FBSDprivate_1.0 { Index: lib/libc/stdlib/atoll.c =================================================================== --- lib/libc/stdlib/atoll.c (revision 225653) +++ lib/libc/stdlib/atoll.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -31,6 +36,7 @@ __FBSDID("$FreeBSD$"); #include +#include long long atoll(str) @@ -38,3 +44,11 @@ { return strtoll(str, (char **)NULL, 10); } + +long long +atoll_l(str, locale) + const char *str; + locale_t locale; +{ + return strtoll_l(str, (char **)NULL, 10, locale); +} Index: lib/libc/stdlib/strfmon.c =================================================================== --- lib/libc/stdlib/strfmon.c (revision 225653) +++ lib/libc/stdlib/strfmon.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2001 Alexey Zelkin * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -38,6 +43,7 @@ #include #include #include +#include "xlocale_private.h" /* internal flags */ #define NEED_GROUPING 0x01 /* print digits grouped (default) */ @@ -92,11 +98,10 @@ static int __calc_left_pad(int, char *); static char *__format_grouped_double(double, int *, int, int, int); -ssize_t -strfmon(char * __restrict s, size_t maxsize, const char * __restrict format, - ...) +static ssize_t +vstrfmon_l(char * __restrict s, size_t maxsize, locale_t loc, + const char * __restrict format, va_list ap) { - va_list ap; char *dst; /* output destination pointer */ const char *fmt; /* current format poistion pointer */ struct lconv *lc; /* pointer to lconv structure */ @@ -119,10 +124,10 @@ char *tmpptr; /* temporary vars */ int sverrno; + FIX_LOCALE(loc); - va_start(ap, format); - lc = localeconv(); + lc = localeconv_l(loc); dst = s; fmt = format; asciivalue = NULL; @@ -380,7 +385,6 @@ } PRINT('\0'); - va_end(ap); free(asciivalue); free(currency_symbol); return (dst - s - 1); /* return size of put data except trailing '\0' */ @@ -399,10 +403,34 @@ if (currency_symbol != NULL) free(currency_symbol); errno = sverrno; - va_end(ap); return (-1); } +ssize_t +strfmon_l(char * __restrict s, size_t maxsize, locale_t loc, const char * __restrict format, + ...) +{ + size_t ret; + va_list ap; + FIX_LOCALE(loc); + va_start(ap, format); + ret = vstrfmon_l(s, maxsize, loc, format, ap); + va_end(ap); + return ret; +} +ssize_t +strfmon(char * __restrict s, size_t maxsize, const char * __restrict format, + ...) +{ + size_t ret; + va_list ap; + va_start(ap, format); + ret = vstrfmon_l(s, maxsize, __get_locale(), format, ap); + va_end(ap); + return ret; +} + + static void __setup_vars(int flags, char *cs_precedes, char *sep_by_space, char *sign_posn, char **signstr) { Index: lib/libc/stdlib/atof.c =================================================================== --- lib/libc/stdlib/atof.c (revision 225653) +++ lib/libc/stdlib/atof.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -34,6 +39,7 @@ __FBSDID("$FreeBSD$"); #include +#include double atof(ascii) @@ -41,3 +47,11 @@ { return strtod(ascii, (char **)NULL); } + +double +atof_l(ascii, locale) + const char *ascii; + locale_t locale; +{ + return strtod_l(ascii, (char **)NULL, locale); +} Index: lib/libc/stdlib/strtoimax.c =================================================================== --- lib/libc/stdlib/strtoimax.c (revision 225653) +++ lib/libc/stdlib/strtoimax.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -37,6 +42,7 @@ #include #include #include +#include "xlocale_private.h" /* * Convert a string to an intmax_t integer. @@ -45,13 +51,15 @@ * alphabets and digits are each contiguous. */ intmax_t -strtoimax(const char * __restrict nptr, char ** __restrict endptr, int base) +strtoimax_l(const char * __restrict nptr, char ** __restrict endptr, int base, + locale_t locale) { const char *s; uintmax_t acc; char c; uintmax_t cutoff; int neg, any, cutlim; + FIX_LOCALE(locale); /* * Skip white space and pick up leading +/- sign if any. @@ -61,7 +69,7 @@ s = nptr; do { c = *s++; - } while (isspace((unsigned char)c)); + } while (isspace_l((unsigned char)c, locale)); if (c == '-') { neg = 1; c = *s++; @@ -138,3 +146,8 @@ *endptr = (char *)(any ? s - 1 : nptr); return (acc); } +intmax_t +strtoimax(const char * __restrict nptr, char ** __restrict endptr, int base) +{ + return strtoimax_l(nptr, endptr, base, __get_locale()); +} Index: lib/libc/stdlib/atol.c =================================================================== --- lib/libc/stdlib/atol.c (revision 225653) +++ lib/libc/stdlib/atol.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -34,6 +39,7 @@ __FBSDID("$FreeBSD$"); #include +#include long atol(str) @@ -41,3 +47,11 @@ { return strtol(str, (char **)NULL, 10); } + +long +atol_l(str, locale) + const char *str; + locale_t locale; +{ + return strtol_l(str, (char **)NULL, 10, locale); +} Index: lib/libc/stdlib/strtoumax.c =================================================================== --- lib/libc/stdlib/strtoumax.c (revision 225653) +++ lib/libc/stdlib/strtoumax.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -37,6 +42,7 @@ #include #include #include +#include "xlocale_private.h" /* * Convert a string to a uintmax_t integer. @@ -45,13 +51,15 @@ * alphabets and digits are each contiguous. */ uintmax_t -strtoumax(const char * __restrict nptr, char ** __restrict endptr, int base) +strtoumax_l(const char * __restrict nptr, char ** __restrict endptr, int base, + locale_t locale) { const char *s; uintmax_t acc; char c; uintmax_t cutoff; int neg, any, cutlim; + FIX_LOCALE(locale); /* * See strtoimax for comments as to the logic used. @@ -59,7 +67,7 @@ s = nptr; do { c = *s++; - } while (isspace((unsigned char)c)); + } while (isspace_l((unsigned char)c, locale)); if (c == '-') { neg = 1; c = *s++; @@ -116,3 +124,8 @@ *endptr = (char *)(any ? s - 1 : nptr); return (acc); } +uintmax_t +strtoumax(const char * __restrict nptr, char ** __restrict endptr, int base) +{ + return strtoumax_l(nptr, endptr, base, __get_locale()); +} Index: lib/libc/stdlib/strtoul.c =================================================================== --- lib/libc/stdlib/strtoul.c (revision 225653) +++ lib/libc/stdlib/strtoul.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -37,6 +42,7 @@ #include #include #include +#include "xlocale_private.h" /* * Convert a string to an unsigned long integer. @@ -45,13 +51,14 @@ * alphabets and digits are each contiguous. */ unsigned long -strtoul(const char * __restrict nptr, char ** __restrict endptr, int base) +strtoul_l(const char * __restrict nptr, char ** __restrict endptr, int base, locale_t locale) { const char *s; unsigned long acc; char c; unsigned long cutoff; int neg, any, cutlim; + FIX_LOCALE(locale); /* * See strtol for comments as to the logic used. @@ -59,7 +66,7 @@ s = nptr; do { c = *s++; - } while (isspace((unsigned char)c)); + } while (isspace_l((unsigned char)c, locale)); if (c == '-') { neg = 1; c = *s++; @@ -116,3 +123,8 @@ *endptr = (char *)(any ? s - 1 : nptr); return (acc); } +unsigned long +strtoul(const char * __restrict nptr, char ** __restrict endptr, int base) +{ + return strtoul_l(nptr, endptr, base, __get_locale()); +} Index: lib/libc/stdlib/strtoull.c =================================================================== --- lib/libc/stdlib/strtoull.c (revision 225653) +++ lib/libc/stdlib/strtoull.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -37,6 +42,7 @@ #include #include #include +#include "xlocale_private.h" /* * Convert a string to an unsigned long long integer. @@ -45,13 +51,15 @@ * alphabets and digits are each contiguous. */ unsigned long long -strtoull(const char * __restrict nptr, char ** __restrict endptr, int base) +strtoull_l(const char * __restrict nptr, char ** __restrict endptr, int base, + locale_t locale) { const char *s; unsigned long long acc; char c; unsigned long long cutoff; int neg, any, cutlim; + FIX_LOCALE(locale); /* * See strtoq for comments as to the logic used. @@ -59,7 +67,7 @@ s = nptr; do { c = *s++; - } while (isspace((unsigned char)c)); + } while (isspace_l((unsigned char)c, locale)); if (c == '-') { neg = 1; c = *s++; @@ -116,3 +124,8 @@ *endptr = (char *)(any ? s - 1 : nptr); return (acc); } +unsigned long long +strtoull(const char * __restrict nptr, char ** __restrict endptr, int base) +{ + return strtoull_l(nptr, endptr, base, __get_locale()); +} Index: lib/libc/stdlib/strtoll.c =================================================================== --- lib/libc/stdlib/strtoll.c (revision 225653) +++ lib/libc/stdlib/strtoll.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -37,6 +42,7 @@ #include #include #include +#include /* * Convert a string to a long long integer. @@ -45,13 +51,15 @@ * alphabets and digits are each contiguous. */ long long -strtoll(const char * __restrict nptr, char ** __restrict endptr, int base) +strtoll_l(const char * __restrict nptr, char ** __restrict endptr, int base, + locale_t locale) { const char *s; unsigned long long acc; char c; unsigned long long cutoff; int neg, any, cutlim; + FIX_LOCALE(locale); /* * Skip white space and pick up leading +/- sign if any. @@ -61,7 +69,7 @@ s = nptr; do { c = *s++; - } while (isspace((unsigned char)c)); + } while (isspace_l((unsigned char)c, locale)); if (c == '-') { neg = 1; c = *s++; @@ -138,3 +146,8 @@ *endptr = (char *)(any ? s - 1 : nptr); return (acc); } +long long +strtoll(const char * __restrict nptr, char ** __restrict endptr, int base) +{ + return strtoll_l(nptr, endptr, base, __get_locale()); +} Index: lib/libc/stdlib/strtol.c =================================================================== --- lib/libc/stdlib/strtol.c (revision 225653) +++ lib/libc/stdlib/strtol.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -37,6 +42,7 @@ #include #include #include +#include "xlocale_private.h" /* @@ -46,13 +52,15 @@ * alphabets and digits are each contiguous. */ long -strtol(const char * __restrict nptr, char ** __restrict endptr, int base) +strtol_l(const char * __restrict nptr, char ** __restrict endptr, int base, + locale_t locale) { const char *s; unsigned long acc; char c; unsigned long cutoff; int neg, any, cutlim; + FIX_LOCALE(locale); /* * Skip white space and pick up leading +/- sign if any. @@ -62,7 +70,7 @@ s = nptr; do { c = *s++; - } while (isspace((unsigned char)c)); + } while (isspace_l((unsigned char)c, locale)); if (c == '-') { neg = 1; c = *s++; @@ -138,3 +146,13 @@ *endptr = (char *)(any ? s - 1 : nptr); return (acc); } +long +strtol(const char * __restrict nptr, char ** __restrict endptr, int base) +{ + return strtol_l(nptr, endptr, base, __get_locale()); +} +long double +strtold(const char * __restrict nptr, char ** __restrict endptr) +{ + return strtold_l(nptr, endptr, __get_locale()); +} Index: lib/libc/stdlib/atoi.c =================================================================== --- lib/libc/stdlib/atoi.c (revision 225653) +++ lib/libc/stdlib/atoi.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -34,6 +39,7 @@ __FBSDID("$FreeBSD$"); #include +#include int atoi(str) @@ -41,3 +47,11 @@ { return (int)strtol(str, (char **)NULL, 10); } + +int +atoi_l(str, locale) + const char *str; + locale_t locale; +{ + return (int)strtol_l(str, (char **)NULL, 10, locale); +} Index: lib/libc/stdio/putwc.c =================================================================== --- lib/libc/stdio/putwc.c (revision 225653) +++ lib/libc/stdio/putwc.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -33,6 +38,7 @@ #include "un-namespace.h" #include "libc_private.h" #include "local.h" +#include "xlocale_private.h" #undef putwc @@ -41,8 +47,13 @@ * macro, may evaluate `fp' more than once. */ wint_t +putwc_l(wchar_t wc, FILE *fp, locale_t locale) +{ + FIX_LOCALE(locale); + return (fputwc_l(wc, fp, locale)); +} +wint_t putwc(wchar_t wc, FILE *fp) { - - return (fputwc(wc, fp)); + return putwc_l(wc, fp, __get_locale()); } Index: lib/libc/stdio/printf.c =================================================================== --- lib/libc/stdio/printf.c (revision 225653) +++ lib/libc/stdio/printf.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Chris Torek. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -38,6 +43,7 @@ #include #include +#include int printf(char const * __restrict fmt, ...) @@ -50,3 +56,14 @@ va_end(ap); return (ret); } +int +printf_l(locale_t locale, char const * __restrict fmt, ...) +{ + int ret; + va_list ap; + + va_start(ap, fmt); + ret = vfprintf_l(stdout, locale, fmt, ap); + va_end(ap); + return (ret); +} Index: lib/libc/stdio/getwchar.c =================================================================== --- lib/libc/stdio/getwchar.c (revision 225653) +++ lib/libc/stdio/getwchar.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -30,6 +35,7 @@ #include "namespace.h" #include #include +#include #include "un-namespace.h" #include "libc_private.h" #include "local.h" @@ -42,6 +48,10 @@ wint_t getwchar(void) { - return (fgetwc(stdin)); } +wint_t +getwchar_l(locale_t locale) +{ + return (fgetwc_l(stdin, locale)); +} Index: lib/libc/stdio/Symbol.map =================================================================== --- lib/libc/stdio/Symbol.map (revision 225653) +++ lib/libc/stdio/Symbol.map (working copy) @@ -108,6 +108,43 @@ __swbuf; wprintf; wscanf; + asprintf_l; + fprintf_l; + fwprintf_l; + printf_l; + snprintf_l; + sprintf_l; + swprintf_l; + vasprintf_l; + vfprintf_l; + vfwprintf_l; + vprintf_l; + vsnprintf_l; + vsprintf_l; + vswprintf_l; + vwprintf_l; + wprintf_l; + fgetwc_l; + fputwc_l; + ungetwc_l; + vfwscanf_l; + vswscanf_l; + fscanf_l; + fwscanf_l; + scanf_l; + sscanf_l; + swscanf_l; + vfscanf_l; + vscanf_l; + vsscanf_l; + vwscanf_l; + wscanf_l; + fgetws_l; + fputws_l; + getwc_l; + getwchar_l; + putwc_l; + putwchar_l; }; FBSD_1.1 { Index: lib/libc/stdio/fgetwln.c =================================================================== --- lib/libc/stdio/fgetwln.c (revision 225653) +++ lib/libc/stdio/fgetwln.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002-2004 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -33,18 +38,20 @@ #include "un-namespace.h" #include "libc_private.h" #include "local.h" +#include "xlocale_private.h" wchar_t * -fgetwln(FILE * __restrict fp, size_t *lenp) +fgetwln_l(FILE * __restrict fp, size_t *lenp, locale_t locale) { wint_t wc; size_t len; + FIX_LOCALE(locale); FLOCKFILE(fp); ORIENT(fp, 1); len = 0; - while ((wc = __fgetwc(fp)) != WEOF) { + while ((wc = __fgetwc(fp, locale)) != WEOF) { #define GROW 512 if (len * sizeof(wchar_t) >= fp->_lb._size && __slbexpand(fp, (len + GROW) * sizeof(wchar_t))) @@ -65,3 +72,8 @@ *lenp = 0; return (NULL); } +wchar_t * +fgetwln(FILE * __restrict fp, size_t *lenp) +{ + return fgetwln_l(fp, lenp, __get_locale()); +} Index: lib/libc/stdio/getwc.c =================================================================== --- lib/libc/stdio/getwc.c (revision 225653) +++ lib/libc/stdio/getwc.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -30,6 +35,7 @@ #include "namespace.h" #include #include +#include #include "un-namespace.h" #include "libc_private.h" #include "local.h" @@ -43,6 +49,10 @@ wint_t getwc(FILE *fp) { - return (fgetwc(fp)); } +wint_t +getwc_l(FILE *fp, locale_t locale) +{ + return (fgetwc_l(fp, locale)); +} Index: lib/libc/stdio/vsnprintf.c =================================================================== --- lib/libc/stdio/vsnprintf.c (revision 225653) +++ lib/libc/stdio/vsnprintf.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Chris Torek. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -39,15 +44,17 @@ #include #include #include "local.h" +#include "xlocale_private.h" int -vsnprintf(char * __restrict str, size_t n, const char * __restrict fmt, - __va_list ap) +vsnprintf_l(char * __restrict str, size_t n, locale_t locale, + const char * __restrict fmt, __va_list ap) { size_t on; int ret; char dummy[2]; FILE f = FAKE_FILE; + FIX_LOCALE(locale); on = n; if (n != 0) @@ -64,8 +71,14 @@ f._flags = __SWR | __SSTR; f._bf._base = f._p = (unsigned char *)str; f._bf._size = f._w = n; - ret = __vfprintf(&f, fmt, ap); + ret = __vfprintf(&f, locale, fmt, ap); if (on > 0) *f._p = '\0'; return (ret); } +int +vsnprintf(char * __restrict str, size_t n, const char * __restrict fmt, + __va_list ap) +{ + return vsnprintf_l(str, n, __get_locale(), fmt, ap); +} Index: lib/libc/stdio/putwchar.c =================================================================== --- lib/libc/stdio/putwchar.c (revision 225653) +++ lib/libc/stdio/putwchar.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -33,6 +38,7 @@ #include "un-namespace.h" #include "libc_private.h" #include "local.h" +#include "xlocale_private.h" #undef putwchar @@ -40,8 +46,13 @@ * Synonym for fputwc(wc, stdout). */ wint_t +putwchar_l(wchar_t wc, locale_t locale) +{ + FIX_LOCALE(locale); + return (fputwc_l(wc, stdout, locale)); +} +wint_t putwchar(wchar_t wc) { - - return (fputwc(wc, stdout)); + return putwchar_l(wc, __get_locale()); } Index: lib/libc/stdio/vswprintf.c =================================================================== --- lib/libc/stdio/vswprintf.c (revision 225653) +++ lib/libc/stdio/vswprintf.c (working copy) @@ -4,6 +4,11 @@ * Copyright (c) 1997 Todd C. Miller * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -38,10 +43,11 @@ #include #include #include "local.h" +#include "xlocale_private.h" int -vswprintf(wchar_t * __restrict s, size_t n, const wchar_t * __restrict fmt, - __va_list ap) +vswprintf_l(wchar_t * __restrict s, size_t n, locale_t locale, + const wchar_t * __restrict fmt, __va_list ap) { static const mbstate_t initial; mbstate_t mbs; @@ -49,6 +55,7 @@ char *mbp; int ret, sverrno; size_t nwc; + FIX_LOCALE(locale); if (n == 0) { errno = EINVAL; @@ -62,7 +69,7 @@ return (-1); } f._bf._size = f._w = 127; /* Leave room for the NUL */ - ret = __vfwprintf(&f, fmt, ap); + ret = __vfwprintf(&f, locale, fmt, ap); if (ret < 0) { sverrno = errno; free(f._bf._base); @@ -76,7 +83,7 @@ * fputwc() did in __vfwprintf(). */ mbs = initial; - nwc = mbsrtowcs(s, (const char **)&mbp, n, &mbs); + nwc = mbsrtowcs_l(s, (const char **)&mbp, n, &mbs, locale); free(f._bf._base); if (nwc == (size_t)-1) { errno = EILSEQ; @@ -90,3 +97,9 @@ return (ret); } +int +vswprintf(wchar_t * __restrict s, size_t n, const wchar_t * __restrict fmt, + __va_list ap) +{ + return vswprintf_l(s, n, __get_locale(), fmt, ap); +} Index: lib/libc/stdio/vsscanf.c =================================================================== --- lib/libc/stdio/vsscanf.c (revision 225653) +++ lib/libc/stdio/vsscanf.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * This code is derived from software contributed to Berkeley by * Donn Seeley at UUNET Technologies, Inc. * @@ -39,6 +44,7 @@ #include #include #include "local.h" +#include "xlocale_private.h" static int eofread(void *, char *, int); @@ -52,14 +58,21 @@ } int -vsscanf(const char * __restrict str, const char * __restrict fmt, - __va_list ap) +vsscanf_l(const char * __restrict str, locale_t locale, + const char * __restrict fmt, __va_list ap) { FILE f = FAKE_FILE; + FIX_LOCALE(locale); f._flags = __SRD; f._bf._base = f._p = (unsigned char *)str; f._bf._size = f._r = strlen(str); f._read = eofread; - return (__svfscanf(&f, fmt, ap)); + return (__svfscanf(&f, locale, fmt, ap)); } +int +vsscanf(const char * __restrict str, const char * __restrict fmt, + __va_list ap) +{ + return vsscanf_l(str, __get_locale(), fmt, ap); +} Index: lib/libc/stdio/snprintf.c =================================================================== --- lib/libc/stdio/snprintf.c (revision 225653) +++ lib/libc/stdio/snprintf.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * This code is derived from software contributed to Berkeley by * Chris Torek. * @@ -39,6 +44,7 @@ #include #include #include +#include "xlocale_private.h" #include "local.h" @@ -59,9 +65,34 @@ f._flags = __SWR | __SSTR; f._bf._base = f._p = (unsigned char *)str; f._bf._size = f._w = n; - ret = __vfprintf(&f, fmt, ap); + ret = __vfprintf(&f, __get_locale(), fmt, ap); if (on > 0) *f._p = '\0'; va_end(ap); return (ret); } +int +snprintf_l(char * __restrict str, size_t n, locale_t locale, + char const * __restrict fmt, ...) +{ + size_t on; + int ret; + va_list ap; + FILE f = FAKE_FILE; + FIX_LOCALE(locale); + + on = n; + if (n != 0) + n--; + if (n > INT_MAX) + n = INT_MAX; + va_start(ap, fmt); + f._flags = __SWR | __SSTR; + f._bf._base = f._p = (unsigned char *)str; + f._bf._size = f._w = n; + ret = __vfprintf(&f, locale, fmt, ap); + if (on > 0) + *f._p = '\0'; + va_end(ap); + return (ret); +} Index: lib/libc/stdio/ungetwc.c =================================================================== --- lib/libc/stdio/ungetwc.c (revision 225653) +++ lib/libc/stdio/ungetwc.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002-2004 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -37,19 +42,21 @@ #include "libc_private.h" #include "local.h" #include "mblocal.h" +#include "xlocale_private.h" /* * Non-MT-safe version. */ wint_t -__ungetwc(wint_t wc, FILE *fp) +__ungetwc(wint_t wc, FILE *fp, locale_t locale) { char buf[MB_LEN_MAX]; size_t len; + struct xlocale_ctype *l = XLOCALE_CTYPE(locale); if (wc == WEOF) return (WEOF); - if ((len = __wcrtomb(buf, wc, &fp->_mbstate)) == (size_t)-1) { + if ((len = l->__wcrtomb(buf, wc, &fp->_mbstate)) == (size_t)-1) { fp->_flags |= __SERR; return (WEOF); } @@ -64,14 +71,20 @@ * MT-safe version. */ wint_t -ungetwc(wint_t wc, FILE *fp) +ungetwc_l(wint_t wc, FILE *fp, locale_t locale) { wint_t r; + FIX_LOCALE(locale); FLOCKFILE(fp); ORIENT(fp, 1); - r = __ungetwc(wc, fp); + r = __ungetwc(wc, fp, locale); FUNLOCKFILE(fp); return (r); } +wint_t +ungetwc(wint_t wc, FILE *fp) +{ + return ungetwc_l(wc, fp, __get_locale()); +} Index: lib/libc/stdio/swprintf.c =================================================================== --- lib/libc/stdio/swprintf.c (revision 225653) +++ lib/libc/stdio/swprintf.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002 Tim J. Robbins * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -30,6 +35,7 @@ #include #include #include +#include int swprintf(wchar_t * __restrict s, size_t n, const wchar_t * __restrict fmt, ...) @@ -43,3 +49,16 @@ return (ret); } +int +swprintf_l(wchar_t * __restrict s, size_t n, locale_t locale, + const wchar_t * __restrict fmt, ...) +{ + int ret; + va_list ap; + + va_start(ap, fmt); + ret = vswprintf_l(s, n, locale, fmt, ap); + va_end(ap); + + return (ret); +} Index: lib/libc/stdio/wscanf.c =================================================================== --- lib/libc/stdio/wscanf.c (revision 225653) +++ lib/libc/stdio/wscanf.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002 Tim J. Robbins * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -30,6 +35,7 @@ #include #include #include +#include int wscanf(const wchar_t * __restrict fmt, ...) @@ -43,3 +49,15 @@ return (r); } +int +wscanf_l(locale_t locale, const wchar_t * __restrict fmt, ...) +{ + va_list ap; + int r; + + va_start(ap, fmt); + r = vfwscanf_l(stdin, locale, fmt, ap); + va_end(ap); + + return (r); +} Index: lib/libc/stdio/fscanf.c =================================================================== --- lib/libc/stdio/fscanf.c (revision 225653) +++ lib/libc/stdio/fscanf.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Chris Torek. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -42,6 +47,7 @@ #include "un-namespace.h" #include "libc_private.h" #include "local.h" +#include "xlocale_private.h" int fscanf(FILE * __restrict fp, char const * __restrict fmt, ...) @@ -51,8 +57,22 @@ va_start(ap, fmt); FLOCKFILE(fp); - ret = __svfscanf(fp, fmt, ap); + ret = __svfscanf(fp, __get_locale(), fmt, ap); va_end(ap); FUNLOCKFILE(fp); return (ret); } +int +fscanf_l(FILE * __restrict fp, locale_t locale, char const * __restrict fmt, ...) +{ + int ret; + va_list ap; + FIX_LOCALE(locale); + + va_start(ap, fmt); + FLOCKFILE(fp); + ret = __svfscanf(fp, locale, fmt, ap); + va_end(ap); + FUNLOCKFILE(fp); + return (ret); +} Index: lib/libc/stdio/fprintf.c =================================================================== --- lib/libc/stdio/fprintf.c (revision 225653) +++ lib/libc/stdio/fprintf.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Chris Torek. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -38,6 +43,7 @@ #include #include +#include "xlocale_private.h" int fprintf(FILE * __restrict fp, const char * __restrict fmt, ...) @@ -46,7 +52,19 @@ va_list ap; va_start(ap, fmt); - ret = vfprintf(fp, fmt, ap); + ret = vfprintf_l(fp, __get_locale(), fmt, ap); va_end(ap); return (ret); } +int +fprintf_l(FILE * __restrict fp, locale_t locale, const char * __restrict fmt, ...) +{ + int ret; + va_list ap; + FIX_LOCALE(locale); + + va_start(ap, fmt); + ret = vfprintf_l(fp, locale, fmt, ap); + va_end(ap); + return (ret); +} Index: lib/libc/stdio/vscanf.c =================================================================== --- lib/libc/stdio/vscanf.c (revision 225653) +++ lib/libc/stdio/vscanf.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Donn Seeley at UUNET Technologies, Inc. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -41,16 +46,26 @@ #include "un-namespace.h" #include "libc_private.h" #include "local.h" +#include "xlocale_private.h" int -vscanf(fmt, ap) +vscanf_l(locale, fmt, ap) + locale_t locale; const char * __restrict fmt; __va_list ap; { int retval; + FIX_LOCALE(locale); FLOCKFILE(stdin); - retval = __svfscanf(stdin, fmt, ap); + retval = __svfscanf(stdin, locale, fmt, ap); FUNLOCKFILE(stdin); return (retval); } +int +vscanf(fmt, ap) + const char * __restrict fmt; + __va_list ap; +{ + return vscanf_l(__get_locale(), fmt, ap); +} Index: lib/libc/stdio/printfcommon.h =================================================================== --- lib/libc/stdio/printfcommon.h (revision 225653) +++ lib/libc/stdio/printfcommon.h (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Chris Torek. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -79,14 +84,14 @@ * remain valid until io_flush() is called. */ static inline int -io_print(struct io_state *iop, const CHAR * __restrict ptr, int len) +io_print(struct io_state *iop, const CHAR * __restrict ptr, int len, locale_t locale) { iop->iov[iop->uio.uio_iovcnt].iov_base = (char *)ptr; iop->iov[iop->uio.uio_iovcnt].iov_len = len; iop->uio.uio_resid += len; if (++iop->uio.uio_iovcnt >= NIOV) - return (__sprint(iop->fp, &iop->uio)); + return (__sprint(iop->fp, &iop->uio, locale)); else return (0); } @@ -107,13 +112,14 @@ * or the zeroes array. */ static inline int -io_pad(struct io_state *iop, int howmany, const CHAR * __restrict with) +io_pad(struct io_state *iop, int howmany, const CHAR * __restrict with, + locale_t locale) { int n; while (howmany > 0) { n = (howmany >= PADSIZE) ? PADSIZE : howmany; - if (io_print(iop, with, n)) + if (io_print(iop, with, n, locale)) return (-1); howmany -= n; } @@ -126,7 +132,7 @@ */ static inline int io_printandpad(struct io_state *iop, const CHAR *p, const CHAR *ep, - int len, const CHAR * __restrict with) + int len, const CHAR * __restrict with, locale_t locale) { int p_len; @@ -134,19 +140,19 @@ if (p_len > len) p_len = len; if (p_len > 0) { - if (io_print(iop, p, p_len)) + if (io_print(iop, p, p_len, locale)) return (-1); } else { p_len = 0; } - return (io_pad(iop, len - p_len, with)); + return (io_pad(iop, len - p_len, with, locale)); } static inline int -io_flush(struct io_state *iop) +io_flush(struct io_state *iop, locale_t locale) { - return (__sprint(iop->fp, &iop->uio)); + return (__sprint(iop->fp, &iop->uio, locale)); } /* Index: lib/libc/stdio/sprintf.c =================================================================== --- lib/libc/stdio/sprintf.c (revision 225653) +++ lib/libc/stdio/sprintf.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Chris Torek. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -40,6 +45,7 @@ #include #include #include "local.h" +#include "xlocale_private.h" int sprintf(char * __restrict str, char const * __restrict fmt, ...) @@ -52,3 +58,16 @@ va_end(ap); return (ret); } +int +sprintf_l(char * __restrict str, locale_t locale, char const * __restrict fmt, + ...) +{ + int ret; + va_list ap; + FIX_LOCALE(locale); + + va_start(ap, fmt); + ret = vsprintf_l(str, locale, fmt, ap); + va_end(ap); + return (ret); +} Index: lib/libc/stdio/vprintf.c =================================================================== --- lib/libc/stdio/vprintf.c (revision 225653) +++ lib/libc/stdio/vprintf.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Chris Torek. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -37,10 +42,15 @@ __FBSDID("$FreeBSD$"); #include +#include int vprintf(const char * __restrict fmt, __va_list ap) { - return (vfprintf(stdout, fmt, ap)); } +int +vprintf_l(locale_t locale, const char * __restrict fmt, __va_list ap) +{ + return (vfprintf_l(stdout, locale, fmt, ap)); +} Index: lib/libc/stdio/wprintf.c =================================================================== --- lib/libc/stdio/wprintf.c (revision 225653) +++ lib/libc/stdio/wprintf.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002 Tim J. Robbins * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -30,6 +35,7 @@ #include #include #include +#include int wprintf(const wchar_t * __restrict fmt, ...) @@ -43,3 +49,15 @@ return (ret); } +int +wprintf_l(locale_t locale, const wchar_t * __restrict fmt, ...) +{ + int ret; + va_list ap; + + va_start(ap, fmt); + ret = vfwprintf_l(stdout, locale, fmt, ap); + va_end(ap); + + return (ret); +} Index: lib/libc/stdio/vfwprintf.c =================================================================== --- lib/libc/stdio/vfwprintf.c (revision 225653) +++ lib/libc/stdio/vfwprintf.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Chris Torek. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -65,10 +70,11 @@ #include "local.h" #include "fvwrite.h" #include "printflocal.h" +#include "xlocale_private.h" -static int __sprint(FILE *, struct __suio *); -static int __sbprintf(FILE *, const wchar_t *, va_list) __noinline; -static wint_t __xfputwc(wchar_t, FILE *); +static int __sprint(FILE *, struct __suio *, locale_t); +static int __sbprintf(FILE *, locale_t, const wchar_t *, va_list) __noinline; +static wint_t __xfputwc(wchar_t, FILE *, locale_t); static wchar_t *__mbsconv(char *, int); #define CHAR wchar_t @@ -85,28 +91,28 @@ static const mbstate_t initial_mbs; static inline wchar_t -get_decpt(void) +get_decpt(locale_t locale) { mbstate_t mbs; wchar_t decpt; int nconv; mbs = initial_mbs; - nconv = mbrtowc(&decpt, localeconv()->decimal_point, MB_CUR_MAX, &mbs); + nconv = mbrtowc(&decpt, localeconv_l(locale)->decimal_point, MB_CUR_MAX, &mbs); if (nconv == (size_t)-1 || nconv == (size_t)-2) decpt = '.'; /* failsafe */ return (decpt); } static inline wchar_t -get_thousep(void) +get_thousep(locale_t locale) { mbstate_t mbs; wchar_t thousep; int nconv; mbs = initial_mbs; - nconv = mbrtowc(&thousep, localeconv()->thousands_sep, + nconv = mbrtowc(&thousep, localeconv_l(locale)->thousands_sep, MB_CUR_MAX, &mbs); if (nconv == (size_t)-1 || nconv == (size_t)-2) thousep = '\0'; /* failsafe */ @@ -119,11 +125,11 @@ * of wide characters that will be printed. */ static int -grouping_init(struct grouping_state *gs, int ndigits) +grouping_init(struct grouping_state *gs, int ndigits, locale_t locale) { - gs->grouping = localeconv()->grouping; - gs->thousands_sep = get_thousep(); + gs->grouping = localeconv_l(locale)->grouping; + gs->thousands_sep = get_thousep(locale); gs->nseps = gs->nrepeats = 0; gs->lead = ndigits; @@ -145,11 +151,11 @@ */ static int grouping_print(struct grouping_state *gs, struct io_state *iop, - const CHAR *cp, const CHAR *ep) + const CHAR *cp, const CHAR *ep, locale_t locale) { const CHAR *cp0 = cp; - if (io_printandpad(iop, cp, ep, gs->lead, zeroes)) + if (io_printandpad(iop, cp, ep, gs->lead, zeroes, locale)) return (-1); cp += gs->lead; while (gs->nseps > 0 || gs->nrepeats > 0) { @@ -159,9 +165,9 @@ gs->grouping--; gs->nseps--; } - if (io_print(iop, &gs->thousands_sep, 1)) + if (io_print(iop, &gs->thousands_sep, 1, locale)) return (-1); - if (io_printandpad(iop, cp, ep, *gs->grouping, zeroes)) + if (io_printandpad(iop, cp, ep, *gs->grouping, zeroes, locale)) return (-1); cp += *gs->grouping; } @@ -180,7 +186,7 @@ * string eclipses the benefits of buffering. */ static int -__sprint(FILE *fp, struct __suio *uio) +__sprint(FILE *fp, struct __suio *uio, locale_t locale) { struct __siov *iov; wchar_t *p; @@ -191,7 +197,7 @@ p = (wchar_t *)iov->iov_base; len = iov->iov_len; for (i = 0; i < len; i++) { - if (__xfputwc(p[i], fp) == WEOF) + if (__xfputwc(p[i], fp, locale) == WEOF) return (-1); } } @@ -205,7 +211,7 @@ * worries about ungetc buffers and so forth. */ static int -__sbprintf(FILE *fp, const wchar_t *fmt, va_list ap) +__sbprintf(FILE *fp, locale_t locale, const wchar_t *fmt, va_list ap) { int ret; FILE fake; @@ -229,7 +235,7 @@ fake._lbfsize = 0; /* not actually used, but Just In Case */ /* do the work, then copy any error status */ - ret = __vfwprintf(&fake, fmt, ap); + ret = __vfwprintf(&fake, locale, fmt, ap); if (ret >= 0 && __fflush(&fake)) ret = WEOF; if (fake._flags & __SERR) @@ -242,7 +248,7 @@ * File must already be locked. */ static wint_t -__xfputwc(wchar_t wc, FILE *fp) +__xfputwc(wchar_t wc, FILE *fp, locale_t locale) { mbstate_t mbs; char buf[MB_LEN_MAX]; @@ -251,7 +257,7 @@ size_t len; if ((fp->_flags & __SSTR) == 0) - return (__fputwc(wc, fp)); + return (__fputwc(wc, fp, locale)); mbs = initial_mbs; if ((len = wcrtomb(buf, wc, &mbs)) == (size_t)-1) { @@ -343,21 +349,27 @@ * MT-safe version */ int -vfwprintf(FILE * __restrict fp, const wchar_t * __restrict fmt0, va_list ap) +vfwprintf_l(FILE * __restrict fp, locale_t locale, + const wchar_t * __restrict fmt0, va_list ap) { int ret; - + FIX_LOCALE(locale); FLOCKFILE(fp); /* optimise fprintf(stderr) (and other unbuffered Unix files) */ if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) && fp->_file >= 0) - ret = __sbprintf(fp, fmt0, ap); + ret = __sbprintf(fp, locale, fmt0, ap); else - ret = __vfwprintf(fp, fmt0, ap); + ret = __vfwprintf(fp, locale, fmt0, ap); FUNLOCKFILE(fp); return (ret); } +int +vfwprintf(FILE * __restrict fp, const wchar_t * __restrict fmt0, va_list ap) +{ + return vfwprintf_l(fp, __get_locale(), fmt0, ap); +} /* * The size of the buffer we use as scratch space for integer @@ -374,7 +386,7 @@ * Non-MT-safe version */ int -__vfwprintf(FILE *fp, const wchar_t *fmt0, va_list ap) +__vfwprintf(FILE *fp, locale_t locale, const wchar_t *fmt0, va_list ap) { wchar_t *fmt; /* format string */ wchar_t ch; /* character from fmt */ @@ -437,19 +449,19 @@ /* BEWARE, these `goto error' on error. */ #define PRINT(ptr, len) do { \ - if (io_print(&io, (ptr), (len))) \ + if (io_print(&io, (ptr), (len), locale)) \ goto error; \ } while (0) #define PAD(howmany, with) { \ - if (io_pad(&io, (howmany), (with))) \ + if (io_pad(&io, (howmany), (with), locale)) \ goto error; \ } #define PRINTANDPAD(p, ep, len, with) { \ - if (io_printandpad(&io, (p), (ep), (len), (with))) \ + if (io_printandpad(&io, (p), (ep), (len), (with), locale)) \ goto error; \ } #define FLUSH() { \ - if (io_flush(&io)) \ + if (io_flush(&io, locale)) \ goto error; \ } @@ -529,7 +541,7 @@ io_init(&io, fp); ret = 0; #ifndef NO_FLOATING_POINT - decimal_point = get_decpt(); + decimal_point = get_decpt(locale); #endif /* @@ -816,7 +828,7 @@ if (prec || flags & ALT) size += prec + 1; if ((flags & GROUPING) && expt > 0) - size += grouping_init(&gs, expt); + size += grouping_init(&gs, expt, locale); } break; #endif /* !NO_FLOATING_POINT */ @@ -955,7 +967,7 @@ if (size > BUF) /* should never happen */ abort(); if ((flags & GROUPING) && size != 0) - size += grouping_init(&gs, size); + size += grouping_init(&gs, size, locale); break; default: /* "%?" prints ?, unless ? is NUL */ if (ch == '\0') @@ -1018,7 +1030,7 @@ /* leading zeroes from decimal precision */ PAD(dprec - size, zeroes); if (gs.grouping) { - if (grouping_print(&gs, &io, cp, buf+BUF) < 0) + if (grouping_print(&gs, &io, cp, buf+BUF, locale) < 0) goto error; } else { PRINT(cp, size); @@ -1036,7 +1048,7 @@ } else { if (gs.grouping) { n = grouping_print(&gs, &io, - cp, convbuf + ndig); + cp, convbuf + ndig, locale); if (n < 0) goto error; cp += n; Index: lib/libc/stdio/vdprintf.c =================================================================== --- lib/libc/stdio/vdprintf.c (revision 225653) +++ lib/libc/stdio/vdprintf.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2009 David Schultz * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -35,6 +40,7 @@ #include "un-namespace.h" #include "local.h" +#include "xlocale_private.h" int vdprintf(int fd, const char * __restrict fmt, va_list ap) @@ -57,7 +63,7 @@ f._bf._base = buf; f._bf._size = sizeof(buf); - if ((ret = __vfprintf(&f, fmt, ap)) < 0) + if ((ret = __vfprintf(&f, __get_locale(), fmt, ap)) < 0) return (ret); return (__fflush(&f) ? EOF : ret); Index: lib/libc/stdio/vfprintf.c =================================================================== --- lib/libc/stdio/vfprintf.c (revision 225653) +++ lib/libc/stdio/vfprintf.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Chris Torek. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -57,6 +62,7 @@ #include #include +#include "xlocale_private.h" #include "un-namespace.h" #include "libc_private.h" @@ -64,8 +70,8 @@ #include "fvwrite.h" #include "printflocal.h" -static int __sprint(FILE *, struct __suio *); -static int __sbprintf(FILE *, const char *, va_list) __printflike(2, 0) +static int __sprint(FILE *, struct __suio *, locale_t); +static int __sbprintf(FILE *, locale_t, const char *, va_list) __printflike(3, 0) __noinline; static char *__wcsconv(wchar_t *, int); @@ -87,11 +93,11 @@ * of bytes that will be needed. */ static int -grouping_init(struct grouping_state *gs, int ndigits) +grouping_init(struct grouping_state *gs, int ndigits, locale_t loc) { struct lconv *locale; - locale = localeconv(); + locale = localeconv_l(loc); gs->grouping = locale->grouping; gs->thousands_sep = locale->thousands_sep; gs->thousep_len = strlen(gs->thousands_sep); @@ -116,11 +122,11 @@ */ static int grouping_print(struct grouping_state *gs, struct io_state *iop, - const CHAR *cp, const CHAR *ep) + const CHAR *cp, const CHAR *ep, locale_t locale) { const CHAR *cp0 = cp; - if (io_printandpad(iop, cp, ep, gs->lead, zeroes)) + if (io_printandpad(iop, cp, ep, gs->lead, zeroes, locale)) return (-1); cp += gs->lead; while (gs->nseps > 0 || gs->nrepeats > 0) { @@ -130,9 +136,9 @@ gs->grouping--; gs->nseps--; } - if (io_print(iop, gs->thousands_sep, gs->thousep_len)) + if (io_print(iop, gs->thousands_sep, gs->thousep_len, locale)) return (-1); - if (io_printandpad(iop, cp, ep, *gs->grouping, zeroes)) + if (io_printandpad(iop, cp, ep, *gs->grouping, zeroes, locale)) return (-1); cp += *gs->grouping; } @@ -146,7 +152,7 @@ * then reset it so that it can be reused. */ static int -__sprint(FILE *fp, struct __suio *uio) +__sprint(FILE *fp, struct __suio *uio, locale_t locale) { int err; @@ -166,7 +172,7 @@ * worries about ungetc buffers and so forth. */ static int -__sbprintf(FILE *fp, const char *fmt, va_list ap) +__sbprintf(FILE *fp, locale_t locale, const char *fmt, va_list ap) { int ret; FILE fake = FAKE_FILE; @@ -190,7 +196,7 @@ fake._lbfsize = 0; /* not actually used, but Just In Case */ /* do the work, then copy any error status */ - ret = __vfprintf(&fake, fmt, ap); + ret = __vfprintf(&fake, locale, fmt, ap); if (ret >= 0 && __fflush(&fake)) ret = EOF; if (fake._flags & __SERR) @@ -261,21 +267,27 @@ * MT-safe version */ int -vfprintf(FILE * __restrict fp, const char * __restrict fmt0, va_list ap) - +vfprintf_l(FILE * __restrict fp, locale_t locale, const char * __restrict fmt0, + va_list ap) { int ret; + FIX_LOCALE(locale); FLOCKFILE(fp); /* optimise fprintf(stderr) (and other unbuffered Unix files) */ if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) && fp->_file >= 0) - ret = __sbprintf(fp, fmt0, ap); + ret = __sbprintf(fp, locale, fmt0, ap); else - ret = __vfprintf(fp, fmt0, ap); + ret = __vfprintf(fp, locale, fmt0, ap); FUNLOCKFILE(fp); return (ret); } +int +vfprintf(FILE * __restrict fp, const char * __restrict fmt0, va_list ap) +{ + return vfprintf_l(fp, __get_locale(), fmt0, ap); +} /* * The size of the buffer we use as scratch space for integer @@ -292,7 +304,7 @@ * Non-MT-safe version */ int -__vfprintf(FILE *fp, const char *fmt0, va_list ap) +__vfprintf(FILE *fp, locale_t locale, const char *fmt0, va_list ap) { char *fmt; /* format string */ int ch; /* character from fmt */ @@ -357,19 +369,19 @@ /* BEWARE, these `goto error' on error. */ #define PRINT(ptr, len) { \ - if (io_print(&io, (ptr), (len))) \ + if (io_print(&io, (ptr), (len), locale)) \ goto error; \ } #define PAD(howmany, with) { \ - if (io_pad(&io, (howmany), (with))) \ + if (io_pad(&io, (howmany), (with), locale)) \ goto error; \ } #define PRINTANDPAD(p, ep, len, with) { \ - if (io_printandpad(&io, (p), (ep), (len), (with))) \ + if (io_printandpad(&io, (p), (ep), (len), (with), locale)) \ goto error; \ } #define FLUSH() { \ - if (io_flush(&io)) \ + if (io_flush(&io, locale)) \ goto error; \ } @@ -454,7 +466,7 @@ ret = 0; #ifndef NO_FLOATING_POINT dtoaresult = NULL; - decimal_point = localeconv()->decimal_point; + decimal_point = localeconv_l(locale)->decimal_point; /* The overwhelmingly common case is decpt_len == 1. */ decpt_len = (decimal_point[1] == '\0' ? 1 : strlen(decimal_point)); #endif @@ -750,7 +762,7 @@ if (prec || flags & ALT) size += prec + decpt_len; if ((flags & GROUPING) && expt > 0) - size += grouping_init(&gs, expt); + size += grouping_init(&gs, expt, locale); } break; #endif /* !NO_FLOATING_POINT */ @@ -887,7 +899,7 @@ if (size > BUF) /* should never happen */ abort(); if ((flags & GROUPING) && size != 0) - size += grouping_init(&gs, size); + size += grouping_init(&gs, size, locale); break; default: /* "%?" prints ?, unless ? is NUL */ if (ch == '\0') @@ -950,7 +962,7 @@ /* leading zeroes from decimal precision */ PAD(dprec - size, zeroes); if (gs.grouping) { - if (grouping_print(&gs, &io, cp, buf+BUF) < 0) + if (grouping_print(&gs, &io, cp, buf+BUF, locale) < 0) goto error; } else { PRINT(cp, size); @@ -968,7 +980,7 @@ } else { if (gs.grouping) { n = grouping_print(&gs, &io, - cp, dtoaend); + cp, dtoaend, locale); if (n < 0) goto error; cp += n; Index: lib/libc/stdio/local.h =================================================================== --- lib/libc/stdio/local.h (revision 225653) +++ lib/libc/stdio/local.h (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Chris Torek. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -37,6 +42,7 @@ #include #include #include +#include /* * Information local to this implementation of stdio, @@ -50,8 +56,8 @@ extern int _fseeko(FILE *, off_t, int, int); extern int __fflush(FILE *fp); extern void __fcloseall(void); -extern wint_t __fgetwc(FILE *); -extern wint_t __fputwc(wchar_t, FILE *); +extern wint_t __fgetwc(FILE *, locale_t); +extern wint_t __fputwc(wchar_t, FILE *, locale_t); extern int __sflush(FILE *); extern FILE *__sfp(void); extern int __slbexpand(FILE *, size_t); @@ -65,15 +71,15 @@ extern void __smakebuf(FILE *); extern int __swhatbuf(FILE *, size_t *, int *); extern int _fwalk(int (*)(FILE *)); -extern int __svfscanf(FILE *, const char *, __va_list); +extern int __svfscanf(FILE *, locale_t, const char *, __va_list); extern int __swsetup(FILE *); extern int __sflags(const char *, int *); extern int __ungetc(int, FILE *); -extern wint_t __ungetwc(wint_t, FILE *); -extern int __vfprintf(FILE *, const char *, __va_list); +extern wint_t __ungetwc(wint_t, FILE *, locale_t); +extern int __vfprintf(FILE *, locale_t, const char *, __va_list); extern int __vfscanf(FILE *, const char *, __va_list); -extern int __vfwprintf(FILE *, const wchar_t *, __va_list); -extern int __vfwscanf(FILE * __restrict, const wchar_t * __restrict, +extern int __vfwprintf(FILE *, locale_t, const wchar_t *, __va_list); +extern int __vfwscanf(FILE * __restrict, locale_t, const wchar_t * __restrict, __va_list); extern size_t __fread(void * __restrict buf, size_t size, size_t count, FILE * __restrict fp); Index: lib/libc/stdio/fwprintf.c =================================================================== --- lib/libc/stdio/fwprintf.c (revision 225653) +++ lib/libc/stdio/fwprintf.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002 Tim J. Robbins * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -30,6 +35,7 @@ #include #include #include +#include int fwprintf(FILE * __restrict fp, const wchar_t * __restrict fmt, ...) @@ -43,3 +49,15 @@ return (ret); } +int +fwprintf_l(FILE * __restrict fp, locale_t locale, const wchar_t * __restrict fmt, ...) +{ + int ret; + va_list ap; + + va_start(ap, fmt); + ret = vfwprintf_l(fp, locale, fmt, ap); + va_end(ap); + + return (ret); +} Index: lib/libc/stdio/fputwc.c =================================================================== --- lib/libc/stdio/fputwc.c (revision 225653) +++ lib/libc/stdio/fputwc.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002-2004 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -42,10 +47,11 @@ * Non-MT-safe version. */ wint_t -__fputwc(wchar_t wc, FILE *fp) +__fputwc(wchar_t wc, FILE *fp, locale_t locale) { char buf[MB_LEN_MAX]; size_t i, len; + struct xlocale_ctype *l = XLOCALE_CTYPE(locale); if (MB_CUR_MAX == 1 && wc > 0 && wc <= UCHAR_MAX) { /* @@ -56,7 +62,7 @@ *buf = (unsigned char)wc; len = 1; } else { - if ((len = __wcrtomb(buf, wc, &fp->_mbstate)) == (size_t)-1) { + if ((len = l->__wcrtomb(buf, wc, &fp->_mbstate)) == (size_t)-1) { fp->_flags |= __SERR; return (WEOF); } @@ -73,14 +79,20 @@ * MT-safe version. */ wint_t -fputwc(wchar_t wc, FILE *fp) +fputwc_l(wchar_t wc, FILE *fp, locale_t locale) { wint_t r; + FIX_LOCALE(locale); FLOCKFILE(fp); ORIENT(fp, 1); - r = __fputwc(wc, fp); + r = __fputwc(wc, fp, locale); FUNLOCKFILE(fp); return (r); } +wint_t +fputwc(wchar_t wc, FILE *fp) +{ + return fputwc_l(wc, fp, __get_locale()); +} Index: lib/libc/stdio/vsprintf.c =================================================================== --- lib/libc/stdio/vsprintf.c (revision 225653) +++ lib/libc/stdio/vsprintf.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Chris Torek. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -39,17 +44,25 @@ #include #include #include "local.h" +#include "xlocale_private.h" int -vsprintf(char * __restrict str, const char * __restrict fmt, __va_list ap) +vsprintf_l(char * __restrict str, locale_t locale, + const char * __restrict fmt, __va_list ap) { int ret; FILE f = FAKE_FILE; + FIX_LOCALE(locale); f._flags = __SWR | __SSTR; f._bf._base = f._p = (unsigned char *)str; f._bf._size = f._w = INT_MAX; - ret = __vfprintf(&f, fmt, ap); + ret = __vfprintf(&f, locale, fmt, ap); *f._p = 0; return (ret); } +int +vsprintf(char * __restrict str, const char * __restrict fmt, __va_list ap) +{ + return vsprintf_l(str, __get_locale(), fmt, ap); +} Index: lib/libc/stdio/vwprintf.c =================================================================== --- lib/libc/stdio/vwprintf.c (revision 225653) +++ lib/libc/stdio/vwprintf.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002 Tim J. Robbins * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -30,10 +35,15 @@ #include #include #include +#include int vwprintf(const wchar_t * __restrict fmt, va_list ap) { - return (vfwprintf(stdout, fmt, ap)); } +int +vwprintf_l(locale_t locale, const wchar_t * __restrict fmt, va_list ap) +{ + return (vfwprintf_l(stdout, locale, fmt, ap)); +} Index: lib/libc/stdio/fwscanf.c =================================================================== --- lib/libc/stdio/fwscanf.c (revision 225653) +++ lib/libc/stdio/fwscanf.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002 Tim J. Robbins * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -30,6 +35,7 @@ #include #include #include +#include int fwscanf(FILE * __restrict fp, const wchar_t * __restrict fmt, ...) @@ -43,3 +49,15 @@ return (r); } +int +fwscanf_l(FILE * __restrict fp, locale_t locale, const wchar_t * __restrict fmt, ...) +{ + va_list ap; + int r; + + va_start(ap, fmt); + r = vfwscanf_l(fp, locale, fmt, ap); + va_end(ap); + + return (r); +} Index: lib/libc/stdio/fputws.c =================================================================== --- lib/libc/stdio/fputws.c (revision 225653) +++ lib/libc/stdio/fputws.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002-2004 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -39,13 +44,15 @@ #include "mblocal.h" int -fputws(const wchar_t * __restrict ws, FILE * __restrict fp) +fputws_l(const wchar_t * __restrict ws, FILE * __restrict fp, locale_t locale) { size_t nbytes; char buf[BUFSIZ]; struct __suio uio; struct __siov iov; const wchar_t *wsp; + FIX_LOCALE(locale); + struct xlocale_ctype *l = XLOCALE_CTYPE(locale); FLOCKFILE(fp); ORIENT(fp, 1); @@ -56,7 +63,7 @@ iov.iov_base = buf; do { wsp = ws; - nbytes = __wcsnrtombs(buf, &wsp, SIZE_T_MAX, sizeof(buf), + nbytes = l->__wcsnrtombs(buf, &wsp, SIZE_T_MAX, sizeof(buf), &fp->_mbstate); if (nbytes == (size_t)-1) goto error; @@ -71,3 +78,9 @@ FUNLOCKFILE(fp); return (-1); } + +int +fputws(const wchar_t * __restrict ws, FILE * __restrict fp) +{ + return fputws_l(ws, fp, __get_locale()); +} Index: lib/libc/stdio/scanf.c =================================================================== --- lib/libc/stdio/scanf.c (revision 225653) +++ lib/libc/stdio/scanf.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Chris Torek. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -42,6 +47,7 @@ #include "un-namespace.h" #include "libc_private.h" #include "local.h" +#include "xlocale_private.h" int scanf(char const * __restrict fmt, ...) @@ -51,8 +57,22 @@ va_start(ap, fmt); FLOCKFILE(stdin); - ret = __svfscanf(stdin, fmt, ap); + ret = __svfscanf(stdin, __get_locale(), fmt, ap); FUNLOCKFILE(stdin); va_end(ap); return (ret); } +int +scanf_l(locale_t locale, char const * __restrict fmt, ...) +{ + int ret; + va_list ap; + FIX_LOCALE(locale); + + va_start(ap, fmt); + FLOCKFILE(stdin); + ret = __svfscanf(stdin, locale, fmt, ap); + FUNLOCKFILE(stdin); + va_end(ap); + return (ret); +} Index: lib/libc/stdio/swscanf.c =================================================================== --- lib/libc/stdio/swscanf.c (revision 225653) +++ lib/libc/stdio/swscanf.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002 Tim J. Robbins * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -30,6 +35,7 @@ #include #include #include +#include int swscanf(const wchar_t * __restrict str, const wchar_t * __restrict fmt, ...) @@ -43,3 +49,16 @@ return (r); } +int +swscanf_l(const wchar_t * __restrict str, locale_t locale, + const wchar_t * __restrict fmt, ...) +{ + va_list ap; + int r; + + va_start(ap, fmt); + r = vswscanf_l(str, locale, fmt, ap); + va_end(ap); + + return (r); +} Index: lib/libc/stdio/vwscanf.c =================================================================== --- lib/libc/stdio/vwscanf.c (revision 225653) +++ lib/libc/stdio/vwscanf.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002 Tim J. Robbins * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -30,10 +35,15 @@ #include #include #include +#include int vwscanf(const wchar_t * __restrict fmt, va_list ap) { - return (vfwscanf(stdin, fmt, ap)); } +int +vwscanf_l(locale_t locale, const wchar_t * __restrict fmt, va_list ap) +{ + return (vfwscanf_l(stdin, locale, fmt, ap)); +} Index: lib/libc/stdio/sscanf.c =================================================================== --- lib/libc/stdio/sscanf.c (revision 225653) +++ lib/libc/stdio/sscanf.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Chris Torek. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -39,6 +44,7 @@ #include #include #include +#include #include "local.h" int @@ -52,3 +58,15 @@ va_end(ap); return (ret); } +int +sscanf_l(const char * __restrict str, locale_t locale, + char const * __restrict fmt, ...) +{ + int ret; + va_list ap; + + va_start(ap, fmt); + ret = vsscanf_l(str, locale, fmt, ap); + va_end(ap); + return (ret); +} Index: lib/libc/stdio/fgetwc.c =================================================================== --- lib/libc/stdio/fgetwc.c (revision 225653) +++ lib/libc/stdio/fgetwc.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002-2004 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -36,31 +41,39 @@ #include "libc_private.h" #include "local.h" #include "mblocal.h" +#include "xlocale_private.h" /* * MT-safe version. */ wint_t -fgetwc(FILE *fp) +fgetwc_l(FILE *fp, locale_t locale) { wint_t r; + FIX_LOCALE(locale); FLOCKFILE(fp); ORIENT(fp, 1); - r = __fgetwc(fp); + r = __fgetwc(fp, locale); FUNLOCKFILE(fp); return (r); } +wint_t +fgetwc(FILE *fp) +{ + return fgetwc_l(fp, __get_locale()); +} /* * Non-MT-safe version. */ wint_t -__fgetwc(FILE *fp) +__fgetwc(FILE *fp, locale_t locale) { wchar_t wc; size_t nconv; + struct xlocale_ctype *l = XLOCALE_CTYPE(locale); if (fp->_r <= 0 && __srefill(fp)) return (WEOF); @@ -71,7 +84,7 @@ return (wc); } do { - nconv = __mbrtowc(&wc, fp->_p, fp->_r, &fp->_mbstate); + nconv = l->__mbrtowc(&wc, fp->_p, fp->_r, &fp->_mbstate); if (nconv == (size_t)-1) break; else if (nconv == (size_t)-2) Index: lib/libc/stdio/vfscanf.c =================================================================== --- lib/libc/stdio/vfscanf.c (revision 225653) +++ lib/libc/stdio/vfscanf.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * This code is derived from software contributed to Berkeley by * Chris Torek. * @@ -51,6 +56,7 @@ #include "collate.h" #include "libc_private.h" #include "local.h" +#include "xlocale_private.h" #ifndef NO_FLOATING_POINT #include @@ -95,11 +101,12 @@ static const u_char *__sccl(char *, const u_char *); #ifndef NO_FLOATING_POINT -static int parsefloat(FILE *, char *, char *); +static int parsefloat(FILE *, char *, char *, locale_t); #endif __weak_reference(__vfscanf, vfscanf); + /* * __vfscanf - MT-safe version */ @@ -109,16 +116,27 @@ int ret; FLOCKFILE(fp); - ret = __svfscanf(fp, fmt0, ap); + ret = __svfscanf(fp, __get_locale(), fmt0, ap); FUNLOCKFILE(fp); return (ret); } +int +vfscanf_l(FILE *fp, locale_t locale, char const *fmt0, va_list ap) +{ + int ret; + FIX_LOCALE(locale); + FLOCKFILE(fp); + ret = __svfscanf(fp, locale, fmt0, ap); + FUNLOCKFILE(fp); + return (ret); +} + /* * __svfscanf - non-MT-safe version of __vfscanf */ int -__svfscanf(FILE *fp, const char *fmt0, va_list ap) +__svfscanf(FILE *fp, locale_t locale, const char *fmt0, va_list ap) { const u_char *fmt = (const u_char *)fmt0; int c; /* character from format, or conversion */ @@ -455,8 +473,7 @@ !ccltab[wctob(*wcp)]) { while (n != 0) { n--; - __ungetc(buf[n], - fp); + __ungetc(buf[n], fp); } break; } @@ -555,8 +572,7 @@ if (iswspace(*wcp)) { while (n != 0) { n--; - __ungetc(buf[n], - fp); + __ungetc(buf[n], fp); } break; } @@ -733,9 +749,9 @@ *p = 0; if ((flags & UNSIGNED) == 0) - res = strtoimax(buf, (char **)NULL, base); + res = strtoimax_l(buf, (char **)NULL, base, locale); else - res = strtoumax(buf, (char **)NULL, base); + res = strtoumax_l(buf, (char **)NULL, base, locale); if (flags & POINTER) *va_arg(ap, void **) = (void *)(uintptr_t)res; @@ -766,17 +782,17 @@ /* scan a floating point number as if by strtod */ if (width == 0 || width > sizeof(buf) - 1) width = sizeof(buf) - 1; - if ((width = parsefloat(fp, buf, buf + width)) == 0) + if ((width = parsefloat(fp, buf, buf + width, locale)) == 0) goto match_failure; if ((flags & SUPPRESS) == 0) { if (flags & LONGDBL) { - long double res = strtold(buf, &p); + long double res = strtold_l(buf, &p, locale); *va_arg(ap, long double *) = res; } else if (flags & LONG) { - double res = strtod(buf, &p); + double res = strtod_l(buf, &p, locale); *va_arg(ap, double *) = res; } else { - float res = strtof(buf, &p); + float res = strtof_l(buf, &p, locale); *va_arg(ap, float *) = res; } nassigned++; @@ -805,6 +821,8 @@ const u_char *fmt; { int c, n, v, i; + struct xlocale_collate *table = + (struct xlocale_collate*)__get_locale()->components[XLC_COLLATE]; /* first `clear' the whole table */ c = *fmt++; /* first char hat => negated scanset */ @@ -858,8 +876,8 @@ */ n = *fmt; if (n == ']' - || (__collate_load_error ? n < c : - __collate_range_cmp (n, c) < 0 + || (table->__collate_load_error ? n < c : + __collate_range_cmp (table, n, c) < 0 ) ) { c = '-'; @@ -867,14 +885,14 @@ } fmt++; /* fill in the range */ - if (__collate_load_error) { + if (table->__collate_load_error) { do { tab[++c] = v; } while (c < n); } else { for (i = 0; i < 256; i ++) - if ( __collate_range_cmp (c, i) < 0 - && __collate_range_cmp (i, n) <= 0 + if ( __collate_range_cmp (table, c, i) < 0 + && __collate_range_cmp (table, i, n) <= 0 ) tab[i] = v; } @@ -908,7 +926,7 @@ #ifndef NO_FLOATING_POINT static int -parsefloat(FILE *fp, char *buf, char *end) +parsefloat(FILE *fp, char *buf, char *end, locale_t locale) { char *commit, *p; int infnanpos = 0, decptpos = 0; @@ -917,7 +935,7 @@ S_DIGITS, S_DECPT, S_FRAC, S_EXP, S_EXPDIGITS } state = S_START; unsigned char c; - const char *decpt = localeconv()->decimal_point; + const char *decpt = localeconv_l(locale)->decimal_point; _Bool gotmantdig = 0, ishex = 0; /* Index: lib/libc/stdio/fgetws.c =================================================================== --- lib/libc/stdio/fgetws.c (revision 225653) +++ lib/libc/stdio/fgetws.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002-2004 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -38,12 +43,14 @@ #include "mblocal.h" wchar_t * -fgetws(wchar_t * __restrict ws, int n, FILE * __restrict fp) +fgetws_l(wchar_t * __restrict ws, int n, FILE * __restrict fp, locale_t locale) { wchar_t *wsp; size_t nconv; const char *src; unsigned char *nl; + FIX_LOCALE(locale); + struct xlocale_ctype *l = XLOCALE_CTYPE(locale); FLOCKFILE(fp); ORIENT(fp, 1); @@ -60,7 +67,7 @@ do { src = fp->_p; nl = memchr(fp->_p, '\n', fp->_r); - nconv = __mbsnrtowcs(wsp, &src, + nconv = l->__mbsnrtowcs(wsp, &src, nl != NULL ? (nl - fp->_p + 1) : fp->_r, n - 1, &fp->_mbstate); if (nconv == (size_t)-1) @@ -86,7 +93,7 @@ if (wsp == ws) /* EOF */ goto error; - if (!__mbsinit(&fp->_mbstate)) + if (!l->__mbsinit(&fp->_mbstate)) /* Incomplete character */ goto error; *wsp = L'\0'; @@ -98,3 +105,8 @@ FUNLOCKFILE(fp); return (NULL); } +wchar_t * +fgetws(wchar_t * __restrict ws, int n, FILE * __restrict fp) +{ + return fgetws_l(ws, n, fp, __get_locale()); +} Index: lib/libc/stdio/vasprintf.c =================================================================== --- lib/libc/stdio/vasprintf.c (revision 225653) +++ lib/libc/stdio/vasprintf.c (working copy) @@ -4,6 +4,11 @@ * Copyright (c) 1997 Todd C. Miller * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -33,13 +38,15 @@ #include #include #include +#include "xlocale_private.h" #include "local.h" int -vasprintf(char **str, const char *fmt, __va_list ap) +vasprintf_l(char **str, locale_t locale, const char *fmt, __va_list ap) { FILE f = FAKE_FILE; int ret; + FIX_LOCALE(locale); f._flags = __SWR | __SSTR | __SALC; f._bf._base = f._p = malloc(128); @@ -49,7 +56,7 @@ return (-1); } f._bf._size = f._w = 127; /* Leave room for the NUL */ - ret = __vfprintf(&f, fmt, ap); + ret = __vfprintf(&f, locale, fmt, ap); if (ret < 0) { free(f._bf._base); *str = NULL; @@ -60,3 +67,8 @@ *str = (char *)f._bf._base; return (ret); } +int +vasprintf(char **str, const char *fmt, __va_list ap) +{ + return vasprintf_l(str, __get_locale(), fmt, ap); +} Index: lib/libc/stdio/vfwscanf.c =================================================================== --- lib/libc/stdio/vfwscanf.c (revision 225653) +++ lib/libc/stdio/vfwscanf.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Chris Torek. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -53,11 +58,8 @@ #include "libc_private.h" #include "local.h" +#include "xlocale_private.h" -#ifndef NO_FLOATING_POINT -#include -#endif - #define BUF 513 /* Maximum length of numeric string. */ /* @@ -96,7 +98,7 @@ #define CT_FLOAT 4 /* %[efgEFG] conversion */ #ifndef NO_FLOATING_POINT -static int parsefloat(FILE *, wchar_t *, wchar_t *); +static int parsefloat(FILE *, wchar_t *, wchar_t *, locale_t); #endif #define INCCL(_c) \ @@ -109,22 +111,30 @@ * MT-safe version. */ int -vfwscanf(FILE * __restrict fp, const wchar_t * __restrict fmt, va_list ap) +vfwscanf_l(FILE * __restrict fp, locale_t locale, + const wchar_t * __restrict fmt, va_list ap) { int ret; + FIX_LOCALE(locale); FLOCKFILE(fp); ORIENT(fp, 1); - ret = __vfwscanf(fp, fmt, ap); + ret = __vfwscanf(fp, locale, fmt, ap); FUNLOCKFILE(fp); return (ret); } +int +vfwscanf(FILE * __restrict fp, const wchar_t * __restrict fmt, va_list ap) +{ + return vfwscanf_l(fp, __get_locale(), fmt, ap); +} /* * Non-MT-safe version. */ int -__vfwscanf(FILE * __restrict fp, const wchar_t * __restrict fmt, va_list ap) +__vfwscanf(FILE * __restrict fp, locale_t locale, + const wchar_t * __restrict fmt, va_list ap) { wint_t c; /* character from format, or conversion */ size_t width; /* field width, or 0 */ @@ -159,11 +169,11 @@ if (c == 0) return (nassigned); if (iswspace(c)) { - while ((c = __fgetwc(fp)) != WEOF && - iswspace(c)) + while ((c = __fgetwc(fp, locale)) != WEOF && + iswspace_l(c, locale)) ; if (c != WEOF) - __ungetwc(c, fp); + __ungetwc(c, fp, locale); continue; } if (c != '%') @@ -178,10 +188,10 @@ switch (c) { case '%': literal: - if ((wi = __fgetwc(fp)) == WEOF) + if ((wi = __fgetwc(fp, locale)) == WEOF) goto input_failure; if (wi != c) { - __ungetwc(wi, fp); + __ungetwc(wi, fp, locale); goto input_failure; } nread++; @@ -341,11 +351,11 @@ * that suppress this. */ if ((flags & NOSKIP) == 0) { - while ((wi = __fgetwc(fp)) != WEOF && iswspace(wi)) + while ((wi = __fgetwc(fp, locale)) != WEOF && iswspace(wi)) nread++; if (wi == WEOF) goto input_failure; - __ungetwc(wi, fp); + __ungetwc(wi, fp, locale); } /* @@ -362,7 +372,7 @@ p = va_arg(ap, wchar_t *); n = 0; while (width-- != 0 && - (wi = __fgetwc(fp)) != WEOF) { + (wi = __fgetwc(fp, locale)) != WEOF) { if (!(flags & SUPPRESS)) *p++ = (wchar_t)wi; n++; @@ -378,7 +388,7 @@ n = 0; mbs = initial_mbs; while (width != 0 && - (wi = __fgetwc(fp)) != WEOF) { + (wi = __fgetwc(fp, locale)) != WEOF) { if (width >= MB_CUR_MAX && !(flags & SUPPRESS)) { nconv = wcrtomb(mbp, wi, &mbs); @@ -390,7 +400,7 @@ if (nconv == (size_t)-1) goto input_failure; if (nconv > width) { - __ungetwc(wi, fp); + __ungetwc(wi, fp, locale); break; } if (!(flags & SUPPRESS)) @@ -418,20 +428,20 @@ /* take only those things in the class */ if ((flags & SUPPRESS) && (flags & LONG)) { n = 0; - while ((wi = __fgetwc(fp)) != WEOF && + while ((wi = __fgetwc(fp, locale)) != WEOF && width-- != 0 && INCCL(wi)) n++; if (wi != WEOF) - __ungetwc(wi, fp); + __ungetwc(wi, fp, locale); if (n == 0) goto match_failure; } else if (flags & LONG) { p0 = p = va_arg(ap, wchar_t *); - while ((wi = __fgetwc(fp)) != WEOF && + while ((wi = __fgetwc(fp, locale)) != WEOF && width-- != 0 && INCCL(wi)) *p++ = (wchar_t)wi; if (wi != WEOF) - __ungetwc(wi, fp); + __ungetwc(wi, fp, locale); n = p - p0; if (n == 0) goto match_failure; @@ -442,7 +452,7 @@ mbp = va_arg(ap, char *); n = 0; mbs = initial_mbs; - while ((wi = __fgetwc(fp)) != WEOF && + while ((wi = __fgetwc(fp, locale)) != WEOF && width != 0 && INCCL(wi)) { if (width >= MB_CUR_MAX && !(flags & SUPPRESS)) { @@ -466,7 +476,7 @@ n++; } if (wi != WEOF) - __ungetwc(wi, fp); + __ungetwc(wi, fp, locale); if (!(flags & SUPPRESS)) { *mbp = 0; nassigned++; @@ -481,29 +491,29 @@ if (width == 0) width = (size_t)~0; if ((flags & SUPPRESS) && (flags & LONG)) { - while ((wi = __fgetwc(fp)) != WEOF && + while ((wi = __fgetwc(fp, locale)) != WEOF && width-- != 0 && !iswspace(wi)) nread++; if (wi != WEOF) - __ungetwc(wi, fp); + __ungetwc(wi, fp, locale); } else if (flags & LONG) { p0 = p = va_arg(ap, wchar_t *); - while ((wi = __fgetwc(fp)) != WEOF && + while ((wi = __fgetwc(fp, locale)) != WEOF && width-- != 0 && !iswspace(wi)) { *p++ = (wchar_t)wi; nread++; } if (wi != WEOF) - __ungetwc(wi, fp); + __ungetwc(wi, fp, locale); *p = '\0'; nassigned++; } else { if (!(flags & SUPPRESS)) mbp = va_arg(ap, char *); mbs = initial_mbs; - while ((wi = __fgetwc(fp)) != WEOF && + while ((wi = __fgetwc(fp, locale)) != WEOF && width != 0 && !iswspace(wi)) { if (width >= MB_CUR_MAX && @@ -528,7 +538,7 @@ nread++; } if (wi != WEOF) - __ungetwc(wi, fp); + __ungetwc(wi, fp, locale); if (!(flags & SUPPRESS)) { *mbp = 0; nassigned++; @@ -544,7 +554,7 @@ width = sizeof(buf) / sizeof(*buf) - 1; flags |= SIGNOK | NDIGITS | NZDIGITS; for (p = buf; width; width--) { - c = __fgetwc(fp); + c = __fgetwc(fp, locale); /* * Switch on the character; `goto ok' * if we accept it as a part of number. @@ -628,7 +638,7 @@ * for a number. Stop accumulating digits. */ if (c != WEOF) - __ungetwc(c, fp); + __ungetwc(c, fp, locale); break; ok: /* @@ -644,13 +654,13 @@ */ if (flags & NDIGITS) { if (p > buf) - __ungetwc(*--p, fp); + __ungetwc(*--p, fp, locale); goto match_failure; } c = p[-1]; if (c == 'x' || c == 'X') { --p; - __ungetwc(c, fp); + __ungetwc(c, fp, locale); } if ((flags & SUPPRESS) == 0) { uintmax_t res; @@ -691,7 +701,7 @@ if (width == 0 || width > sizeof(buf) / sizeof(*buf) - 1) width = sizeof(buf) / sizeof(*buf) - 1; - if ((width = parsefloat(fp, buf, buf + width)) == 0) + if ((width = parsefloat(fp, buf, buf + width, locale)) == 0) goto match_failure; if ((flags & SUPPRESS) == 0) { if (flags & LONGDBL) { @@ -720,7 +730,7 @@ #ifndef NO_FLOATING_POINT static int -parsefloat(FILE *fp, wchar_t *buf, wchar_t *end) +parsefloat(FILE *fp, wchar_t *buf, wchar_t *end, locale_t locale) { mbstate_t mbs; size_t nconv; @@ -751,7 +761,7 @@ commit = buf - 1; c = WEOF; for (p = buf; p < end; ) { - if ((c = __fgetwc(fp)) == WEOF) + if ((c = __fgetwc(fp, locale)) == WEOF) break; reswitch: switch (state) { @@ -871,9 +881,9 @@ parsedone: if (c != WEOF) - __ungetwc(c, fp); + __ungetwc(c, fp, locale); while (commit < --p) - __ungetwc(*p, fp); + __ungetwc(*p, fp, locale); *++commit = '\0'; return (commit - buf); } Index: lib/libc/stdio/asprintf.c =================================================================== --- lib/libc/stdio/asprintf.c (revision 225653) +++ lib/libc/stdio/asprintf.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Chris Torek. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -35,6 +40,7 @@ #include #include +#include int asprintf(char ** __restrict s, char const * __restrict fmt, ...) @@ -47,3 +53,15 @@ va_end(ap); return (ret); } +int +asprintf_l(char ** __restrict s, locale_t locale, char const * __restrict fmt, + ...) +{ + int ret; + va_list ap; + + va_start(ap, fmt); + ret = vasprintf_l(s, locale, fmt, ap); + va_end(ap); + return (ret); +} Index: lib/libc/stdio/vswscanf.c =================================================================== --- lib/libc/stdio/vswscanf.c (revision 225653) +++ lib/libc/stdio/vswscanf.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Donn Seeley at UUNET Technologies, Inc. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -46,6 +51,7 @@ #include #include #include "local.h" +#include "xlocale_private.h" static int eofread(void *, char *, int); @@ -57,8 +63,8 @@ } int -vswscanf(const wchar_t * __restrict str, const wchar_t * __restrict fmt, - va_list ap) +vswscanf_l(const wchar_t * __restrict str, locale_t locale, + const wchar_t * __restrict fmt, va_list ap) { static const mbstate_t initial; mbstate_t mbs; @@ -67,6 +73,7 @@ size_t mlen; int r; const wchar_t *strp; + FIX_LOCALE(locale); /* * XXX Convert the wide character string to multibyte, which @@ -76,7 +83,7 @@ return (EOF); mbs = initial; strp = str; - if ((mlen = wcsrtombs(mbstr, &strp, SIZE_T_MAX, &mbs)) == (size_t)-1) { + if ((mlen = wcsrtombs_l(mbstr, &strp, SIZE_T_MAX, &mbs, locale)) == (size_t)-1) { free(mbstr); return (EOF); } @@ -84,8 +91,14 @@ f._bf._base = f._p = (unsigned char *)mbstr; f._bf._size = f._r = mlen; f._read = eofread; - r = __vfwscanf(&f, fmt, ap); + r = __vfwscanf(&f, locale, fmt, ap); free(mbstr); return (r); } +int +vswscanf(const wchar_t * __restrict str, const wchar_t * __restrict fmt, + va_list ap) +{ + return vswscanf_l(str, __get_locale(), fmt, ap); +} Index: lib/libc/locale/collate.c =================================================================== --- lib/libc/locale/collate.c (revision 225653) +++ lib/libc/locale/collate.c (working copy) @@ -3,6 +3,16 @@ * at Electronni Visti IA, Kiev, Ukraine. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -44,24 +54,77 @@ #include "libc_private.h" -int __collate_load_error = 1; -int __collate_substitute_nontrivial; +/* + * To avoid modifying the original (single-threaded) code too much, we'll just + * define the old globals as fields inside the table. + * + * We also modify the collation table test functions to search the thread-local + * table first and the global table second. + */ +#define __collate_load_error (table->__collate_load_error) +#define __collate_substitute_nontrivial (table->__collate_substitute_nontrivial) +#define __collate_substitute_table_ptr (table->__collate_substitute_table_ptr) +#define __collate_char_pri_table_ptr (table->__collate_char_pri_table_ptr) +#define __collate_chain_pri_table (table->__collate_chain_pri_table) -u_char __collate_substitute_table[UCHAR_MAX + 1][STR_LEN]; -struct __collate_st_char_pri __collate_char_pri_table[UCHAR_MAX + 1]; -struct __collate_st_chain_pri *__collate_chain_pri_table; +struct xlocale_collate __xlocale_global_collate = { + {{0}, "C"}, 1, 0 +}; + +static struct xlocale_collate c_collate= { + {{0}, "C"}, 1, 0 +}; + void __collate_err(int ex, const char *f) __dead2; int +__collate_load_tables_l(const char *encoding, struct xlocale_collate *table); + +static void +destruct_collate(void *t) +{ + struct xlocale_collate *table = t; + if (__collate_chain_pri_table) { + free(__collate_chain_pri_table); + } + free(t); +} + +void * +__collate_load(const char *encoding, locale_t unused) +{ + if (strcmp(encoding, "C") == 0 || strcmp(encoding, "POSIX") == 0) { + return &c_collate; + } + struct xlocale_collate *table = calloc(sizeof(struct xlocale_collate), 1); + table->header.header.destructor = destruct_collate; + // FIXME: Make sure that _LDP_CACHE is never returned. We should be doing + // the caching outside of this section + if (__collate_load_tables_l(encoding, table) != _LDP_LOADED) { + xlocale_release(table); + return NULL; + } + return table; +} + +/** + * Load the collation tables for the specified encoding into the global table. + */ +int __collate_load_tables(const char *encoding) { + return __collate_load_tables_l(encoding, &__xlocale_global_collate); +} + +int +__collate_load_tables_l(const char *encoding, struct xlocale_collate *table) +{ FILE *fp; int i, saverr, chains; uint32_t u32; char strbuf[STR_LEN], buf[PATH_MAX]; void *TMP_substitute_table, *TMP_char_pri_table, *TMP_chain_pri_table; - static char collate_encoding[ENCODING_LEN + 1]; /* 'encoding' must be already checked. */ if (strcmp(encoding, "C") == 0 || strcmp(encoding, "POSIX") == 0) { @@ -69,18 +132,6 @@ return (_LDP_CACHE); } - /* - * If the locale name is the same as our cache, use the cache. - */ - if (strcmp(encoding, collate_encoding) == 0) { - __collate_load_error = 0; - return (_LDP_CACHE); - } - - /* - * Slurp the locale file into the cache. - */ - /* 'PathLocale' must be already set & checked. */ /* Range checking not needed, encoding has fixed size */ (void)strcpy(buf, _PathLocale); @@ -165,7 +216,6 @@ sizeof(*__collate_chain_pri_table), chains, fp); (void)fclose(fp); - (void)strcpy(collate_encoding, encoding); if (__collate_substitute_table_ptr != NULL) free(__collate_substitute_table_ptr); __collate_substitute_table_ptr = TMP_substitute_table; @@ -201,7 +251,7 @@ } u_char * -__collate_substitute(const u_char *s) +__collate_substitute(struct xlocale_collate *table, const u_char *s) { int dest_len, len, nlen; int delta = strlen(s); @@ -228,7 +278,7 @@ } void -__collate_lookup(const u_char *t, int *len, int *prim, int *sec) +__collate_lookup(struct xlocale_collate *table, const u_char *t, int *len, int *prim, int *sec) { struct __collate_st_chain_pri *p2; Index: lib/libc/locale/xlocale.c =================================================================== --- lib/libc/locale/xlocale.c (revision 0) +++ lib/libc/locale/xlocale.c (revision 0) @@ -0,0 +1,312 @@ +/*- + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by David Chisnall under sponsorship from + * the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions * are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include "libc_private.h" +#include "xlocale_private.h" + +/** + * Each locale loader declares a global component. This is used by setlocale() + * and also by xlocale with LC_GLOBAL_LOCALE.. + */ +extern struct xlocale_component __xlocale_global_collate; +extern struct xlocale_component __xlocale_global_ctype; +extern struct xlocale_component __xlocale_global_monetary; +extern struct xlocale_component __xlocale_global_numeric; +extern struct xlocale_component __xlocale_global_time; +extern struct xlocale_component __xlocale_global_messages; +/* + * Private functions in setlocale.c. + */ +const char * +__get_locale_env(int category); +int +__detect_path_locale(void); + +struct _xlocale __xlocale_global_locale = { + {0}, + { + &__xlocale_global_collate, + &__xlocale_global_ctype, + &__xlocale_global_monetary, + &__xlocale_global_numeric, + &__xlocale_global_time, + &__xlocale_global_messages + }, + 1, + 0, + 1, + 0 +}; + +static void*(*constructors[])(const char*, locale_t) = +{ + __collate_load, + __ctype_load, + __monetary_load, + __numeric_load, + __time_load, + __messages_load +}; + +static pthread_key_t locale_info_key; +static int fake_tls; +static locale_t thread_local_locale; + +static void init_key(void) +{ + pthread_key_create(&locale_info_key, xlocale_release); + pthread_setspecific(locale_info_key, (void*)42); + if (pthread_getspecific(locale_info_key) == (void*)42) { + pthread_setspecific(locale_info_key, 0); + } else { + fake_tls = 1; + } + __detect_path_locale(); +} + +static pthread_once_t once_control = PTHREAD_ONCE_INIT; + +static locale_t +get_thread_locale(void) +{ + _once(&once_control, init_key); + + return fake_tls ? thread_local_locale : + pthread_getspecific(locale_info_key); +} + +locale_t +__get_locale(void) +{ + locale_t l = get_thread_locale(); + return l ? l : &__xlocale_global_locale; + +} + +static void +set_thread_locale(locale_t loc) +{ + pthread_once(&once_control, init_key); + + if (NULL != loc) { + xlocale_retain((struct xlocale_refcounted*)loc); + } + locale_t old = pthread_getspecific(locale_info_key); + if ((NULL != old) && (loc != old)) { + xlocale_release((struct xlocale_refcounted*)old); + } + if (fake_tls) { + thread_local_locale = loc; + } else { + pthread_setspecific(locale_info_key, loc); + } +} + +/** + * Clean up a locale, once its reference count reaches zero. This function is + * called by xlocale_release(), it should not be called directly. + */ +static void +destruct_locale(void *l) +{ + locale_t loc = l; + for (int type=0 ; typecomponents[type]) { + xlocale_release(loc->components[type]); + } + } + if (loc->csym) { + free(loc->csym); + } + free(l); +} + +/** + * Allocates a new, uninitialised, locale. + */ +static locale_t +alloc_locale(void) +{ + locale_t new = calloc(sizeof(struct _xlocale), 1); + new->header.destructor = destruct_locale; + new->monetary_locale_changed = 1; + new->numeric_locale_changed = 1; + return new; +} +static void +copyflags(locale_t new, locale_t old) +{ + new->using_monetary_locale = old->using_monetary_locale; + new->using_numeric_locale = old->using_numeric_locale; + new->using_time_locale = old->using_time_locale; + new->using_messages_locale = old->using_messages_locale; +} + +static int dupcomponent(int type, locale_t base, locale_t new) +{ + /* Always copy from the global locale, since it has mutable components. */ + struct xlocale_component *src = base->components[type]; + if (&__xlocale_global_locale == base) { + new->components[type] = constructors[type](src->locale, new); + if (new->components[type]) { + strncpy(new->components[type]->locale, src->locale, ENCODING_LEN); + } + } else { + new->components[type] = xlocale_retain(base->components[type]); + } + return 0 != new->components[type]; +} + +/* + * Public interfaces. These are the five public functions described by the + * xlocale interface. + */ + +locale_t newlocale(int mask, const char *locale, locale_t base) +{ + int type; + const char *realLocale = locale; + int useenv = 0; + int success = 1; + + _once(&once_control, init_key); + + locale_t new = alloc_locale(); + if (NULL == new) { + return NULL; + } + + FIX_LOCALE(base); + copyflags(new, base); + + if (NULL == locale) { + realLocale = "C"; + } else if ('\0' == locale[0]) { + useenv = 1; + } + + for (type=0 ; typecomponents[type] = constructors[type](realLocale, new); + if (new->components[type]) { + strncpy(new->components[type]->locale, realLocale, ENCODING_LEN); + } else { + success = 0; + } + } else { + if (!dupcomponent(type, base, new)) { + success = 0; + } + } + mask >>= 1; + } + if (0 == success) { + xlocale_release(new); + new = NULL; + } + + return new; +} + +locale_t duplocale(locale_t base) +{ + locale_t new = alloc_locale(); + int type; + + _once(&once_control, init_key); + + if (NULL == new) { + return NULL; + } + + FIX_LOCALE(base); + copyflags(new, base); + + for (type=0 ; typecomponents[type]->locale; + } + mask >>= 1; + } + return NULL; +} + +/* + * Installs the specified locale_t as this thread's locale. + */ +locale_t uselocale(locale_t loc) +{ + locale_t old = get_thread_locale(); + if (NULL != loc) { + if (LC_GLOBAL_LOCALE == loc) { + loc = NULL; + } + set_thread_locale(loc); + } + return old ? old : LC_GLOBAL_LOCALE; +} + Index: lib/libc/locale/ascii.c =================================================================== --- lib/libc/locale/ascii.c (revision 225653) +++ lib/libc/locale/ascii.c (working copy) @@ -6,6 +6,11 @@ * This code is derived from software contributed to Berkeley by * Paul Borman at Krystal Technologies. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -56,17 +61,17 @@ size_t, size_t, mbstate_t * __restrict); int -_ascii_init(_RuneLocale *rl) +_ascii_init(struct xlocale_ctype *l,_RuneLocale *rl) { - __mbrtowc = _ascii_mbrtowc; - __mbsinit = _ascii_mbsinit; - __mbsnrtowcs = _ascii_mbsnrtowcs; - __wcrtomb = _ascii_wcrtomb; - __wcsnrtombs = _ascii_wcsnrtombs; - _CurrentRuneLocale = rl; - __mb_cur_max = 1; - __mb_sb_limit = 128; + l->__mbrtowc = _ascii_mbrtowc; + l->__mbsinit = _ascii_mbsinit; + l->__mbsnrtowcs = _ascii_mbsnrtowcs; + l->__wcrtomb = _ascii_wcrtomb; + l->__wcsnrtombs = _ascii_wcsnrtombs; + l->runes = rl; + l->__mb_cur_max = 1; + l->__mb_sb_limit = 128; return(0); } Index: lib/libc/locale/collate.h =================================================================== --- lib/libc/locale/collate.h (revision 225653) +++ lib/libc/locale/collate.h (working copy) @@ -3,6 +3,11 @@ * at Electronni Visti IA, Kiev, Ukraine. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -33,6 +38,7 @@ #include #include #include +#include "xlocale_private.h" #define STR_LEN 10 #define TABLE_SIZE 100 @@ -47,20 +53,26 @@ int prim, sec; }; -extern int __collate_load_error; -extern int __collate_substitute_nontrivial; #define __collate_substitute_table (*__collate_substitute_table_ptr) -extern u_char __collate_substitute_table[UCHAR_MAX + 1][STR_LEN]; #define __collate_char_pri_table (*__collate_char_pri_table_ptr) -extern struct __collate_st_char_pri __collate_char_pri_table[UCHAR_MAX + 1]; -extern struct __collate_st_chain_pri *__collate_chain_pri_table; +struct xlocale_collate { + struct xlocale_component header; + int __collate_load_error; + int __collate_substitute_nontrivial; + + u_char (*__collate_substitute_table_ptr)[UCHAR_MAX + 1][STR_LEN]; + struct __collate_st_char_pri (*__collate_char_pri_table_ptr)[UCHAR_MAX + 1]; + struct __collate_st_chain_pri *__collate_chain_pri_table; +}; + + __BEGIN_DECLS u_char *__collate_strdup(u_char *); -u_char *__collate_substitute(const u_char *); +u_char *__collate_substitute(struct xlocale_collate *, const u_char *); int __collate_load_tables(const char *); -void __collate_lookup(const u_char *, int *, int *, int *); -int __collate_range_cmp(int, int); +void __collate_lookup(struct xlocale_collate *, const u_char *, int *, int *, int *); +int __collate_range_cmp(struct xlocale_collate *, int, int); #ifdef COLLATE_DEBUG void __collate_print_tables(void); #endif Index: lib/libc/locale/wcstoumax.c =================================================================== --- lib/libc/locale/wcstoumax.c (revision 225653) +++ lib/libc/locale/wcstoumax.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -41,19 +46,21 @@ #include #include #include +#include "xlocale_private.h" /* * Convert a wide character string to a uintmax_t integer. */ uintmax_t -wcstoumax(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, - int base) +wcstoumax_l(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, + int base, locale_t locale) { const wchar_t *s; uintmax_t acc; wchar_t c; uintmax_t cutoff; int neg, any, cutlim; + FIX_LOCALE(locale); /* * See strtoimax for comments as to the logic used. @@ -61,7 +68,7 @@ s = nptr; do { c = *s++; - } while (iswspace(c)); + } while (iswspace_l(c, locale)); if (c == L'-') { neg = 1; c = *s++; @@ -86,8 +93,8 @@ cutlim = UINTMAX_MAX % base; for ( ; ; c = *s++) { #ifdef notyet - if (iswdigit(c)) - c = digittoint(c); + if (iswdigit_l(c, locale)) + c = digittoint_l(c, locale); else #endif if (c >= L'0' && c <= L'9') @@ -120,3 +127,9 @@ *endptr = (wchar_t *)(any ? s - 1 : nptr); return (acc); } +uintmax_t +wcstoumax(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, + int base) +{ + return wcstoumax_l(nptr, endptr, base, __get_locale()); +} Index: lib/libc/locale/mbtowc.c =================================================================== --- lib/libc/locale/mbtowc.c (revision 225653) +++ lib/libc/locale/mbtowc.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002-2004 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -32,19 +37,24 @@ #include "mblocal.h" int -mbtowc(wchar_t * __restrict pwc, const char * __restrict s, size_t n) +mbtowc_l(wchar_t * __restrict pwc, const char * __restrict s, size_t n, locale_t locale) { static const mbstate_t initial; - static mbstate_t mbs; size_t rval; + FIX_LOCALE(locale); if (s == NULL) { /* No support for state dependent encodings. */ - mbs = initial; + locale->mbtowc = initial; return (0); } - rval = __mbrtowc(pwc, s, n, &mbs); + rval = XLOCALE_CTYPE(locale)->__mbrtowc(pwc, s, n, &locale->mbtowc); if (rval == (size_t)-1 || rval == (size_t)-2) return (-1); return ((int)rval); } +int +mbtowc(wchar_t * __restrict pwc, const char * __restrict s, size_t n) +{ + return mbtowc_l(pwc, s, n, __get_locale()); +} Index: lib/libc/locale/wcstoul.c =================================================================== --- lib/libc/locale/wcstoul.c (revision 225653) +++ lib/libc/locale/wcstoul.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -35,18 +40,21 @@ #include #include #include +#include "xlocale_private.h" /* * Convert a wide character string to an unsigned long integer. */ unsigned long -wcstoul(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, int base) +wcstoul_l(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, + int base, locale_t locale) { const wchar_t *s; unsigned long acc; wchar_t c; unsigned long cutoff; int neg, any, cutlim; + FIX_LOCALE(locale); /* * See strtol for comments as to the logic used. @@ -54,7 +62,7 @@ s = nptr; do { c = *s++; - } while (iswspace(c)); + } while (iswspace_l(c, locale)); if (c == L'-') { neg = 1; c = *s++; @@ -79,8 +87,8 @@ cutlim = ULONG_MAX % base; for ( ; ; c = *s++) { #ifdef notyet - if (iswdigit(c)) - c = digittoint(c); + if (iswdigit_l(c, locale)) + c = digittoint_l(c, locale); else #endif if (c >= L'0' && c <= L'9') @@ -113,3 +121,8 @@ *endptr = (wchar_t *)(any ? s - 1 : nptr); return (acc); } +unsigned long +wcstoul(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, int base) +{ + return wcstoul_l(nptr, endptr, base, __get_locale()); +} Index: lib/libc/locale/gb2312.c =================================================================== --- lib/libc/locale/gb2312.c (revision 225653) +++ lib/libc/locale/gb2312.c (working copy) @@ -3,6 +3,11 @@ * Copyright (c) 2003 David Xu * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -35,8 +40,6 @@ #include #include "mblocal.h" -extern int __mb_sb_limit; - static size_t _GB2312_mbrtowc(wchar_t * __restrict, const char * __restrict, size_t, mbstate_t * __restrict); static int _GB2312_mbsinit(const mbstate_t *); @@ -49,15 +52,15 @@ } _GB2312State; int -_GB2312_init(_RuneLocale *rl) +_GB2312_init(struct xlocale_ctype *l, _RuneLocale *rl) { - _CurrentRuneLocale = rl; - __mbrtowc = _GB2312_mbrtowc; - __wcrtomb = _GB2312_wcrtomb; - __mbsinit = _GB2312_mbsinit; - __mb_cur_max = 2; - __mb_sb_limit = 128; + l->runes = rl; + l->__mbrtowc = _GB2312_mbrtowc; + l->__wcrtomb = _GB2312_wcrtomb; + l->__mbsinit = _GB2312_mbsinit; + l->__mb_cur_max = 2; + l->__mb_sb_limit = 128; return (0); } Index: lib/libc/locale/Symbol.map =================================================================== --- lib/libc/locale/Symbol.map (revision 225653) +++ lib/libc/locale/Symbol.map (working copy) @@ -99,6 +99,98 @@ iswctype; wctype; wcwidth; + newlocale; + duplocale; + freelocale; + querylocale; + uselocale; + __getCurrentRuneLocale; + btowc_l; + localeconv_l; + mblen_l; + mbrlen_l; + mbrtowc_l; + mbsinit_l; + mbsnrtowcs_l; + mbsrtowcs_l; + mbstowcs_l; + mbtowc_l; + nl_langinfo_l; + strcoll_l; + strfmon_l; + strftime_l; + strptime_l; + strxfrm_l; + wcrtomb_l; + wcscoll_l; + wcsnrtombs_l; + wcsrtombs_l; + wcstombs_l; + wcsxfrm_l; + wctob_l; + wctomb_l; + ___tolower_l; + ___toupper_l; + ___runetype_l; + digittoint_l; + isalnum_l; + isalpha_l; + isblank_l; + iscntrl_l; + isdigit_l; + isgraph_l; + ishexnumber_l; + isideogram_l; + islower_l; + isnumber_l; + isphonogram_l; + isprint_l; + ispunct_l; + isrune_l; + isspace_l; + isspecial_l; + isupper_l; + isxdigit_l; + tolower_l; + toupper_l; + iswalnum_l; + iswalpha_l; + iswblank_l; + iswcntrl_l; + iswdigit_l; + iswgraph_l; + iswhexnumber_l; + iswideogram_l; + iswlower_l; + iswnumber_l; + iswphonogram_l; + iswprint_l; + iswpunct_l; + iswrune_l; + iswspace_l; + iswspecial_l; + iswupper_l; + iswxdigit_l; + towlower_l; + towupper_l; + iswctype_l; + wctype_l; + nextwctype_l; + ___mb_cur_max; + ___mb_cur_max_l; + towctrans_l; + wctrans_l; + wcsftime_l; + wcstod_l; + wcstof_l; + wcstoimax_l; + wcstol_l; + wcstold_l; + wcstoll_l; + wcstoul_l; + wcstoull_l; + wcstoumax_l; + __runes_for_locale; }; FBSDprivate_1.0 { Index: lib/libc/locale/mblocal.h =================================================================== --- lib/libc/locale/mblocal.h (revision 225653) +++ lib/libc/locale/mblocal.h (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2004 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -30,35 +35,45 @@ #define _MBLOCAL_H_ #include +#include "xlocale_private.h" + /* - * Rune initialization function prototypes. + * Conversion function pointers for current encoding. */ -int _none_init(_RuneLocale *); -int _ascii_init(_RuneLocale *); -int _UTF8_init(_RuneLocale *); -int _EUC_init(_RuneLocale *); -int _GB18030_init(_RuneLocale *); -int _GB2312_init(_RuneLocale *); -int _GBK_init(_RuneLocale *); -int _BIG5_init(_RuneLocale *); -int _MSKanji_init(_RuneLocale *); +struct xlocale_ctype { + struct xlocale_component header; + _RuneLocale *runes; + size_t (*__mbrtowc)(wchar_t * __restrict, const char * __restrict, + size_t, mbstate_t * __restrict); + int (*__mbsinit)(const mbstate_t *); + size_t (*__mbsnrtowcs)(wchar_t * __restrict, const char ** __restrict, + size_t, size_t, mbstate_t * __restrict); + size_t (*__wcrtomb)(char * __restrict, wchar_t, mbstate_t * __restrict); + size_t (*__wcsnrtombs)(char * __restrict, const wchar_t ** __restrict, + size_t, size_t, mbstate_t * __restrict); + int __mb_cur_max; + int __mb_sb_limit; +}; +#define XLOCALE_CTYPE(x) ((struct xlocale_ctype*)(x)->components[XLC_CTYPE]) +extern struct xlocale_ctype __xlocale_global_ctype; /* - * Conversion function pointers for current encoding. + * Rune initialization function prototypes. */ -extern size_t (*__mbrtowc)(wchar_t * __restrict, const char * __restrict, - size_t, mbstate_t * __restrict); -extern int (*__mbsinit)(const mbstate_t *); -extern size_t (*__mbsnrtowcs)(wchar_t * __restrict, const char ** __restrict, - size_t, size_t, mbstate_t * __restrict); -extern size_t (*__wcrtomb)(char * __restrict, wchar_t, mbstate_t * __restrict); -extern size_t (*__wcsnrtombs)(char * __restrict, const wchar_t ** __restrict, - size_t, size_t, mbstate_t * __restrict); +int _none_init(struct xlocale_ctype *, _RuneLocale *); +int _ascii_init(struct xlocale_ctype *, _RuneLocale *); +int _UTF8_init(struct xlocale_ctype *, _RuneLocale *); +int _EUC_init(struct xlocale_ctype *, _RuneLocale *); +int _GB18030_init(struct xlocale_ctype *, _RuneLocale *); +int _GB2312_init(struct xlocale_ctype *, _RuneLocale *); +int _GBK_init(struct xlocale_ctype *, _RuneLocale *); +int _BIG5_init(struct xlocale_ctype *, _RuneLocale *); +int _MSKanji_init(struct xlocale_ctype *, _RuneLocale *); extern size_t __mbsnrtowcs_std(wchar_t * __restrict, const char ** __restrict, - size_t, size_t, mbstate_t * __restrict); + size_t, size_t, mbstate_t * __restrict); extern size_t __wcsnrtombs_std(char * __restrict, const wchar_t ** __restrict, - size_t, size_t, mbstate_t * __restrict); + size_t, size_t, mbstate_t * __restrict); #endif /* _MBLOCAL_H_ */ Index: lib/libc/locale/DESIGN.xlocale =================================================================== --- lib/libc/locale/DESIGN.xlocale (revision 0) +++ lib/libc/locale/DESIGN.xlocale (revision 0) @@ -0,0 +1,157 @@ +Design of xlocale +================= + +The xlocale APIs come from Darwin, although a subset is now part of POSIX 2008. +They fall into two broad categories: + +- Manipulation of per-thread locales (POSIX) +- Locale-aware functions taking an explicit locale argument (Darwin) + +This document describes the implementation of these APIs for FreeBSD. + +Goals +----- + +The overall goal of this implementation is to be compatible with the Darwin +version. Additionally, it should include minimal changes to the existing +locale code. A lot of the existing locale code originates with 4BSD or earlier +and has had over a decade of testing. Replacing this code, unless absolutely +necessary, gives us the potential for more bugs without much benefit. + +With this in mind, various libc-private functions have been modified to take a +locale_t parameter. This causes a compiler error if they are accidentally +called without a locale. This approach was taken, rather than adding _l +variants of these functions, to make it harder for accidental uses of the +global-locale versions to slip in. + +Locale Objects +-------------- + +A locale is encapsulated in a `locale_t`, which is an opaque type: a pointer to +a `struct _xlocale`. The name `_xlocale` is unfortunate, as it does not fit +well with existing conventions, but is used because this is the name the Darwin +implementation gives to this structure and so may be used by existing (bad) code. + +This structure should include all of the information corresponding to a locale. +A locale_t is almost immutable after creation. There are no functions that modify it, +and it can therefore be used without locking. It is the responsibility of the +caller to ensure that a locale is not deallocated during a call that uses it. + +Each locale contains a number of components, one for each of the categories +supported by `setlocale()`. These are likewise immutable after creation. This +differs from the Darwin implementation, which includes a deprecated +`setinvalidrune()` function that can modify the rune locale. + +The exception to these mutability rules is a set of `mbstate_t` flags stored +with each locale. These are used by various functions that previously had a +static local `mbstate_t` variable. + +The components are reference counted, and so can be aliased between locale +objects. This makes copying locales very cheap. + +The Global Locale +----------------- + +All locales and locale components are reference counted. The global locale, +however, is special. It, and all of its components, are static and so no +malloc() memory is required when using a single locale. + +This means that threads using the global locale are subject to the same +constraints as with the pre-xlocale libc. Calls to any locale-aware functions +in threads using the global locale, while modifying the global locale, have +undefined behaviour. + +Because of this, we have to ensure that we always copy the components of the +global locale, rather than alias them. + +It would be cleaner to simply remove the special treatment of the global locale +and have a locale_t lazily allocated for the global context. This would cost a +little more `malloc()` memory, so is not done in the initial version. + +Caching +------- + +The existing locale implementation included several ad-hoc caching layers. +None of these were thread safe. Caching is only really of use for supporting +the pattern where the locale is briefly changed to something and then changed +back. + +The current xlocale implementation removes the caching entirely. This pattern +is not one that should be encouraged. If you need to make some calls with a +modified locale, then you should use the _l suffix versions of the calls, +rather than switch the global locale. If you do need to temporarily switch the +locale and then switch it back, `uselocale()` provides a way of doing this very +easily: It returns the old locale, which can then be passed to a subsequent +call to `uselocale()` to restore it, without the need to load any locale data +from the disk. + +If, in the future, it is determined that caching is beneficial, it can be added +quite easily in xlocale.c. Given, however, that any locale-aware call is going +to be a preparation for presenting data to the user, and so is invariably going +to be part of an I/O operation, this seems like a case of premature +optimisation. + +localeconv +---------- + +The `localeconv()` function is an exception to the immutable-after-creation +rule. In the classic implementation, this function returns a pointer to some +global storage, which is initialised with the data from the current locale. +This is not possible in a multithreaded environment, with multiple locales. + +Instead, each locale contains a `struct lconv` that is lazily initialised on +calls to `localeconv()`. This is not protected by any locking, however this is +still safe on any machine where word-sized stores are atomic: two concurrent +calls will write the same data into the structure. + +Explicit Locale Calls +--------------------- + +A large number of functions have been modified to take an explicit `locale_t` +parameter. The old APIs are then reimplemented with a call to `__get_locale()` +to supply the `locale_t` parameter. This is in line with the Darwin public +APIs, but also simplifies the modifications to these functions. The +`__get_locale()` function is now the only way to access the current locale +within libc. All of the old globals have gone, so there is now a linker error +if any functions attempt to use them. + +The ctype.h functions are a little different. These are not implemented in +terms of their locale-aware versions, for performance reasons. Each of these +is implemented as a short inline function. + +Differences to Darwin APIs +-------------------------- + +`strtoq_l()` and `strtouq_l() `are not provided. These are extensions to +deprecated functions - we should not be encouraging people to use deprecated +interfaces. + +Locale Placeholders +------------------- + +The pointer values 0 and -1 have special meanings as `locale_t` values. Any +public function that accepts a `locale_t` parameter must use the `FIX_LOCALE()` +macro on it before using it. For efficiency, this can be emitted in functions +which *only* use their locale parameter as an argument to another public +function, as the callee will do the `FIX_LOCALE()` itself. + +Potential Improvements +---------------------- + +Currently, the current rune set is accessed via a function call. This makes it +fairly expensive to use any of the ctype.h functions. We could improve this +quite a lot by storing the rune locale data in a __thread-qualified variable. + +Several of the existing FreeBSD locale-aware functions appear to be wrong. For +example, most of the `strto*()` family should probably use `digittoint_l()`, +but instead they assume ASCII. These will break if using a character encoding +that does not put numbers and the letters A-F in the same location as ASCII. +Some functions, like `strcoll()` only work on single-byte encodings. No +attempt has been made to fix existing limitations in the libc functions other +than to add support for xlocale. + +Intuitively, setting a thread-local locale should ensure that all locale-aware +functions can be used safely from that thread. In fact, this is not the case +in either this implementation or the Darwin one. You must call `duplocale()` +or `newlocale()` before calling `uselocale()`. This is a bit ugly, and it +would be better if libc ensure that every thread had its own locale object. Index: lib/libc/locale/mbsrtowcs.c =================================================================== --- lib/libc/locale/mbsrtowcs.c (revision 225653) +++ lib/libc/locale/mbsrtowcs.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002-2004 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -34,12 +39,17 @@ #include "mblocal.h" size_t +mbsrtowcs_l(wchar_t * __restrict dst, const char ** __restrict src, size_t len, + mbstate_t * __restrict ps, locale_t locale) +{ + FIX_LOCALE(locale); + if (ps == NULL) + ps = &locale->mbsrtowcs; + return (XLOCALE_CTYPE(locale)->__mbsnrtowcs(dst, src, SIZE_T_MAX, len, ps)); +} +size_t mbsrtowcs(wchar_t * __restrict dst, const char ** __restrict src, size_t len, mbstate_t * __restrict ps) { - static mbstate_t mbs; - - if (ps == NULL) - ps = &mbs; - return (__mbsnrtowcs(dst, src, SIZE_T_MAX, len, ps)); + return mbsrtowcs_l(dst, src, len, ps, __get_locale()); } Index: lib/libc/locale/utf8.c =================================================================== --- lib/libc/locale/utf8.c (revision 225653) +++ lib/libc/locale/utf8.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002-2004 Tim J. Robbins * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -55,22 +60,22 @@ } _UTF8State; int -_UTF8_init(_RuneLocale *rl) +_UTF8_init(struct xlocale_ctype *l, _RuneLocale *rl) { - __mbrtowc = _UTF8_mbrtowc; - __wcrtomb = _UTF8_wcrtomb; - __mbsinit = _UTF8_mbsinit; - __mbsnrtowcs = _UTF8_mbsnrtowcs; - __wcsnrtombs = _UTF8_wcsnrtombs; - _CurrentRuneLocale = rl; - __mb_cur_max = 6; + l->__mbrtowc = _UTF8_mbrtowc; + l->__wcrtomb = _UTF8_wcrtomb; + l->__mbsinit = _UTF8_mbsinit; + l->__mbsnrtowcs = _UTF8_mbsnrtowcs; + l->__wcsnrtombs = _UTF8_wcsnrtombs; + l->runes = rl; + l->__mb_cur_max = 6; /* * UCS-4 encoding used as the internal representation, so * slots 0x0080-0x00FF are occuped and must be excluded * from the single byte ctype by setting the limit. */ - __mb_sb_limit = 128; + l->__mb_sb_limit = 128; return (0); } Index: lib/libc/locale/collcmp.c =================================================================== --- lib/libc/locale/collcmp.c (revision 225653) +++ lib/libc/locale/collcmp.c (working copy) @@ -2,6 +2,11 @@ * Copyright (C) 1996 by Andrey A. Chernov, Moscow, Russia. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -28,17 +33,20 @@ __FBSDID("$FreeBSD$"); #include +#include #include "collate.h" /* * Compare two characters using collate */ -int __collate_range_cmp(int c1, int c2) +int __collate_range_cmp(struct xlocale_collate *table, int c1, int c2) { static char s1[2], s2[2]; s1[0] = c1; s2[0] = c2; - return (strcoll(s1, s2)); + struct _xlocale l = {{0}}; + l.components[XLC_COLLATE] = (struct xlocale_component *)table; + return (strcoll_l(s1, s2, &l)); } Index: lib/libc/locale/Makefile.inc =================================================================== --- lib/libc/locale/Makefile.inc (revision 225653) +++ lib/libc/locale/Makefile.inc (working copy) @@ -5,7 +5,7 @@ .PATH: ${.CURDIR}/${LIBC_ARCH}/locale ${.CURDIR}/locale SRCS+= ascii.c big5.c btowc.c collate.c collcmp.c euc.c fix_grouping.c \ - gb18030.c gb2312.c gbk.c isctype.c iswctype.c \ + gb18030.c gb2312.c gbk.c ctype.c isctype.c iswctype.c \ ldpart.c lmessages.c lmonetary.c lnumeric.c localeconv.c mblen.c \ mbrlen.c \ mbrtowc.c mbsinit.c mbsnrtowcs.c \ @@ -20,7 +20,8 @@ wcstoimax.c wcstol.c wcstold.c wcstoll.c \ wcstombs.c \ wcstoul.c wcstoull.c wcstoumax.c wctob.c wctomb.c wctrans.c wctype.c \ - wcwidth.c + wcwidth.c\ + xlocale.c SYM_MAPS+=${.CURDIR}/locale/Symbol.map Index: lib/libc/locale/wcstof.c =================================================================== --- lib/libc/locale/wcstof.c (revision 225653) +++ lib/libc/locale/wcstof.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002, 2003 Tim J. Robbins * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -30,12 +35,14 @@ #include #include #include +#include "xlocale_private.h" /* * See wcstod() for comments as to the logic used. */ float -wcstof(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr) +wcstof_l(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, + locale_t locale) { static const mbstate_t initial; mbstate_t mbs; @@ -43,13 +50,14 @@ char *buf, *end; const wchar_t *wcp; size_t len; + FIX_LOCALE(locale); - while (iswspace(*nptr)) + while (iswspace_l(*nptr, locale)) nptr++; wcp = nptr; mbs = initial; - if ((len = wcsrtombs(NULL, &wcp, 0, &mbs)) == (size_t)-1) { + if ((len = wcsrtombs_l(NULL, &wcp, 0, &mbs, locale)) == (size_t)-1) { if (endptr != NULL) *endptr = (wchar_t *)nptr; return (0.0); @@ -57,9 +65,9 @@ if ((buf = malloc(len + 1)) == NULL) return (0.0); mbs = initial; - wcsrtombs(buf, &wcp, len + 1, &mbs); + wcsrtombs_l(buf, &wcp, len + 1, &mbs, locale); - val = strtof(buf, &end); + val = strtof_l(buf, &end, locale); if (endptr != NULL) *endptr = (wchar_t *)nptr + (end - buf); @@ -68,3 +76,8 @@ return (val); } +float +wcstof(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr) +{ + return wcstof_l(nptr, endptr, __get_locale()); +} Index: lib/libc/locale/localeconv.3 =================================================================== --- lib/libc/locale/localeconv.3 (revision 225653) +++ lib/libc/locale/localeconv.3 (working copy) @@ -44,6 +44,9 @@ .In locale.h .Ft struct lconv * .Fn localeconv "void" +.In xlocale.h +.Ft struct lconv * +.Fn localeconv_l "locale_t locale" .Sh DESCRIPTION The .Fn localeconv @@ -196,6 +199,11 @@ A .Dv CHAR_MAX result similarly denotes an unavailable value. +.Pp +The +.Fn localeconv_l +function takes an explicit locale parameter. For more information, see +.Xr xlocale 3 . .Sh RETURN VALUES The .Fn localeconv @@ -204,6 +212,13 @@ .Xr setlocale 3 or .Fn localeconv . +The return value for +.Fn localeconv_l +is stored with the locale. It will remain valid until a subsequent call to +.Xr freelocale 3 . +If a thread-local locale is in effect then the return value from +.Fn localeconv +will remain valid until the locale is destroyed. .Sh ERRORS No errors are defined. .Sh SEE ALSO Index: lib/libc/locale/mbsinit.c =================================================================== --- lib/libc/locale/mbsinit.c (revision 225653) +++ lib/libc/locale/mbsinit.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002-2004 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -31,8 +36,13 @@ #include "mblocal.h" int +mbsinit_l(const mbstate_t *ps, locale_t locale) +{ + FIX_LOCALE(locale); + return (XLOCALE_CTYPE(locale)->__mbsinit(ps)); +} +int mbsinit(const mbstate_t *ps) { - - return (__mbsinit(ps)); + return mbsinit_l(ps, __get_locale()); } Index: lib/libc/locale/wcwidth.c =================================================================== --- lib/libc/locale/wcwidth.c (revision 225653) +++ lib/libc/locale/wcwidth.c (working copy) @@ -10,6 +10,11 @@ * This code is derived from software contributed to Berkeley by * Paul Borman at Krystal Technologies. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -39,12 +44,18 @@ __FBSDID("$FreeBSD$"); #include +#include +#include #undef wcwidth int wcwidth(wchar_t wc) { - return (__wcwidth(wc)); } +int +wcwidth_l(wchar_t wc, locale_t locale) +{ + return (__wcwidth_l(wc, locale)); +} Index: lib/libc/locale/setlocale.c =================================================================== --- lib/libc/locale/setlocale.c (revision 225653) +++ lib/libc/locale/setlocale.c (working copy) @@ -95,7 +95,7 @@ static char *currentlocale(void); static char *loadlocale(int); -static const char *__get_locale_env(int); +const char *__get_locale_env(int); char * setlocale(category, locale) @@ -278,13 +278,14 @@ if (func(new) != _LDP_ERROR) { (void)strcpy(old, new); + (void)strcpy(__xlocale_global_locale.components[category-1]->locale, new); return (old); } return (NULL); } -static const char * +const char * __get_locale_env(category) int category; { Index: lib/libc/locale/runetype.c =================================================================== --- lib/libc/locale/runetype.c (revision 225653) +++ lib/libc/locale/runetype.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Paul Borman at Krystal Technologies. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -36,12 +41,15 @@ #include #include #include +#include +#include "mblocal.h" unsigned long -___runetype(__ct_rune_t c) +___runetype_l(__ct_rune_t c, locale_t locale) { size_t lim; - _RuneRange *rr = &_CurrentRuneLocale->__runetype_ext; + FIX_LOCALE(locale); + _RuneRange *rr = &(XLOCALE_CTYPE(locale)->runes->__runetype_ext); _RuneEntry *base, *re; if (c < 0 || c == EOF) @@ -64,3 +72,18 @@ return(0L); } +unsigned long +___runetype(__ct_rune_t c) +{ + return ___runetype_l(c, __get_locale()); +} + +int ___mb_cur_max(void) +{ + return XLOCALE_CTYPE(__get_locale())->__mb_cur_max; +} +int ___mb_cur_max_l(locale_t locale) +{ + FIX_LOCALE(locale); + return XLOCALE_CTYPE(locale)->__mb_cur_max; +} Index: lib/libc/locale/btowc.c =================================================================== --- lib/libc/locale/btowc.c (revision 225653) +++ lib/libc/locale/btowc.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002, 2003 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -32,12 +37,13 @@ #include "mblocal.h" wint_t -btowc(int c) +btowc_l(int c, locale_t l) { static const mbstate_t initial; mbstate_t mbs = initial; char cc; wchar_t wc; + FIX_LOCALE(l); if (c == EOF) return (WEOF); @@ -47,7 +53,12 @@ * counts. */ cc = (char)c; - if (__mbrtowc(&wc, &cc, 1, &mbs) > 1) + if (XLOCALE_CTYPE(l)->__mbrtowc(&wc, &cc, 1, &mbs) > 1) return (WEOF); return (wc); } +wint_t +btowc(int c) +{ + return btowc_l(c, __get_locale()); +} Index: lib/libc/locale/mbrlen.c =================================================================== --- lib/libc/locale/mbrlen.c (revision 225653) +++ lib/libc/locale/mbrlen.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002-2004 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -31,11 +36,16 @@ #include "mblocal.h" size_t -mbrlen(const char * __restrict s, size_t n, mbstate_t * __restrict ps) +mbrlen_l(const char * __restrict s, size_t n, mbstate_t * __restrict ps, locale_t locale) { - static mbstate_t mbs; - + FIX_LOCALE(locale); if (ps == NULL) - ps = &mbs; - return (__mbrtowc(NULL, s, n, ps)); + ps = &locale->mbrlen; + return (XLOCALE_CTYPE(locale)->__mbrtowc(NULL, s, n, ps)); } + +size_t +mbrlen(const char * __restrict s, size_t n, mbstate_t * __restrict ps) +{ + return mbrlen_l(s, n, ps, __get_locale()); +} Index: lib/libc/locale/lmessages.c =================================================================== --- lib/libc/locale/lmessages.c (revision 225653) +++ lib/libc/locale/lmessages.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2001 Alexey Zelkin * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -36,6 +41,14 @@ #define LCMESSAGES_SIZE_MIN \ (offsetof(struct lc_messages_T, yesstr) / sizeof(char *)) +struct xlocale_messages { + struct xlocale_component header; + char *buffer; + struct lc_messages_T locale; +}; + +struct xlocale_messages __xlocale_global_messages; + static char empty[] = ""; static const struct lc_messages_T _C_messages_locale = { @@ -45,33 +58,55 @@ "no" /* nostr */ }; -static struct lc_messages_T _messages_locale; -static int _messages_using_locale; -static char *_messages_locale_buf; +static void destruct_messages(void *v) +{ + struct xlocale_messages *l = v; + if (l->buffer) + free(l->buffer); + free(l); +} -int -__messages_load_locale(const char *name) +static int +messages_load_locale(struct xlocale_messages *loc, int *using_locale, const char *name) { int ret; + struct lc_messages_T *l = &loc->locale; - ret = __part_load_locale(name, &_messages_using_locale, - &_messages_locale_buf, "LC_MESSAGES", + ret = __part_load_locale(name, using_locale, + &loc->buffer, "LC_MESSAGES", LCMESSAGES_SIZE_FULL, LCMESSAGES_SIZE_MIN, - (const char **)&_messages_locale); + (const char **)l); if (ret == _LDP_LOADED) { - if (_messages_locale.yesstr == NULL) - _messages_locale.yesstr = empty; - if (_messages_locale.nostr == NULL) - _messages_locale.nostr = empty; + if (l->yesstr == NULL) + l->yesstr = empty; + if (l->nostr == NULL) + l->nostr = empty; } return (ret); } +int +__messages_load_locale(const char *name) +{ + return messages_load_locale(&__xlocale_global_messages, + &__xlocale_global_locale.using_messages_locale, name); +} +void * +__messages_load(const char *name, locale_t l) +{ + struct xlocale_messages *new = calloc(sizeof(struct xlocale_messages), 1); + new->header.header.destructor = destruct_messages; + if (messages_load_locale(new, &l->using_messages_locale, name) == _LDP_ERROR) { + xlocale_release(new); + return NULL; + } + return new; +} struct lc_messages_T * -__get_current_messages_locale(void) +__get_current_messages_locale(locale_t loc) { - return (_messages_using_locale - ? &_messages_locale + return (loc->using_messages_locale + ? &((struct xlocale_messages *)loc->components[XLC_MESSAGES])->locale : (struct lc_messages_T *)&_C_messages_locale); } Index: lib/libc/locale/big5.c =================================================================== --- lib/libc/locale/big5.c (revision 225653) +++ lib/libc/locale/big5.c (working copy) @@ -6,6 +6,11 @@ * This code is derived from software contributed to Berkeley by * Paul Borman at Krystal Technologies. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -62,15 +67,15 @@ } _BIG5State; int -_BIG5_init(_RuneLocale *rl) +_BIG5_init(struct xlocale_ctype *l, _RuneLocale *rl) { - __mbrtowc = _BIG5_mbrtowc; - __wcrtomb = _BIG5_wcrtomb; - __mbsinit = _BIG5_mbsinit; - _CurrentRuneLocale = rl; - __mb_cur_max = 2; - __mb_sb_limit = 128; + l->__mbrtowc = _BIG5_mbrtowc; + l->__wcrtomb = _BIG5_wcrtomb; + l->__mbsinit = _BIG5_mbsinit; + l->runes = rl; + l->__mb_cur_max = 2; + l->__mb_sb_limit = 128; return (0); } Index: lib/libc/locale/lmessages.h =================================================================== --- lib/libc/locale/lmessages.h (revision 225653) +++ lib/libc/locale/lmessages.h (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2000, 2001 Alexey Zelkin * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -29,6 +34,8 @@ #ifndef _LMESSAGES_H_ #define _LMESSAGES_H_ +#include "xlocale_private.h" + struct lc_messages_T { const char *yesexpr; const char *noexpr; @@ -36,7 +43,7 @@ const char *nostr; }; -struct lc_messages_T *__get_current_messages_locale(void); +struct lc_messages_T *__get_current_messages_locale(locale_t); int __messages_load_locale(const char *); #endif /* !_LMESSAGES_H_ */ Index: lib/libc/locale/duplocale.3 =================================================================== --- lib/libc/locale/duplocale.3 (revision 0) +++ lib/libc/locale/duplocale.3 (revision 0) @@ -0,0 +1,76 @@ +.\" Copyright (c) 2011 The FreeBSD Foundation +.\" All rights reserved. +.\" +.\" This documentation was written by David Chisnall under sponsorship from +.\" the FreeBSD Foundation. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.Dd September 17 2011 +.Dt DUPLOCALE 3 +.Os +.Sh NAME +.Nm duplocale +.Nd duplicate an locale +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.In xlocale.h +.Ft locale_t +.Fn duplocale "locale_t locale" +.Sh DESCRIPTION +Duplicates an existing +.Fa locale_t +returning a new +.Fa locale_t +that refers to the same locale values but has independent internal state. +Various functions, such as +.Xr mblen 3 +require presistent state. These functions formerly used static variables and +calls to them from multiple threads had undefined behavior. They now use +fields in the +.Fa locale_t +associated with the current thread by +.Xr uselocale 3 . +These calls are therefore only thread safe on threads with a unique per-thread +locale. +.Pt +The locale returned by this call must be freed with +.Xr freelocale 3 . +.Sh BUGS +Ideally, +.Xr uselocale 3 +should make a copy of the +.Fa locale_t +implicitly to ensure thread safety, and a copy of the global locale should be +installed lazily on each thread. The FreeBSD implementation does not do this, +for compatibility with Darwin. +.Sh SEE ALSO +.Xr freelocale 3 , +.Xr localeconv 3 , +.Xr newlocale 3 , +.Xr querylocale 3 , +.Xr uselocale 3 , +.Xr xlocale 3 +.Sh STANDARDS +This function, conforms to +.St -p1003.1-2008 Index: lib/libc/locale/uselocale.3 =================================================================== --- lib/libc/locale/uselocale.3 (revision 0) +++ lib/libc/locale/uselocale.3 (revision 0) @@ -0,0 +1,60 @@ +.\" Copyright (c) 2011 The FreeBSD Foundation +.\" All rights reserved. +.\" +.\" This documentation was written by David Chisnall under sponsorship from +.\" the FreeBSD Foundation. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)ctype.3 8.1 (Berkeley) 6/4/93 +.\" $FreeBSD: head/lib/libc/locale/ctype.3 196820 2009-09-04 07:44:58Z des $ +.\" +.Dd September 17 2011 +.Dt USELOCALE 3 +.Os +.Sh NAME +.Nm uselocale +.Nd Sets a thread-local locale. +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.In xlocale.h +.Ft locale_t +.Fn uselocale "locale_t locale" +.Sh DESCRIPTION +Specifies the locale for this thread to use. Specifying +.Fa LC_GLOBAL_LOCALE +disables the per-thread locale, while NULL returns the current locale without +setting a new one. +.Sh RETURN VALUES +Returns the previous locale, or LC_GLOBAL_LOCALE if this thread has no locale +associated with it. +.Sh SEE ALSO +.Xr duplocale 3 , +.Xr freelocale 3 , +.Xr localeconv 3 , +.Xr newlocale 3 , +.Xr querylocale 3 , +.Xr xlocale 3 +.Sh STANDARDS +This function, conforms to +.St -p1003.1-2008 Index: lib/libc/locale/freelocale.3 =================================================================== --- lib/libc/locale/freelocale.3 (revision 0) +++ lib/libc/locale/freelocale.3 (revision 0) @@ -0,0 +1,60 @@ +.\" Copyright (c) 2011 The FreeBSD Foundation +.\" All rights reserved. +.\" +.\" This documentation was written by David Chisnall under sponsorship from +.\" the FreeBSD Foundation. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.Dd September 17 2011 +.Dt FREELOCALE 3 +.Os +.Sh NAME +.Nm freelocale +.Nd Frees a locale created with +.Xr duplocale 3 +or +.Xr newlocale 3 . +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.In xlocale.h +.Ft int +.Fn freelocale "locale_t locale" +.Sh DESCRIPTION +Frees a +.Fa locale_t . +This relinquishes any resources held exclusively by this locale. Note that +locales share reference-counted components, so a call to this function is not +guaranteed to free all of the components. +.Sh RETURN VALUES +Returns 0 on success or -1 on error. +.Sh SEE ALSO +.Xr duplocale 3 , +.Xr localeconv 3 , +.Xr newlocale 3 , +.Xr querylocale 3 , +.Xr uselocale 3 , +.Xr xlocale 3 +.Sh STANDARDS +This function, conforms to +.St -p1003.1-2008 . Index: lib/libc/locale/wcsrtombs.c =================================================================== --- lib/libc/locale/wcsrtombs.c (revision 225653) +++ lib/libc/locale/wcsrtombs.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002-2004 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -34,12 +39,18 @@ #include "mblocal.h" size_t +wcsrtombs_l(char * __restrict dst, const wchar_t ** __restrict src, size_t len, + mbstate_t * __restrict ps, locale_t locale) +{ + FIX_LOCALE(locale); + if (ps == NULL) + ps = &locale->wcsrtombs; + return (XLOCALE_CTYPE(locale)->__wcsnrtombs(dst, src, SIZE_T_MAX, len, ps)); +} + +size_t wcsrtombs(char * __restrict dst, const wchar_t ** __restrict src, size_t len, mbstate_t * __restrict ps) { - static mbstate_t mbs; - - if (ps == NULL) - ps = &mbs; - return (__wcsnrtombs(dst, src, SIZE_T_MAX, len, ps)); + return wcsrtombs_l(dst, src, len, ps, __get_locale()); } Index: lib/libc/locale/localeconv.c =================================================================== --- lib/libc/locale/localeconv.c (revision 225653) +++ lib/libc/locale/localeconv.c (working copy) @@ -3,6 +3,11 @@ * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -48,25 +53,24 @@ * lconv structure are computed only when the monetary or numeric * locale has been changed. */ -int __mlocale_changed = 1; -int __nlocale_changed = 1; /* * Return the current locale conversion. */ struct lconv * -localeconv() +localeconv_l(locale_t loc) { - static struct lconv ret; + FIX_LOCALE(loc); + struct lconv *ret = &loc->lconv; - if (__mlocale_changed) { + if (loc->monetary_locale_changed) { /* LC_MONETARY part */ struct lc_monetary_T * mptr; -#define M_ASSIGN_STR(NAME) (ret.NAME = (char*)mptr->NAME) -#define M_ASSIGN_CHAR(NAME) (ret.NAME = mptr->NAME[0]) +#define M_ASSIGN_STR(NAME) (ret->NAME = (char*)mptr->NAME) +#define M_ASSIGN_CHAR(NAME) (ret->NAME = mptr->NAME[0]) - mptr = __get_current_monetary_locale(); + mptr = __get_current_monetary_locale(loc); M_ASSIGN_STR(int_curr_symbol); M_ASSIGN_STR(currency_symbol); M_ASSIGN_STR(mon_decimal_point); @@ -88,21 +92,26 @@ M_ASSIGN_CHAR(int_n_sep_by_space); M_ASSIGN_CHAR(int_p_sign_posn); M_ASSIGN_CHAR(int_n_sign_posn); - __mlocale_changed = 0; + loc->monetary_locale_changed = 0; } - if (__nlocale_changed) { + if (loc->numeric_locale_changed) { /* LC_NUMERIC part */ struct lc_numeric_T * nptr; -#define N_ASSIGN_STR(NAME) (ret.NAME = (char*)nptr->NAME) +#define N_ASSIGN_STR(NAME) (ret->NAME = (char*)nptr->NAME) - nptr = __get_current_numeric_locale(); + nptr = __get_current_numeric_locale(loc); N_ASSIGN_STR(decimal_point); N_ASSIGN_STR(thousands_sep); N_ASSIGN_STR(grouping); - __nlocale_changed = 0; + loc->numeric_locale_changed = 0; } - return (&ret); + return ret; } +struct lconv * +localeconv(void) +{ + return localeconv_l(__get_locale()); +} Index: lib/libc/locale/wcsnrtombs.c =================================================================== --- lib/libc/locale/wcsnrtombs.c (revision 225653) +++ lib/libc/locale/wcsnrtombs.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002-2004 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -34,16 +39,22 @@ #include "mblocal.h" size_t +wcsnrtombs_l(char * __restrict dst, const wchar_t ** __restrict src, size_t nwc, + size_t len, mbstate_t * __restrict ps, locale_t locale) +{ + FIX_LOCALE(locale); + if (ps == NULL) + ps = &locale->wcsnrtombs; + return (XLOCALE_CTYPE(locale)->__wcsnrtombs(dst, src, nwc, len, ps)); +} +size_t wcsnrtombs(char * __restrict dst, const wchar_t ** __restrict src, size_t nwc, size_t len, mbstate_t * __restrict ps) { - static mbstate_t mbs; - - if (ps == NULL) - ps = &mbs; - return (__wcsnrtombs(dst, src, nwc, len, ps)); + return wcsnrtombs_l(dst, src, nwc, len, ps, __get_locale()); } + size_t __wcsnrtombs_std(char * __restrict dst, const wchar_t ** __restrict src, size_t nwc, size_t len, mbstate_t * __restrict ps) @@ -53,13 +64,14 @@ const wchar_t *s; size_t nbytes; size_t nb; + struct xlocale_ctype *l = XLOCALE_CTYPE(__get_locale()); s = *src; nbytes = 0; if (dst == NULL) { while (nwc-- > 0) { - if ((nb = __wcrtomb(buf, *s, ps)) == (size_t)-1) + if ((nb = l->__wcrtomb(buf, *s, ps)) == (size_t)-1) /* Invalid character - wcrtomb() sets errno. */ return ((size_t)-1); else if (*s == L'\0') @@ -73,7 +85,7 @@ while (len > 0 && nwc-- > 0) { if (len > (size_t)MB_CUR_MAX) { /* Enough space to translate in-place. */ - if ((nb = __wcrtomb(dst, *s, ps)) == (size_t)-1) { + if ((nb = l->__wcrtomb(dst, *s, ps)) == (size_t)-1) { *src = s; return ((size_t)-1); } @@ -86,7 +98,7 @@ * character is too long for the buffer. */ mbsbak = *ps; - if ((nb = __wcrtomb(buf, *s, ps)) == (size_t)-1) { + if ((nb = l->__wcrtomb(buf, *s, ps)) == (size_t)-1) { *src = s; return ((size_t)-1); } Index: lib/libc/locale/gbk.c =================================================================== --- lib/libc/locale/gbk.c (revision 225653) +++ lib/libc/locale/gbk.c (working copy) @@ -6,6 +6,11 @@ * This code is derived from software contributed to Berkeley by * Paul Borman at Krystal Technologies. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -55,15 +60,15 @@ } _GBKState; int -_GBK_init(_RuneLocale *rl) +_GBK_init(struct xlocale_ctype *l, _RuneLocale *rl) { - __mbrtowc = _GBK_mbrtowc; - __wcrtomb = _GBK_wcrtomb; - __mbsinit = _GBK_mbsinit; - _CurrentRuneLocale = rl; - __mb_cur_max = 2; - __mb_sb_limit = 128; + l->__mbrtowc = _GBK_mbrtowc; + l->__wcrtomb = _GBK_wcrtomb; + l->__mbsinit = _GBK_mbsinit; + l->runes = rl; + l->__mb_cur_max = 2; + l->__mb_sb_limit = 128; return (0); } Index: lib/libc/locale/querylocale.3 =================================================================== --- lib/libc/locale/querylocale.3 (revision 0) +++ lib/libc/locale/querylocale.3 (revision 0) @@ -0,0 +1,55 @@ +.\" Copyright (c) 2011 The FreeBSD Foundation +.\" All rights reserved. +.\" +.\" This documentation was written by David Chisnall under sponsorship from +.\" the FreeBSD Foundation. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.Dd September 17 2011 +.Dt QUERYLOCALE 3 +.Os +.Sh NAME +.Nm querylocale +.Nd Look up the locale name for a specified category. +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.In xlocale.h +.Ft const char * +.Fn querylocale "int mask" "locale_t locale" +.Sh DESCRIPTION +Returns the name of the locale for the category specified by +.Fa mask. +This possible values for the mask are the same as those in +.Xr newlocale 3 . If more than one bit in the mask is set, the returned value +is undefined. +.Sh SEE ALSO +.Xr duplocale 3 , +.Xr freelocale 3 , +.Xr localeconv 3 , +.Xr newlocale 3 , +.Xr uselocale 3 , +.Xr xlocale 3 +.Sh STANDARDS +This function, conforms to +.St -p1003.1-2008 Index: lib/libc/locale/wctype.c =================================================================== --- lib/libc/locale/wctype.c (revision 225653) +++ lib/libc/locale/wctype.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -30,17 +35,27 @@ #include #include #include +#include #undef iswctype int iswctype(wint_t wc, wctype_t charclass) { - return (__istype(wc, charclass)); } +int +iswctype_l(wint_t wc, wctype_t charclass, locale_t locale) +{ + return __istype_l(wc, charclass, locale); +} +/* + * IMPORTANT: The 0 in the call to this function in wctype() must be changed to + * __get_locale() if wctype_l() ie ever modified to actually use the locale + * parameter. + */ wctype_t -wctype(const char *property) +wctype_l(const char *property, locale_t locale) { static const struct { const char *name; @@ -72,3 +87,8 @@ return (props[i].mask); } + +wctype_t wctype(const char *property) +{ + return wctype_l(property, 0); +} Index: lib/libc/locale/lnumeric.c =================================================================== --- lib/libc/locale/lnumeric.c (revision 225653) +++ lib/libc/locale/lnumeric.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2000, 2001 Alexey Zelkin * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -32,7 +37,6 @@ #include "ldpart.h" #include "lnumeric.h" -extern int __nlocale_changed; extern const char *__fix_locale_grouping_str(const char *); #define LCNUMERIC_SIZE (sizeof(struct lc_numeric_T) / sizeof(char *)) @@ -45,37 +49,67 @@ numempty /* grouping */ }; -static struct lc_numeric_T _numeric_locale; -static int _numeric_using_locale; -static char *_numeric_locale_buf; +static void +destruct_numeric(void *v) +{ + struct xlocale_numeric *l = v; + if (l->buffer) + free(l->buffer); + free(l); +} -int -__numeric_load_locale(const char *name) +struct xlocale_numeric __xlocale_global_numeric; + +static int +numeric_load_locale(struct xlocale_numeric *loc, int *using_locale, int *changed, + const char *name) { int ret; + struct lc_numeric_T *l = &loc->locale; - ret = __part_load_locale(name, &_numeric_using_locale, - &_numeric_locale_buf, "LC_NUMERIC", + ret = __part_load_locale(name, using_locale, + &loc->buffer, "LC_NUMERIC", LCNUMERIC_SIZE, LCNUMERIC_SIZE, - (const char **)&_numeric_locale); + (const char**)l); if (ret != _LDP_ERROR) - __nlocale_changed = 1; + *changed= 1; if (ret == _LDP_LOADED) { /* Can't be empty according to C99 */ - if (*_numeric_locale.decimal_point == '\0') - _numeric_locale.decimal_point = + if (*l->decimal_point == '\0') + l->decimal_point = _C_numeric_locale.decimal_point; - _numeric_locale.grouping = - __fix_locale_grouping_str(_numeric_locale.grouping); + l->grouping = + __fix_locale_grouping_str(l->grouping); } return (ret); } +int +__numeric_load_locale(const char *name) +{ + return numeric_load_locale(&__xlocale_global_numeric, + &__xlocale_global_locale.using_numeric_locale, + &__xlocale_global_locale.numeric_locale_changed, name); +} +void * +__numeric_load(const char *name, locale_t l) +{ + struct xlocale_numeric *new = calloc(sizeof(struct xlocale_numeric), 1); + new->header.header.destructor = destruct_numeric; + if (numeric_load_locale(new, &l->using_numeric_locale, + &l->numeric_locale_changed, name) == _LDP_ERROR) + { + xlocale_release(new); + return NULL; + } + return new; +} + struct lc_numeric_T * -__get_current_numeric_locale(void) +__get_current_numeric_locale(locale_t loc) { - return (_numeric_using_locale - ? &_numeric_locale + return (loc->using_numeric_locale + ? &((struct xlocale_numeric *)loc->components[XLC_NUMERIC])->locale : (struct lc_numeric_T *)&_C_numeric_locale); } Index: lib/libc/locale/wcstoimax.c =================================================================== --- lib/libc/locale/wcstoimax.c (revision 225653) +++ lib/libc/locale/wcstoimax.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -41,19 +46,21 @@ #include #include #include +#include "xlocale_private.h" /* * Convert a wide character string to an intmax_t integer. */ intmax_t -wcstoimax(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, - int base) +wcstoimax_l(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, + int base, locale_t locale) { const wchar_t *s; uintmax_t acc; wchar_t c; uintmax_t cutoff; int neg, any, cutlim; + FIX_LOCALE(locale); /* * See strtoimax for comments as to the logic used. @@ -61,7 +68,7 @@ s = nptr; do { c = *s++; - } while (iswspace(c)); + } while (iswspace_l(c, locale)); if (c == L'-') { neg = 1; c = *s++; @@ -88,8 +95,8 @@ cutoff /= base; for ( ; ; c = *s++) { #ifdef notyet - if (iswdigit(c)) - c = digittoint(c); + if (iswdigit_l(c, locale)) + c = digittoint_l(c, locale); else #endif if (c >= L'0' && c <= L'9') @@ -122,3 +129,9 @@ *endptr = (wchar_t *)(any ? s - 1 : nptr); return (acc); } +intmax_t +wcstoimax(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, + int base) +{ + return wcstoimax_l(nptr, endptr, base, __get_locale()); +} Index: lib/libc/locale/lnumeric.h =================================================================== --- lib/libc/locale/lnumeric.h (revision 225653) +++ lib/libc/locale/lnumeric.h (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2000, 2001 Alexey Zelkin * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -28,14 +33,20 @@ #ifndef _LNUMERIC_H_ #define _LNUMERIC_H_ +#include "xlocale_private.h" struct lc_numeric_T { const char *decimal_point; const char *thousands_sep; const char *grouping; }; +struct xlocale_numeric { + struct xlocale_component header; + char *buffer; + struct lc_numeric_T locale; +}; -struct lc_numeric_T *__get_current_numeric_locale(void); +struct lc_numeric_T *__get_current_numeric_locale(locale_t loc); int __numeric_load_locale(const char *); #endif /* !_LNUMERIC_H_ */ Index: lib/libc/locale/wctomb.c =================================================================== --- lib/libc/locale/wctomb.c (revision 225653) +++ lib/libc/locale/wctomb.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002-2004 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -32,18 +37,23 @@ #include "mblocal.h" int -wctomb(char *s, wchar_t wchar) +wctomb_l(char *s, wchar_t wchar, locale_t locale) { static const mbstate_t initial; - static mbstate_t mbs; size_t rval; + FIX_LOCALE(locale); if (s == NULL) { /* No support for state dependent encodings. */ - mbs = initial; + locale->wctomb = initial; return (0); } - if ((rval = __wcrtomb(s, wchar, &mbs)) == (size_t)-1) + if ((rval = XLOCALE_CTYPE(locale)->__wcrtomb(s, wchar, &locale->wctomb)) == (size_t)-1) return (-1); return ((int)rval); } +int +wctomb(char *s, wchar_t wchar) +{ + return wctomb_l(s, wchar, __get_locale()); +} Index: lib/libc/locale/toupper.c =================================================================== --- lib/libc/locale/toupper.c (revision 225653) +++ lib/libc/locale/toupper.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Paul Borman at Krystal Technologies. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -36,13 +41,17 @@ #include #include #include +#include +#include "mblocal.h" __ct_rune_t -___toupper(c) +___toupper_l(c, l) __ct_rune_t c; + locale_t l; { size_t lim; - _RuneRange *rr = &_CurrentRuneLocale->__mapupper_ext; + FIX_LOCALE(l); + _RuneRange *rr = &XLOCALE_CTYPE(l)->runes->__maplower_ext; _RuneEntry *base, *re; if (c < 0 || c == EOF) @@ -53,7 +62,9 @@ for (lim = rr->__nranges; lim != 0; lim >>= 1) { re = base + (lim >> 1); if (re->__min <= c && c <= re->__max) + { return (re->__map + c - re->__min); + } else if (c > re->__max) { base = re + 1; lim--; @@ -62,3 +73,9 @@ return(c); } +__ct_rune_t +___toupper(c) + __ct_rune_t c; +{ + return ___toupper_l(c, __get_locale()); +} Index: lib/libc/locale/wcstombs.c =================================================================== --- lib/libc/locale/wcstombs.c (revision 225653) +++ lib/libc/locale/wcstombs.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002-2004 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -33,13 +38,21 @@ #include "mblocal.h" size_t -wcstombs(char * __restrict s, const wchar_t * __restrict pwcs, size_t n) +wcstombs_l(char * __restrict s, const wchar_t * __restrict pwcs, size_t n, + locale_t locale) { static const mbstate_t initial; mbstate_t mbs; const wchar_t *pwcsp; + FIX_LOCALE(locale); mbs = initial; pwcsp = pwcs; - return (__wcsnrtombs(s, &pwcsp, SIZE_T_MAX, n, &mbs)); + return (XLOCALE_CTYPE(locale)->__wcsnrtombs(s, &pwcsp, SIZE_T_MAX, n, &mbs)); } +size_t +wcstombs(char * __restrict s, const wchar_t * __restrict pwcs, size_t n) +{ + return wcstombs_l(s, pwcs, n, __get_locale()); +} + Index: lib/libc/locale/wcstoull.c =================================================================== --- lib/libc/locale/wcstoull.c (revision 225653) +++ lib/libc/locale/wcstoull.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -41,19 +46,21 @@ #include #include #include +#include "xlocale_private.h" /* * Convert a wide character string to an unsigned long long integer. */ unsigned long long -wcstoull(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, - int base) +wcstoull_l(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, + int base, locale_t locale) { const wchar_t *s; unsigned long long acc; wchar_t c; unsigned long long cutoff; int neg, any, cutlim; + FIX_LOCALE(locale); /* * See strtoull for comments as to the logic used. @@ -61,7 +68,7 @@ s = nptr; do { c = *s++; - } while (iswspace(c)); + } while (iswspace_l(c, locale)); if (c == L'-') { neg = 1; c = *s++; @@ -86,8 +93,8 @@ cutlim = ULLONG_MAX % base; for ( ; ; c = *s++) { #ifdef notyet - if (iswdigit(c)) - c = digittoint(c); + if (iswdigit_l(c, locale)) + c = digittoint_l(c, locale); else #endif if (c >= L'0' && c <= L'9') @@ -120,3 +127,9 @@ *endptr = (wchar_t *)(any ? s - 1 : nptr); return (acc); } +unsigned long long +wcstoull(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, + int base) +{ + return wcstoull_l(nptr, endptr, base, __get_locale()); +} Index: lib/libc/locale/euc.c =================================================================== --- lib/libc/locale/euc.c (revision 225653) +++ lib/libc/locale/euc.c (working copy) @@ -6,6 +6,11 @@ * This code is derived from software contributed to Berkeley by * Paul Borman at Krystal Technologies. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -70,7 +75,7 @@ } _EucState; int -_EUC_init(_RuneLocale *rl) +_EUC_init(struct xlocale_ctype *l, _RuneLocale *rl) { _EucInfo *ei; int x, new__mb_cur_max; @@ -113,12 +118,12 @@ } rl->__variable = ei; rl->__variable_len = sizeof(_EucInfo); - _CurrentRuneLocale = rl; - __mb_cur_max = new__mb_cur_max; - __mbrtowc = _EUC_mbrtowc; - __wcrtomb = _EUC_wcrtomb; - __mbsinit = _EUC_mbsinit; - __mb_sb_limit = 256; + l->runes = rl; + l->__mb_cur_max = new__mb_cur_max; + l->__mbrtowc = _EUC_mbrtowc; + l->__wcrtomb = _EUC_wcrtomb; + l->__mbsinit = _EUC_mbsinit; + l->__mb_sb_limit = 256; return (0); } Index: lib/libc/locale/wctob.c =================================================================== --- lib/libc/locale/wctob.c (revision 225653) +++ lib/libc/locale/wctob.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002-2004 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -33,13 +38,19 @@ #include "mblocal.h" int -wctob(wint_t c) +wctob_l(wint_t c, locale_t locale) { static const mbstate_t initial; mbstate_t mbs = initial; char buf[MB_LEN_MAX]; + FIX_LOCALE(locale); - if (c == WEOF || __wcrtomb(buf, c, &mbs) != 1) + if (c == WEOF || XLOCALE_CTYPE(locale)->__wcrtomb(buf, c, &mbs) != 1) return (EOF); return ((unsigned char)*buf); } +int +wctob(wint_t c) +{ + return wctob_l(c, __get_locale()); +} Index: lib/libc/locale/wcstold.c =================================================================== --- lib/libc/locale/wcstold.c (revision 225653) +++ lib/libc/locale/wcstold.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002, 2003 Tim J. Robbins * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -30,12 +35,14 @@ #include #include #include +#include "xlocale_private.h" /* * See wcstod() for comments as to the logic used. */ long double -wcstold(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr) +wcstold_l(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, + locale_t locale) { static const mbstate_t initial; mbstate_t mbs; @@ -43,13 +50,14 @@ char *buf, *end; const wchar_t *wcp; size_t len; + FIX_LOCALE(locale); - while (iswspace(*nptr)) + while (iswspace_l(*nptr, locale)) nptr++; wcp = nptr; mbs = initial; - if ((len = wcsrtombs(NULL, &wcp, 0, &mbs)) == (size_t)-1) { + if ((len = wcsrtombs_l(NULL, &wcp, 0, &mbs, locale)) == (size_t)-1) { if (endptr != NULL) *endptr = (wchar_t *)nptr; return (0.0); @@ -57,9 +65,9 @@ if ((buf = malloc(len + 1)) == NULL) return (0.0); mbs = initial; - wcsrtombs(buf, &wcp, len + 1, &mbs); + wcsrtombs_l(buf, &wcp, len + 1, &mbs, locale); - val = strtold(buf, &end); + val = strtold_l(buf, &end, locale); if (endptr != NULL) *endptr = (wchar_t *)nptr + (end - buf); @@ -68,3 +76,8 @@ return (val); } +long double +wcstold(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr) +{ + return wcstold_l(nptr, endptr, __get_locale()); +} Index: lib/libc/locale/wctrans.c =================================================================== --- lib/libc/locale/wctrans.c (revision 225653) +++ lib/libc/locale/wctrans.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -30,6 +35,7 @@ #include #include #include +#include "xlocale_private.h" enum { _WCT_ERROR = 0, @@ -38,15 +44,14 @@ }; wint_t -towctrans(wint_t wc, wctrans_t desc) +towctrans_l(wint_t wc, wctrans_t desc, locale_t locale) { - switch (desc) { case _WCT_TOLOWER: - wc = towlower(wc); + wc = towlower_l(wc, locale); break; case _WCT_TOUPPER: - wc = towupper(wc); + wc = towupper_l(wc, locale); break; case _WCT_ERROR: default: @@ -56,9 +61,18 @@ return (wc); } +wint_t +towctrans(wint_t wc, wctrans_t desc) +{ + return towctrans_l(wc, desc, __get_locale()); +} +/* + * wctrans() calls this will a 0 locale. If this is ever modified to actually + * use the locale, wctrans() must be modified to call __get_locale(). + */ wctrans_t -wctrans(const char *charclass) +wctrans_l(const char *charclass, locale_t locale) { struct { const char *name; @@ -78,3 +92,10 @@ errno = EINVAL; return (ccls[i].trans); } + +wctrans_t +wctrans(const char *charclass) +{ + return wctrans_l(charclass, 0); +} + Index: lib/libc/locale/gb18030.c =================================================================== --- lib/libc/locale/gb18030.c (revision 225653) +++ lib/libc/locale/gb18030.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002-2004 Tim J. Robbins * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -39,8 +44,6 @@ #include #include "mblocal.h" -extern int __mb_sb_limit; - static size_t _GB18030_mbrtowc(wchar_t * __restrict, const char * __restrict, size_t, mbstate_t * __restrict); static int _GB18030_mbsinit(const mbstate_t *); @@ -53,15 +56,15 @@ } _GB18030State; int -_GB18030_init(_RuneLocale *rl) +_GB18030_init(struct xlocale_ctype *l, _RuneLocale *rl) { - __mbrtowc = _GB18030_mbrtowc; - __wcrtomb = _GB18030_wcrtomb; - __mbsinit = _GB18030_mbsinit; - _CurrentRuneLocale = rl; - __mb_cur_max = 4; - __mb_sb_limit = 128; + l->__mbrtowc = _GB18030_mbrtowc; + l->__wcrtomb = _GB18030_wcrtomb; + l->__mbsinit = _GB18030_mbsinit; + l->runes = rl; + l->__mb_cur_max = 4; + l->__mb_sb_limit = 128; return (0); } Index: lib/libc/locale/nl_langinfo.c =================================================================== --- lib/libc/locale/nl_langinfo.c (revision 225653) +++ lib/libc/locale/nl_langinfo.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2001, 2003 Alexey Zelkin * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -41,15 +46,16 @@ #define _REL(BASE) ((int)item-BASE) char * -nl_langinfo(nl_item item) +nl_langinfo_l(nl_item item, locale_t loc) { - char *ret, *s, *cs; - static char *csym = NULL; + char *ret, *cs; + const char *s; + FIX_LOCALE(loc); switch (item) { case CODESET: ret = ""; - if ((s = setlocale(LC_CTYPE, NULL)) != NULL) { + if ((s = querylocale(LC_CTYPE_MASK, loc)) != NULL) { if ((cs = strchr(s, '.')) != NULL) ret = cs + 1; else if (strcmp(s, "C") == 0 || @@ -58,46 +64,46 @@ } break; case D_T_FMT: - ret = (char *) __get_current_time_locale()->c_fmt; + ret = (char *) __get_current_time_locale(loc)->c_fmt; break; case D_FMT: - ret = (char *) __get_current_time_locale()->x_fmt; + ret = (char *) __get_current_time_locale(loc)->x_fmt; break; case T_FMT: - ret = (char *) __get_current_time_locale()->X_fmt; + ret = (char *) __get_current_time_locale(loc)->X_fmt; break; case T_FMT_AMPM: - ret = (char *) __get_current_time_locale()->ampm_fmt; + ret = (char *) __get_current_time_locale(loc)->ampm_fmt; break; case AM_STR: - ret = (char *) __get_current_time_locale()->am; + ret = (char *) __get_current_time_locale(loc)->am; break; case PM_STR: - ret = (char *) __get_current_time_locale()->pm; + ret = (char *) __get_current_time_locale(loc)->pm; break; case DAY_1: case DAY_2: case DAY_3: case DAY_4: case DAY_5: case DAY_6: case DAY_7: - ret = (char*) __get_current_time_locale()->weekday[_REL(DAY_1)]; + ret = (char*) __get_current_time_locale(loc)->weekday[_REL(DAY_1)]; break; case ABDAY_1: case ABDAY_2: case ABDAY_3: case ABDAY_4: case ABDAY_5: case ABDAY_6: case ABDAY_7: - ret = (char*) __get_current_time_locale()->wday[_REL(ABDAY_1)]; + ret = (char*) __get_current_time_locale(loc)->wday[_REL(ABDAY_1)]; break; case MON_1: case MON_2: case MON_3: case MON_4: case MON_5: case MON_6: case MON_7: case MON_8: case MON_9: case MON_10: case MON_11: case MON_12: - ret = (char*) __get_current_time_locale()->month[_REL(MON_1)]; + ret = (char*) __get_current_time_locale(loc)->month[_REL(MON_1)]; break; case ABMON_1: case ABMON_2: case ABMON_3: case ABMON_4: case ABMON_5: case ABMON_6: case ABMON_7: case ABMON_8: case ABMON_9: case ABMON_10: case ABMON_11: case ABMON_12: - ret = (char*) __get_current_time_locale()->mon[_REL(ABMON_1)]; + ret = (char*) __get_current_time_locale(loc)->mon[_REL(ABMON_1)]; break; case ALTMON_1: case ALTMON_2: case ALTMON_3: case ALTMON_4: case ALTMON_5: case ALTMON_6: case ALTMON_7: case ALTMON_8: case ALTMON_9: case ALTMON_10: case ALTMON_11: case ALTMON_12: ret = (char*) - __get_current_time_locale()->alt_month[_REL(ALTMON_1)]; + __get_current_time_locale(loc)->alt_month[_REL(ALTMON_1)]; break; case ERA: /* XXX: need to be implemented */ @@ -120,16 +126,16 @@ ret = ""; break; case RADIXCHAR: - ret = (char*) __get_current_numeric_locale()->decimal_point; + ret = (char*) __get_current_numeric_locale(loc)->decimal_point; break; case THOUSEP: - ret = (char*) __get_current_numeric_locale()->thousands_sep; + ret = (char*) __get_current_numeric_locale(loc)->thousands_sep; break; case YESEXPR: - ret = (char*) __get_current_messages_locale()->yesexpr; + ret = (char*) __get_current_messages_locale(loc)->yesexpr; break; case NOEXPR: - ret = (char*) __get_current_messages_locale()->noexpr; + ret = (char*) __get_current_messages_locale(loc)->noexpr; break; /* * YESSTR and NOSTR items marked with LEGACY are available, but not @@ -137,45 +143,51 @@ * they're subject to remove in future specification editions. */ case YESSTR: /* LEGACY */ - ret = (char*) __get_current_messages_locale()->yesstr; + ret = (char*) __get_current_messages_locale(loc)->yesstr; break; case NOSTR: /* LEGACY */ - ret = (char*) __get_current_messages_locale()->nostr; + ret = (char*) __get_current_messages_locale(loc)->nostr; break; /* * SUSv2 special formatted currency string */ case CRNCYSTR: ret = ""; - cs = (char*) __get_current_monetary_locale()->currency_symbol; + cs = (char*) __get_current_monetary_locale(loc)->currency_symbol; if (*cs != '\0') { - char pos = localeconv()->p_cs_precedes; + char pos = localeconv_l(loc)->p_cs_precedes; - if (pos == localeconv()->n_cs_precedes) { + if (pos == localeconv_l(loc)->n_cs_precedes) { char psn = '\0'; if (pos == CHAR_MAX) { - if (strcmp(cs, __get_current_monetary_locale()->mon_decimal_point) == 0) + if (strcmp(cs, __get_current_monetary_locale(loc)->mon_decimal_point) == 0) psn = '.'; } else psn = pos ? '-' : '+'; if (psn != '\0') { int clen = strlen(cs); - if ((csym = reallocf(csym, clen + 2)) != NULL) { - *csym = psn; - strcpy(csym + 1, cs); - ret = csym; + if ((loc->csym = reallocf(loc->csym, clen + 2)) != NULL) { + *loc->csym = psn; + strcpy(loc->csym + 1, cs); + ret = loc->csym; } } } } break; case D_MD_ORDER: /* FreeBSD local extension */ - ret = (char *) __get_current_time_locale()->md_order; + ret = (char *) __get_current_time_locale(loc)->md_order; break; default: ret = ""; } return (ret); } + +char * +nl_langinfo(nl_item item) +{ + return nl_langinfo_l(item, __get_locale()); +} Index: lib/libc/locale/table.c =================================================================== --- lib/libc/locale/table.c (revision 225653) +++ lib/libc/locale/table.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Paul Borman at Krystal Technologies. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -41,7 +46,7 @@ #include #include "mblocal.h" -_RuneLocale _DefaultRuneLocale = { +const _RuneLocale _DefaultRuneLocale = { _RUNE_MAGIC_1, "NONE", NULL, @@ -245,5 +250,14 @@ }, }; -_RuneLocale *_CurrentRuneLocale = &_DefaultRuneLocale; +#undef _CurrentRuneLocale +_RuneLocale *_CurrentRuneLocale = (_RuneLocale*)&_DefaultRuneLocale; +_RuneLocale * +__runes_for_locale(locale_t locale, int *mb_sb_limit) +{ + FIX_LOCALE(locale); + struct xlocale_ctype *c = XLOCALE_CTYPE(locale); + *mb_sb_limit = c->__mb_sb_limit; + return c->runes; +} Index: lib/libc/locale/wcstoll.c =================================================================== --- lib/libc/locale/wcstoll.c (revision 225653) +++ lib/libc/locale/wcstoll.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -41,18 +46,21 @@ #include #include #include +#include "xlocale_private.h" /* * Convert a wide character string to a long long integer. */ long long -wcstoll(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, int base) +wcstoll_l(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, + int base, locale_t locale) { const wchar_t *s; unsigned long long acc; wchar_t c; unsigned long long cutoff; int neg, any, cutlim; + FIX_LOCALE(locale); /* * See strtoll for comments as to the logic used. @@ -60,7 +68,7 @@ s = nptr; do { c = *s++; - } while (iswspace(c)); + } while (iswspace_l(c, locale)); if (c == L'-') { neg = 1; c = *s++; @@ -87,8 +95,8 @@ cutoff /= base; for ( ; ; c = *s++) { #ifdef notyet - if (iswdigit(c)) - c = digittoint(c); + if (iswdigit_l(c, locale)) + c = digittoint_l(c, locale); else #endif if (c >= L'0' && c <= L'9') @@ -121,3 +129,8 @@ *endptr = (wchar_t *)(any ? s - 1 : nptr); return (acc); } +long long +wcstoll(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, int base) +{ + return wcstoll_l(nptr, endptr, base, __get_locale()); +} Index: lib/libc/locale/tolower.c =================================================================== --- lib/libc/locale/tolower.c (revision 225653) +++ lib/libc/locale/tolower.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Paul Borman at Krystal Technologies. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -36,13 +41,17 @@ #include #include #include +#include +#include "mblocal.h" __ct_rune_t -___tolower(c) +___tolower_l(c, l) __ct_rune_t c; + locale_t l; { size_t lim; - _RuneRange *rr = &_CurrentRuneLocale->__maplower_ext; + FIX_LOCALE(l); + _RuneRange *rr = &XLOCALE_CTYPE(l)->runes->__maplower_ext; _RuneEntry *base, *re; if (c < 0 || c == EOF) @@ -62,3 +71,9 @@ return(c); } +__ct_rune_t +___tolower(c) + __ct_rune_t c; +{ + return ___tolower_l(c, __get_locale()); +} Index: lib/libc/locale/mskanji.c =================================================================== --- lib/libc/locale/mskanji.c (revision 225653) +++ lib/libc/locale/mskanji.c (working copy) @@ -6,6 +6,11 @@ * (C) Sin'ichiro MIYATANI / Phase One, Inc * May 12, 1995 * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -60,15 +65,15 @@ } _MSKanjiState; int -_MSKanji_init(_RuneLocale *rl) +_MSKanji_init(struct xlocale_ctype *l, _RuneLocale *rl) { - __mbrtowc = _MSKanji_mbrtowc; - __wcrtomb = _MSKanji_wcrtomb; - __mbsinit = _MSKanji_mbsinit; - _CurrentRuneLocale = rl; - __mb_cur_max = 2; - __mb_sb_limit = 256; + l->__mbrtowc = _MSKanji_mbrtowc; + l->__wcrtomb = _MSKanji_wcrtomb; + l->__mbsinit = _MSKanji_mbsinit; + l->runes = rl; + l->__mb_cur_max = 2; + l->__mb_sb_limit = 256; return (0); } Index: lib/libc/locale/mblen.c =================================================================== --- lib/libc/locale/mblen.c (revision 225653) +++ lib/libc/locale/mblen.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002-2004 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -32,19 +37,25 @@ #include "mblocal.h" int -mblen(const char *s, size_t n) +mblen_l(const char *s, size_t n, locale_t locale) { static const mbstate_t initial; - static mbstate_t mbs; size_t rval; + FIX_LOCALE(locale); if (s == NULL) { /* No support for state dependent encodings. */ - mbs = initial; + locale->mblen = initial; return (0); } - rval = __mbrtowc(NULL, s, n, &mbs); + rval = XLOCALE_CTYPE(locale)->__mbrtowc(NULL, s, n, &locale->mblen); if (rval == (size_t)-1 || rval == (size_t)-2) return (-1); return ((int)rval); } + +int +mblen(const char *s, size_t n) +{ + return mblen_l(s, n, __get_locale()); +} Index: lib/libc/locale/none.c =================================================================== --- lib/libc/locale/none.c (revision 225653) +++ lib/libc/locale/none.c (working copy) @@ -6,6 +6,11 @@ * This code is derived from software contributed to Berkeley by * Paul Borman at Krystal Technologies. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -64,17 +69,17 @@ int __mb_sb_limit = 256; /* Expected to be <= _CACHED_RUNES */ int -_none_init(_RuneLocale *rl) +_none_init(struct xlocale_ctype *l, _RuneLocale *rl) { - __mbrtowc = _none_mbrtowc; - __mbsinit = _none_mbsinit; - __mbsnrtowcs = _none_mbsnrtowcs; - __wcrtomb = _none_wcrtomb; - __wcsnrtombs = _none_wcsnrtombs; - _CurrentRuneLocale = rl; - __mb_cur_max = 1; - __mb_sb_limit = 256; + l->__mbrtowc = _none_mbrtowc; + l->__mbsinit = _none_mbsinit; + l->__mbsnrtowcs = _none_mbsnrtowcs; + l->__wcrtomb = _none_wcrtomb; + l->__wcsnrtombs = _none_wcsnrtombs; + l->runes = rl; + l->__mb_cur_max = 1; + l->__mb_sb_limit = 256; return(0); } @@ -192,3 +197,14 @@ size_t (*__wcsnrtombs)(char * __restrict, const wchar_t ** __restrict, size_t, size_t, mbstate_t * __restrict) = _none_wcsnrtombs; +struct xlocale_ctype __xlocale_global_ctype = { + {{0}, "C"}, + (_RuneLocale*)&_DefaultRuneLocale, + _none_mbrtowc, + _none_mbsinit, + _none_mbsnrtowcs, + _none_wcrtomb, + _none_wcsnrtombs, + 1, /* __mb_cur_max, */ + 256 /* __mb_sb_limit */ +}; Index: lib/libc/locale/mbstowcs.c =================================================================== --- lib/libc/locale/mbstowcs.c (revision 225653) +++ lib/libc/locale/mbstowcs.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002-2004 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -33,13 +38,19 @@ #include "mblocal.h" size_t -mbstowcs(wchar_t * __restrict pwcs, const char * __restrict s, size_t n) +mbstowcs_l(wchar_t * __restrict pwcs, const char * __restrict s, size_t n, locale_t locale) { static const mbstate_t initial; mbstate_t mbs; const char *sp; + FIX_LOCALE(locale); mbs = initial; sp = s; - return (__mbsnrtowcs(pwcs, &sp, SIZE_T_MAX, n, &mbs)); + return (XLOCALE_CTYPE(locale)->__mbsnrtowcs(pwcs, &sp, SIZE_T_MAX, n, &mbs)); } +size_t +mbstowcs(wchar_t * __restrict pwcs, const char * __restrict s, size_t n) +{ + return mbstowcs_l(pwcs, s, n, __get_locale()); +} Index: lib/libc/locale/wcstod.c =================================================================== --- lib/libc/locale/wcstod.c (revision 225653) +++ lib/libc/locale/wcstod.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002 Tim J. Robbins * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -30,6 +35,7 @@ #include #include #include +#include "xlocale_private.h" /* * Convert a string to a double-precision number. @@ -41,7 +47,8 @@ * for at least the digits, radix character and letters. */ double -wcstod(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr) +wcstod_l(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, + locale_t locale) { static const mbstate_t initial; mbstate_t mbs; @@ -49,8 +56,9 @@ char *buf, *end; const wchar_t *wcp; size_t len; + FIX_LOCALE(locale); - while (iswspace(*nptr)) + while (iswspace_l(*nptr, locale)) nptr++; /* @@ -65,7 +73,7 @@ */ wcp = nptr; mbs = initial; - if ((len = wcsrtombs(NULL, &wcp, 0, &mbs)) == (size_t)-1) { + if ((len = wcsrtombs_l(NULL, &wcp, 0, &mbs, locale)) == (size_t)-1) { if (endptr != NULL) *endptr = (wchar_t *)nptr; return (0.0); @@ -73,10 +81,10 @@ if ((buf = malloc(len + 1)) == NULL) return (0.0); mbs = initial; - wcsrtombs(buf, &wcp, len + 1, &mbs); + wcsrtombs_l(buf, &wcp, len + 1, &mbs, locale); /* Let strtod() do most of the work for us. */ - val = strtod(buf, &end); + val = strtod_l(buf, &end, locale); /* * We only know where the number ended in the _multibyte_ @@ -92,3 +100,8 @@ return (val); } +double +wcstod(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr) +{ + return wcstod_l(nptr, endptr, __get_locale()); +} Index: lib/libc/locale/setrunelocale.c =================================================================== --- lib/libc/locale/setrunelocale.c (revision 225653) +++ lib/libc/locale/setrunelocale.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Paul Borman at Krystal Technologies. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -49,68 +54,46 @@ extern _RuneLocale *_Read_RuneMagi(FILE *); -static int __setrunelocale(const char *); +static int __setrunelocale(struct xlocale_ctype *l, const char *); +#define __collate_load_error (table->__collate_load_error) +#define __collate_substitute_nontrivial (table->__collate_substitute_nontrivial) +#define __collate_substitute_table_ptr (table->__collate_substitute_table_ptr) +#define __collate_char_pri_table_ptr (table->__collate_char_pri_table_ptr) +#define __collate_chain_pri_table (table->__collate_chain_pri_table) + + +static void destruct_ctype(void *v) +{ + struct xlocale_ctype *l = v; + if (strcmp(l->runes->__encoding, "EUC") == 0) + free(l->runes->__variable); + if (&_DefaultRuneLocale != l->runes) + free(l->runes); + free(l); +} +_RuneLocale *__getCurrentRuneLocale(void) +{ + return XLOCALE_CTYPE(__get_locale())->runes; +} + static int -__setrunelocale(const char *encoding) +__setrunelocale(struct xlocale_ctype *l, const char *encoding) { FILE *fp; char name[PATH_MAX]; _RuneLocale *rl; int saverr, ret; - size_t (*old__mbrtowc)(wchar_t * __restrict, - const char * __restrict, size_t, mbstate_t * __restrict); - size_t (*old__wcrtomb)(char * __restrict, wchar_t, - mbstate_t * __restrict); - int (*old__mbsinit)(const mbstate_t *); - size_t (*old__mbsnrtowcs)(wchar_t * __restrict, - const char ** __restrict, size_t, size_t, mbstate_t * __restrict); - size_t (*old__wcsnrtombs)(char * __restrict, - const wchar_t ** __restrict, size_t, size_t, - mbstate_t * __restrict); - static char ctype_encoding[ENCODING_LEN + 1]; - static _RuneLocale *CachedRuneLocale; - static int Cached__mb_cur_max; - static int Cached__mb_sb_limit; - static size_t (*Cached__mbrtowc)(wchar_t * __restrict, - const char * __restrict, size_t, mbstate_t * __restrict); - static size_t (*Cached__wcrtomb)(char * __restrict, wchar_t, - mbstate_t * __restrict); - static int (*Cached__mbsinit)(const mbstate_t *); - static size_t (*Cached__mbsnrtowcs)(wchar_t * __restrict, - const char ** __restrict, size_t, size_t, mbstate_t * __restrict); - static size_t (*Cached__wcsnrtombs)(char * __restrict, - const wchar_t ** __restrict, size_t, size_t, - mbstate_t * __restrict); + struct xlocale_ctype saved = *l; /* * The "C" and "POSIX" locale are always here. */ if (strcmp(encoding, "C") == 0 || strcmp(encoding, "POSIX") == 0) { - (void) _none_init(&_DefaultRuneLocale); + (void) _none_init(l, (_RuneLocale*)&_DefaultRuneLocale); return (0); } - /* - * If the locale name is the same as our cache, use the cache. - */ - if (CachedRuneLocale != NULL && - strcmp(encoding, ctype_encoding) == 0) { - _CurrentRuneLocale = CachedRuneLocale; - __mb_cur_max = Cached__mb_cur_max; - __mb_sb_limit = Cached__mb_sb_limit; - __mbrtowc = Cached__mbrtowc; - __mbsinit = Cached__mbsinit; - __mbsnrtowcs = Cached__mbsnrtowcs; - __wcrtomb = Cached__wcrtomb; - __wcsnrtombs = Cached__wcsnrtombs; - return (0); - } - - /* - * Slurp the locale file into the cache. - */ - /* Range checking not needed, encoding length already checked before */ (void) strcpy(name, _PathLocale); (void) strcat(name, "/"); @@ -127,63 +110,47 @@ } (void)fclose(fp); - old__mbrtowc = __mbrtowc; - old__mbsinit = __mbsinit; - old__mbsnrtowcs = __mbsnrtowcs; - old__wcrtomb = __wcrtomb; - old__wcsnrtombs = __wcsnrtombs; + l->__mbrtowc = NULL; + l->__mbsinit = NULL; + l->__mbsnrtowcs = __mbsnrtowcs_std; + l->__wcrtomb = NULL; + l->__wcsnrtombs = __wcsnrtombs_std; - __mbrtowc = NULL; - __mbsinit = NULL; - __mbsnrtowcs = __mbsnrtowcs_std; - __wcrtomb = NULL; - __wcsnrtombs = __wcsnrtombs_std; - rl->__sputrune = NULL; rl->__sgetrune = NULL; if (strcmp(rl->__encoding, "NONE") == 0) - ret = _none_init(rl); + ret = _none_init(l, rl); else if (strcmp(rl->__encoding, "ASCII") == 0) - ret = _ascii_init(rl); + ret = _ascii_init(l, rl); else if (strcmp(rl->__encoding, "UTF-8") == 0) - ret = _UTF8_init(rl); + ret = _UTF8_init(l, rl); else if (strcmp(rl->__encoding, "EUC") == 0) - ret = _EUC_init(rl); + ret = _EUC_init(l, rl); else if (strcmp(rl->__encoding, "GB18030") == 0) - ret = _GB18030_init(rl); + ret = _GB18030_init(l, rl); else if (strcmp(rl->__encoding, "GB2312") == 0) - ret = _GB2312_init(rl); + ret = _GB2312_init(l, rl); else if (strcmp(rl->__encoding, "GBK") == 0) - ret = _GBK_init(rl); + ret = _GBK_init(l, rl); else if (strcmp(rl->__encoding, "BIG5") == 0) - ret = _BIG5_init(rl); + ret = _BIG5_init(l, rl); else if (strcmp(rl->__encoding, "MSKanji") == 0) - ret = _MSKanji_init(rl); + ret = _MSKanji_init(l, rl); else ret = EFTYPE; if (ret == 0) { - if (CachedRuneLocale != NULL) { - /* See euc.c */ - if (strcmp(CachedRuneLocale->__encoding, "EUC") == 0) - free(CachedRuneLocale->__variable); - free(CachedRuneLocale); + /* Free the old runes if it exists. */ + /* FIXME: The "EUC" check here is a hideous abstraction violation. */ + if ((saved.runes != &_DefaultRuneLocale) && (saved.runes)) { + if (strcmp(saved.runes->__encoding, "EUC") == 0) { + free(saved.runes->__variable); + } + free(saved.runes); } - CachedRuneLocale = _CurrentRuneLocale; - Cached__mb_cur_max = __mb_cur_max; - Cached__mb_sb_limit = __mb_sb_limit; - Cached__mbrtowc = __mbrtowc; - Cached__mbsinit = __mbsinit; - Cached__mbsnrtowcs = __mbsnrtowcs; - Cached__wcrtomb = __wcrtomb; - Cached__wcsnrtombs = __wcsnrtombs; - (void)strcpy(ctype_encoding, encoding); } else { - __mbrtowc = old__mbrtowc; - __mbsinit = old__mbsinit; - __mbsnrtowcs = old__mbsnrtowcs; - __wcrtomb = old__wcrtomb; - __wcsnrtombs = old__wcsnrtombs; + /* Restore the saved version if this failed. */ + memcpy(l, &saved, sizeof(struct xlocale_ctype)); free(rl); } @@ -193,12 +160,24 @@ int __wrap_setrunelocale(const char *locale) { - int ret = __setrunelocale(locale); + int ret = __setrunelocale(&__xlocale_global_ctype, locale); if (ret != 0) { errno = ret; return (_LDP_ERROR); } + __mb_cur_max = __xlocale_global_ctype.__mb_cur_max; + __mb_sb_limit = __xlocale_global_ctype.__mb_sb_limit; return (_LDP_LOADED); } - +void *__ctype_load(const char *locale, locale_t unused) +{ + struct xlocale_ctype *l = calloc(sizeof(struct xlocale_ctype), 1); + l->header.header.destructor = destruct_ctype; + if (__setrunelocale(l, locale)) + { + free(l); + return NULL; + } + return l; +} Index: lib/libc/locale/lmonetary.c =================================================================== --- lib/libc/locale/lmonetary.c (revision 225653) +++ lib/libc/locale/lmonetary.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2000, 2001 Alexey Zelkin * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -34,7 +39,6 @@ #include "ldpart.h" #include "lmonetary.h" -extern int __mlocale_changed; extern const char * __fix_locale_grouping_str(const char *); #define LCMONETARY_SIZE_FULL (sizeof(struct lc_monetary_T) / sizeof(char *)) @@ -69,9 +73,7 @@ numempty /* int_n_sign_posn */ }; -static struct lc_monetary_T _monetary_locale; -static int _monetary_using_locale; -static char *_monetary_locale_buf; +struct xlocale_monetary __xlocale_global_monetary; static char cnv(const char *str) @@ -83,23 +85,34 @@ return ((char)i); } -int -__monetary_load_locale(const char *name) +static void +destruct_monetary(void *v) { + struct xlocale_monetary *l = v; + if (l->buffer) + free(l->buffer); + free(l); +} + +static int +monetary_load_locale_l(struct xlocale_monetary *loc, int *using_locale, + int *changed, const char *name) +{ int ret; + struct lc_monetary_T *l = &loc->locale; - ret = __part_load_locale(name, &_monetary_using_locale, - &_monetary_locale_buf, "LC_MONETARY", + ret = __part_load_locale(name, using_locale, + &loc->buffer, "LC_MONETARY", LCMONETARY_SIZE_FULL, LCMONETARY_SIZE_MIN, - (const char **)&_monetary_locale); + (const char **)l); if (ret != _LDP_ERROR) - __mlocale_changed = 1; + *changed = 1; if (ret == _LDP_LOADED) { - _monetary_locale.mon_grouping = - __fix_locale_grouping_str(_monetary_locale.mon_grouping); + l->mon_grouping = + __fix_locale_grouping_str(l->mon_grouping); -#define M_ASSIGN_CHAR(NAME) (((char *)_monetary_locale.NAME)[0] = \ - cnv(_monetary_locale.NAME)) +#define M_ASSIGN_CHAR(NAME) (((char *)l->NAME)[0] = \ + cnv(l->NAME)) M_ASSIGN_CHAR(int_frac_digits); M_ASSIGN_CHAR(frac_digits); @@ -117,9 +130,9 @@ */ #define M_ASSIGN_ICHAR(NAME) \ do { \ - if (_monetary_locale.int_##NAME == NULL) \ - _monetary_locale.int_##NAME = \ - _monetary_locale.NAME; \ + if (l->int_##NAME == NULL) \ + l->int_##NAME = \ + l->NAME; \ else \ M_ASSIGN_CHAR(int_##NAME); \ } while (0) @@ -133,12 +146,32 @@ } return (ret); } +int +__monetary_load_locale(const char *name) +{ + return monetary_load_locale_l(&__xlocale_global_monetary, + &__xlocale_global_locale.using_monetary_locale, + &__xlocale_global_locale.monetary_locale_changed, name); +} +void* __monetary_load(const char *name, locale_t l) +{ + struct xlocale_monetary *new = calloc(sizeof(struct xlocale_monetary), 1); + new->header.header.destructor = destruct_monetary; + if (monetary_load_locale_l(new, &l->using_monetary_locale, + &l->monetary_locale_changed, name) == _LDP_ERROR) + { + xlocale_release(new); + return NULL; + } + return new; +} + struct lc_monetary_T * -__get_current_monetary_locale(void) +__get_current_monetary_locale(locale_t loc) { - return (_monetary_using_locale - ? &_monetary_locale + return (loc->using_monetary_locale + ? &((struct xlocale_monetary*)loc->components[XLC_MONETARY])->locale : (struct lc_monetary_T *)&_C_monetary_locale); } Index: lib/libc/locale/nextwctype.c =================================================================== --- lib/libc/locale/nextwctype.c (revision 225653) +++ lib/libc/locale/nextwctype.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2004 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -30,12 +35,15 @@ #include #include #include +#include "mblocal.h" wint_t -nextwctype(wint_t wc, wctype_t wct) +nextwctype_l(wint_t wc, wctype_t wct, locale_t locale) { size_t lim; - _RuneRange *rr = &_CurrentRuneLocale->__runetype_ext; + FIX_LOCALE(locale); + _RuneLocale *runes = XLOCALE_CTYPE(locale)->runes; + _RuneRange *rr = &runes->__runetype_ext; _RuneEntry *base, *re; int noinc; @@ -43,7 +51,7 @@ if (wc < _CACHED_RUNES) { wc++; while (wc < _CACHED_RUNES) { - if (_CurrentRuneLocale->__runetype[wc] & wct) + if (runes->__runetype[wc] & wct) return (wc); wc++; } @@ -88,3 +96,8 @@ } return (-1); } +wint_t +nextwctype(wint_t wc, wctype_t wct) +{ + return nextwctype_l(wc, wct, __get_locale()); +} Index: lib/libc/locale/wcstol.c =================================================================== --- lib/libc/locale/wcstol.c (revision 225653) +++ lib/libc/locale/wcstol.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -35,18 +40,21 @@ #include #include #include +#include "xlocale_private.h" /* * Convert a string to a long integer. */ long -wcstol(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, int base) +wcstol_l(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, int + base, locale_t locale) { const wchar_t *s; unsigned long acc; wchar_t c; unsigned long cutoff; int neg, any, cutlim; + FIX_LOCALE(locale); /* * See strtol for comments as to the logic used. @@ -54,7 +62,7 @@ s = nptr; do { c = *s++; - } while (iswspace(c)); + } while (iswspace_l(c, locale)); if (c == '-') { neg = 1; c = *s++; @@ -81,8 +89,8 @@ cutoff /= base; for ( ; ; c = *s++) { #ifdef notyet - if (iswdigit(c)) - c = digittoint(c); + if (iswdigit_l(c, locale)) + c = digittoint_l(c, locale); else #endif if (c >= L'0' && c <= L'9') @@ -115,3 +123,8 @@ *endptr = (wchar_t *)(any ? s - 1 : nptr); return (acc); } +long +wcstol(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, int base) +{ + return wcstol_l(nptr, endptr, base, __get_locale()); +} Index: lib/libc/locale/wcrtomb.c =================================================================== --- lib/libc/locale/wcrtomb.c (revision 225653) +++ lib/libc/locale/wcrtomb.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002-2004 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -31,11 +36,17 @@ #include "mblocal.h" size_t -wcrtomb(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps) +wcrtomb_l(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps, + locale_t locale) { - static mbstate_t mbs; - + FIX_LOCALE(locale); if (ps == NULL) - ps = &mbs; - return (__wcrtomb(s, wc, ps)); + ps = &locale->wcrtomb; + return (XLOCALE_CTYPE(locale)->__wcrtomb(s, wc, ps)); } + +size_t +wcrtomb(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps) +{ + return wcrtomb_l(s, wc, ps, __get_locale()); +} Index: lib/libc/locale/lmonetary.h =================================================================== --- lib/libc/locale/lmonetary.h (revision 225653) +++ lib/libc/locale/lmonetary.h (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2000, 2001 Alexey Zelkin * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -28,6 +33,7 @@ #ifndef _LMONETARY_H_ #define _LMONETARY_H_ +#include "xlocale_private.h" struct lc_monetary_T { const char *int_curr_symbol; @@ -52,8 +58,13 @@ const char *int_p_sign_posn; const char *int_n_sign_posn; }; +struct xlocale_monetary { + struct xlocale_component header; + char *buffer; + struct lc_monetary_T locale; +}; -struct lc_monetary_T *__get_current_monetary_locale(void); +struct lc_monetary_T *__get_current_monetary_locale(locale_t loc); int __monetary_load_locale(const char *); #endif /* !_LMONETARY_H_ */ Index: lib/libc/locale/wcsftime.c =================================================================== --- lib/libc/locale/wcsftime.c (revision 225653) +++ lib/libc/locale/wcsftime.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002 Tim J. Robbins * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -32,6 +37,7 @@ #include #include #include +#include "xlocale_private.h" /* * Convert date and time to a wide-character string. @@ -47,8 +53,9 @@ * format specifications in the format string. */ size_t -wcsftime(wchar_t * __restrict wcs, size_t maxsize, - const wchar_t * __restrict format, const struct tm * __restrict timeptr) +wcsftime_l(wchar_t * __restrict wcs, size_t maxsize, + const wchar_t * __restrict format, const struct tm * __restrict timeptr, + locale_t locale) { static const mbstate_t initial; mbstate_t mbs; @@ -57,6 +64,7 @@ const wchar_t *formatp; size_t n, sflen; int sverrno; + FIX_LOCALE(locale); sformat = dst = NULL; @@ -66,13 +74,13 @@ */ mbs = initial; formatp = format; - sflen = wcsrtombs(NULL, &formatp, 0, &mbs); + sflen = wcsrtombs_l(NULL, &formatp, 0, &mbs, locale); if (sflen == (size_t)-1) goto error; if ((sformat = malloc(sflen + 1)) == NULL) goto error; mbs = initial; - wcsrtombs(sformat, &formatp, sflen + 1, &mbs); + wcsrtombs_l(sformat, &formatp, sflen + 1, &mbs, locale); /* * Allocate memory for longest multibyte sequence that will fit @@ -87,11 +95,11 @@ } if ((dst = malloc(maxsize * MB_CUR_MAX)) == NULL) goto error; - if (strftime(dst, maxsize, sformat, timeptr) == 0) + if (strftime_l(dst, maxsize, sformat, timeptr, locale) == 0) goto error; dstp = dst; mbs = initial; - n = mbsrtowcs(wcs, &dstp, maxsize, &mbs); + n = mbsrtowcs_l(wcs, &dstp, maxsize, &mbs, locale); if (n == (size_t)-2 || n == (size_t)-1 || dstp != NULL) goto error; @@ -106,3 +114,9 @@ errno = sverrno; return (0); } +size_t +wcsftime(wchar_t * __restrict wcs, size_t maxsize, + const wchar_t * __restrict format, const struct tm * __restrict timeptr) +{ + return wcsftime_l(wcs, maxsize, format, timeptr, __get_locale()); +} Index: lib/libc/locale/xlocale_private.h =================================================================== --- lib/libc/locale/xlocale_private.h (revision 0) +++ lib/libc/locale/xlocale_private.h (revision 0) @@ -0,0 +1,199 @@ +/*- + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by David Chisnall under sponsorship from + * the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions * are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _XLOCALE_PRIVATE__H_ +#define _XLOCALE_PRIVATE__H_ + +#include +#include +#include +#include +#include "setlocale.h" + +enum { + XLC_COLLATE = 0, + XLC_CTYPE, + XLC_MONETARY, + XLC_NUMERIC, + XLC_TIME, + XLC_MESSAGES, + XLC_LAST +}; + + +/** + * Header used for objects that are reference counted. Objects may optionally + * have a destructor associated, which is responsible for destroying the + * structure. Global / static versions of the structure should have no + * destructor set - they can then have their reference counts manipulated as + * normal, but will not do anything with them. + * + * The header stores a retain count - objects are assumed to have a reference + * count of 1 when they are created, but the retain count is 0. When the + * retain count is less than 0, they are freed. + */ +struct xlocale_refcounted { + /** Number of references to this component. */ + long retain_count; + /** Function used to destroy this component, if one is required*/ + void(*destructor)(void*); +}; +/** + * Header for a locale component. All locale components must begin with this + * header. + */ +struct xlocale_component { + struct xlocale_refcounted header; + /** Name of the locale used for this component. */ + char locale[ENCODING_LEN+1]; +}; + +/** + * xlocale structure, stores per-thread locale information. + * + * Note: We could save a few bytes by using a bitfield for the flags at the end + * of this structure. I imagine that most programs will not have more than + * half a dozen locales though, so this doesn't seem worthwhile. + */ +struct _xlocale { + struct xlocale_refcounted header; + /** Components for the locale. */ + struct xlocale_component *components[XLC_LAST]; + /** Flag indicating if components[XLC_MONETARY] has changed since the last + * call to localeconv_l() with this locale. */ + int monetary_locale_changed; + /** Flag indicating whether this locale is actually using a locale for + * LC_MONETARY (1), or if it should use the C default instead (0). */ + int using_monetary_locale; + /** Flag indicating if components[XLC_NUMERIC] has changed since the last + * call to localeconv_l() with this locale. */ + int numeric_locale_changed; + /** Flag indicating whether this locale is actually using a locale for + * LC_NUMERIC (1), or if it should use the C default instead (0). */ + int using_numeric_locale; + /** Flag indicating whether this locale is actually using a locale for + * LC_TIME (1), or if it should use the C default instead (0). */ + int using_time_locale; + /** Flag indicating whether this locale is actually using a locale for + * LC_MESSAGES (1), or if it should use the C default instead (0). */ + int using_messages_locale; + /** The structure to be returned from localeconv_l() for this locale. */ + struct lconv lconv; + /** Persistent state used by mblen() calls. */ + __mbstate_t mblen; + /** Persistent state used by mbrlen() calls. */ + __mbstate_t mbrlen; + /** Persistent state used by mbrtowc() calls. */ + __mbstate_t mbrtowc; + /** Persistent state used by mbsnrtowcs() calls. */ + __mbstate_t mbsnrtowcs; + /** Persistent state used by mbsrtowcs() calls. */ + __mbstate_t mbsrtowcs; + /** Persistent state used by mbtowc() calls. */ + __mbstate_t mbtowc; + /** Persistent state used by wcrtomb() calls. */ + __mbstate_t wcrtomb; + /** Persistent state used by wcsnrtombs() calls. */ + __mbstate_t wcsnrtombs; + /** Persistent state used by wcsrtombs() calls. */ + __mbstate_t wcsrtombs; + /** Persistent state used by wctomb() calls. */ + __mbstate_t wctomb; + /** Buffer used by nl_langinfo_l() */ + char *csym; +}; + +/** + * Increments the reference count of a reference-counted structure. + */ +__attribute__((unused)) static void* +xlocale_retain(void *val) +{ + struct xlocale_refcounted *obj = val; + __sync_fetch_and_add(&(obj->retain_count), 1); + return val; +} +/** + * Decrements the reference count of a reference-counted structure, freeing it + * if this is the last reference, calling its destructor if it has one. + */ +__attribute__((unused)) static void +xlocale_release(void *val) +{ + struct xlocale_refcounted *obj = val; + long count = __sync_sub_and_fetch(&(obj->retain_count), 1); + if (count < 0) + { + if (0 != obj->destructor) + { + obj->destructor(obj); + } + } +} + +/** + * Load functions. Each takes the name of a locale and a pointer to the data + * to be initialised as arguments. Two special values are allowed for the + */ +extern void* __collate_load(const char*, locale_t); +extern void* __ctype_load(const char*, locale_t); +extern void* __messages_load(const char*, locale_t); +extern void* __monetary_load(const char*, locale_t); +extern void* __numeric_load(const char*, locale_t); +extern void* __time_load(const char*, locale_t); + +extern struct _xlocale __xlocale_global_locale; + +/** + * Returns the current locale for this thread, or the global locale if none is + * set. The caller does not have to free the locale. The return value from + * this call is not guaranteed to remain valid after the locale changes. As + * such, this should only be called within libc functions. + */ +locale_t __get_locale(void); + +/** + * Two magic values are allowed for locale_t objects. NULL and -1. This + * function maps those to the real locales that they represent. + */ +static inline locale_t get_real_locale(locale_t locale) +{ + switch ((intptr_t)locale) + { + case 0: return &__xlocale_global_locale; + case -1: return __get_locale(); + default: return locale; + } +} + +/** + * Replace a plaecholder locale with the real global or thread-local locale_t. + */ +#define FIX_LOCALE(l) (l = get_real_locale(l)) + +#endif Index: lib/libc/locale/newlocale.3 =================================================================== --- lib/libc/locale/newlocale.3 (revision 0) +++ lib/libc/locale/newlocale.3 (revision 0) @@ -0,0 +1,108 @@ +.\" Copyright (c) 2011 The FreeBSD Foundation +.\" All rights reserved. +.\" +.\" This documentation was written by David Chisnall under sponsorship from +.\" the FreeBSD Foundation. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.Dd September 17 2011 +.Dt newlocale 3 +.Os +.Sh NAME +.Nm newlocale +.Nd Creates a new locale +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.In xlocale +.Ft +.Fn newlocale "int mask" "const char * locale" "locale_t base" +.Sh DESCRIPTION +Creates a new locale, inheriting some properties from an existing locale. The +.Fa mask +defines the components that the new locale will have set to the locale with the +name specified in the +.Fa locale +parameter. Any other components will be inherited from +.Fa base . +.Pt +The +.Fa mask +is either +.Fa LC_ALL_MASK, +indicating all possible locale components, or the logical OR of some +combination of the following: +.Bl -tag -width "LC_MESSAGES_MASK" -offset indent +.It LC_COLLATE_MASK +The locale for string collation routines. This controls alphabetic ordering in +.Xr strcoll 3 + and +.Xr strxfrm 3 . +.It LC_CTYPE_MASK +The locale for the +.Xr ctype 3 +and +.Xr multibyte 3 +functions. This controls recognition of upper and lower case, alpha- betic or +non-alphabetic characters, and so on. +.It LC_MESSAGES_MASK +Set a locale for message catalogs, see +.Xr catopen 3 +function. +.It LC_MONETARY_MASK +Set a locale for formatting monetary values; this affects +the +.Xr localeconv 3 +function. +.It LC_NUMERIC_MASK +Set a locale for formatting numbers. This controls the for- +matting of decimal points in input and output of floating +point numbers in functions such as +.Xr printf 3 +and +.Xr scanf 3 , +as well as values returned by +.Xr localeconv 3 . +.It LC_TIME_MASK +Set a locale for formatting dates and times using the +.Xr strftime 3 +function. +.El + +This function uses the same rules for loading locale components as +.Xr setlocale 3 . +.Sh RETURN VALUES +Returns a new, valid, +.Fa locale_t +or NULL if an error occurs. You must free the returned locale with +.Xr freelocale 3 . +.Sh SEE ALSO +.Xr duplocale 3 , +.Xr freelocale 3 , +.Xr localeconv 3 , +.Xr querylocale 3 , +.Xr uselocale 3 , +.Xr xlocale 3 +.Sh STANDARDS +This function, conforms to +.St -p1003.1-2008 Index: lib/libc/locale/mbsnrtowcs.c =================================================================== --- lib/libc/locale/mbsnrtowcs.c (revision 225653) +++ lib/libc/locale/mbsnrtowcs.c (working copy) @@ -1,6 +1,11 @@ /*- * Copyright (c) 2002-2004 Tim J. Robbins. + * + * Copyright (c) 2011 The FreeBSD Foundation * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -34,14 +39,19 @@ #include "mblocal.h" size_t +mbsnrtowcs_l(wchar_t * __restrict dst, const char ** __restrict src, + size_t nms, size_t len, mbstate_t * __restrict ps, locale_t locale) +{ + FIX_LOCALE(locale); + if (ps == NULL) + ps = &locale->mbsnrtowcs; + return (XLOCALE_CTYPE(locale)->__mbsnrtowcs(dst, src, nms, len, ps)); +} +size_t mbsnrtowcs(wchar_t * __restrict dst, const char ** __restrict src, size_t nms, size_t len, mbstate_t * __restrict ps) { - static mbstate_t mbs; - - if (ps == NULL) - ps = &mbs; - return (__mbsnrtowcs(dst, src, nms, len, ps)); + return mbsnrtowcs_l(dst, src, nms, len, ps, __get_locale()); } size_t @@ -52,13 +62,14 @@ size_t nchr; wchar_t wc; size_t nb; + struct xlocale_ctype *ct = XLOCALE_CTYPE(__get_locale()); s = *src; nchr = 0; if (dst == NULL) { for (;;) { - if ((nb = __mbrtowc(&wc, s, nms, ps)) == (size_t)-1) + if ((nb = ct->__mbrtowc(&wc, s, nms, ps)) == (size_t)-1) /* Invalid sequence - mbrtowc() sets errno. */ return ((size_t)-1); else if (nb == 0 || nb == (size_t)-2) @@ -71,7 +82,7 @@ } while (len-- > 0) { - if ((nb = __mbrtowc(dst, s, nms, ps)) == (size_t)-1) { + if ((nb = ct->__mbrtowc(dst, s, nms, ps)) == (size_t)-1) { *src = s; return ((size_t)-1); } else if (nb == (size_t)-2) { Index: lib/libc/locale/xlocale.3 =================================================================== --- lib/libc/locale/xlocale.3 (revision 0) +++ lib/libc/locale/xlocale.3 (revision 0) @@ -0,0 +1,265 @@ +.\" Copyright (c) 2011 The FreeBSD Foundation +.\" All rights reserved. +.\" +.\" This documentation was written by David Chisnall under sponsorship from +.\" the FreeBSD Foundation. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.Dd September 17 2011 +.Dt XLOCALE 3 +.Os +.Sh NAME +.Nm xlocale +.Nd Thread-safe extended locale support. +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.In xlocale.h +.Sh DESCRIPTION +The extended locale support includes a set of functions for setting +thread-local locales, as well convenience functions for performing locale-aware +calls with a specified locale. +.Pp +The core of the xlocale API is the +.Fa locale_t +type. This is an opqaue type encapsulating a locale. Instances of this can be +either set as the locale for a specific thread or passed directly to the +.Fa _l +suffixed variants of various standard C functions. Two special +.Fa locale_t +values are available: +.Bl -bullet -offset indent +.It +NULL refers to the current locale for the thread, or to the global locale if no +locale has been set for this thread. +.It +LC_GLOBAL_LOCALE refers to the global locale. +.El +.Pp +The global locale is the locale set with the +.Xr setlocale 3 +function. +.Sh CAVEATS +The +.Xr setlocale 3 +function, and others in the family, refer to the global locale. Other +functions that depend on the locale, however, will take the thread-local locale +if one has been set. This means that the idiom of setting the locale using +.Xr setlocale 3 , +calling a locale-dependent function, and then restoring the locale will not +have the expected behavior if the current thread has had a locale set using +.Xr uselocale 3 . +You should avoid this idiom and prefer to use the +.Fa _l +suffixed versions instead. +.Sh SEE ALSO +.Xr duplocale 3 , +.Xr freelocale 3 , +.Xr localeconv 3 , +.Xr newlocale 3 , +.Xr querylocale 3 , +.Xr uselocale 3 , +.Sh CONVENIENCE FUNCTIONS +The xlocale API includes a number of +.Fa _l +suffixed convenience functions. These are variants of standard C functions +that have been modified to take an explicit +.Fa locale_t +parameter as the final argument or, in the case of variadic functions, as an +additional argument directly before the format string. +.Pp +These functions are exposed by including +.In xlocale.h +.Em after +including the relevant headers for the standard variant. For example, the +.Xr strtol_l 3 +function is exposed by including +.In xlocale.h +after +.In stdlib.h , +which defines +.Xr strtol 3 . +.Pp +For reference, a complete list of the locale-aware functions that are available +in this form, along with the headers that expose them, is provided here: +.Pp +.Bl -tag -width " " +.It In wctype.h +.Xr iswalnum_l 3 , +.Xr iswalpha_l 3 , +.Xr iswcntrl_l 3 , +.Xr iswctype_l 3 , +.Xr iswdigit_l 3 , +.Xr iswgraph_l 3 , +.Xr iswlower_l 3 , +.Xr iswprint_l 3 , +.Xr iswpunct_l 3 , +.Xr iswspace_l 3 , +.Xr iswupper_l 3 , +.Xr iswxdigit_l 3 , +.Xr towlower_l 3 , +.Xr towupper_l 3 , +.Xr wctype_l 3 , +.It In ctype.h +.Xr digittoint_l 3 , +.Xr isalnum_l 3 , +.Xr isalpha_l 3 , +.Xr isblank_l 3 , +.Xr iscntrl_l 3 , +.Xr isdigit_l 3 , +.Xr isgraph_l 3 , +.Xr ishexnumber_l 3 , +.Xr isideogram_l 3 , +.Xr islower_l 3 , +.Xr isnumber_l 3 , +.Xr isphonogram_l 3 , +.Xr isprint_l 3 , +.Xr ispunct_l 3 , +.Xr isrune_l 3 , +.Xr isspace_l 3 , +.Xr isspecial_l 3 , +.Xr isupper_l 3 , +.Xr isxdigit_l 3 , +.Xr tolower_l 3 , +.Xr toupper_l 3 +.It In inttypes.h +.Xr strtoimax_l 3 , +.Xr strtoumax_l 3 , +.Xr wcstoimax_l 3 , +.Xr wcstoumax_l 3 +.It In langinfo.h +.Xr nl_langinfo_l 3 +.It In monetary.h +.Xr strfmon_l 3 +.It In stdio.h +.Xr asprintf_l 3 , +.Xr fprintf_l 3 , +.Xr fscanf_l 3 , +.Xr printf_l 3 , +.Xr scanf_l 3 , +.Xr snprintf_l 3 , +.Xr sprintf_l 3 , +.Xr sscanf_l 3 , +.Xr vasprintf_l 3 , +.Xr vfprintf_l 3 , +.Xr vfscanf_l 3 , +.Xr vprintf_l 3 , +.Xr vscanf_l 3 , +.Xr vsnprintf_l 3 , +.Xr vsprintf_l 3 , +.Xr vsscanf_l 3 +.It In stdlib.h +.Xr atof_l 3 , +.Xr atoi_l 3 , +.Xr atol_l 3 , +.Xr atoll_l 3 , +.Xr mblen_l 3 , +.Xr mbstowcs_l 3 , +.Xr mbtowc_l 3 , +.Xr strtod_l 3 , +.Xr strtof_l 3 , +.Xr strtol_l 3 , +.Xr strtold_l 3 , +.Xr strtoll_l 3 , +.Xr strtoq_l 3 , +.Xr strtoul_l 3 , +.Xr strtoull_l 3 , +.Xr strtouq_l 3 , +.Xr wcstombs_l 3 , +.Xr wctomb_l 3 +.It In string.h +.Xr strcoll_l 3 , +.Xr strxfrm_l 3 , +.Xr strcasecmp_l 3 , +.Xr strcasestr_l 3 , +.Xr strncasecmp_l 3 +.It In time.h +.Xr strftime_l 3 +.Xr strptime_l 3 +.It In wchar.h +.Xr btowc_l 3 , +.Xr fgetwc_l 3 , +.Xr fgetws_l 3 , +.Xr fputwc_l 3 , +.Xr fputws_l 3 , +.Xr fwprintf_l 3 , +.Xr fwscanf_l 3 , +.Xr getwc_l 3 , +.Xr getwchar_l 3 , +.Xr mbrlen_l 3 , +.Xr mbrtowc_l 3 , +.Xr mbsinit_l 3 , +.Xr mbsnrtowcs_l 3 , +.Xr mbsrtowcs_l 3 , +.Xr putwc_l 3 , +.Xr putwchar_l 3 , +.Xr swprintf_l 3 , +.Xr swscanf_l 3 , +.Xr ungetwc_l 3 , +.Xr vfwprintf_l 3 , +.Xr vfwscanf_l 3 , +.Xr vswprintf_l 3 , +.Xr vswscanf_l 3 , +.Xr vwprintf_l 3 , +.Xr vwscanf_l 3 , +.Xr wcrtomb_l 3 , +.Xr wcscoll_l 3 , +.Xr wcsftime_l 3 , +.Xr wcsnrtombs_l 3 , +.Xr wcsrtombs_l 3 , +.Xr wcstod_l 3 , +.Xr wcstof_l 3 , +.Xr wcstol_l 3 , +.Xr wcstold_l 3 , +.Xr wcstoll_l 3 , +.Xr wcstoul_l 3 , +.Xr wcstoull_l 3 , +.Xr wcswidth_l 3 , +.Xr wcsxfrm_l 3 , +.Xr wctob_l 3 , +.Xr wcwidth_l 3 , +.Xr wprintf_l 3 , +.Xr wscanf_l 3 +.It In wctype.h +.Xr iswblank_l 3 , +.Xr iswhexnumber_l 3 , +.Xr iswideogram_l 3 , +.Xr iswnumber_l 3 , +.Xr iswphonogram_l 3 , +.Xr iswrune_l 3 , +.Xr iswspecial_l 3 , +.Xr nextwctype_l 3 , +.Xr towctrans_l 3 , +.Xr wctrans_l 3 +.It In xlocale.h +.Xr localeconv_l 3 +.El +.Sh STANDARDS +The functions +conform to +.St -p1003.1-2008 . +.Sh HISTORY +The xlocale APIs first appeared in Darwin 8.0. This implementation was +written by David Chisnall, under sponsorship from the FreeBSD Foundation and +first appeared in +.Fx 9.1 . Index: lib/libc/locale/mbrtowc.c =================================================================== --- lib/libc/locale/mbrtowc.c (revision 225653) +++ lib/libc/locale/mbrtowc.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002-2004 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -31,12 +36,18 @@ #include "mblocal.h" size_t +mbrtowc_l(wchar_t * __restrict pwc, const char * __restrict s, + size_t n, mbstate_t * __restrict ps, locale_t locale) +{ + FIX_LOCALE(locale); + if (ps == NULL) + ps = &locale->mbrtowc; + return (XLOCALE_CTYPE(locale)->__mbrtowc(pwc, s, n, ps)); +} + +size_t mbrtowc(wchar_t * __restrict pwc, const char * __restrict s, size_t n, mbstate_t * __restrict ps) { - static mbstate_t mbs; - - if (ps == NULL) - ps = &mbs; - return (__mbrtowc(pwc, s, n, ps)); + return mbrtowc_l(pwc, s, n, ps, __get_locale()); } Index: lib/libc/locale/ctype.c =================================================================== --- lib/libc/locale/ctype.c (revision 0) +++ lib/libc/locale/ctype.c (revision 0) @@ -0,0 +1,31 @@ +/*- + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by David Chisnall under sponsorship from + * the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions * are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#define _XLOCALE_INLINE +#include +#include +#include Index: lib/libc/stdtime/timelocal.h =================================================================== --- lib/libc/stdtime/timelocal.h (revision 225653) +++ lib/libc/stdtime/timelocal.h (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1997-2002 FreeBSD Project. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -28,6 +33,7 @@ #ifndef _TIMELOCAL_H_ #define _TIMELOCAL_H_ +#include "xlocale_private.h" /* * Private header file for the strftime and strptime localization @@ -49,7 +55,7 @@ const char *ampm_fmt; }; -struct lc_time_T *__get_current_time_locale(void); +struct lc_time_T *__get_current_time_locale(locale_t); int __time_load_locale(const char *); #endif /* !_TIMELOCAL_H_ */ Index: lib/libc/stdtime/strptime.c =================================================================== --- lib/libc/stdtime/strptime.c (revision 225653) +++ lib/libc/stdtime/strptime.c (working copy) @@ -22,6 +22,11 @@ /* * Copyright (c) 1994 Powerdog Industries. All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -72,19 +77,20 @@ #include "libc_private.h" #include "timelocal.h" -static char * _strptime(const char *, const char *, struct tm *, int *); +static char * _strptime(const char *, const char *, struct tm *, int *, locale_t); #define asizeof(a) (sizeof (a) / sizeof ((a)[0])) static char * -_strptime(const char *buf, const char *fmt, struct tm *tm, int *GMTp) +_strptime(const char *buf, const char *fmt, struct tm *tm, int *GMTp, + locale_t locale) { char c; const char *ptr; int i, len; int Ealternative, Oalternative; - struct lc_time_T *tptr = __get_current_time_locale(); + struct lc_time_T *tptr = __get_current_time_locale(locale); ptr = fmt; while (*ptr != 0) { @@ -94,8 +100,8 @@ c = *ptr++; if (c != '%') { - if (isspace((unsigned char)c)) - while (*buf != 0 && isspace((unsigned char)*buf)) + if (isspace_l((unsigned char)c, locale)) + while (*buf != 0 && isspace_l((unsigned char)*buf, locale)) buf++; else if (c != *buf++) return 0; @@ -114,18 +120,18 @@ break; case '+': - buf = _strptime(buf, tptr->date_fmt, tm, GMTp); + buf = _strptime(buf, tptr->date_fmt, tm, GMTp, locale); if (buf == 0) return 0; break; case 'C': - if (!isdigit((unsigned char)*buf)) + if (!isdigit_l((unsigned char)*buf, locale)) return 0; /* XXX This will break for 3-digit centuries. */ len = 2; - for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { + for (i = 0; len && *buf != 0 && isdigit_l((unsigned char)*buf, locale); buf++) { i *= 10; i += *buf - '0'; len--; @@ -137,13 +143,13 @@ break; case 'c': - buf = _strptime(buf, tptr->c_fmt, tm, GMTp); + buf = _strptime(buf, tptr->c_fmt, tm, GMTp, locale); if (buf == 0) return 0; break; case 'D': - buf = _strptime(buf, "%m/%d/%y", tm, GMTp); + buf = _strptime(buf, "%m/%d/%y", tm, GMTp, locale); if (buf == 0) return 0; break; @@ -161,47 +167,47 @@ goto label; case 'F': - buf = _strptime(buf, "%Y-%m-%d", tm, GMTp); + buf = _strptime(buf, "%Y-%m-%d", tm, GMTp, locale); if (buf == 0) return 0; break; case 'R': - buf = _strptime(buf, "%H:%M", tm, GMTp); + buf = _strptime(buf, "%H:%M", tm, GMTp, locale); if (buf == 0) return 0; break; case 'r': - buf = _strptime(buf, tptr->ampm_fmt, tm, GMTp); + buf = _strptime(buf, tptr->ampm_fmt, tm, GMTp, locale); if (buf == 0) return 0; break; case 'T': - buf = _strptime(buf, "%H:%M:%S", tm, GMTp); + buf = _strptime(buf, "%H:%M:%S", tm, GMTp, locale); if (buf == 0) return 0; break; case 'X': - buf = _strptime(buf, tptr->X_fmt, tm, GMTp); + buf = _strptime(buf, tptr->X_fmt, tm, GMTp, locale); if (buf == 0) return 0; break; case 'x': - buf = _strptime(buf, tptr->x_fmt, tm, GMTp); + buf = _strptime(buf, tptr->x_fmt, tm, GMTp, locale); if (buf == 0) return 0; break; case 'j': - if (!isdigit((unsigned char)*buf)) + if (!isdigit_l((unsigned char)*buf, locale)) return 0; len = 3; - for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { + for (i = 0; len && *buf != 0 && isdigit_l((unsigned char)*buf, locale); buf++) { i *= 10; i += *buf - '0'; len--; @@ -214,14 +220,14 @@ case 'M': case 'S': - if (*buf == 0 || isspace((unsigned char)*buf)) + if (*buf == 0 || isspace_l((unsigned char)*buf, locale)) break; - if (!isdigit((unsigned char)*buf)) + if (!isdigit_l((unsigned char)*buf, locale)) return 0; len = 2; - for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { + for (i = 0; len && *buf != 0 && isdigit_l((unsigned char)*buf, locale); buf++) { i *= 10; i += *buf - '0'; len--; @@ -237,8 +243,8 @@ tm->tm_sec = i; } - if (*buf != 0 && isspace((unsigned char)*buf)) - while (*ptr != 0 && !isspace((unsigned char)*ptr)) + if (*buf != 0 && isspace_l((unsigned char)*buf, locale)) + while (*ptr != 0 && !isspace_l((unsigned char)*ptr, locale)) ptr++; break; @@ -254,11 +260,11 @@ * XXX The %l specifier may gobble one too many * digits if used incorrectly. */ - if (!isdigit((unsigned char)*buf)) + if (!isdigit_l((unsigned char)*buf, locale)) return 0; len = 2; - for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { + for (i = 0; len && *buf != 0 && isdigit_l((unsigned char)*buf, locale); buf++) { i *= 10; i += *buf - '0'; len--; @@ -271,8 +277,8 @@ tm->tm_hour = i; - if (*buf != 0 && isspace((unsigned char)*buf)) - while (*ptr != 0 && !isspace((unsigned char)*ptr)) + if (*buf != 0 && isspace_l((unsigned char)*buf, locale)) + while (*ptr != 0 && !isspace_l((unsigned char)*ptr, locale)) ptr++; break; @@ -282,7 +288,7 @@ * specifiers. */ len = strlen(tptr->am); - if (strncasecmp(buf, tptr->am, len) == 0) { + if (strncasecmp_l(buf, tptr->am, len, locale) == 0) { if (tm->tm_hour > 12) return 0; if (tm->tm_hour == 12) @@ -292,7 +298,7 @@ } len = strlen(tptr->pm); - if (strncasecmp(buf, tptr->pm, len) == 0) { + if (strncasecmp_l(buf, tptr->pm, len, locale) == 0) { if (tm->tm_hour > 12) return 0; if (tm->tm_hour != 12) @@ -307,12 +313,12 @@ case 'a': for (i = 0; i < asizeof(tptr->weekday); i++) { len = strlen(tptr->weekday[i]); - if (strncasecmp(buf, tptr->weekday[i], - len) == 0) + if (strncasecmp_l(buf, tptr->weekday[i], + len, locale) == 0) break; len = strlen(tptr->wday[i]); - if (strncasecmp(buf, tptr->wday[i], - len) == 0) + if (strncasecmp_l(buf, tptr->wday[i], + len, locale) == 0) break; } if (i == asizeof(tptr->weekday)) @@ -330,11 +336,11 @@ * point to calculate a real value, so just check the * range for now. */ - if (!isdigit((unsigned char)*buf)) + if (!isdigit_l((unsigned char)*buf, locale)) return 0; len = 2; - for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { + for (i = 0; len && *buf != 0 && isdigit_l((unsigned char)*buf, locale); buf++) { i *= 10; i += *buf - '0'; len--; @@ -342,13 +348,13 @@ if (i > 53) return 0; - if (*buf != 0 && isspace((unsigned char)*buf)) - while (*ptr != 0 && !isspace((unsigned char)*ptr)) + if (*buf != 0 && isspace_l((unsigned char)*buf, locale)) + while (*ptr != 0 && !isspace_l((unsigned char)*ptr, locale)) ptr++; break; case 'w': - if (!isdigit((unsigned char)*buf)) + if (!isdigit_l((unsigned char)*buf, locale)) return 0; i = *buf - '0'; @@ -357,8 +363,8 @@ tm->tm_wday = i; - if (*buf != 0 && isspace((unsigned char)*buf)) - while (*ptr != 0 && !isspace((unsigned char)*ptr)) + if (*buf != 0 && isspace_l((unsigned char)*buf, locale)) + while (*ptr != 0 && !isspace_l((unsigned char)*ptr, locale)) ptr++; break; @@ -372,11 +378,11 @@ * XXX The %e specifier may gobble one too many * digits if used incorrectly. */ - if (!isdigit((unsigned char)*buf)) + if (!isdigit_l((unsigned char)*buf, locale)) return 0; len = 2; - for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { + for (i = 0; len && *buf != 0 && isdigit_l((unsigned char)*buf, locale); buf++) { i *= 10; i += *buf - '0'; len--; @@ -386,8 +392,8 @@ tm->tm_mday = i; - if (*buf != 0 && isspace((unsigned char)*buf)) - while (*ptr != 0 && !isspace((unsigned char)*ptr)) + if (*buf != 0 && isspace_l((unsigned char)*buf, locale)) + while (*ptr != 0 && !isspace_l((unsigned char)*ptr, locale)) ptr++; break; @@ -398,15 +404,15 @@ if (Oalternative) { if (c == 'B') { len = strlen(tptr->alt_month[i]); - if (strncasecmp(buf, + if (strncasecmp_l(buf, tptr->alt_month[i], - len) == 0) + len, locale) == 0) break; } } else { len = strlen(tptr->month[i]); - if (strncasecmp(buf, tptr->month[i], - len) == 0) + if (strncasecmp_l(buf, tptr->month[i], + len, locale) == 0) break; } } @@ -417,8 +423,8 @@ if (i == asizeof(tptr->month) && !Oalternative) { for (i = 0; i < asizeof(tptr->month); i++) { len = strlen(tptr->mon[i]); - if (strncasecmp(buf, tptr->mon[i], - len) == 0) + if (strncasecmp_l(buf, tptr->mon[i], + len, locale) == 0) break; } } @@ -430,11 +436,11 @@ break; case 'm': - if (!isdigit((unsigned char)*buf)) + if (!isdigit_l((unsigned char)*buf, locale)) return 0; len = 2; - for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { + for (i = 0; len && *buf != 0 && isdigit_l((unsigned char)*buf, locale); buf++) { i *= 10; i += *buf - '0'; len--; @@ -444,8 +450,8 @@ tm->tm_mon = i - 1; - if (*buf != 0 && isspace((unsigned char)*buf)) - while (*ptr != 0 && !isspace((unsigned char)*ptr)) + if (*buf != 0 && isspace_l((unsigned char)*buf, locale)) + while (*ptr != 0 && !isspace_l((unsigned char)*ptr, locale)) ptr++; break; @@ -458,7 +464,7 @@ sverrno = errno; errno = 0; - n = strtol(buf, &cp, 10); + n = strtol_l(buf, &cp, 10, locale); if (errno == ERANGE || (long)(t = n) != n) { errno = sverrno; return 0; @@ -472,14 +478,14 @@ case 'Y': case 'y': - if (*buf == 0 || isspace((unsigned char)*buf)) + if (*buf == 0 || isspace_l((unsigned char)*buf, locale)) break; - if (!isdigit((unsigned char)*buf)) + if (!isdigit_l((unsigned char)*buf, locale)) return 0; len = (c == 'Y') ? 4 : 2; - for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { + for (i = 0; len && *buf != 0 && isdigit_l((unsigned char)*buf, locale); buf++) { i *= 10; i += *buf - '0'; len--; @@ -493,8 +499,8 @@ tm->tm_year = i; - if (*buf != 0 && isspace((unsigned char)*buf)) - while (*ptr != 0 && !isspace((unsigned char)*ptr)) + if (*buf != 0 && isspace_l((unsigned char)*buf, locale)) + while (*ptr != 0 && !isspace_l((unsigned char)*ptr, locale)) ptr++; break; @@ -503,7 +509,7 @@ const char *cp; char *zonestr; - for (cp = buf; *cp && isupper((unsigned char)*cp); ++cp) {/*empty*/} + for (cp = buf; *cp && isupper_l((unsigned char)*cp, locale); ++cp) {/*empty*/} if (cp - buf) { zonestr = alloca(cp - buf + 1); strncpy(zonestr, buf, cp - buf); @@ -537,7 +543,7 @@ buf++; i = 0; for (len = 4; len > 0; len--) { - if (isdigit((unsigned char)*buf)) { + if (isdigit_l((unsigned char)*buf, locale)) { i *= 10; i += *buf - '0'; buf++; @@ -557,14 +563,15 @@ char * -strptime(const char * __restrict buf, const char * __restrict fmt, - struct tm * __restrict tm) +strptime_l(const char * __restrict buf, const char * __restrict fmt, + struct tm * __restrict tm, locale_t loc) { char *ret; int gmt; + FIX_LOCALE(loc); gmt = 0; - ret = _strptime(buf, fmt, tm, &gmt); + ret = _strptime(buf, fmt, tm, &gmt, loc); if (ret && gmt) { time_t t = timegm(tm); localtime_r(&t, tm); @@ -572,3 +579,9 @@ return (ret); } +char * +strptime(const char * __restrict buf, const char * __restrict fmt, + struct tm * __restrict tm) +{ + return strptime_l(buf, fmt, tm, __get_locale()); +} Index: lib/libc/stdtime/timelocal.c =================================================================== --- lib/libc/stdtime/timelocal.c (revision 225653) +++ lib/libc/stdtime/timelocal.c (working copy) @@ -3,6 +3,11 @@ * Copyright (c) 1997 FreeBSD Inc. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -33,10 +38,14 @@ #include "ldpart.h" #include "timelocal.h" -static struct lc_time_T _time_locale; -static int _time_using_locale; -static char *time_locale_buf; +struct xlocale_time { + struct xlocale_component header; + char *buffer; + struct lc_time_T locale; +}; +struct xlocale_time __xlocale_global_time; + #define LCTIME_SIZE (sizeof(struct lc_time_T) / sizeof(char *)) static const struct lc_time_T _C_time_locale = { @@ -99,19 +108,47 @@ "%I:%M:%S %p" }; +static void destruct_time(void *v) +{ + struct xlocale_time *l = v; + if (l->buffer) + free(l->buffer); + free(l); +} + +#include struct lc_time_T * -__get_current_time_locale(void) +__get_current_time_locale(locale_t loc) { - return (_time_using_locale - ? &_time_locale + return (loc->using_time_locale + ? &((struct xlocale_time *)loc->components[XLC_TIME])->locale : (struct lc_time_T *)&_C_time_locale); } +static int +time_load_locale(struct xlocale_time *l, int *using_locale, const char *name) +{ + struct lc_time_T *time_locale = &l->locale; + return (__part_load_locale(name, using_locale, + &l->buffer, "LC_TIME", + LCTIME_SIZE, LCTIME_SIZE, + (const char **)time_locale)); +} int __time_load_locale(const char *name) { - return (__part_load_locale(name, &_time_using_locale, - &time_locale_buf, "LC_TIME", - LCTIME_SIZE, LCTIME_SIZE, - (const char **)&_time_locale)); + return time_load_locale(&__xlocale_global_time, + &__xlocale_global_locale.using_time_locale, name); } +extern void* __time_load(const char* name, locale_t loc) +{ + struct xlocale_time *new = calloc(sizeof(struct xlocale_time), 1); + new->header.header.destructor = destruct_time; + if (time_load_locale(new, &loc->using_time_locale, name) == _LDP_ERROR) + { + xlocale_release(new); + return NULL; + } + return new; +} + Index: lib/libc/stdtime/strftime.c =================================================================== --- lib/libc/stdtime/strftime.c (revision 225653) +++ lib/libc/stdtime/strftime.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1989 The Regents of the University of California. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms are permitted * provided that the above copyright notice and this paragraph are * duplicated in all such forms and that any documentation, @@ -43,7 +48,7 @@ static char * _add(const char *, char *, const char *); static char * _conv(int, const char *, char *, const char *); static char * _fmt(const char *, const struct tm *, char *, const char *, - int *); + int *, locale_t); static char * _yconv(int, int, int, int, char *, const char *); extern char * tzname[]; @@ -82,29 +87,30 @@ }; size_t -strftime(char * __restrict s, size_t maxsize, const char * __restrict format, - const struct tm * __restrict t) +strftime_l(char * __restrict s, size_t maxsize, const char * __restrict format, + const struct tm * __restrict t, locale_t loc) { char * p; int warn; + FIX_LOCALE(loc); tzset(); warn = IN_NONE; - p = _fmt(((format == NULL) ? "%c" : format), t, s, s + maxsize, &warn); + p = _fmt(((format == NULL) ? "%c" : format), t, s, s + maxsize, &warn, loc); #ifndef NO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU if (warn != IN_NONE && getenv(YEAR_2000_NAME) != NULL) { - (void) fprintf(stderr, "\n"); + (void) fprintf_l(stderr, loc, "\n"); if (format == NULL) - (void) fprintf(stderr, "NULL strftime format "); - else (void) fprintf(stderr, "strftime format \"%s\" ", + (void) fprintf_l(stderr, loc, "NULL strftime format "); + else (void) fprintf_l(stderr, loc, "strftime format \"%s\" ", format); - (void) fprintf(stderr, "yields only two digits of years in "); + (void) fprintf_l(stderr, loc, "yields only two digits of years in "); if (warn == IN_SOME) - (void) fprintf(stderr, "some locales"); + (void) fprintf_l(stderr, loc, "some locales"); else if (warn == IN_THIS) - (void) fprintf(stderr, "the current locale"); - else (void) fprintf(stderr, "all locales"); - (void) fprintf(stderr, "\n"); + (void) fprintf_l(stderr, loc, "the current locale"); + else (void) fprintf_l(stderr, loc, "all locales"); + (void) fprintf_l(stderr, loc, "\n"); } #endif /* !defined NO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU */ if (p == s + maxsize) @@ -113,16 +119,24 @@ return p - s; } +size_t +strftime(char * __restrict s, size_t maxsize, const char * __restrict format, + const struct tm * __restrict t) +{ + return strftime_l(s, maxsize, format, t, __get_locale()); +} + static char * -_fmt(format, t, pt, ptlim, warnp) +_fmt(format, t, pt, ptlim, warnp, loc) const char * format; const struct tm * const t; char * pt; const char * const ptlim; int * warnp; +locale_t loc; { int Ealternative, Oalternative, PadIndex; - struct lc_time_T *tptr = __get_current_time_locale(); + struct lc_time_T *tptr = __get_current_time_locale(loc); for ( ; *format; ++format) { if (*format == '%') { @@ -175,7 +189,7 @@ { int warn2 = IN_SOME; - pt = _fmt(tptr->c_fmt, t, pt, ptlim, &warn2); + pt = _fmt(tptr->c_fmt, t, pt, ptlim, &warn2, loc); if (warn2 == IN_ALL) warn2 = IN_THIS; if (warn2 > *warnp) @@ -183,7 +197,7 @@ } continue; case 'D': - pt = _fmt("%m/%d/%y", t, pt, ptlim, warnp); + pt = _fmt("%m/%d/%y", t, pt, ptlim, warnp, loc); continue; case 'd': pt = _conv(t->tm_mday, fmt_padding[PAD_FMT_DAYOFMONTH][PadIndex], @@ -216,7 +230,7 @@ fmt_padding[PAD_FMT_SDAYOFMONTH][PadIndex], pt, ptlim); continue; case 'F': - pt = _fmt("%Y-%m-%d", t, pt, ptlim, warnp); + pt = _fmt("%Y-%m-%d", t, pt, ptlim, warnp, loc); continue; case 'H': pt = _conv(t->tm_hour, fmt_padding[PAD_FMT_HMS][PadIndex], @@ -285,11 +299,11 @@ pt, ptlim); continue; case 'R': - pt = _fmt("%H:%M", t, pt, ptlim, warnp); + pt = _fmt("%H:%M", t, pt, ptlim, warnp, loc); continue; case 'r': pt = _fmt(tptr->ampm_fmt, t, pt, ptlim, - warnp); + warnp, loc); continue; case 'S': pt = _conv(t->tm_sec, fmt_padding[PAD_FMT_HMS][PadIndex], @@ -313,7 +327,7 @@ } continue; case 'T': - pt = _fmt("%H:%M:%S", t, pt, ptlim, warnp); + pt = _fmt("%H:%M:%S", t, pt, ptlim, warnp, loc); continue; case 't': pt = _add("\t", pt, ptlim); @@ -428,7 +442,7 @@ ** "date as dd-bbb-YYYY" ** (ado, 1993-05-24) */ - pt = _fmt("%e-%b-%Y", t, pt, ptlim, warnp); + pt = _fmt("%e-%b-%Y", t, pt, ptlim, warnp, loc); continue; case 'W': pt = _conv((t->tm_yday + DAYSPERWEEK - @@ -441,13 +455,13 @@ pt = _conv(t->tm_wday, "%d", pt, ptlim); continue; case 'X': - pt = _fmt(tptr->X_fmt, t, pt, ptlim, warnp); + pt = _fmt(tptr->X_fmt, t, pt, ptlim, warnp, loc); continue; case 'x': { int warn2 = IN_SOME; - pt = _fmt(tptr->x_fmt, t, pt, ptlim, &warn2); + pt = _fmt(tptr->x_fmt, t, pt, ptlim, &warn2, loc); if (warn2 == IN_ALL) warn2 = IN_THIS; if (warn2 > *warnp) @@ -534,7 +548,7 @@ continue; case '+': pt = _fmt(tptr->date_fmt, t, pt, ptlim, - warnp); + warnp, loc); continue; case '-': if (PadIndex != PAD_DEFAULT) Index: lib/libc/gen/glob.c =================================================================== --- lib/libc/gen/glob.c (revision 225653) +++ lib/libc/gen/glob.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Guido van Rossum. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -751,6 +756,8 @@ { int ok, negate_range; Char c, k; + struct xlocale_collate *table = + (struct xlocale_collate*)__get_locale()->components[XLC_COLLATE]; while (pat < patend) { c = *pat++; @@ -775,10 +782,10 @@ ++pat; while (((c = *pat++) & M_MASK) != M_END) if ((*pat & M_MASK) == M_RNG) { - if (__collate_load_error ? + if (table->__collate_load_error ? CHAR(c) <= CHAR(k) && CHAR(k) <= CHAR(pat[1]) : - __collate_range_cmp(CHAR(c), CHAR(k)) <= 0 - && __collate_range_cmp(CHAR(k), CHAR(pat[1])) <= 0 + __collate_range_cmp(table, CHAR(c), CHAR(k)) <= 0 + && __collate_range_cmp(table, CHAR(k), CHAR(pat[1])) <= 0 ) ok = 1; pat += 2; Index: lib/libc/gen/fnmatch.c =================================================================== --- lib/libc/gen/fnmatch.c (revision 225653) +++ lib/libc/gen/fnmatch.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Guido van Rossum. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -222,6 +227,8 @@ wchar_t c, c2; size_t pclen; const char *origpat; + struct xlocale_collate *table = + (struct xlocale_collate*)__get_locale()->components[XLC_COLLATE]; /* * A bracket expression starting with an unquoted circumflex @@ -276,10 +283,10 @@ if (flags & FNM_CASEFOLD) c2 = towlower(c2); - if (__collate_load_error ? + if (table->__collate_load_error ? c <= test && test <= c2 : - __collate_range_cmp(c, test) <= 0 - && __collate_range_cmp(test, c2) <= 0 + __collate_range_cmp(table, c, test) <= 0 + && __collate_range_cmp(table, test, c2) <= 0 ) ok = 1; } else if (c == test) Index: lib/libc/regex/regcomp.c =================================================================== --- lib/libc/regex/regcomp.c (revision 225653) +++ lib/libc/regex/regcomp.c (working copy) @@ -3,9 +3,19 @@ * Copyright (c) 1992, 1993, 1994 * The Regents of the University of California. All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * This code is derived from software contributed to Berkeley by * Henry Spencer. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -730,6 +740,8 @@ char c; wint_t start, finish; wint_t i; + struct xlocale_collate *table = + (struct xlocale_collate*)__get_locale()->components[XLC_COLLATE]; /* classify what we've got */ switch ((MORE()) ? PEEK() : '\0') { @@ -778,14 +790,14 @@ if (start == finish) CHadd(p, cs, start); else { - if (__collate_load_error) { + if (table->__collate_load_error) { (void)REQUIRE((uch)start <= (uch)finish, REG_ERANGE); CHaddrange(p, cs, start, finish); } else { - (void)REQUIRE(__collate_range_cmp(start, finish) <= 0, REG_ERANGE); + (void)REQUIRE(__collate_range_cmp(table, start, finish) <= 0, REG_ERANGE); for (i = 0; i <= UCHAR_MAX; i++) { - if ( __collate_range_cmp(start, i) <= 0 - && __collate_range_cmp(i, finish) <= 0 + if ( __collate_range_cmp(table, start, i) <= 0 + && __collate_range_cmp(table, i, finish) <= 0 ) CHadd(p, cs, i); } Index: lib/libc/Makefile =================================================================== --- lib/libc/Makefile (revision 225653) +++ lib/libc/Makefile (working copy) @@ -3,6 +3,9 @@ SHLIBDIR?= /lib +DEBUG_CFLAGS+=-g +CFLAGS+=-g + .include # Pick the current architecture directory for libc. In general, this is @@ -36,6 +39,7 @@ CFLAGS+=${CANCELPOINTS_CFLAGS} .endif + # # Only link with static libgcc.a (no libgcc_eh.a). # Index: lib/libc/gdtoa/machdep_ldisd.c =================================================================== --- lib/libc/gdtoa/machdep_ldisd.c (revision 225653) +++ lib/libc/gdtoa/machdep_ldisd.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2003 David Schultz * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -34,10 +39,10 @@ __FBSDID("$FreeBSD$"); #include "gdtoaimp.h" +#undef strtold_l long double -strtold(const char * __restrict s, char ** __restrict sp) +strtold_l(const char * __restrict s, char ** __restrict sp, locale_t locale) { - - return strtod(s, sp); + return __strtod_l(s, sp, locale); } Index: lib/libc/gdtoa/machdep_ldisx.c =================================================================== --- lib/libc/gdtoa/machdep_ldisx.c (revision 225653) +++ lib/libc/gdtoa/machdep_ldisx.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2003 David Schultz * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -38,10 +43,11 @@ #include "gdtoaimp.h" long double -strtold(const char * __restrict s, char ** __restrict sp) +strtold_l(const char * __restrict s, char ** __restrict sp, locale_t locale) { long double result; + FIX_LOCALE(locale); - strtorx(s, sp, FLT_ROUNDS, &result); + strtorx_l(s, sp, FLT_ROUNDS, &result, locale); return result; } Index: lib/libc/gdtoa/machdep_ldisQ.c =================================================================== --- lib/libc/gdtoa/machdep_ldisQ.c (revision 225653) +++ lib/libc/gdtoa/machdep_ldisQ.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2003 David Schultz * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -38,10 +43,10 @@ #include "gdtoaimp.h" long double -strtold(const char * __restrict s, char ** __restrict sp) +strtold_l(const char * __restrict s, char ** __restrict sp, locale_t locale) { long double result; - strtorQ(s, sp, FLT_ROUNDS, &result); + strtorQ_l(s, sp, FLT_ROUNDS, &result, locale); return result; } Index: lib/libc/string/strcasecmp.c =================================================================== --- lib/libc/string/strcasecmp.c (revision 225653) +++ lib/libc/string/strcasecmp.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1987, 1993 * The Regents of the University of California. All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -35,36 +40,50 @@ #include #include +#include "xlocale_private.h" typedef unsigned char u_char; int -strcasecmp(const char *s1, const char *s2) +strcasecmp_l(const char *s1, const char *s2, locale_t locale) { const u_char *us1 = (const u_char *)s1, *us2 = (const u_char *)s2; + FIX_LOCALE(locale); - while (tolower(*us1) == tolower(*us2++)) + while (tolower_l(*us1, locale) == tolower_l(*us2++, locale)) if (*us1++ == '\0') return (0); - return (tolower(*us1) - tolower(*--us2)); + return (tolower_l(*us1, locale) - tolower_l(*--us2, locale)); } +int +strcasecmp(const char *s1, const char *s2) +{ + return strcasecmp_l(s1, s2, __get_locale()); +} int -strncasecmp(const char *s1, const char *s2, size_t n) +strncasecmp_l(const char *s1, const char *s2, size_t n, locale_t locale) { + FIX_LOCALE(locale); if (n != 0) { const u_char *us1 = (const u_char *)s1, *us2 = (const u_char *)s2; do { - if (tolower(*us1) != tolower(*us2++)) - return (tolower(*us1) - tolower(*--us2)); + if (tolower_l(*us1, locale) != tolower_l(*us2++, locale)) + return (tolower_l(*us1, locale) - tolower_l(*--us2, locale)); if (*us1++ == '\0') break; } while (--n != 0); } return (0); } + +int +strncasecmp(const char *s1, const char *s2, size_t n) +{ + return strncasecmp_l(s1, s2, n, __get_locale()); +} Index: lib/libc/string/wcscoll.c =================================================================== --- lib/libc/string/wcscoll.c (revision 225653) +++ lib/libc/string/wcscoll.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002 Tim J. Robbins * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -41,12 +46,15 @@ * with extended character sets. */ int -wcscoll(const wchar_t *ws1, const wchar_t *ws2) +wcscoll_l(const wchar_t *ws1, const wchar_t *ws2, locale_t locale) { char *mbs1, *mbs2; int diff, sverrno; + FIX_LOCALE(locale); + struct xlocale_collate *table = + (struct xlocale_collate*)locale->components[XLC_COLLATE]; - if (__collate_load_error || MB_CUR_MAX > 1) + if (table->__collate_load_error || MB_CUR_MAX > 1) /* * Locale has no special collating order, could not be * loaded, or has an extended character set; do a fast binary @@ -67,7 +75,7 @@ return (wcscmp(ws1, ws2)); } - diff = strcoll(mbs1, mbs2); + diff = strcoll_l(mbs1, mbs2, locale); sverrno = errno; free(mbs1); free(mbs2); @@ -76,6 +84,12 @@ return (diff); } +int +wcscoll(const wchar_t *ws1, const wchar_t *ws2) +{ + return wcscoll_l(ws1, ws2, __get_locale()); +} + static char * __mbsdup(const wchar_t *ws) { Index: lib/libc/string/wcswidth.c =================================================================== --- lib/libc/string/wcswidth.c (revision 225653) +++ lib/libc/string/wcswidth.c (working copy) @@ -10,6 +10,11 @@ * This code is derived from software contributed to Berkeley by * Paul Borman at Krystal Technologies. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -39,19 +44,26 @@ __FBSDID("$FreeBSD$"); #include +#include "xlocale_private.h" int -wcswidth(const wchar_t *pwcs, size_t n) +wcswidth_l(const wchar_t *pwcs, size_t n, locale_t locale) { wchar_t wc; int len, l; + FIX_LOCALE(locale); len = 0; while (n-- > 0 && (wc = *pwcs++) != L'\0') { - if ((l = wcwidth(wc)) < 0) + if ((l = wcwidth_l(wc, locale)) < 0) return (-1); len += l; } return (len); } +int +wcswidth(const wchar_t *pwcs, size_t n) +{ + return wcswidth_l(pwcs, n, __get_locale()); +} Index: lib/libc/string/Symbol.map =================================================================== --- lib/libc/string/Symbol.map (revision 225653) +++ lib/libc/string/Symbol.map (working copy) @@ -75,6 +75,11 @@ wmemcpy; wmemmove; wmemset; + strcasecmp_l; + strcasestr_l; + strncasecmp_l; + wcswidth_l; + wcwidth_l; }; FBSD_1.1 { Index: lib/libc/string/strcoll.c =================================================================== --- lib/libc/string/strcoll.c (revision 225653) +++ lib/libc/string/strcoll.c (working copy) @@ -3,6 +3,11 @@ * at Electronni Visti IA, Kiev, Ukraine. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -32,21 +37,26 @@ #include #include "collate.h" +#include + int -strcoll(const char *s, const char *s2) +strcoll_l(const char *s, const char *s2, locale_t locale) { int len, len2, prim, prim2, sec, sec2, ret, ret2; const char *t, *t2; char *tt, *tt2; + FIX_LOCALE(locale); + struct xlocale_collate *table = + (struct xlocale_collate*)locale->components[XLC_COLLATE]; - if (__collate_load_error) + if (table->__collate_load_error) return strcmp(s, s2); len = len2 = 1; ret = ret2 = 0; - if (__collate_substitute_nontrivial) { - t = tt = __collate_substitute(s); - t2 = tt2 = __collate_substitute(s2); + if (table->__collate_substitute_nontrivial) { + t = tt = __collate_substitute(table, s); + t2 = tt2 = __collate_substitute(table, s2); } else { tt = tt2 = NULL; t = s; @@ -55,11 +65,11 @@ while(*t && *t2) { prim = prim2 = 0; while(*t && !prim) { - __collate_lookup(t, &len, &prim, &sec); + __collate_lookup(table, t, &len, &prim, &sec); t += len; } while(*t2 && !prim2) { - __collate_lookup(t2, &len2, &prim2, &sec2); + __collate_lookup(table, t2, &len2, &prim2, &sec2); t2 += len2; } if(!prim || !prim2) @@ -83,3 +93,10 @@ return ret; } + +int +strcoll(const char *s, const char *s2) +{ + return strcoll_l(s, s2, __get_locale()); +} + Index: lib/libc/string/wcsxfrm.c =================================================================== --- lib/libc/string/wcsxfrm.c (revision 225653) +++ lib/libc/string/wcsxfrm.c (working copy) @@ -3,6 +3,11 @@ * at Electronni Visti IA, Kiev, Ukraine. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -43,11 +48,14 @@ * the logic used. */ size_t -wcsxfrm(wchar_t * __restrict dest, const wchar_t * __restrict src, size_t len) +wcsxfrm_l(wchar_t * __restrict dest, const wchar_t * __restrict src, size_t len, locale_t locale) { int prim, sec, l; size_t slen; char *mbsrc, *s, *ss; + FIX_LOCALE(locale); + struct xlocale_collate *table = + (struct xlocale_collate*)locale->components[XLC_COLLATE]; if (*src == L'\0') { if (len != 0) @@ -55,7 +63,7 @@ return (0); } - if (__collate_load_error || MB_CUR_MAX > 1) { + if (table->__collate_load_error || MB_CUR_MAX > 1) { slen = wcslen(src); if (len > 0) { if (slen < len) @@ -71,10 +79,10 @@ mbsrc = __mbsdup(src); slen = 0; prim = sec = 0; - ss = s = __collate_substitute(mbsrc); + ss = s = __collate_substitute(table, mbsrc); while (*s != '\0') { while (*s != '\0' && prim == 0) { - __collate_lookup(s, &l, &prim, &sec); + __collate_lookup(table, s, &l, &prim, &sec); s += l; } if (prim != 0) { @@ -93,6 +101,11 @@ return (slen); } +size_t +wcsxfrm(wchar_t * __restrict dest, const wchar_t * __restrict src, size_t len) +{ + return wcsxfrm_l(dest, src, len, __get_locale()); +} static char * __mbsdup(const wchar_t *ws) Index: lib/libc/string/strcasestr.c =================================================================== --- lib/libc/string/strcasestr.c (revision 225653) +++ lib/libc/string/strcasestr.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Chris Torek. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -35,26 +40,33 @@ #include #include +#include "xlocale_private.h" /* * Find the first occurrence of find in s, ignore case. */ char * -strcasestr(const char *s, const char *find) +strcasestr_l(const char *s, const char *find, locale_t locale) { char c, sc; size_t len; + FIX_LOCALE(locale); if ((c = *find++) != 0) { - c = tolower((unsigned char)c); + c = tolower_l((unsigned char)c, locale); len = strlen(find); do { do { if ((sc = *s++) == 0) return (NULL); - } while ((char)tolower((unsigned char)sc) != c); - } while (strncasecmp(s, find, len) != 0); + } while ((char)tolower_l((unsigned char)sc, locale) != c); + } while (strncasecmp_l(s, find, len, locale) != 0); s--; } return ((char *)s); } +char * +strcasestr(const char *s, const char *find) +{ + return strcasestr_l(s, find, __get_locale()); +} Index: lib/libc/string/strxfrm.c =================================================================== --- lib/libc/string/strxfrm.c (revision 225653) +++ lib/libc/string/strxfrm.c (working copy) @@ -3,6 +3,11 @@ * at Electronni Visti IA, Kiev, Ukraine. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -33,11 +38,22 @@ #include "collate.h" size_t +strxfrm_l(char * __restrict dest, const char * __restrict src, size_t len, locale_t loc); +size_t strxfrm(char * __restrict dest, const char * __restrict src, size_t len) { + return strxfrm_l(dest, src, len, __get_locale()); +} + +size_t +strxfrm_l(char * __restrict dest, const char * __restrict src, size_t len, locale_t locale) +{ int prim, sec, l; size_t slen; char *s, *ss; + FIX_LOCALE(locale); + struct xlocale_collate *table = + (struct xlocale_collate*)locale->components[XLC_COLLATE]; if (!*src) { if (len > 0) @@ -45,15 +61,15 @@ return 0; } - if (__collate_load_error) + if (table->__collate_load_error) return strlcpy(dest, src, len); slen = 0; prim = sec = 0; - ss = s = __collate_substitute(src); + ss = s = __collate_substitute(table, src); while (*s) { while (*s && !prim) { - __collate_lookup(s, &l, &prim, &sec); + __collate_lookup(table, s, &l, &prim, &sec); s += l; } if (prim) { Index: sys/sys/cdefs.h =================================================================== --- sys/sys/cdefs.h (revision 225653) +++ sys/sys/cdefs.h (working copy) @@ -249,7 +249,7 @@ #define __func__ NULL #endif -#if (defined(__INTEL_COMPILER) || (defined(__GNUC__) && __GNUC__ >= 2)) && !defined(__STRICT_ANSI__) || __STDC_VERSION__ >= 199901 +#if (defined(__INTEL_COMPILER) || (defined(__GNUC__) && __GNUC__ >= 2)) && !defined(__STRICT_ANSI__) || __STDC_VERSION__ >= 199901 || __cplusplus >= 201103L #define __LONG_LONG_SUPPORTED #endif --Apple-Mail=_42B7C1B0-E4C4-4143-8596-7785C86E8855-- From owner-freebsd-hackers@FreeBSD.ORG Tue Sep 20 20:05:14 2011 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 545E0106566B for ; Tue, 20 Sep 2011 20:05:14 +0000 (UTC) (envelope-from hselasky@c2i.net) Received: from swip.net (mailfe03.c2i.net [212.247.154.66]) by mx1.freebsd.org (Postfix) with ESMTP id D945F8FC16 for ; Tue, 20 Sep 2011 20:05:13 +0000 (UTC) X-Cloudmark-Score: 0.000000 [] X-Cloudmark-Analysis: v=1.1 cv=yVKV3zusvCapyMfYJBNW2j35FMEuTKq6vh/tt/1L5+g= c=1 sm=1 a=SvYTsOw2Z4kA:10 a=d1FtHp7U9EQA:10 a=WQU8e4WWZSUA:10 a=Q9fys5e9bTEA:10 a=CL8lFSKtTFcA:10 a=i9M/sDlu2rpZ9XS819oYzg==:17 a=V_AnRJfqi--2y7o2DCcA:9 a=PUjeQqilurYA:10 a=i9M/sDlu2rpZ9XS819oYzg==:117 Received: from [188.126.198.129] (account mc467741@c2i.net HELO laptop002.hselasky.homeunix.org) by mailfe03.swip.net (CommuniGate Pro SMTP 5.2.19) with ESMTPA id 14131984; Tue, 20 Sep 2011 22:05:12 +0200 From: Hans Petter Selasky To: freebsd-hackers@freebsd.org, geoffrey levand Date: Tue, 20 Sep 2011 22:02:19 +0200 User-Agent: KMail/1.13.5 (FreeBSD/8.2-STABLE; KDE/4.4.5; amd64; ; ) References: In-Reply-To: X-Face: *nPdTl_}RuAI6^PVpA02T?$%Xa^>@hE0uyUIoiha$pC:9TVgl.Oq,NwSZ4V" =?utf-8?q?=7CLR=2E+tj=7Dg5=0A=09=25V?=,x^qOs~mnU3]Gn; cQLv&.N>TrxmSFf+p6(30a/{)KUU!s}w\IhQBj}[g}bj0I3^glmC( =?utf-8?q?=0A=09=3AAuzV9=3A=2EhESm-x4h240C=609=3Dw?= MIME-Version: 1.0 Content-Type: Text/Plain; charset="iso-8859-15" Content-Transfer-Encoding: 7bit Message-Id: <201109202202.19481.hselasky@c2i.net> Cc: Subject: Re: Sharing device driver between kernel and user space X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 20 Sep 2011 20:05:14 -0000 On Tuesday 20 September 2011 20:35:57 geoffrey levand wrote: > Currently i'm developing VUART device drivers for PS3 architecture. VUART > is bi-directional FIFO queue between 2 logical partitions on PS3. I want > to use the device in the kernel and user space. During system boot PS3 > system has to read/write some data from/to the VUART devices and sometimes > i want to access the device from user space , e.g. with character device > driver by using read/write syscalls. The quuestion is what is the best > solution to share the device between kernel and user lands. One solution i > found would be to porohibit kernel access to the device as soon as a user > application opens the corresponding character device. And allow it again > when the application calls close syscall. The user space should have > higher priority then the kernel. Are there any better solutions for this > problem ? Forgot to mention that a VUART device cannot be accessed > simultaneously by user land and the kernel. The VUART devices are used by > PS3 management logical partition to provide different request/response > services and event notification to other logical partitions. E.g. setting > video mode or configuring audio outputs. > Have you looked at cuse4bsd in ports/multimedia/cuse4bsd-kmod ? --HPS From owner-freebsd-hackers@FreeBSD.ORG Tue Sep 20 20:05:28 2011 Return-Path: Delivered-To: hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id C3B1C106566C; Tue, 20 Sep 2011 20:05:28 +0000 (UTC) (envelope-from mavbsd@gmail.com) Received: from mail-bw0-f54.google.com (mail-bw0-f54.google.com [209.85.214.54]) by mx1.freebsd.org (Postfix) with ESMTP id 2C5138FC14; Tue, 20 Sep 2011 20:05:27 +0000 (UTC) Received: by bkbzs8 with SMTP id zs8so1082971bkb.13 for ; Tue, 20 Sep 2011 13:05:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=sender:message-id:date:from:user-agent:mime-version:to:cc:subject :references:in-reply-to:x-enigmail-version:content-type :content-transfer-encoding; bh=sgUcdFTFJMRmgON8kmnyi122Lx2waymVM5Q8T72Owno=; b=JME+Xbnr4Wu39hyagOJEBcY1om1uMT2r9veF1iHABrRqFxrMs2eQ4cBYxHg3RsgzAJ 3TIgyvZToLv3WJ7iQ8tmX4+XhAAMWv4+v4BfMzTIaFBGn166EMpNr3uwPIT1e9Suv43Y x7izH7ZggQXsn8XC6W67iguClLsrP8LN9bX1E= Received: by 10.204.132.89 with SMTP id a25mr896588bkt.185.1316549127204; Tue, 20 Sep 2011 13:05:27 -0700 (PDT) Received: from mavbook.mavhome.dp.ua (pc.mavhome.dp.ua. [212.86.226.226]) by mx.google.com with ESMTPS id m18sm2508127bkt.12.2011.09.20.13.05.24 (version=SSLv3 cipher=OTHER); Tue, 20 Sep 2011 13:05:25 -0700 (PDT) Sender: Alexander Motin Message-ID: <4E78F1E7.7020502@FreeBSD.org> Date: Tue, 20 Sep 2011 23:04:55 +0300 From: Alexander Motin User-Agent: Mozilla/5.0 (X11; FreeBSD amd64; rv:6.0.2) Gecko/20110910 Thunderbird/6.0.2 MIME-Version: 1.0 To: Andriy Gapon References: <4E78E755.8050404@FreeBSD.org> In-Reply-To: <4E78E755.8050404@FreeBSD.org> X-Enigmail-Version: undefined Content-Type: text/plain; charset=x-viet-vps Content-Transfer-Encoding: 7bit Cc: hackers@FreeBSD.org Subject: Re: SW_WATCHDOG vs new eventtimer code X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 20 Sep 2011 20:05:28 -0000 Hi. On 20.09.2011 22:19, Andriy Gapon wrote: > just want to check with you first if the following makes sense. > I use SW_WATCHDOG on one of the test machines, which was recently updated to > from stable/8 to head. Now it seems to get seemingly random watchdog events. > My theory is that this is because of the eventtimer logic. > If during idle period we accumulate enough timer ticks and then run all those > ticks very rapidly, then the SW_WATCHDOG code may get an impression that it was > not patted for many real ticks. > Not sure what would be the best way to make SW_WATCHDOG happier/smarter. Eventtimer code now set to generate interrupts at least 4 times per second for each CPU. As soon as SW_WATCHDOG only handles periods more then one second, I would say it should not be hurt. I would try to add some debug there to see what's going on (how big the tick busts are). I'll try it to do it tomorrow. -- Alexander Motin From owner-freebsd-hackers@FreeBSD.ORG Tue Sep 20 20:28:21 2011 Return-Path: Delivered-To: hackers@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id B92F8106566C; Tue, 20 Sep 2011 20:28:21 +0000 (UTC) (envelope-from avg@FreeBSD.org) Received: from citadel.icyb.net.ua (citadel.icyb.net.ua [212.40.38.140]) by mx1.freebsd.org (Postfix) with ESMTP id D753F8FC12; Tue, 20 Sep 2011 20:28:20 +0000 (UTC) Received: from porto.starpoint.kiev.ua (porto-e.starpoint.kiev.ua [212.40.38.100]) by citadel.icyb.net.ua (8.8.8p3/ICyb-2.3exp) with ESMTP id XAA09286; Tue, 20 Sep 2011 23:28:19 +0300 (EEST) (envelope-from avg@FreeBSD.org) Received: from localhost ([127.0.0.1]) by porto.starpoint.kiev.ua with esmtp (Exim 4.34 (FreeBSD)) id 1R66vT-000LDz-9G; Tue, 20 Sep 2011 23:28:19 +0300 Message-ID: <4E78F762.5000906@FreeBSD.org> Date: Tue, 20 Sep 2011 23:28:18 +0300 From: Andriy Gapon User-Agent: Mozilla/5.0 (X11; FreeBSD amd64; rv:6.0.2) Gecko/20110907 Thunderbird/6.0.2 MIME-Version: 1.0 To: Alexander Motin References: <4E78E755.8050404@FreeBSD.org> <4E78F1E7.7020502@FreeBSD.org> In-Reply-To: <4E78F1E7.7020502@FreeBSD.org> X-Enigmail-Version: undefined Content-Type: text/plain; charset=x-viet-vps Content-Transfer-Encoding: 7bit Cc: hackers@FreeBSD.org Subject: Re: SW_WATCHDOG vs new eventtimer code X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 20 Sep 2011 20:28:21 -0000 on 20/09/2011 23:04 Alexander Motin said the following: > Hi. > > On 20.09.2011 22:19, Andriy Gapon wrote: >> just want to check with you first if the following makes sense. >> I use SW_WATCHDOG on one of the test machines, which was recently updated to >> from stable/8 to head. Now it seems to get seemingly random watchdog events. >> My theory is that this is because of the eventtimer logic. >> If during idle period we accumulate enough timer ticks and then run all those >> ticks very rapidly, then the SW_WATCHDOG code may get an impression that it was >> not patted for many real ticks. >> Not sure what would be the best way to make SW_WATCHDOG happier/smarter. > > Eventtimer code now set to generate interrupts at least 4 times per > second for each CPU. As soon as SW_WATCHDOG only handles periods more > then one second, I would say it should not be hurt. I would try to add > some debug there to see what's going on (how big the tick busts are). > I'll try it to do it tomorrow. Just in case, here is a debugging snippet from a panic that I've got: ... #12 0xffffffff80425d80 in watchdog_fire () at /usr/src/sys/kern/kern_clock.c:858 #13 0xffffffff8042603e in hardclock_anycpu (cnt=15761, usermode=Variable "usermode" is not available. ) at atomic.h:183 #14 0xffffffff80660ae5 in handleevents (now=0xffffff80e3e0b8b0, fake=0) at /usr/src/sys/kern/kern_clocksource.c:209 #15 0xffffffff80661b48 in timercb (et=Variable "et" is not available. ) at /usr/src/sys/kern/kern_clocksource.c:379 #16 0xffffffff802cc068 in hpet_intr_single (arg=Variable "arg" is not available. ) at /usr/src/sys/dev/acpica/acpi_hpet.c:258 #17 0xffffffff802cc71e in hpet_intr (arg=0xffffff80e3e0b5b0) at /usr/src/sys/dev/acpica/acpi_hpet.c:276 #18 0xffffffff80444b02 in intr_event_handle (ie=0xfffffe0002751500, frame=0xffffff80e3e0ba30) at /usr/src/sys/kern/kern_intr.c:1428 #19 0xffffffff8062f920 in intr_remove_handler (cookie=0xffffff80e3e0b5b0) at /usr/src/sys/amd64/amd64/intr_machdep.c:197 #20 0xffffffff8069cca9 in lapic_enable_pmc () at /usr/src/sys/x86/x86/local_apic.c:431 #21 0xffffffff8062cc70 in Xapic_isr2 () at apic_vector.S:87 #22 0xffffffff80443118 in intr_event_execute_handlers (p=0xfffffe0002758000, ie=0xfffffe0002a5eb00) at /usr/src/sys/kern/kern_intr.c:1244 #23 0xffffffff80444164 in ithread_loop (arg=0xfffffe0002758000) at /usr/src/sys/kern/kern_intr.c:1269 #24 0xffffffff8044053a in fork_exit (callout=0xffffffff80444024 , arg=0xfffffe0002b4f700, frame=0xffffff80e3e0bc50) at /usr/src/sys/kern/kern_fork.c:1024 #25 0xffffffff8062cb0e in Xint0x80_syscall () at ia32_exception.S:62 #26 0x0000000000000000 in ?? () Previous frame inner to this frame (corrupt stack?) (kgdb) fr 14 #14 0xffffffff80660ae5 in handleevents (now=0xffffff80e3e0b8b0, fake=0) at /usr/src/sys/kern/kern_clocksource.c:209 209 while (bintime_cmp(now, &state->nextstat, >=)) { (kgdb) list 204 } 205 if (runs && fake < 2) { 206 hardclock_anycpu(runs, usermode); 207 done = 1; 208 } 209 while (bintime_cmp(now, &state->nextstat, >=)) { 210 if (fake < 2) 211 statclock(usermode); 212 bintime_add(&state->nextstat, &statperiod); 213 done = 1; (kgdb) p state->nextstat $1 = {sec = 90, frac = 15986939599958264124} (kgdb) p *now $3 = {sec = 106, frac = 11494276814354478452} (kgdb) p statperiod $4 = {sec = 0, frac = 145249953336295682} (kgdb) fr 13 #13 0xffffffff8042603e in hardclock_anycpu (cnt=15761, usermode=Variable "usermode" is not available. ) at atomic.h:183 183 atomic.h: No such file or directory. in atomic.h (kgdb) p cnt $5 = 15761 (kgdb) p newticks $6 = 15000 (kgdb) p watchdog_ticks $7 = 16000 Watchdog timeout was set to ~16 seconds. -- Andriy Gapon From owner-freebsd-hackers@FreeBSD.ORG Tue Sep 20 21:43:14 2011 Return-Path: Delivered-To: hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 28059106566C for ; Tue, 20 Sep 2011 21:43:14 +0000 (UTC) (envelope-from cbergstrom@pathscale.com) Received: from mail-gx0-f182.google.com (mail-gx0-f182.google.com [209.85.161.182]) by mx1.freebsd.org (Postfix) with ESMTP id DF59B8FC16 for ; Tue, 20 Sep 2011 21:43:13 +0000 (UTC) Received: by gxk28 with SMTP id 28so916543gxk.13 for ; Tue, 20 Sep 2011 14:43:13 -0700 (PDT) Received: by 10.68.199.38 with SMTP id jh6mr134067pbc.393.1316553590299; Tue, 20 Sep 2011 14:19:50 -0700 (PDT) Received: from [192.168.1.34] (ppp-61-90-24-186.revip.asianet.co.th. [61.90.24.186]) by mx.google.com with ESMTPS id i8sm9660881pbp.1.2011.09.20.14.19.48 (version=SSLv3 cipher=OTHER); Tue, 20 Sep 2011 14:19:49 -0700 (PDT) Message-ID: <4E790410.7050005@pathscale.com> Date: Wed, 21 Sep 2011 04:22:24 +0700 From: =?ISO-8859-1?Q?=22C=2E_Bergstr=F6m=22?= User-Agent: Mozilla/5.0 (X11; U; SunOS i86pc; en-US; rv:1.9.2.7) Gecko/20101031 Lightning/1.0b2 Thunderbird/3.1.1 MIME-Version: 1.0 To: David Chisnall References: <20110919172214.GJ33993@hoeg.nl> <3A86EAEA-1861-43A6-95DC-FC700BE0E507@theravensnest.org> In-Reply-To: <3A86EAEA-1861-43A6-95DC-FC700BE0E507@theravensnest.org> Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Cc: Ed Schouten , hackers@freebsd.org Subject: Re: xlocale patch X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 20 Sep 2011 21:43:14 -0000 On 09/21/11 02:17 AM, David Chisnall wrote: > Ooops, I forgot I uninstalled the subversion-freebsd package and installed subversion to work on libc++ (it would be really nice if these two could coexist, by the way...). > > The updated version of the diff now passes all of the libc++ locale tests (309 files, multiple tests in each), with my copy of libc++. I've just pushed the exception handling bits required to support std::exception_ptr to libcxxrt, so we can now build a mostly-working BSD licensed C++ stack. > > For anyone that's interested, the full results of the libc++ test suite are here: > > http://pastebin.com/UCskvjCv > > For those two lazy Sounds about right - David - If you have the time we may be able to extend part of our test-suite to help you validate this. Building and running boost tests is also a good way to flush out bugs and really stress things as well. (Same goes for QT or Chromium.. etc) From owner-freebsd-hackers@FreeBSD.ORG Tue Sep 20 22:31:50 2011 Return-Path: Delivered-To: hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 9603E106566C for ; Tue, 20 Sep 2011 22:31:50 +0000 (UTC) (envelope-from lev@FreeBSD.org) Received: from onlyone.friendlyhosting.spb.ru (onlyone.friendlyhosting.spb.ru [IPv6:2a01:4f8:131:60a2::2]) by mx1.freebsd.org (Postfix) with ESMTP id 5C21D8FC13 for ; Tue, 20 Sep 2011 22:31:50 +0000 (UTC) Received: from lion.home.serebryakov.spb.ru (unknown [IPv6:2001:470:923f:1:f803:edca:622b:8392]) (Authenticated sender: lev@serebryakov.spb.ru) by onlyone.friendlyhosting.spb.ru (Postfix) with ESMTPA id 9175C4AC1C; Wed, 21 Sep 2011 02:31:49 +0400 (MSD) Date: Wed, 21 Sep 2011 02:31:47 +0400 From: Lev Serebryakov Organization: FreeBSD X-Priority: 3 (Normal) Message-ID: <1016063405.20110921023147@serebryakov.spb.ru> To: David Chisnall In-Reply-To: <3A86EAEA-1861-43A6-95DC-FC700BE0E507@theravensnest.org> References: <20110919172214.GJ33993@hoeg.nl> <3A86EAEA-1861-43A6-95DC-FC700BE0E507@theravensnest.org> MIME-Version: 1.0 Content-Type: text/plain; charset=windows-1251 Content-Transfer-Encoding: quoted-printable Cc: hackers@freebsd.org Subject: Re: xlocale patch X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list Reply-To: lev@FreeBSD.org List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 20 Sep 2011 22:31:50 -0000 Hello, David. You wrote 20 =F1=E5=ED=F2=FF=E1=F0=FF 2011 =E3., 23:17:28: > Ooops, I forgot I uninstalled the subversion-freebsd package and > installed subversion to work on libc++ (it would be really nice if > these two could coexist, by the way...). How does subversion-freebsd prevent you from working on libc++? Is it uses $FreeBSD$ string? :) FreeBSD changes are: (1) Support for additional keywords to make $FreeBSD works. (2) Different style of merge conflict markers. (3) Commit message template. (3) could be annoying, but not show-stopper for sure. Next version of subversion will not have -freebsd variant, but will have three different options for mentioned hacks :) --=20 // Black Lion AKA Lev Serebryakov From owner-freebsd-hackers@FreeBSD.ORG Wed Sep 21 08:41:53 2011 Return-Path: Delivered-To: hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 7888B106564A; Wed, 21 Sep 2011 08:41:53 +0000 (UTC) (envelope-from mavbsd@gmail.com) Received: from mail-fx0-f54.google.com (mail-fx0-f54.google.com [209.85.161.54]) by mx1.freebsd.org (Postfix) with ESMTP id CC4568FC16; Wed, 21 Sep 2011 08:41:52 +0000 (UTC) Received: by fxg9 with SMTP id 9so1888123fxg.13 for ; Wed, 21 Sep 2011 01:41:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=sender:message-id:date:from:user-agent:mime-version:to:cc:subject :references:in-reply-to:x-enigmail-version:content-type :content-transfer-encoding; bh=QZjX0RUvN+rB5ijgDCEptz8IWZcQWnYFk3tloypKPK8=; b=X3CAxFicWXP/2lHG4G5HcT++TEBaKj+nt2dgsEGWk+1re17+xuI2KbMvyIR4l4DXWX 0IVip9XBmMtqtgqq6aNqEsMDmj6rbXY2ijn4/VJ3b+uPRrFalvaof2EAoPIV2rsoHjt3 O8wAuLT9V2rt6CX59brIP1dAKgf4W2bfLbPQM= Received: by 10.223.58.209 with SMTP id i17mr708048fah.22.1316594511738; Wed, 21 Sep 2011 01:41:51 -0700 (PDT) Received: from mavbook2.mavhome.dp.ua (pc.mavhome.dp.ua. [212.86.226.226]) by mx.google.com with ESMTPS id f10sm3660496fac.14.2011.09.21.01.41.50 (version=SSLv3 cipher=OTHER); Wed, 21 Sep 2011 01:41:50 -0700 (PDT) Sender: Alexander Motin Message-ID: <4E79A2F9.4010802@FreeBSD.org> Date: Wed, 21 Sep 2011 11:40:25 +0300 From: Alexander Motin User-Agent: Thunderbird 2.0.0.23 (X11/20091212) MIME-Version: 1.0 To: Andriy Gapon References: <4E78E755.8050404@FreeBSD.org> <4E78F1E7.7020502@FreeBSD.org> <4E78F762.5000906@FreeBSD.org> In-Reply-To: <4E78F762.5000906@FreeBSD.org> X-Enigmail-Version: 0.96.0 Content-Type: text/plain; charset=x-viet-vps Content-Transfer-Encoding: 7bit Cc: hackers@FreeBSD.org Subject: Re: SW_WATCHDOG vs new eventtimer code X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 21 Sep 2011 08:41:53 -0000 Andriy Gapon wrote: > on 20/09/2011 23:04 Alexander Motin said the following: >> On 20.09.2011 22:19, Andriy Gapon wrote: >>> just want to check with you first if the following makes sense. >>> I use SW_WATCHDOG on one of the test machines, which was recently updated to >>> from stable/8 to head. Now it seems to get seemingly random watchdog events. >>> My theory is that this is because of the eventtimer logic. >>> If during idle period we accumulate enough timer ticks and then run all those >>> ticks very rapidly, then the SW_WATCHDOG code may get an impression that it was >>> not patted for many real ticks. >>> Not sure what would be the best way to make SW_WATCHDOG happier/smarter. >> Eventtimer code now set to generate interrupts at least 4 times per >> second for each CPU. As soon as SW_WATCHDOG only handles periods more >> then one second, I would say it should not be hurt. I would try to add >> some debug there to see what's going on (how big the tick busts are). >> I'll try it to do it tomorrow. I've built kernel with SW_WATCHDOG and run watchdogd with most tight parameters (-s 1 -t 2), but observed no problems so far. > Just in case, here is a debugging snippet from a panic that I've got: > #14 0xffffffff80660ae5 in handleevents (now=0xffffff80e3e0b8b0, fake=0) at > /usr/src/sys/kern/kern_clocksource.c:209 > 209 while (bintime_cmp(now, &state->nextstat, >=)) { > (kgdb) list > 204 } > 205 if (runs && fake < 2) { > 206 hardclock_anycpu(runs, usermode); > 207 done = 1; > 208 } > 209 while (bintime_cmp(now, &state->nextstat, >=)) { > 210 if (fake < 2) > 211 statclock(usermode); > 212 bintime_add(&state->nextstat, &statperiod); > 213 done = 1; > (kgdb) p state->nextstat > $1 = {sec = 90, frac = 15986939599958264124} > (kgdb) p *now > $3 = {sec = 106, frac = 11494276814354478452} > (kgdb) p statperiod > $4 = {sec = 0, frac = 145249953336295682} > > (kgdb) fr 13 > #13 0xffffffff8042603e in hardclock_anycpu (cnt=15761, usermode=Variable > "usermode" is not available. > ) at atomic.h:183 > 183 atomic.h: No such file or directory. > in atomic.h > (kgdb) p cnt > $5 = 15761 > (kgdb) p newticks > $6 = 15000 > (kgdb) p watchdog_ticks > $7 = 16000 > > Watchdog timeout was set to ~16 seconds. It looks like your system was out for about 15 seconds or for some reason system uptime jumped 15 seconds forward. Have you done anything special at the moment or have you seen anything strange in system behavior? What timecounter are you using? I see you are using HPET eventtimer, but on what hardware (is it per-CPU or global)? Building kernel with KTR_SPARE2 ktrace enabled should help to collect valuable info about timers behavior before the crash. -- Alexander Motin From owner-freebsd-hackers@FreeBSD.ORG Wed Sep 21 08:56:56 2011 Return-Path: Delivered-To: hackers@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 52BDD106566B; Wed, 21 Sep 2011 08:56:56 +0000 (UTC) (envelope-from avg@FreeBSD.org) Received: from citadel.icyb.net.ua (citadel.icyb.net.ua [212.40.38.140]) by mx1.freebsd.org (Postfix) with ESMTP id 716A48FC15; Wed, 21 Sep 2011 08:56:55 +0000 (UTC) Received: from porto.starpoint.kiev.ua (porto-e.starpoint.kiev.ua [212.40.38.100]) by citadel.icyb.net.ua (8.8.8p3/ICyb-2.3exp) with ESMTP id LAA21362; Wed, 21 Sep 2011 11:56:53 +0300 (EEST) (envelope-from avg@FreeBSD.org) Received: from localhost ([127.0.0.1]) by porto.starpoint.kiev.ua with esmtp (Exim 4.34 (FreeBSD)) id 1R6Ibt-000O2B-KM; Wed, 21 Sep 2011 11:56:53 +0300 Message-ID: <4E79A6D3.2060102@FreeBSD.org> Date: Wed, 21 Sep 2011 11:56:51 +0300 From: Andriy Gapon User-Agent: Mozilla/5.0 (X11; FreeBSD amd64; rv:6.0.2) Gecko/20110907 Thunderbird/6.0.2 MIME-Version: 1.0 To: Alexander Motin References: <4E78E755.8050404@FreeBSD.org> <4E78F1E7.7020502@FreeBSD.org> <4E78F762.5000906@FreeBSD.org> <4E79A2F9.4010802@FreeBSD.org> In-Reply-To: <4E79A2F9.4010802@FreeBSD.org> X-Enigmail-Version: undefined Content-Type: text/plain; charset=x-viet-vps Content-Transfer-Encoding: 7bit Cc: hackers@FreeBSD.org Subject: Re: SW_WATCHDOG vs new eventtimer code X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 21 Sep 2011 08:56:56 -0000 on 21/09/2011 11:40 Alexander Motin said the following: > It looks like your system was out for about 15 seconds or for some > reason system uptime jumped 15 seconds forward. Have you done anything > special at the moment or have you seen anything strange in system > behavior? Nope. I just looked away for a second :-) > What timecounter are you using? I see you are using HPET > eventtimer, but on what hardware (is it per-CPU or global)? The timecounter is the new TSC-low. The HPET eventtimer was global, I think. It is an ICH9-based system. > Building kernel with KTR_SPARE2 ktrace enabled should help to collect > valuable info about timers behavior before the crash. I will try to debug this further using your suggestion. Thank you! -- Andriy Gapon From owner-freebsd-hackers@FreeBSD.ORG Wed Sep 21 06:05:32 2011 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 07185106566C for ; Wed, 21 Sep 2011 06:05:32 +0000 (UTC) (envelope-from geoffrey.levand@mail.ru) Received: from f177.mail.ru (f177.mail.ru [94.100.178.94]) by mx1.freebsd.org (Postfix) with ESMTP id 7C8118FC12 for ; Wed, 21 Sep 2011 06:05:31 +0000 (UTC) Received: from mail by f177.mail.ru with local id 1R6Fvx-0005sO-00; Wed, 21 Sep 2011 10:05:25 +0400 Received: from [217.228.7.75] by e.mail.ru with HTTP; Wed, 21 Sep 2011 10:05:25 +0400 From: =?UTF-8?B?Z2VvZmZyZXkgbGV2YW5k?= To: =?UTF-8?B?SGFucyBQZXR0ZXIgU2VsYXNreQ==?= Mime-Version: 1.0 X-Mailer: mPOP Web-Mail 2.19 X-Originating-IP: [217.228.7.75] Date: Wed, 21 Sep 2011 10:05:25 +0400 References: <201109202202.19481.hselasky@c2i.net> In-Reply-To: <201109202202.19481.hselasky@c2i.net> Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: base64 Message-Id: X-Spam: Not detected X-Mras: Ok X-Mailman-Approved-At: Wed, 21 Sep 2011 11:12:26 +0000 Cc: freebsd-hackers@freebsd.org Subject: Re[2]: Sharing device driver between kernel and user space X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list Reply-To: =?UTF-8?B?Z2VvZmZyZXkgbGV2YW5k?= List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 21 Sep 2011 06:05:32 -0000 SSB0aGluayB5b3UgbWlzdW5kZXJzdG9vZCB3aGF0IGkgbmVlZC4gSWYgaSBnb3QgaXQgcmlnaHQg dGhlbiBjdXNlNGJzZCBhbGxvd3MgdXNlciBhcHBsaWNhdGlvbnMgdG8gY3JlYXRlIGNoYXIgZGV2 aWNlcywgcmlnaHQgPwpJIGRvIG5vdCB3YW50IHRvIGNyZWF0ZSBjaGFyYWN0ZXIgZGV2aWNlcyBm cm9tIHVzZXIgc3BhY2UuIE15IFZVQVJUIGtlcm5lbAptb2R1bGUgc2hvdWxkIHByb3ZpZGUgdGhl IGNoYXJhY3RlciBkZXZpY2UgZm9yIHVzZXIgc3BhY2UuIFdoYXQgaSBuZWVkIGlzIGEgd2F5IHRv IHN5bmNocm9uaXplIGFjY2Vzcwp0byBWVUFSVCBkYXRhIGJldHdlZW4ga2VybmVsIGFuZCB1c2Vy IHNwYWNlLiBUaGUga2VybmVsIGRldmljZSBkcml2ZXIgc2hvdWxkIHByb3ZpZGUgMiBpbnRlcmZh Y2VzOiBvbmUgZm9yIHVzZXIgc3BhY2UKICh0aHJvdWdoIGNoYXIgZGV2KSBhbmQgdGhlIG90aGVy IGZvciBrZXJuZWwgbGFuZC4gVGhlIHByb2JsZW0gaXMgaG93IHRvIHN5bmNocm9uaXplIHRoZSBh Y2Nlc3MgdG8gVlVBUlQgZGF0YSBiZXR3ZWVuIDIKbGFuZHMgYmVjYXVzZSBWVUFSVCBjYW5ub3Qg YmUgc2hhcmVkIGJ5IGJvdGggc2ltdWx0YW5lb3VzbHkuCgoyMSDRgdC10L3RgtGP0LHRgNGPIDIw MTEsIDAwOjA1INC+0YIgSGFucyBQZXR0ZXIgU2VsYXNreSA8aHNlbGFza3lAYzJpLm5ldD46Cj4g T24gVHVlc2RheSAyMCBTZXB0ZW1iZXIgMjAxMSAyMDozNTo1NyBnZW9mZnJleSBsZXZhbmQgd3Jv dGU6Cj4gPiBDdXJyZW50bHkgaSdtIGRldmVsb3BpbmcgVlVBUlQgZGV2aWNlIGRyaXZlcnMgZm9y IFBTMyBhcmNoaXRlY3R1cmUuIFZVQVJUCj4gPiBpcyBiaS1kaXJlY3Rpb25hbCBGSUZPIHF1ZXVl IGJldHdlZW4gMiBsb2dpY2FsIHBhcnRpdGlvbnMgb24gUFMzLiBJIHdhbnQKPiA+IHRvIHVzZSB0 aGUgZGV2aWNlIGluIHRoZSBrZXJuZWwgYW5kIHVzZXIgc3BhY2UuIER1cmluZyBzeXN0ZW0gYm9v dCBQUzMKPiA+IHN5c3RlbSBoYXMgdG8gcmVhZC93cml0ZSBzb21lIGRhdGEgZnJvbS90byB0aGUg VlVBUlQgZGV2aWNlcyBhbmQgc29tZXRpbWVzCj4gPiBpIHdhbnQgdG8gYWNjZXNzIHRoZSBkZXZp Y2UgZnJvbSB1c2VyIHNwYWNlICwgZS5nLiB3aXRoIGNoYXJhY3RlciBkZXZpY2UKPiA+IGRyaXZl ciBieSB1c2luZyByZWFkL3dyaXRlIHN5c2NhbGxzLiBUaGUgcXV1ZXN0aW9uIGlzIHdoYXQgaXMg dGhlIGJlc3QKPiA+IHNvbHV0aW9uIHRvIHNoYXJlIHRoZSBkZXZpY2UgYmV0d2VlbiBrZXJuZWwg YW5kIHVzZXIgbGFuZHMuIE9uZSBzb2x1dGlvbiBpCj4gPiBmb3VuZCB3b3VsZCBiZSB0byBwb3Jv aGliaXQga2VybmVsIGFjY2VzcyB0byB0aGUgZGV2aWNlIGFzIHNvb24gYXMgYSB1c2VyCj4gPiBh cHBsaWNhdGlvbiBvcGVucyB0aGUgY29ycmVzcG9uZGluZyBjaGFyYWN0ZXIgZGV2aWNlLiBBbmQg YWxsb3cgaXQgYWdhaW4KPiA+IHdoZW4gdGhlIGFwcGxpY2F0aW9uIGNhbGxzIGNsb3NlIHN5c2Nh bGwuIFRoZSB1c2VyIHNwYWNlIHNob3VsZCBoYXZlCj4gPiBoaWdoZXIgcHJpb3JpdHkgdGhlbiB0 aGUga2VybmVsLiBBcmUgdGhlcmUgYW55IGJldHRlciBzb2x1dGlvbnMgZm9yIHRoaXMKPiA+IHBy b2JsZW0gPyBGb3Jnb3QgdG8gbWVudGlvbiB0aGF0IGEgVlVBUlQgZGV2aWNlIGNhbm5vdCBiZSBh Y2Nlc3NlZAo+ID4gc2ltdWx0YW5lb3VzbHkgYnkgdXNlciBsYW5kIGFuZCB0aGUga2VybmVsLiBU aGUgVlVBUlQgZGV2aWNlcyBhcmUgdXNlZCBieQo+ID4gUFMzIG1hbmFnZW1lbnQgbG9naWNhbCBw YXJ0aXRpb24gdG8gcHJvdmlkZSBkaWZmZXJlbnQgcmVxdWVzdC9yZXNwb25zZQo+ID4gc2Vydmlj ZXMgYW5kIGV2ZW50IG5vdGlmaWNhdGlvbiB0byBvdGhlciBsb2dpY2FsIHBhcnRpdGlvbnMuIEUu Zy4gc2V0dGluZwo+ID4gdmlkZW8gbW9kZSBvciBjb25maWd1cmluZyBhdWRpbyBvdXRwdXRzLgo+ ID4KPiAKPiBIYXZlIHlvdSBsb29rZWQgYXQgY3VzZTRic2QgaW4gcG9ydHMvbXVsdGltZWRpYS9j dXNlNGJzZC1rbW9kID8KPiAKPiAtLUhQUwo+IF9fX19fX19fX19fX19fX19fX19fX19fX19fX19f X19fX19fX19fX19fX19fX19fCj4gZnJlZWJzZC1oYWNrZXJzQGZyZWVic2Qub3JnIG1haWxpbmcg bGlzdAo+IGh0dHA6Ly9saXN0cy5mcmVlYnNkLm9yZy9tYWlsbWFuL2xpc3RpbmZvL2ZyZWVic2Qt aGFja2Vycwo+IFRvIHVuc3Vic2NyaWJlLCBzZW5kIGFueSBtYWlsIHRvICJmcmVlYnNkLWhhY2tl cnMtdW5zdWJzY3JpYmVAZnJlZWJzZC5vcmciCj4g From owner-freebsd-hackers@FreeBSD.ORG Wed Sep 21 11:26:55 2011 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id D3425106566C for ; Wed, 21 Sep 2011 11:26:55 +0000 (UTC) (envelope-from hselasky@c2i.net) Received: from swip.net (mailfe03.c2i.net [212.247.154.66]) by mx1.freebsd.org (Postfix) with ESMTP id 52E518FC13 for ; Wed, 21 Sep 2011 11:26:54 +0000 (UTC) X-Cloudmark-Score: 0.000000 [] X-Cloudmark-Analysis: v=1.1 cv=yVKV3zusvCapyMfYJBNW2j35FMEuTKq6vh/tt/1L5+g= c=1 sm=1 a=SvYTsOw2Z4kA:10 a=d1FtHp7U9EQA:10 a=WQU8e4WWZSUA:10 a=Q9fys5e9bTEA:10 a=CL8lFSKtTFcA:10 a=i9M/sDlu2rpZ9XS819oYzg==:17 a=uLdibwT2YJnq9gv0iqYA:9 a=PUjeQqilurYA:10 a=i9M/sDlu2rpZ9XS819oYzg==:117 Received: from [188.126.198.129] (account mc467741@c2i.net HELO laptop002.hselasky.homeunix.org) by mailfe03.swip.net (CommuniGate Pro SMTP 5.2.19) with ESMTPA id 14396916; Wed, 21 Sep 2011 13:26:52 +0200 From: Hans Petter Selasky To: freebsd-hackers@freebsd.org, geoffrey levand Date: Wed, 21 Sep 2011 13:24:01 +0200 User-Agent: KMail/1.13.5 (FreeBSD/8.2-STABLE; KDE/4.4.5; amd64; ; ) References: <201109202202.19481.hselasky@c2i.net> In-Reply-To: X-Face: *nPdTl_}RuAI6^PVpA02T?$%Xa^>@hE0uyUIoiha$pC:9TVgl.Oq, NwSZ4V"|LR.+tj}g5 %V,x^qOs~mnU3]Gn; cQLv&.N>TrxmSFf+p6(30a/{)KUU!s}w\IhQBj}[g}bj0I3^glmC( :AuzV9:.hESm-x4h240C`9=w MIME-Version: 1.0 Content-Type: Text/Plain; charset="iso-8859-15" Content-Transfer-Encoding: 7bit Message-Id: <201109211324.01978.hselasky@c2i.net> Cc: Subject: Re: Sharing device driver between kernel and user space X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 21 Sep 2011 11:26:55 -0000 On Wednesday 21 September 2011 08:05:25 geoffrey levand wrote: > I think you misunderstood what i need. If i got it right then cuse4bsd > allows user applications to create char devices, right ? I do not want to > create character devices from user space. My VUART kernel module should > provide the character device for user space. What i need is a way to > synchronize access to VUART data between kernel and user space. The kernel > device driver should provide 2 interfaces: one for user space (through > char dev) and the other for kernel land. The problem is how to synchronize > the access to VUART data between 2 lands because VUART cannot be shared by > both simultaneously. Ok, I'm not a PS3 expert. --HPS From owner-freebsd-hackers@FreeBSD.ORG Wed Sep 21 12:26:16 2011 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id F3388106564A for ; Wed, 21 Sep 2011 12:26:16 +0000 (UTC) (envelope-from freebsd-hackers@m.gmane.org) Received: from lo.gmane.org (lo.gmane.org [80.91.229.12]) by mx1.freebsd.org (Postfix) with ESMTP id 7B0E88FC12 for ; Wed, 21 Sep 2011 12:26:16 +0000 (UTC) Received: from list by lo.gmane.org with local (Exim 4.69) (envelope-from ) id 1R6LsU-00078J-6z for freebsd-hackers@freebsd.org; Wed, 21 Sep 2011 14:26:14 +0200 Received: from lara.cc.fer.hr ([161.53.72.113]) by main.gmane.org with esmtp (Gmexim 0.1 (Debian)) id 1AlnuQ-0007hv-00 for ; Wed, 21 Sep 2011 14:26:14 +0200 Received: from ivoras by lara.cc.fer.hr with local (Gmexim 0.1 (Debian)) id 1AlnuQ-0007hv-00 for ; Wed, 21 Sep 2011 14:26:14 +0200 X-Injected-Via-Gmane: http://gmane.org/ To: freebsd-hackers@freebsd.org From: Ivan Voras Date: Wed, 21 Sep 2011 14:25:48 +0200 Lines: 46 Message-ID: References: <201109202202.19481.hselasky@c2i.net> Mime-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha1; protocol="application/pgp-signature"; boundary="------------enigA9ACA5241980A903A14E5E64" X-Complaints-To: usenet@dough.gmane.org X-Gmane-NNTP-Posting-Host: lara.cc.fer.hr User-Agent: Mozilla/5.0 (X11; FreeBSD amd64; rv:6.0.1) Gecko/20110907 Thunderbird/6.0.1 In-Reply-To: X-Enigmail-Version: 1.1.2 Subject: Re: Sharing device driver between kernel and user space X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 21 Sep 2011 12:26:17 -0000 This is an OpenPGP/MIME signed message (RFC 2440 and 3156) --------------enigA9ACA5241980A903A14E5E64 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable On 21/09/2011 08:05, geoffrey levand wrote: > I think you misunderstood what i need. If i got it right then cuse4bsd = allows user applications to create char devices, right ? > I do not want to create character devices from user space. My VUART ker= nel > module should provide the character device for user space. What i need = is a way to synchronize access > to VUART data between kernel and user space. The kernel device driver s= hould provide 2 interfaces: one for user space > (through char dev) and the other for kernel land. The problem is how t= o synchronize the access to VUART data between 2 > lands because VUART cannot be shared by both simultaneously. I'm not sure I understand your question but what exactly is the problem here? As the userland will access the device through the char device, you need kernel code which services this device's requests. This kernel code can use any number of synchronization operations provided by the kernel to protect access to any and all needed resources. In other words, you should have a single point of entry to the device in the kernel anyway (e.g. a module, a header file, whatever) and then you may need just a simple sx(9) lock or a sema(9) semaphore, assuming the device access needs sleeping, or mutex(9) if it doesn't. --------------enigA9ACA5241980A903A14E5E64 Content-Type: application/pgp-signature; name="signature.asc" Content-Description: OpenPGP digital signature Content-Disposition: attachment; filename="signature.asc" -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.18 (FreeBSD) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/ iEYEARECAAYFAk5519IACgkQldnAQVacBcgwWACeO64/8QOZVbYcpr7hlLAnKIuu A3cAn24SYUw4255MeHd9XnbYgdb/mMfR =r7GV -----END PGP SIGNATURE----- --------------enigA9ACA5241980A903A14E5E64-- From owner-freebsd-hackers@FreeBSD.ORG Wed Sep 21 14:24:09 2011 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 0A495106566B for ; Wed, 21 Sep 2011 14:24:09 +0000 (UTC) (envelope-from ivoras@gmail.com) Received: from mail-gx0-f182.google.com (mail-gx0-f182.google.com [209.85.161.182]) by mx1.freebsd.org (Postfix) with ESMTP id BC1828FC0C for ; Wed, 21 Sep 2011 14:24:08 +0000 (UTC) Received: by gxk26 with SMTP id 26so468536gxk.13 for ; Wed, 21 Sep 2011 07:24:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=mime-version:sender:in-reply-to:references:from:date :x-google-sender-auth:message-id:subject:to:cc:content-type :content-transfer-encoding; bh=mwsH2AOsLygs2/Jo9mNjf3PlYADuhiE861deIDaEFo0=; b=HmsZMe4JJ4mRYUIvhNIP7tgL1m5jHzSPBJE8fokMfWY2tU0dRN42ibYu6E4kAQPqPe iCaUulb80mAnWPeSTdT8IPy0F7bkDVgzqaN7LHcNGE70OfCSQyLuaO8D4idJhQhtdSBl gL48x9EDAKY7Wyw95WMEUzvsHRzRCnusS8zaQ= Received: by 10.101.148.13 with SMTP id a13mr810850ano.44.1316615048131; Wed, 21 Sep 2011 07:24:08 -0700 (PDT) MIME-Version: 1.0 Sender: ivoras@gmail.com Received: by 10.100.43.9 with HTTP; Wed, 21 Sep 2011 07:23:28 -0700 (PDT) In-Reply-To: References: From: Ivan Voras Date: Wed, 21 Sep 2011 16:23:28 +0200 X-Google-Sender-Auth: RoXF_X7jA0ydKSXBk3d0yDl36QU Message-ID: To: geoffrey levand Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable Cc: freebsd-hackers@freebsd.org Subject: Re: Re[2]: Sharing device driver between kernel and user space X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 21 Sep 2011 14:24:09 -0000 On 21 September 2011 16:09, geoffrey levand wrote= : > Sure i can use the synchronization primitives, the problem is that the re= sponse to a request sent to PS3 VUART port is not > available immediately, and i have to disallow kernel access to the PS3 VU= ART while i'm waiting for the response in user > space. I send request with write syscall from user space and wait for res= ponse with read syscall. In the period of time > between sending request and receiving response i could receive some other= packets from VUART port, e.g. some kind of > event notification, =C2=A0i have to skip them. But kernel should not inte= rfer until i get my response. > So i would need to lock out the kernel during this time. I think i found = a good solution for this problem, just use a IOCTL > which tells kernel device driver to stop processing kernel requests and e= vents, something like SET_USER_MODE. > After that i can use it in user space. Have you read sema(9)? Or if returning EBUSY is acceptable when the resource is in use by $whatever, maybe you just need a boolean variable. From owner-freebsd-hackers@FreeBSD.ORG Wed Sep 21 14:09:15 2011 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id D3DDE1065675 for ; Wed, 21 Sep 2011 14:09:15 +0000 (UTC) (envelope-from geoffrey.levand@mail.ru) Received: from f285.mail.ru (f285.mail.ru [217.69.138.185]) by mx1.freebsd.org (Postfix) with ESMTP id 48CE58FC19 for ; Wed, 21 Sep 2011 14:09:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=mail.ru; s=mail; h=Message-Id:Content-Transfer-Encoding:Content-Type:Reply-To:In-Reply-To:References:Date:Mime-Version:Subject:Cc:To:From; bh=SXFV8LwseK+DS2Ci5saQU9x8dAPzm6pg20sL1aXZjyU=; b=1EkppZPd2xf0OUj2zMjLfGAaWKctwHTIaIcYCvzNFgj7W3wBhHOAqDcxm2Vyc/rj1QXi/hT0kYm61eWvIY0mBouwdIg5Nj5TMC9zQna7JPmNhahDUbVgpF8c68RInpiA; Received: from mail by f285.mail.ru with local id 1R6NU8-0005JS-00; Wed, 21 Sep 2011 18:09:12 +0400 Received: from [194.77.155.74] by e.mail.ru with HTTP; Wed, 21 Sep 2011 18:09:12 +0400 From: =?UTF-8?B?Z2VvZmZyZXkgbGV2YW5k?= To: =?UTF-8?B?SXZhbiBWb3Jhcw==?= Mime-Version: 1.0 X-Mailer: mPOP Web-Mail 2.19 X-Originating-IP: [194.77.155.74] Date: Wed, 21 Sep 2011 18:09:12 +0400 References: In-Reply-To: X-Priority: Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: base64 Message-Id: X-Spam: Not detected X-Mras: Ok X-Mailman-Approved-At: Wed, 21 Sep 2011 15:20:13 +0000 Cc: freebsd-hackers@freebsd.org Subject: Re[2]: Sharing device driver between kernel and user space X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list Reply-To: =?UTF-8?B?Z2VvZmZyZXkgbGV2YW5k?= List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 21 Sep 2011 14:09:16 -0000 U3VyZSBpIGNhbiB1c2UgdGhlIHN5bmNocm9uaXphdGlvbiBwcmltaXRpdmVzLCB0aGUgcHJvYmxl bSBpcyB0aGF0IHRoZSByZXNwb25zZSB0byBhIHJlcXVlc3Qgc2VudCB0byBQUzMgVlVBUlQgcG9y dCBpcyBub3QgCmF2YWlsYWJsZSBpbW1lZGlhdGVseSwgYW5kIGkgaGF2ZSB0byBkaXNhbGxvdyBr ZXJuZWwgYWNjZXNzIHRvIHRoZSBQUzMgVlVBUlQgd2hpbGUgaSdtIHdhaXRpbmcgZm9yIHRoZSBy ZXNwb25zZSBpbiB1c2VyIApzcGFjZS4gSSBzZW5kIHJlcXVlc3Qgd2l0aCB3cml0ZSBzeXNjYWxs IGZyb20gdXNlciBzcGFjZSBhbmQgd2FpdCBmb3IgcmVzcG9uc2Ugd2l0aCByZWFkIHN5c2NhbGwu IEluIHRoZSBwZXJpb2Qgb2YgdGltZSAKYmV0d2VlbiBzZW5kaW5nIHJlcXVlc3QgYW5kIHJlY2Vp dmluZyByZXNwb25zZSBpIGNvdWxkIHJlY2VpdmUgc29tZSBvdGhlciBwYWNrZXRzIGZyb20gVlVB UlQgcG9ydCwgZS5nLiBzb21lIGtpbmQgb2YgCmV2ZW50IG5vdGlmaWNhdGlvbiwgIGkgaGF2ZSB0 byBza2lwIHRoZW0uIEJ1dCBrZXJuZWwgc2hvdWxkIG5vdCBpbnRlcmZlciB1bnRpbCBpIGdldCBt eSByZXNwb25zZS4gClNvIGkgd291bGQgbmVlZCB0byBsb2NrIG91dCB0aGUga2VybmVsIGR1cmlu ZyB0aGlzIHRpbWUuIEkgdGhpbmsgaSBmb3VuZCBhIGdvb2Qgc29sdXRpb24gZm9yIHRoaXMgcHJv YmxlbSwganVzdCB1c2UgYSBJT0NUTCAKd2hpY2ggdGVsbHMga2VybmVsIGRldmljZSBkcml2ZXIg dG8gc3RvcCBwcm9jZXNzaW5nIGtlcm5lbCByZXF1ZXN0cyBhbmQgZXZlbnRzLCBzb21ldGhpbmcg bGlrZSBTRVRfVVNFUl9NT0RFLgpBZnRlciB0aGF0IGkgY2FuIHVzZSBpdCBpbiB1c2VyIHNwYWNl LgoKCjIxINGB0LXQvdGC0Y/QsdGA0Y8gMjAxMSwgMTY6Mjcg0L7RgiBJdmFuIFZvcmFzIDxpdm9y YXNAZnJlZWJzZC5vcmc+Ogo+IE9uIDIxLzA5LzIwMTEgMDg6MDUsIGdlb2ZmcmV5IGxldmFuZCB3 cm90ZToKPiA+IEkgdGhpbmsgeW91IG1pc3VuZGVyc3Rvb2Qgd2hhdCBpIG5lZWQuIElmIGkgZ290 IGl0IHJpZ2h0IHRoZW4gY3VzZTRic2QKPiBhbGxvd3MgdXNlciBhcHBsaWNhdGlvbnMgdG8gY3Jl YXRlIGNoYXIgZGV2aWNlcywgcmlnaHQgPwo+ID4gSSBkbyBub3Qgd2FudCB0byBjcmVhdGUgY2hh cmFjdGVyIGRldmljZXMgZnJvbSB1c2VyIHNwYWNlLiBNeSBWVUFSVCBrZXJuZWwKPiA+IG1vZHVs ZSBzaG91bGQgcHJvdmlkZSB0aGUgY2hhcmFjdGVyIGRldmljZSBmb3IgdXNlciBzcGFjZS4gV2hh dCBpIG5lZWQgaXMgYQo+IHdheSB0byBzeW5jaHJvbml6ZSBhY2Nlc3MKPiA+IHRvIFZVQVJUIGRh dGEgYmV0d2VlbiBrZXJuZWwgYW5kIHVzZXIgc3BhY2UuIFRoZSBrZXJuZWwgZGV2aWNlIGRyaXZl ciBzaG91bGQKPiBwcm92aWRlIDIgaW50ZXJmYWNlczogb25lIGZvciB1c2VyIHNwYWNlCj4gPiAg KHRocm91Z2ggY2hhciBkZXYpIGFuZCB0aGUgb3RoZXIgZm9yIGtlcm5lbCBsYW5kLiBUaGUgcHJv YmxlbSBpcyBob3cgdG8KPiBzeW5jaHJvbml6ZSB0aGUgYWNjZXNzIHRvIFZVQVJUIGRhdGEgYmV0 d2VlbiAyCj4gPiBsYW5kcyBiZWNhdXNlIFZVQVJUIGNhbm5vdCBiZSBzaGFyZWQgYnkgYm90aCBz aW11bHRhbmVvdXNseS4KPiAKPiBJJ20gbm90IHN1cmUgSSB1bmRlcnN0YW5kIHlvdXIgcXVlc3Rp b24gYnV0IHdoYXQgZXhhY3RseSBpcyB0aGUgcHJvYmxlbQo+IGhlcmU/IEFzIHRoZSB1c2VybGFu ZCB3aWxsIGFjY2VzcyB0aGUgZGV2aWNlIHRocm91Z2ggdGhlIGNoYXIgZGV2aWNlLAo+IHlvdSBu ZWVkIGtlcm5lbCBjb2RlIHdoaWNoIHNlcnZpY2VzIHRoaXMgZGV2aWNlJ3MgcmVxdWVzdHMuIFRo aXMga2VybmVsCj4gY29kZSBjYW4gdXNlIGFueSBudW1iZXIgb2Ygc3luY2hyb25pemF0aW9uIG9w ZXJhdGlvbnMgcHJvdmlkZWQgYnkgdGhlCj4ga2VybmVsIHRvIHByb3RlY3QgYWNjZXNzIHRvIGFu eSBhbmQgYWxsIG5lZWRlZCByZXNvdXJjZXMuCj4gCj4gSW4gb3RoZXIgd29yZHMsIHlvdSBzaG91 bGQgaGF2ZSBhIHNpbmdsZSBwb2ludCBvZiBlbnRyeSB0byB0aGUgZGV2aWNlIGluCj4gdGhlIGtl cm5lbCBhbnl3YXkgKGUuZy4gYSBtb2R1bGUsIGEgaGVhZGVyIGZpbGUsIHdoYXRldmVyKSBhbmQg dGhlbiB5b3UKPiBtYXkgbmVlZCBqdXN0IGEgc2ltcGxlIHN4KDkpIGxvY2sgb3IgYSBzZW1hKDkp IHNlbWFwaG9yZSwgYXNzdW1pbmcgdGhlCj4gZGV2aWNlIGFjY2VzcyBuZWVkcyBzbGVlcGluZywg b3IgbXV0ZXgoOSkgaWYgaXQgZG9lc24ndC4K From owner-freebsd-hackers@FreeBSD.ORG Wed Sep 21 19:29:08 2011 Return-Path: Delivered-To: hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 56EA9106566C for ; Wed, 21 Sep 2011 19:29:08 +0000 (UTC) (envelope-from theraven@theravensnest.org) Received: from theravensnest.org (theravensnest.org [109.169.23.128]) by mx1.freebsd.org (Postfix) with ESMTP id C742A8FC15 for ; Wed, 21 Sep 2011 19:29:06 +0000 (UTC) Received: from [192.168.0.128] (cpc1-cwma5-0-0-cust192.7-3.cable.virginmedia.com [80.4.12.193]) (authenticated bits=0) by theravensnest.org (8.14.4/8.14.4) with ESMTP id p8LKPq1R064998 (version=TLSv1/SSLv3 cipher=DHE-DSS-AES128-SHA bits=128 verify=NO) for ; Wed, 21 Sep 2011 21:25:52 +0100 (BST) (envelope-from theraven@theravensnest.org) From: David Chisnall Mime-Version: 1.0 (Apple Message framework v1244.3) Content-Type: multipart/mixed; boundary="Apple-Mail=_D1FEC970-512C-409C-B503-1C81695F7BCD" Date: Wed, 21 Sep 2011 20:28:54 +0100 In-Reply-To: <3A86EAEA-1861-43A6-95DC-FC700BE0E507@theravensnest.org> To: hackers@freebsd.org References: <20110919172214.GJ33993@hoeg.nl> <3A86EAEA-1861-43A6-95DC-FC700BE0E507@theravensnest.org> Message-Id: X-Mailer: Apple Mail (2.1244.3) X-Mailman-Approved-At: Wed, 21 Sep 2011 19:37:37 +0000 Cc: Subject: Re: xlocale patch X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 21 Sep 2011 19:29:08 -0000 --Apple-Mail=_D1FEC970-512C-409C-B503-1C81695F7BCD Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=us-ascii And here's an updated version of the patch. I've fixed some other bugs, = including where wcstod() and wcstodl() in trunk return the wrong value = for any input string starting with spaces, wchar.h's violation of POSIX = by not declaring FILE, and a few C++ incompatibilities in other headers = (e.g. putchar being a macro, which breaks things like = std::putchar(foo)). All of my libcxxrt and libc++ changes have now been = pushed upstream, so this should now be repeatable. =20 The libunwind port still has an irritating bug in the header, where the = extern "C" {} block ends with a semicolon, which causes it to be = rejected in any C++ program, but with that fixed you can compile = libcxxrt (I used cmake .. -DCMAKE_CXX_FLAGS=3D"-I/usr/local/include = -nostdlib -g" - hopefully I'll work out how to make CMake add these = flags automatically soon...). Libc++ should build out of the box with = cmake. The results are now: **************************************************** Results for /root/libcxx/test: using clang version 3.0 (trunk 140248) Target: x86_64-unknown-freebsd9.0 Thread model: posix with -std=3Dc++0x -stdlib=3Dlibc++ -pthread -I/root/libcxx/include = -L/root/libcxx/build/lib ---------------------------------------------------- sections without tests : 1 sections with failures : 16 sections without failures: 1047 + ---- total number of sections : 1064 ---------------------------------------------------- number of tests failed : 53 number of tests passed : 4271 + ---- total number of tests : 4324 **************************************************** For comparison, the results on OS X are: **************************************************** Results for /test: using Apple clang version 3.0 (tags/Apple/clang-211.10.1) (based on LLVM = 3.0svn) Target: x86_64-apple-darwin11.1.0 Thread model: posix with -std=3Dc++0x -stdlib=3Dlibc++ =20 ---------------------------------------------------- sections without tests : 1 sections with failures : 17 sections without failures: 1046 + ---- total number of sections : 1064 ---------------------------------------------------- number of tests failed : 71 number of tests passed : 4253 + ---- total number of tests : 4324 **************************************************** The remaining failures on FreeBSD are: - 27 caused by clang not fully supporting the atomic operations yet - 3 caused by clang not fully supporting the C++11 type-trait intrinsics - 20 that I don't think are real failures - they're caused by the VM = where I'm running the tests not having sufficiently fine-grained time = reporting for the thread operation timeout tests to work properly - 1 is caused by FreeBSD lacking the C1x quick_exit() APIs. - 2 caused by FreeBSD lacking the uchar.h header The first 30 of these should be fixed in clang soon. The next 20 are = probably not real bugs at all. The remaining 3 are fairly minor. David --Apple-Mail=_D1FEC970-512C-409C-B503-1C81695F7BCD Content-Disposition: attachment; filename=xlocale.diff Content-Type: application/octet-stream; x-unix-mode=0644; name="xlocale.diff" Content-Transfer-Encoding: 7bit Index: include/wctype.h =================================================================== --- include/wctype.h (revision 225653) +++ include/wctype.h (working copy) @@ -89,6 +89,7 @@ #endif __END_DECLS +#ifndef __cplusplus #define iswalnum(wc) __istype((wc), _CTYPE_A|_CTYPE_D) #define iswalpha(wc) __istype((wc), _CTYPE_A) #define iswblank(wc) __istype((wc), _CTYPE_B) @@ -113,6 +114,7 @@ #define iswphonogram(wc) __istype((wc), _CTYPE_Q) #define iswrune(wc) __istype((wc), 0xFFFFFF00L) #define iswspecial(wc) __istype((wc), _CTYPE_T) -#endif +#endif /* __BSD_VISIBLE */ +#endif /* __cplusplus */ #endif /* _WCTYPE_H_ */ Index: include/Makefile =================================================================== --- include/Makefile (revision 225653) +++ include/Makefile (working copy) @@ -23,8 +23,9 @@ stdbool.h stddef.h stdio.h stdlib.h string.h stringlist.h \ strings.h sysexits.h tar.h termios.h tgmath.h \ time.h timeconv.h timers.h ttyent.h \ + uchar.h\ ulimit.h unistd.h utime.h utmpx.h uuid.h varargs.h vis.h \ - wchar.h wctype.h wordexp.h + wchar.h wctype.h wordexp.h xlocale.h _xlocale_ctype.h MHDRS= float.h floatingpoint.h stdarg.h Index: include/xlocale.h =================================================================== --- include/xlocale.h (revision 0) +++ include/xlocale.h (revision 0) @@ -0,0 +1,256 @@ +/*- + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by David Chisnall under sponsorship from + * the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions * are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _XLOCALE_H_ +#define _XLOCALE_H_ + +#include + +__BEGIN_DECLS + +/* + * Extended locale versions of the locale-aware functions from string.h. + * + * Include before to expose these. + */ +#ifdef _STRING_H_ +int strcoll_l(const char *, const char *, locale_t); +size_t strxfrm_l(char *, const char *, size_t, locale_t); +int strcasecmp_l(const char *, const char *, locale_t); +char *strcasestr_l(const char *, const char *, locale_t); +int strncasecmp_l(const char *, const char *, size_t, locale_t); +#endif +/* + * Extended locale versions of the locale-aware functions from inttypes.h. + * + * Include before to expose these. + */ +#ifdef _INTTYPES_H_ +intmax_t +strtoimax_l(const char * __restrict, char ** __restrict, int, locale_t); +uintmax_t +strtoumax_l(const char * __restrict, char ** __restrict, int, locale_t); +intmax_t +wcstoimax_l(const wchar_t * __restrict, wchar_t ** __restrict, int , locale_t); +uintmax_t +wcstoumax_l(const wchar_t * __restrict, wchar_t ** __restrict, int, locale_t); +#endif +/* + * Extended locale versions of the locale-aware functions from monetary.h. + * + * Include before to expose these. + */ +#ifdef _MONETARY_H_ +ssize_t strfmon_l(char *, size_t, locale_t, const char *, ...) +# if __GNUC__ > 2 || __GNUC__ == 2 && __GNUC_MINOR__ >= 7 + __attribute__((__format__ (__strfmon__, 4, 5))) +# endif + ; +#endif + +/* + * Extended locale versions of the locale-aware functions from stdlib.h. + * + * Include before to expose these. + */ +#ifdef _STDLIB_H_ +double atof_l(const char *, locale_t); +int atoi_l(const char *, locale_t); +long atol_l(const char *, locale_t); +long long atoll_l(const char *, locale_t); +int mblen_l(const char *, size_t, locale_t); +size_t +mbstowcs_l(wchar_t * __restrict, const char * __restrict, size_t, locale_t); +int +mbtowc_l(wchar_t * __restrict, const char * __restrict, size_t, locale_t); +double strtod_l(const char *, char **, locale_t); +float strtof_l(const char *, char **, locale_t); +long strtol_l(const char *, char **, int, locale_t); +long double strtold_l(const char *, char **, locale_t); +long long strtoll_l(const char *, char **, int, locale_t); +unsigned long strtoul_l(const char *, char **, int, locale_t); +unsigned long long strtoull_l(const char *, char **, int, locale_t); +size_t +wcstombs_l(char * __restrict, const wchar_t * __restrict, size_t, locale_t); +int wctomb_l(char *, wchar_t, locale_t); + +int ___mb_cur_max_l(locale_t); +#define MB_CUR_MAX_L(x) (___mb_cur_max_l(x)) + +#endif +/* + * Extended locale versions of the locale-aware functions from time.h. + * + * Include before to expose these. + */ +#ifdef _TIME_H_ +size_t +strftime_l(char * __restrict, size_t, const char * __restrict, const + struct tm * __restrict, locale_t) +# if __GNUC__ > 2 || __GNUC__ == 2 && __GNUC_MINOR__ >= 7 + __attribute__((__format__ (__strftime__, 3, 0))) +# endif + ; +char * +strptime_l(const char * __restrict, const char * __restrict, + struct tm * __restrict, locale_t); +#endif +#ifdef _LANGINFO_H_ +char *nl_langinfo_l(nl_item, locale_t); +#endif +#ifdef _CTYPE_H_ +#include <_xlocale_ctype.h> +#endif +#ifdef _WCTYPE_H_ +#define XLOCALE_WCTYPES 1 +#include <_xlocale_ctype.h> +#endif + +#ifdef _STDIO_H_ +int fprintf_l(FILE * __restrict, locale_t, const char * __restrict, ...) + __printflike(3, 4); +int fscanf_l(FILE * __restrict, locale_t, const char * __restrict, ...) + __scanflike(3, 4); +int printf_l(locale_t, const char * __restrict, ...) __printflike(2, 3); +int scanf_l(locale_t, const char * __restrict, ...) __scanflike(2, 3); +int sprintf_l(char * __restrict, locale_t, const char * __restrict, ...) + __printflike(3, 4); +int sscanf_l(const char * __restrict, locale_t, const char * __restrict, ...) + __scanflike(3, 4); +int vfprintf_l(FILE * __restrict, locale_t, const char * __restrict, __va_list) + __printflike(3, 0); +int vprintf_l(locale_t, const char * __restrict, __va_list) __printflike(2, 0); +int vsprintf_l(char * __restrict, locale_t, const char * __restrict, __va_list) + __printflike(3, 0); + +int snprintf_l(char * __restrict, size_t, locale_t, const char * __restrict, + ...) __printflike(4, 5); +int vfscanf_l(FILE * __restrict, locale_t, const char * __restrict, __va_list) + __scanflike(3, 0); +int vscanf_l(locale_t, const char * __restrict, __va_list) __scanflike(2, 0); +int vsnprintf_l(char * __restrict, size_t, locale_t, const char * __restrict, + va_list) __printflike(4, 0); +int vsscanf_l(const char * __restrict, locale_t, const char * __restrict, + va_list) __scanflike(3, 0); +int dprintf_l(int, locale_t, const char * __restrict, ...) __printflike(3, 4); +int vdprintf_l(int, locale_t, const char * __restrict, __va_list) + __printflike(3, 0); +int asprintf_l(char **, locale_t, const char *, ...) __printflike(3, 4); +int vasprintf_l(char **, locale_t, const char *, __va_list) __printflike(3, 0); +#endif +#ifdef _WCHAR_H_ +wint_t btowc_l(int, locale_t); +wint_t fgetwc_l(struct __sFILE *, locale_t); +wchar_t * +fgetws_l(wchar_t * __restrict, int, struct __sFILE * __restrict, locale_t); +wint_t fputwc_l(wchar_t, struct __sFILE *, locale_t); +int +fputws_l(const wchar_t * __restrict, struct __sFILE * __restrict, locale_t); +int +fwprintf_l(struct __sFILE * __restrict, locale_t, const wchar_t * __restrict, + ...); +int +fwscanf_l(struct __sFILE * __restrict, locale_t, const wchar_t * __restrict, ...); +wint_t getwc_l(struct __sFILE *, locale_t); +wint_t getwchar_l(locale_t); +size_t +mbrlen_l(const char * __restrict, size_t, mbstate_t * __restrict, locale_t); +size_t +mbrtowc_l(wchar_t * __restrict, const char * __restrict, size_t, + mbstate_t * __restrict, locale_t); +int mbsinit_l(const mbstate_t *, locale_t); +size_t +mbsrtowcs_l(wchar_t * __restrict, const char ** __restrict, size_t, + mbstate_t * __restrict, locale_t); +wint_t putwc_l(wchar_t, struct __sFILE *, locale_t); +wint_t putwchar_l(wchar_t, locale_t); +int +swprintf_l(wchar_t * __restrict, size_t n, locale_t, + const wchar_t * __restrict, ...); +int +swscanf_l(const wchar_t * __restrict, locale_t, const wchar_t * __restrict, + ...); +wint_t ungetwc_l(wint_t, struct __sFILE *, locale_t); +int +vfwprintf_l(struct __sFILE * __restrict, locale_t, const wchar_t * __restrict, + __va_list); +int +vswprintf_l(wchar_t * __restrict, size_t n, locale_t, + const wchar_t * __restrict, __va_list); +int vwprintf_l(locale_t, const wchar_t * __restrict, __va_list); +size_t +wcrtomb_l(char * __restrict, wchar_t, mbstate_t * __restrict, locale_t); +int wcscoll_l(const wchar_t *, const wchar_t *, locale_t); +size_t +wcsftime_l(wchar_t * __restrict, size_t, const wchar_t * __restrict, + const struct tm * __restrict, locale_t); +size_t +wcsrtombs_l(char * __restrict, const wchar_t ** __restrict, size_t, + mbstate_t * __restrict, locale_t); +double wcstod_l(const wchar_t * __restrict, wchar_t ** __restrict, locale_t); +long +wcstol_l(const wchar_t * __restrict, wchar_t ** __restrict, int, locale_t); +unsigned long +wcstoul_l(const wchar_t * __restrict, wchar_t ** __restrict, int, locale_t); +int wcswidth_l(const wchar_t *, size_t, locale_t); +size_t +wcsxfrm_l(wchar_t * __restrict, const wchar_t * __restrict, size_t, locale_t); +int wctob_l(wint_t, locale_t); +int wcwidth_l(wchar_t, locale_t); +int wprintf_l(locale_t, const wchar_t * __restrict, ...); +int wscanf_l(locale_t, const wchar_t * __restrict, ...); + +int +vfwscanf_l(struct __sFILE * __restrict, locale_t, const wchar_t * __restrict, + __va_list); +int vswscanf_l(const wchar_t * __restrict, locale_t, +const wchar_t * __restrict, __va_list); +int vwscanf_l(locale_t, const wchar_t * __restrict, __va_list); +float wcstof_l(const wchar_t * __restrict, wchar_t ** __restrict, locale_t); +long double +wcstold_l(const wchar_t * __restrict, wchar_t ** __restrict, locale_t); +long long +wcstoll_l(const wchar_t * __restrict, wchar_t ** __restrict, int, locale_t); +unsigned long long +wcstoull_l(const wchar_t * __restrict, wchar_t ** __restrict, int, locale_t); +size_t +mbsnrtowcs_l(wchar_t * __restrict, const char ** __restrict, size_t, size_t, + mbstate_t * __restrict, locale_t); +int wcscasecmp_l(const wchar_t *, const wchar_t *, locale_t); +int wcsncasecmp_l(const wchar_t *, const wchar_t *, size_t n, locale_t); +size_t +wcsnrtombs_l(char * __restrict, const wchar_t ** __restrict, size_t, size_t, + mbstate_t * __restrict, locale_t); + +#endif + +struct lconv * +localeconv_l(locale_t loc); +__END_DECLS + +#endif Index: include/locale.h =================================================================== --- include/locale.h (revision 225653) +++ include/locale.h (working copy) @@ -79,4 +79,48 @@ char *setlocale(int, const char *); __END_DECLS +#if __POSIX_VISIBLE >= 200809 + +#define LC_COLLATE_MASK (1<<0) +#define LC_CTYPE_MASK (1<<1) +#define LC_MESSAGES_MASK (1<<2) +#define LC_MONETARY_MASK (1<<3) +#define LC_NUMERIC_MASK (1<<4) +#define LC_TIME_MASK (1<<5) +#define LC_ALL_MASK (LC_COLLATE_MASK | LC_CTYPE_MASK | LC_MESSAGES_MASK | \ + LC_MONETARY_MASK | LC_NUMERIC_MASK | LC_TIME_MASK) + +#define LC_GLOBAL_LOCALE ((locale_t)-1) + +__BEGIN_DECLS + +typedef struct _xlocale *locale_t; +/** + * Creates a new locale. + */ +locale_t newlocale(int mask, const char *locale, locale_t base); + +locale_t duplocale(locale_t base); +/* + * Free a locale_t. This is quite a poorly named function. It actually + * disclaims a reference to a locale_t, rather than freeing it. + */ +int +freelocale(locale_t loc); + +/* + * Returns the name of the locale for a particular component of a locale_t. + */ +const char *querylocale(int mask, locale_t loc); + +/* + * Installs the specified locale_t as this thread's locale. + */ +locale_t uselocale(locale_t loc); + +__END_DECLS + +#endif /* __POSIX_VISIBLE >= 200809 */ + + #endif /* _LOCALE_H_ */ Index: include/iso646.h =================================================================== --- include/iso646.h (revision 225653) +++ include/iso646.h (working copy) @@ -29,6 +29,7 @@ #ifndef _ISO646_H_ #define _ISO646_H_ +#ifndef __cplusplus #define and && #define and_eq &= #define bitand & @@ -40,5 +41,6 @@ #define or_eq |= #define xor ^ #define xor_eq ^= +#endif #endif /* !_ISO646_H_ */ Index: include/_xlocale_ctype.h =================================================================== --- include/_xlocale_ctype.h (revision 0) +++ include/_xlocale_ctype.h (revision 0) @@ -0,0 +1,160 @@ +/*- + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by David Chisnall under sponsorship from + * the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions * are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef _XLOCALE_H_ +#error This header should only be included by , never directly. +#endif + +#ifndef _XLOCALE_CTYPE_H_ +__BEGIN_DECLS +unsigned long ___runetype_l(__ct_rune_t, locale_t) __pure; +__ct_rune_t ___tolower_l(__ct_rune_t, locale_t) __pure; +__ct_rune_t ___toupper_l(__ct_rune_t, locale_t) __pure; +_RuneLocale *__runes_for_locale(locale_t, int*); +__END_DECLS +#endif + +#ifndef _XLOCALE_INLINE +# if __GNUC__ && !__GNUC_STDC_INLINE__ +# define _XLOCALE_INLINE extern inline +# else +# define _XLOCALE_INLINE inline +# endif +#endif + +#ifdef XLOCALE_WCTYPES +static __inline int +__maskrune_l(__ct_rune_t _c, unsigned long _f, locale_t locale) +{ + int mb_sb_limit; + _RuneLocale *runes = __runes_for_locale(locale, &mb_sb_limit); + return (_c < 0 || _c >= _CACHED_RUNES) ? ___runetype_l(_c, locale) : + runes->__runetype[_c] & _f; +} + +static __inline int +__istype_l(__ct_rune_t _c, unsigned long _f, locale_t locale) +{ + return (!!__maskrune_l(_c, _f, locale)); +} + +# define XLOCALE_ISCTYPE(fname, cat) \ + _XLOCALE_INLINE int isw##fname##_l(int c, locale_t l)\ + { return __istype_l(c, cat, l); } +#else +static __inline int +__sbmaskrune_l(__ct_rune_t _c, unsigned long _f, locale_t locale) +{ + int mb_sb_limit; + _RuneLocale *runes = __runes_for_locale(locale, &mb_sb_limit); + return (_c < 0 || _c >= mb_sb_limit) ? 0 : + runes->__runetype[_c] & _f; +} + +static __inline int +__sbistype_l(__ct_rune_t _c, unsigned long _f, locale_t locale) +{ + return (!!__sbmaskrune_l(_c, _f, locale)); +} + +# define XLOCALE_ISCTYPE(fname, cat) \ + _XLOCALE_INLINE int is##fname##_l(int c, locale_t l)\ + { return __sbistype_l(c, cat, l); } +#endif + +XLOCALE_ISCTYPE(alnum, _CTYPE_A|_CTYPE_D) +XLOCALE_ISCTYPE(alpha, _CTYPE_A) +XLOCALE_ISCTYPE(blank, _CTYPE_B) +XLOCALE_ISCTYPE(cntrl, _CTYPE_C) +XLOCALE_ISCTYPE(digit, _CTYPE_D) +XLOCALE_ISCTYPE(graph, _CTYPE_G) +XLOCALE_ISCTYPE(hexnumber, _CTYPE_X) +XLOCALE_ISCTYPE(ideogram, _CTYPE_I) +XLOCALE_ISCTYPE(lower, _CTYPE_L) +XLOCALE_ISCTYPE(number, _CTYPE_D) +XLOCALE_ISCTYPE(phonogram, _CTYPE_Q) +XLOCALE_ISCTYPE(print, _CTYPE_R) +XLOCALE_ISCTYPE(punct, _CTYPE_P) +XLOCALE_ISCTYPE(rune, 0xFFFFFF00L) +XLOCALE_ISCTYPE(space, _CTYPE_S) +XLOCALE_ISCTYPE(special, _CTYPE_T) +XLOCALE_ISCTYPE(upper, _CTYPE_U) +XLOCALE_ISCTYPE(xdigit, _CTYPE_X) +#undef XLOCALE_ISCTYPE + +#ifdef XLOCALE_WCTYPES +_XLOCALE_INLINE int towlower_l(int c, locale_t locale) +{ + int mb_sb_limit; + _RuneLocale *runes = __runes_for_locale(locale, &mb_sb_limit); + return (c < 0 || c >= _CACHED_RUNES) ? ___tolower_l(c, locale) : + runes->__maplower[c]; +} +_XLOCALE_INLINE int towupper_l(int c, locale_t locale) +{ + int mb_sb_limit; + _RuneLocale *runes = __runes_for_locale(locale, &mb_sb_limit); + return (c < 0 || c >= _CACHED_RUNES) ? ___toupper_l(c, locale) : + runes->__mapupper[c]; +} +_XLOCALE_INLINE int +__wcwidth_l(__ct_rune_t _c, locale_t locale) +{ + unsigned int _x; + + if (_c == 0) + return (0); + _x = (unsigned int)__maskrune_l(_c, _CTYPE_SWM|_CTYPE_R, locale); + if ((_x & _CTYPE_SWM) != 0) + return ((_x & _CTYPE_SWM) >> _CTYPE_SWS); + return ((_x & _CTYPE_R) != 0 ? 1 : -1); +} +int iswctype_l(wint_t wc, wctype_t charclass, locale_t locale); +wctype_t wctype_l(const char *property, locale_t locale); +wint_t towctrans_l(wint_t wc, wctrans_t desc, locale_t locale); +wint_t nextwctype_l(wint_t wc, wctype_t wct, locale_t locale); +wctrans_t wctrans_l(const char *charclass, locale_t locale); +#undef XLOCALE_WCTYPES +#else +_XLOCALE_INLINE int digittoint_l(int c, locale_t locale) +{ return __sbmaskrune_l((c), 0xFF, locale); } + +_XLOCALE_INLINE int tolower_l(int c, locale_t locale) +{ + int mb_sb_limit; + _RuneLocale *runes = __runes_for_locale(locale, &mb_sb_limit); + return (c < 0 || c >= mb_sb_limit) ? c : + runes->__maplower[c]; +} +_XLOCALE_INLINE int toupper_l(int c, locale_t locale) +{ + int mb_sb_limit; + _RuneLocale *runes = __runes_for_locale(locale, &mb_sb_limit); + return (c < 0 || c >= mb_sb_limit) ? c : + runes->__mapupper[c]; +} +#endif Index: include/runetype.h =================================================================== --- include/runetype.h (revision 225653) +++ include/runetype.h (working copy) @@ -83,8 +83,14 @@ } _RuneLocale; #define _RUNE_MAGIC_1 "RuneMagi" /* Indicates version 0 of RuneLocale */ - -extern _RuneLocale _DefaultRuneLocale; +__BEGIN_DECLS +extern const _RuneLocale _DefaultRuneLocale; +__attribute__((deprecated)) extern _RuneLocale *_CurrentRuneLocale; +/* TODO: This is called quite a lot, so we should use a __thread variable when + * it's available. */ +extern _RuneLocale *__getCurrentRuneLocale(void); +#define _CurrentRuneLocale (__getCurrentRuneLocale()) +__END_DECLS #endif /* !_RUNETYPE_H_ */ Index: include/stdlib.h =================================================================== --- include/stdlib.h (revision 225653) +++ include/stdlib.h (working copy) @@ -71,10 +71,11 @@ #define RAND_MAX 0x7fffffff +__BEGIN_DECLS extern int __mb_cur_max; -#define MB_CUR_MAX __mb_cur_max +extern int ___mb_cur_max(void); +#define MB_CUR_MAX (___mb_cur_max()) -__BEGIN_DECLS void abort(void) __dead2; int abs(int) __pure2; int atexit(void (*)(void)); Index: include/stdio.h =================================================================== --- include/stdio.h (revision 225653) +++ include/stdio.h (working copy) @@ -107,7 +107,7 @@ * inline functions. To preserve ABI compat, these members must not * be disturbed. These members are marked below with (*). */ -typedef struct __sFILE { +struct __sFILE { unsigned char *_p; /* (*) current position in (some) buffer */ int _r; /* (*) read space left for getc() */ int _w; /* (*) write space left for putc() */ @@ -144,8 +144,11 @@ int _fl_count; /* recursive lock count */ int _orientation; /* orientation for fwide() */ __mbstate_t _mbstate; /* multibyte conversion state */ -} FILE; - +}; +#ifndef _STDFILE_DECLARED +#define _STDFILE_DECLARED +typedef struct __sFILE FILE; +#endif #ifndef _STDSTREAM_DECLARED __BEGIN_DECLS extern FILE *__stdinp; @@ -454,7 +457,6 @@ else return (__swbuf(_c, _p)); } -#else /* * This has been tuned to generate reasonable code on the vax using pcc. */ @@ -467,6 +469,7 @@ __swbuf((int)(c), p) : \ (*(p)->_p = (c), (int)*(p)->_p++)) #endif +#ifndef __cplusplus #define __sfeof(p) (((p)->_flags & __SEOF) != 0) #define __sferror(p) (((p)->_flags & __SERR) != 0) @@ -506,6 +509,7 @@ #define getchar_unlocked() getc_unlocked(stdin) #define putchar_unlocked(x) putc_unlocked(x, stdout) #endif +#endif /* __cplusplus */ __END_DECLS #endif /* !_STDIO_H_ */ Index: include/wchar.h =================================================================== --- include/wchar.h (revision 225653) +++ include/wchar.h (working copy) @@ -97,7 +97,10 @@ #define WEOF ((wint_t)-1) #endif -struct __sFILE; +#ifndef _STDFILE_DECLARED +#define _STDFILE_DECLARED +typedef struct __sFILE FILE; +#endif struct tm; __BEGIN_DECLS Index: include/ctype.h =================================================================== --- include/ctype.h (revision 225653) +++ include/ctype.h (working copy) @@ -80,6 +80,7 @@ #endif __END_DECLS +#ifndef __cplusplus #define isalnum(c) __sbistype((c), _CTYPE_A|_CTYPE_D) #define isalpha(c) __sbistype((c), _CTYPE_A) #define iscntrl(c) __sbistype((c), _CTYPE_C) @@ -93,6 +94,7 @@ #define isxdigit(c) __isctype((c), _CTYPE_X) /* ANSI -- locale independent */ #define tolower(c) __sbtolower(c) #define toupper(c) __sbtoupper(c) +#endif /* !__cplusplus */ #if __XSI_VISIBLE /* @@ -112,7 +114,7 @@ #define toascii(c) ((c) & 0x7F) #endif -#if __ISO_C_VISIBLE >= 1999 +#if __ISO_C_VISIBLE >= 1999 && (!defined(__cplusplus)) #define isblank(c) __sbistype((c), _CTYPE_B) #endif Index: contrib/gdtoa/gdtoaimp.h =================================================================== --- contrib/gdtoa/gdtoaimp.h (revision 225653) +++ contrib/gdtoa/gdtoaimp.h (working copy) @@ -201,6 +201,7 @@ #include "namespace.h" #include #include "un-namespace.h" +#include "xlocale_private.h" #ifdef KR_headers #define Char char @@ -526,10 +527,13 @@ #define strtoIx __strtoIx #define strtoIxL __strtoIxL #define strtord __strtord +#define strtord_l __strtord_l #define strtordd __strtordd #define strtorf __strtorf #define strtorQ __strtorQ +#define strtorQ_l __strtorQ_l #define strtorx __strtorx +#define strtorx_l __strtorx_l #define strtorxL __strtorxL #define strtodI __strtodI #define strtopd __strtopd @@ -635,6 +639,7 @@ extern Bigint *set_ones ANSI((Bigint*, int)); extern char *strcp ANSI((char*, const char*)); extern int strtodg ANSI((CONST char*, char**, FPI*, Long*, ULong*)); + extern int strtodg_l ANSI((CONST char*, char**, FPI*, Long*, ULong*, locale_t)); extern int strtoId ANSI((CONST char *, char **, double *, double *)); extern int strtoIdd ANSI((CONST char *, char **, double *, double *)); @@ -644,6 +649,7 @@ extern int strtoIx ANSI((CONST char *, char **, void *, void *)); extern int strtoIxL ANSI((CONST char *, char **, void *, void *)); extern double strtod ANSI((const char *s00, char **se)); + extern double strtod_l ANSI((const char *s00, char **se, locale_t)); extern int strtopQ ANSI((CONST char *, char **, Void *)); extern int strtopf ANSI((CONST char *, char **, float *)); extern int strtopd ANSI((CONST char *, char **, double *)); @@ -651,10 +657,13 @@ extern int strtopx ANSI((CONST char *, char **, Void *)); extern int strtopxL ANSI((CONST char *, char **, Void *)); extern int strtord ANSI((CONST char *, char **, int, double *)); + extern int strtord_l ANSI((CONST char *, char **, int, double *, locale_t)); extern int strtordd ANSI((CONST char *, char **, int, double *)); extern int strtorf ANSI((CONST char *, char **, int, float *)); extern int strtorQ ANSI((CONST char *, char **, int, void *)); + extern int strtorQ_l ANSI((CONST char *, char **, int, void *, locale_t)); extern int strtorx ANSI((CONST char *, char **, int, void *)); + extern int strtorx_l ANSI((CONST char *, char **, int, void *, locale_t)); extern int strtorxL ANSI((CONST char *, char **, int, void *)); extern Bigint *sum ANSI((Bigint*, Bigint*)); extern int trailz ANSI((Bigint*)); Index: contrib/gdtoa/strtopQ.c =================================================================== --- contrib/gdtoa/strtopQ.c (revision 225653) +++ contrib/gdtoa/strtopQ.c (working copy) @@ -56,7 +56,7 @@ strtopQ(CONST char *s, char **sp, void *V) #endif { - static FPI fpi0 = { 113, 1-16383-113+1, 32766 - 16383 - 113 + 1, 1, SI }; + static const FPI fpi0 = { 113, 1-16383-113+1, 32766 - 16383 - 113 + 1, 1, SI }; ULong bits[4]; Long exp; int k; Index: contrib/gdtoa/strtorQ.c =================================================================== --- contrib/gdtoa/strtorQ.c (revision 225653) +++ contrib/gdtoa/strtorQ.c (working copy) @@ -103,9 +103,10 @@ int #ifdef KR_headers -strtorQ(s, sp, rounding, L) CONST char *s; char **sp; int rounding; void *L; +strtorQ_l(s, sp, rounding, L, locale) CONST char *s; char **sp; int rounding; +void *L; locale_t locale; #else -strtorQ(CONST char *s, char **sp, int rounding, void *L) +strtorQ_l(CONST char *s, char **sp, int rounding, void *L, locale_t locale) #endif { static FPI fpi0 = { 113, 1-16383-113+1, 32766-16383-113+1, 1, SI }; @@ -120,7 +121,17 @@ fpi1.rounding = rounding; fpi = &fpi1; } - k = strtodg(s, sp, fpi, &exp, bits); + k = strtodg_l(s, sp, fpi, &exp, bits, locale); ULtoQ((ULong*)L, bits, exp, k); return k; } + + int +#ifdef KR_headers +strtorQ(s, sp, rounding, L) CONST char *s; char **sp; int rounding; void *L; +#else +strtorQ(CONST char *s, char **sp, int rounding, void *L) +#endif +{ + return strtorQ_l(s, sp, rounding, L, __get_locale()); +} Index: contrib/gdtoa/strtodg.c =================================================================== --- contrib/gdtoa/strtodg.c (revision 225653) +++ contrib/gdtoa/strtodg.c (working copy) @@ -34,6 +34,7 @@ #ifdef USE_LOCALE #include "locale.h" #endif +#include "xlocale_private.h" static CONST int fivesbits[] = { 0, 3, 5, 7, 10, 12, 14, 17, 19, 21, @@ -313,12 +314,12 @@ } int -strtodg +strtodg_l #ifdef KR_headers - (s00, se, fpi, exp, bits) - CONST char *s00; char **se; FPI *fpi; Long *exp; ULong *bits; + (s00, se, fpi, exp, bits, l) + CONST char *s00; char **se; FPI *fpi; Long *exp; ULong *bits; locale_t l; #else - (CONST char *s00, char **se, FPI *fpi, Long *exp, ULong *bits) + (CONST char *s00, char **se, FPI *fpi, Long *exp, ULong *bits, locale_t l) #endif { int abe, abits, asub; @@ -334,14 +335,14 @@ Bigint *ab, *bb, *bb1, *bd, *bd0, *bs, *delta, *rvb, *rvb0; #ifdef USE_LOCALE /*{{*/ #ifdef NO_LOCALE_CACHE - char *decimalpoint = localeconv()->decimal_point; + char *decimalpoint = localeconv_l(l)->decimal_point; int dplen = strlen(decimalpoint); #else char *decimalpoint; static char *decimalpoint_cache; static int dplen; if (!(s0 = decimalpoint_cache)) { - s0 = localeconv()->decimal_point; + s0 = localeconv_l(l)->decimal_point; if ((decimalpoint_cache = (char*)MALLOC(strlen(s0) + 1))) { strcpy(decimalpoint_cache, s0); s0 = decimalpoint_cache; @@ -1063,3 +1064,15 @@ } return irv; } + + int +strtodg +#ifdef KR_headers + (s00, se, fpi, exp, bits) + CONST char *s00; char **se; FPI *fpi; Long *exp; ULong *bits; +#else + (CONST char *s00, char **se, FPI *fpi, Long *exp, ULong *bits) +#endif +{ + return strtodg_l(s00, se, fpi, exp, bits, __get_locale()); +} Index: contrib/gdtoa/strtord.c =================================================================== --- contrib/gdtoa/strtord.c (revision 225653) +++ contrib/gdtoa/strtord.c (working copy) @@ -70,9 +70,10 @@ int #ifdef KR_headers -strtord(s, sp, rounding, d) CONST char *s; char **sp; int rounding; double *d; +strtord_l(s, sp, rounding, d, locale) CONST char *s; char **sp; int rounding; +double *d; locale_t locale; #else -strtord(CONST char *s, char **sp, int rounding, double *d) +strtord_l(CONST char *s, char **sp, int rounding, double *d, locale_t locale) #endif { static FPI fpi0 = { 53, 1-1023-53+1, 2046-1023-53+1, 1, SI }; @@ -87,7 +88,17 @@ fpi1.rounding = rounding; fpi = &fpi1; } - k = strtodg(s, sp, fpi, &exp, bits); + k = strtodg_l(s, sp, fpi, &exp, bits, locale); ULtod((ULong*)d, bits, exp, k); return k; } + int +#ifdef KR_headers +strtord(s, sp, rounding, L, locale) CONST char *s; char **sp; int rounding; +void *L; +#else +strtord(CONST char *s, char **sp, int rounding, double *d) +#endif +{ + return strtord_l(s, sp, rounding, d, __get_locale()); +} Index: contrib/gdtoa/strtod.c =================================================================== --- contrib/gdtoa/strtod.c (revision 225653) +++ contrib/gdtoa/strtod.c (working copy) @@ -39,6 +39,7 @@ #ifdef USE_LOCALE #include "locale.h" #endif +#include "xlocale_private.h" #ifdef IEEE_Arith #ifndef NO_IEEE_Scale @@ -82,11 +83,11 @@ #endif /*}*/ double -strtod +strtod_l #ifdef KR_headers - (s00, se) CONST char *s00; char **se; + (s00, se, l) CONST char *s00; char **se; locale_t l #else - (CONST char *s00, char **se) + (CONST char *s00, char **se, locale_t l) #endif { #ifdef Avoid_Underflow @@ -108,14 +109,14 @@ #endif #ifdef USE_LOCALE /*{{*/ #ifdef NO_LOCALE_CACHE - char *decimalpoint = localeconv()->decimal_point; + char *decimalpoint = localeconv_l(l)->decimal_point; int dplen = strlen(decimalpoint); #else char *decimalpoint; static char *decimalpoint_cache; static int dplen; if (!(s0 = decimalpoint_cache)) { - s0 = localeconv()->decimal_point; + s0 = localeconv_l(l)->decimal_point; if ((decimalpoint_cache = (char*)MALLOC(strlen(s0) + 1))) { strcpy(decimalpoint_cache, s0); s0 = decimalpoint_cache; @@ -168,7 +169,7 @@ if (*s == '0') { #ifndef NO_HEX_FP /*{*/ { - static FPI fpi = { 53, 1-1023-53+1, 2046-1023-53+1, 1, SI }; + static const FPI fpi = { 53, 1-1023-53+1, 2046-1023-53+1, 1, SI }; Long exp; ULong bits[2]; switch(s[1]) { @@ -295,7 +296,7 @@ #ifdef INFNAN_CHECK /* Check for Nan and Infinity */ ULong bits[2]; - static FPI fpinan = /* only 52 explicit bits */ + static const FPI fpinan = /* only 52 explicit bits */ { 52, 1-1023-53+1, 2046-1023-53+1, 1, SI }; if (!decpt) switch(c) { @@ -1074,3 +1075,13 @@ return sign ? -dval(&rv) : dval(&rv); } + double +strtod +#ifdef KR_headers + (s00, se, l) CONST char *s00; char **se; locale_t +#else + (CONST char *s00, char **se) +#endif +{ + return strtod_l(s00, se, __get_locale()); +} Index: contrib/gdtoa/strtof.c =================================================================== --- contrib/gdtoa/strtof.c (revision 225653) +++ contrib/gdtoa/strtof.c (working copy) @@ -32,15 +32,16 @@ /* $FreeBSD$ */ #include "gdtoaimp.h" +#include "xlocale_private.h" float #ifdef KR_headers -strtof(s, sp) CONST char *s; char **sp; +strtof_l(s, sp, l) CONST char *s; char **sp; locale_t l; #else -strtof(CONST char *s, char **sp) +strtof_l(CONST char *s, char **sp, locale_t l) #endif { - static FPI fpi0 = { 24, 1-127-24+1, 254-127-24+1, 1, SI }; + static const FPI fpi0 = { 24, 1-127-24+1, 254-127-24+1, 1, SI }; ULong bits[1]; Long exp; int k; @@ -51,7 +52,7 @@ #define fpi &fpi0 #endif - k = strtodg(s, sp, fpi, &exp, bits); + k = strtodg_l(s, sp, fpi, &exp, bits, l); switch(k & STRTOG_Retmask) { case STRTOG_NoNumber: case STRTOG_Zero: @@ -82,3 +83,13 @@ u.L[0] |= 0x80000000L; return u.f; } + + float +#ifdef KR_headers +strtof(s, sp) CONST char *s; char **sp; +#else +strtof(CONST char *s, char **sp) +#endif +{ + return strtof_l(s, sp, __get_locale()); +} Index: contrib/gdtoa/strtorx.c =================================================================== --- contrib/gdtoa/strtorx.c (revision 225653) +++ contrib/gdtoa/strtorx.c (working copy) @@ -106,9 +106,10 @@ int #ifdef KR_headers -strtorx(s, sp, rounding, L) CONST char *s; char **sp; int rounding; void *L; +strtorx_l(s, sp, rounding, L, locale) CONST char *s; char **sp; int rounding; +void *L; locale_t locale; #else -strtorx(CONST char *s, char **sp, int rounding, void *L) +strtorx_l(CONST char *s, char **sp, int rounding, void *L, locale_t locale) #endif { static FPI fpi0 = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, SI }; @@ -123,7 +124,16 @@ fpi1.rounding = rounding; fpi = &fpi1; } - k = strtodg(s, sp, fpi, &exp, bits); + k = strtodg_l(s, sp, fpi, &exp, bits, locale); ULtox((UShort*)L, bits, exp, k); return k; } + int +#ifdef KR_headers +strtorx(s, sp, rounding, L) CONST char *s; char **sp; int rounding; void *L; +#else +strtorx(CONST char *s, char **sp, int rounding, void *L) +#endif +{ + return strtorx_l(s, sp, rounding, L, __get_locale()); +} Index: share/monetdef/zh_CN.UTF-8.src =================================================================== --- share/monetdef/zh_CN.UTF-8.src (revision 225653) +++ share/monetdef/zh_CN.UTF-8.src (working copy) @@ -18,9 +18,9 @@ # negative_sign - # int_frac_digits -0 +2 # frac_digits -0 +2 # p_cs_precedes 1 # p_sep_by_space Index: lib/msun/Symbol.map =================================================================== --- lib/msun/Symbol.map (revision 225653) +++ lib/msun/Symbol.map (working copy) @@ -227,4 +227,21 @@ cexpf; log2; log2f; + coshl; + asinhl; + atanhl; + acoshl; + erfcl; + erfl; + expl; + expm1l; + lgammal; + log10l; + log1pl; + log2l; + logl; + tanhl; + sinhl; + tgammal; + powl; }; Index: lib/msun/src/math.h =================================================================== --- lib/msun/src/math.h (revision 225653) +++ lib/msun/src/math.h (working copy) @@ -230,8 +230,13 @@ double fma(double, double, double); double hypot(double, double); int ilogb(double) __pure2; +#ifdef __cplusplus +bool (isinf)(double) __pure2; +bool (isnan)(double) __pure2; +#else int (isinf)(double) __pure2; int (isnan)(double) __pure2; +#endif double lgamma(double); long long llrint(double); long long llround(double); @@ -398,32 +403,32 @@ * long double versions of ISO/POSIX math functions */ #if __ISO_C_VISIBLE >= 1999 -#if 0 +#if !__NO_IMPRECISE_LIBM_FUNCTIONS long double acoshl(long double); #endif long double acosl(long double); -#if 0 +#if !__NO_IMPRECISE_LIBM_FUNCTIONS long double asinhl(long double); #endif long double asinl(long double); long double atan2l(long double, long double); -#if 0 +#if !__NO_IMPRECISE_LIBM_FUNCTIONS long double atanhl(long double); #endif long double atanl(long double); long double cbrtl(long double); long double ceill(long double); long double copysignl(long double, long double) __pure2; -#if 0 +#if !__NO_IMPRECISE_LIBM_FUNCTIONS long double coshl(long double); #endif long double cosl(long double); -#if 0 +#if !__NO_IMPRECISE_LIBM_FUNCTIONS long double erfcl(long double); long double erfl(long double); #endif long double exp2l(long double); -#if 0 +#if !__NO_IMPRECISE_LIBM_FUNCTIONS long double expl(long double); long double expm1l(long double); #endif @@ -438,18 +443,18 @@ long double hypotl(long double, long double); int ilogbl(long double) __pure2; long double ldexpl(long double, int); -#if 0 +#if !__NO_IMPRECISE_LIBM_FUNCTIONS long double lgammal(long double); #endif long long llrintl(long double); long long llroundl(long double); -#if 0 +#if !__NO_IMPRECISE_LIBM_FUNCTIONS long double log10l(long double); long double log1pl(long double); long double log2l(long double); #endif long double logbl(long double); -#if 0 +#if !__NO_IMPRECISE_LIBM_FUNCTIONS long double logl(long double); #endif long lrintl(long double); @@ -461,7 +466,7 @@ double nexttoward(double, long double); float nexttowardf(float, long double); long double nexttowardl(long double, long double); -#if 0 +#if !__NO_IMPRECISE_LIBM_FUNCTIONS long double powl(long double, long double); #endif long double remainderl(long double, long double); @@ -470,16 +475,16 @@ long double roundl(long double); long double scalblnl(long double, long); long double scalbnl(long double, int); -#if 0 +#if !__NO_IMPRECISE_LIBM_FUNCTIONS long double sinhl(long double); #endif long double sinl(long double); long double sqrtl(long double); -#if 0 +#if !__NO_IMPRECISE_LIBM_FUNCTIONS long double tanhl(long double); #endif long double tanl(long double); -#if 0 +#if !__NO_IMPRECISE_LIBM_FUNCTIONS long double tgammal(long double); #endif long double truncl(long double); Index: lib/msun/src/stubs.c =================================================================== --- lib/msun/src/stubs.c (revision 0) +++ lib/msun/src/stubs.c (revision 0) @@ -0,0 +1,22 @@ +#include + +#define LIBCXX_LONG_DOUBLE_STUB(fn) __attribute__((weak)) long double fn ## l(long double x) { return fn(x); } +#define LIBCXX_LONG_DOUBLE_STUB2(fn) __attribute__((weak)) long double fn ## l(long double x, long double y) { return fn(x, y); } + +LIBCXX_LONG_DOUBLE_STUB(cosh) +LIBCXX_LONG_DOUBLE_STUB(asinh) +LIBCXX_LONG_DOUBLE_STUB(atanh) +LIBCXX_LONG_DOUBLE_STUB(acosh) +LIBCXX_LONG_DOUBLE_STUB(erfc) +LIBCXX_LONG_DOUBLE_STUB(erf) +LIBCXX_LONG_DOUBLE_STUB(exp) +LIBCXX_LONG_DOUBLE_STUB(expm1) +LIBCXX_LONG_DOUBLE_STUB(lgamma) +LIBCXX_LONG_DOUBLE_STUB(log10) +LIBCXX_LONG_DOUBLE_STUB(log1p) +LIBCXX_LONG_DOUBLE_STUB(log2) +LIBCXX_LONG_DOUBLE_STUB(log) +LIBCXX_LONG_DOUBLE_STUB(tanh) +LIBCXX_LONG_DOUBLE_STUB(sinh) +LIBCXX_LONG_DOUBLE_STUB(tgamma) +LIBCXX_LONG_DOUBLE_STUB2(pow) Index: lib/msun/Makefile =================================================================== --- lib/msun/Makefile (revision 225653) +++ lib/msun/Makefile (working copy) @@ -70,7 +70,7 @@ s_scalbln.c s_scalbn.c s_scalbnf.c s_signbit.c \ s_signgam.c s_significand.c s_significandf.c s_sin.c s_sinf.c \ s_tan.c s_tanf.c s_tanh.c s_tanhf.c s_tgammaf.c s_trunc.c s_truncf.c \ - w_cabs.c w_cabsf.c w_drem.c w_dremf.c + w_cabs.c w_cabsf.c w_drem.c w_dremf.c stubs.c # Location of fpmath.h and _fpmath.h LIBCDIR= ${.CURDIR}/../libc Index: lib/libc/stdlib/Symbol.map =================================================================== --- lib/libc/stdlib/Symbol.map (revision 225653) +++ lib/libc/stdlib/Symbol.map (working copy) @@ -90,6 +90,21 @@ tfind; tsearch; twalk; + atof_l; + atoi_l; + atol_l; + atoll_l; + strtod_l; + strtol_l; + strtoll_l; + strtof_l; + strtoimax_l; + strtold_l; + strtoq_l; + strtoul_l; + strtoull_l; + strtoumax_l; + strtouq_l; }; FBSDprivate_1.0 { Index: lib/libc/stdlib/atoll.c =================================================================== --- lib/libc/stdlib/atoll.c (revision 225653) +++ lib/libc/stdlib/atoll.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -31,6 +36,7 @@ __FBSDID("$FreeBSD$"); #include +#include long long atoll(str) @@ -38,3 +44,11 @@ { return strtoll(str, (char **)NULL, 10); } + +long long +atoll_l(str, locale) + const char *str; + locale_t locale; +{ + return strtoll_l(str, (char **)NULL, 10, locale); +} Index: lib/libc/stdlib/strfmon.c =================================================================== --- lib/libc/stdlib/strfmon.c (revision 225653) +++ lib/libc/stdlib/strfmon.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2001 Alexey Zelkin * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -38,6 +43,7 @@ #include #include #include +#include "xlocale_private.h" /* internal flags */ #define NEED_GROUPING 0x01 /* print digits grouped (default) */ @@ -92,11 +98,10 @@ static int __calc_left_pad(int, char *); static char *__format_grouped_double(double, int *, int, int, int); -ssize_t -strfmon(char * __restrict s, size_t maxsize, const char * __restrict format, - ...) +static ssize_t +vstrfmon_l(char * __restrict s, size_t maxsize, locale_t loc, + const char * __restrict format, va_list ap) { - va_list ap; char *dst; /* output destination pointer */ const char *fmt; /* current format poistion pointer */ struct lconv *lc; /* pointer to lconv structure */ @@ -119,10 +124,10 @@ char *tmpptr; /* temporary vars */ int sverrno; + FIX_LOCALE(loc); - va_start(ap, format); - lc = localeconv(); + lc = localeconv_l(loc); dst = s; fmt = format; asciivalue = NULL; @@ -380,7 +385,6 @@ } PRINT('\0'); - va_end(ap); free(asciivalue); free(currency_symbol); return (dst - s - 1); /* return size of put data except trailing '\0' */ @@ -399,10 +403,34 @@ if (currency_symbol != NULL) free(currency_symbol); errno = sverrno; - va_end(ap); return (-1); } +ssize_t +strfmon_l(char * __restrict s, size_t maxsize, locale_t loc, const char * __restrict format, + ...) +{ + size_t ret; + va_list ap; + FIX_LOCALE(loc); + va_start(ap, format); + ret = vstrfmon_l(s, maxsize, loc, format, ap); + va_end(ap); + return ret; +} +ssize_t +strfmon(char * __restrict s, size_t maxsize, const char * __restrict format, + ...) +{ + size_t ret; + va_list ap; + va_start(ap, format); + ret = vstrfmon_l(s, maxsize, __get_locale(), format, ap); + va_end(ap); + return ret; +} + + static void __setup_vars(int flags, char *cs_precedes, char *sep_by_space, char *sign_posn, char **signstr) { Index: lib/libc/stdlib/atof.c =================================================================== --- lib/libc/stdlib/atof.c (revision 225653) +++ lib/libc/stdlib/atof.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -34,6 +39,7 @@ __FBSDID("$FreeBSD$"); #include +#include double atof(ascii) @@ -41,3 +47,11 @@ { return strtod(ascii, (char **)NULL); } + +double +atof_l(ascii, locale) + const char *ascii; + locale_t locale; +{ + return strtod_l(ascii, (char **)NULL, locale); +} Index: lib/libc/stdlib/strtoimax.c =================================================================== --- lib/libc/stdlib/strtoimax.c (revision 225653) +++ lib/libc/stdlib/strtoimax.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -37,6 +42,7 @@ #include #include #include +#include "xlocale_private.h" /* * Convert a string to an intmax_t integer. @@ -45,13 +51,15 @@ * alphabets and digits are each contiguous. */ intmax_t -strtoimax(const char * __restrict nptr, char ** __restrict endptr, int base) +strtoimax_l(const char * __restrict nptr, char ** __restrict endptr, int base, + locale_t locale) { const char *s; uintmax_t acc; char c; uintmax_t cutoff; int neg, any, cutlim; + FIX_LOCALE(locale); /* * Skip white space and pick up leading +/- sign if any. @@ -61,7 +69,7 @@ s = nptr; do { c = *s++; - } while (isspace((unsigned char)c)); + } while (isspace_l((unsigned char)c, locale)); if (c == '-') { neg = 1; c = *s++; @@ -138,3 +146,8 @@ *endptr = (char *)(any ? s - 1 : nptr); return (acc); } +intmax_t +strtoimax(const char * __restrict nptr, char ** __restrict endptr, int base) +{ + return strtoimax_l(nptr, endptr, base, __get_locale()); +} Index: lib/libc/stdlib/atol.c =================================================================== --- lib/libc/stdlib/atol.c (revision 225653) +++ lib/libc/stdlib/atol.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -34,6 +39,7 @@ __FBSDID("$FreeBSD$"); #include +#include long atol(str) @@ -41,3 +47,11 @@ { return strtol(str, (char **)NULL, 10); } + +long +atol_l(str, locale) + const char *str; + locale_t locale; +{ + return strtol_l(str, (char **)NULL, 10, locale); +} Index: lib/libc/stdlib/strtoumax.c =================================================================== --- lib/libc/stdlib/strtoumax.c (revision 225653) +++ lib/libc/stdlib/strtoumax.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -37,6 +42,7 @@ #include #include #include +#include "xlocale_private.h" /* * Convert a string to a uintmax_t integer. @@ -45,13 +51,15 @@ * alphabets and digits are each contiguous. */ uintmax_t -strtoumax(const char * __restrict nptr, char ** __restrict endptr, int base) +strtoumax_l(const char * __restrict nptr, char ** __restrict endptr, int base, + locale_t locale) { const char *s; uintmax_t acc; char c; uintmax_t cutoff; int neg, any, cutlim; + FIX_LOCALE(locale); /* * See strtoimax for comments as to the logic used. @@ -59,7 +67,7 @@ s = nptr; do { c = *s++; - } while (isspace((unsigned char)c)); + } while (isspace_l((unsigned char)c, locale)); if (c == '-') { neg = 1; c = *s++; @@ -116,3 +124,8 @@ *endptr = (char *)(any ? s - 1 : nptr); return (acc); } +uintmax_t +strtoumax(const char * __restrict nptr, char ** __restrict endptr, int base) +{ + return strtoumax_l(nptr, endptr, base, __get_locale()); +} Index: lib/libc/stdlib/strtoul.c =================================================================== --- lib/libc/stdlib/strtoul.c (revision 225653) +++ lib/libc/stdlib/strtoul.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -37,6 +42,7 @@ #include #include #include +#include "xlocale_private.h" /* * Convert a string to an unsigned long integer. @@ -45,13 +51,14 @@ * alphabets and digits are each contiguous. */ unsigned long -strtoul(const char * __restrict nptr, char ** __restrict endptr, int base) +strtoul_l(const char * __restrict nptr, char ** __restrict endptr, int base, locale_t locale) { const char *s; unsigned long acc; char c; unsigned long cutoff; int neg, any, cutlim; + FIX_LOCALE(locale); /* * See strtol for comments as to the logic used. @@ -59,7 +66,7 @@ s = nptr; do { c = *s++; - } while (isspace((unsigned char)c)); + } while (isspace_l((unsigned char)c, locale)); if (c == '-') { neg = 1; c = *s++; @@ -116,3 +123,8 @@ *endptr = (char *)(any ? s - 1 : nptr); return (acc); } +unsigned long +strtoul(const char * __restrict nptr, char ** __restrict endptr, int base) +{ + return strtoul_l(nptr, endptr, base, __get_locale()); +} Index: lib/libc/stdlib/strtoull.c =================================================================== --- lib/libc/stdlib/strtoull.c (revision 225653) +++ lib/libc/stdlib/strtoull.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -37,6 +42,7 @@ #include #include #include +#include "xlocale_private.h" /* * Convert a string to an unsigned long long integer. @@ -45,13 +51,15 @@ * alphabets and digits are each contiguous. */ unsigned long long -strtoull(const char * __restrict nptr, char ** __restrict endptr, int base) +strtoull_l(const char * __restrict nptr, char ** __restrict endptr, int base, + locale_t locale) { const char *s; unsigned long long acc; char c; unsigned long long cutoff; int neg, any, cutlim; + FIX_LOCALE(locale); /* * See strtoq for comments as to the logic used. @@ -59,7 +67,7 @@ s = nptr; do { c = *s++; - } while (isspace((unsigned char)c)); + } while (isspace_l((unsigned char)c, locale)); if (c == '-') { neg = 1; c = *s++; @@ -116,3 +124,8 @@ *endptr = (char *)(any ? s - 1 : nptr); return (acc); } +unsigned long long +strtoull(const char * __restrict nptr, char ** __restrict endptr, int base) +{ + return strtoull_l(nptr, endptr, base, __get_locale()); +} Index: lib/libc/stdlib/strtoll.c =================================================================== --- lib/libc/stdlib/strtoll.c (revision 225653) +++ lib/libc/stdlib/strtoll.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -37,6 +42,7 @@ #include #include #include +#include /* * Convert a string to a long long integer. @@ -45,13 +51,15 @@ * alphabets and digits are each contiguous. */ long long -strtoll(const char * __restrict nptr, char ** __restrict endptr, int base) +strtoll_l(const char * __restrict nptr, char ** __restrict endptr, int base, + locale_t locale) { const char *s; unsigned long long acc; char c; unsigned long long cutoff; int neg, any, cutlim; + FIX_LOCALE(locale); /* * Skip white space and pick up leading +/- sign if any. @@ -61,7 +69,7 @@ s = nptr; do { c = *s++; - } while (isspace((unsigned char)c)); + } while (isspace_l((unsigned char)c, locale)); if (c == '-') { neg = 1; c = *s++; @@ -138,3 +146,8 @@ *endptr = (char *)(any ? s - 1 : nptr); return (acc); } +long long +strtoll(const char * __restrict nptr, char ** __restrict endptr, int base) +{ + return strtoll_l(nptr, endptr, base, __get_locale()); +} Index: lib/libc/stdlib/strtol.c =================================================================== --- lib/libc/stdlib/strtol.c (revision 225653) +++ lib/libc/stdlib/strtol.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -37,6 +42,7 @@ #include #include #include +#include "xlocale_private.h" /* @@ -46,13 +52,15 @@ * alphabets and digits are each contiguous. */ long -strtol(const char * __restrict nptr, char ** __restrict endptr, int base) +strtol_l(const char * __restrict nptr, char ** __restrict endptr, int base, + locale_t locale) { const char *s; unsigned long acc; char c; unsigned long cutoff; int neg, any, cutlim; + FIX_LOCALE(locale); /* * Skip white space and pick up leading +/- sign if any. @@ -62,7 +70,7 @@ s = nptr; do { c = *s++; - } while (isspace((unsigned char)c)); + } while (isspace_l((unsigned char)c, locale)); if (c == '-') { neg = 1; c = *s++; @@ -138,3 +146,13 @@ *endptr = (char *)(any ? s - 1 : nptr); return (acc); } +long +strtol(const char * __restrict nptr, char ** __restrict endptr, int base) +{ + return strtol_l(nptr, endptr, base, __get_locale()); +} +long double +strtold(const char * __restrict nptr, char ** __restrict endptr) +{ + return strtold_l(nptr, endptr, __get_locale()); +} Index: lib/libc/stdlib/atoi.c =================================================================== --- lib/libc/stdlib/atoi.c (revision 225653) +++ lib/libc/stdlib/atoi.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -34,6 +39,7 @@ __FBSDID("$FreeBSD$"); #include +#include int atoi(str) @@ -41,3 +47,11 @@ { return (int)strtol(str, (char **)NULL, 10); } + +int +atoi_l(str, locale) + const char *str; + locale_t locale; +{ + return (int)strtol_l(str, (char **)NULL, 10, locale); +} Index: lib/libc/stdio/putwc.c =================================================================== --- lib/libc/stdio/putwc.c (revision 225653) +++ lib/libc/stdio/putwc.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -33,6 +38,7 @@ #include "un-namespace.h" #include "libc_private.h" #include "local.h" +#include "xlocale_private.h" #undef putwc @@ -41,8 +47,13 @@ * macro, may evaluate `fp' more than once. */ wint_t +putwc_l(wchar_t wc, FILE *fp, locale_t locale) +{ + FIX_LOCALE(locale); + return (fputwc_l(wc, fp, locale)); +} +wint_t putwc(wchar_t wc, FILE *fp) { - - return (fputwc(wc, fp)); + return putwc_l(wc, fp, __get_locale()); } Index: lib/libc/stdio/printf.c =================================================================== --- lib/libc/stdio/printf.c (revision 225653) +++ lib/libc/stdio/printf.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Chris Torek. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -38,6 +43,7 @@ #include #include +#include int printf(char const * __restrict fmt, ...) @@ -50,3 +56,14 @@ va_end(ap); return (ret); } +int +printf_l(locale_t locale, char const * __restrict fmt, ...) +{ + int ret; + va_list ap; + + va_start(ap, fmt); + ret = vfprintf_l(stdout, locale, fmt, ap); + va_end(ap); + return (ret); +} Index: lib/libc/stdio/getwchar.c =================================================================== --- lib/libc/stdio/getwchar.c (revision 225653) +++ lib/libc/stdio/getwchar.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -30,6 +35,7 @@ #include "namespace.h" #include #include +#include #include "un-namespace.h" #include "libc_private.h" #include "local.h" @@ -42,6 +48,10 @@ wint_t getwchar(void) { - return (fgetwc(stdin)); } +wint_t +getwchar_l(locale_t locale) +{ + return (fgetwc_l(stdin, locale)); +} Index: lib/libc/stdio/Symbol.map =================================================================== --- lib/libc/stdio/Symbol.map (revision 225653) +++ lib/libc/stdio/Symbol.map (working copy) @@ -108,6 +108,43 @@ __swbuf; wprintf; wscanf; + asprintf_l; + fprintf_l; + fwprintf_l; + printf_l; + snprintf_l; + sprintf_l; + swprintf_l; + vasprintf_l; + vfprintf_l; + vfwprintf_l; + vprintf_l; + vsnprintf_l; + vsprintf_l; + vswprintf_l; + vwprintf_l; + wprintf_l; + fgetwc_l; + fputwc_l; + ungetwc_l; + vfwscanf_l; + vswscanf_l; + fscanf_l; + fwscanf_l; + scanf_l; + sscanf_l; + swscanf_l; + vfscanf_l; + vscanf_l; + vsscanf_l; + vwscanf_l; + wscanf_l; + fgetws_l; + fputws_l; + getwc_l; + getwchar_l; + putwc_l; + putwchar_l; }; FBSD_1.1 { Index: lib/libc/stdio/fgetwln.c =================================================================== --- lib/libc/stdio/fgetwln.c (revision 225653) +++ lib/libc/stdio/fgetwln.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002-2004 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -33,18 +38,20 @@ #include "un-namespace.h" #include "libc_private.h" #include "local.h" +#include "xlocale_private.h" wchar_t * -fgetwln(FILE * __restrict fp, size_t *lenp) +fgetwln_l(FILE * __restrict fp, size_t *lenp, locale_t locale) { wint_t wc; size_t len; + FIX_LOCALE(locale); FLOCKFILE(fp); ORIENT(fp, 1); len = 0; - while ((wc = __fgetwc(fp)) != WEOF) { + while ((wc = __fgetwc(fp, locale)) != WEOF) { #define GROW 512 if (len * sizeof(wchar_t) >= fp->_lb._size && __slbexpand(fp, (len + GROW) * sizeof(wchar_t))) @@ -65,3 +72,8 @@ *lenp = 0; return (NULL); } +wchar_t * +fgetwln(FILE * __restrict fp, size_t *lenp) +{ + return fgetwln_l(fp, lenp, __get_locale()); +} Index: lib/libc/stdio/getwc.c =================================================================== --- lib/libc/stdio/getwc.c (revision 225653) +++ lib/libc/stdio/getwc.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -30,6 +35,7 @@ #include "namespace.h" #include #include +#include #include "un-namespace.h" #include "libc_private.h" #include "local.h" @@ -43,6 +49,10 @@ wint_t getwc(FILE *fp) { - return (fgetwc(fp)); } +wint_t +getwc_l(FILE *fp, locale_t locale) +{ + return (fgetwc_l(fp, locale)); +} Index: lib/libc/stdio/vsnprintf.c =================================================================== --- lib/libc/stdio/vsnprintf.c (revision 225653) +++ lib/libc/stdio/vsnprintf.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Chris Torek. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -39,15 +44,17 @@ #include #include #include "local.h" +#include "xlocale_private.h" int -vsnprintf(char * __restrict str, size_t n, const char * __restrict fmt, - __va_list ap) +vsnprintf_l(char * __restrict str, size_t n, locale_t locale, + const char * __restrict fmt, __va_list ap) { size_t on; int ret; char dummy[2]; FILE f = FAKE_FILE; + FIX_LOCALE(locale); on = n; if (n != 0) @@ -64,8 +71,14 @@ f._flags = __SWR | __SSTR; f._bf._base = f._p = (unsigned char *)str; f._bf._size = f._w = n; - ret = __vfprintf(&f, fmt, ap); + ret = __vfprintf(&f, locale, fmt, ap); if (on > 0) *f._p = '\0'; return (ret); } +int +vsnprintf(char * __restrict str, size_t n, const char * __restrict fmt, + __va_list ap) +{ + return vsnprintf_l(str, n, __get_locale(), fmt, ap); +} Index: lib/libc/stdio/putwchar.c =================================================================== --- lib/libc/stdio/putwchar.c (revision 225653) +++ lib/libc/stdio/putwchar.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -33,6 +38,7 @@ #include "un-namespace.h" #include "libc_private.h" #include "local.h" +#include "xlocale_private.h" #undef putwchar @@ -40,8 +46,13 @@ * Synonym for fputwc(wc, stdout). */ wint_t +putwchar_l(wchar_t wc, locale_t locale) +{ + FIX_LOCALE(locale); + return (fputwc_l(wc, stdout, locale)); +} +wint_t putwchar(wchar_t wc) { - - return (fputwc(wc, stdout)); + return putwchar_l(wc, __get_locale()); } Index: lib/libc/stdio/vswprintf.c =================================================================== --- lib/libc/stdio/vswprintf.c (revision 225653) +++ lib/libc/stdio/vswprintf.c (working copy) @@ -4,6 +4,11 @@ * Copyright (c) 1997 Todd C. Miller * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -38,10 +43,11 @@ #include #include #include "local.h" +#include "xlocale_private.h" int -vswprintf(wchar_t * __restrict s, size_t n, const wchar_t * __restrict fmt, - __va_list ap) +vswprintf_l(wchar_t * __restrict s, size_t n, locale_t locale, + const wchar_t * __restrict fmt, __va_list ap) { static const mbstate_t initial; mbstate_t mbs; @@ -49,6 +55,7 @@ char *mbp; int ret, sverrno; size_t nwc; + FIX_LOCALE(locale); if (n == 0) { errno = EINVAL; @@ -62,7 +69,7 @@ return (-1); } f._bf._size = f._w = 127; /* Leave room for the NUL */ - ret = __vfwprintf(&f, fmt, ap); + ret = __vfwprintf(&f, locale, fmt, ap); if (ret < 0) { sverrno = errno; free(f._bf._base); @@ -76,7 +83,7 @@ * fputwc() did in __vfwprintf(). */ mbs = initial; - nwc = mbsrtowcs(s, (const char **)&mbp, n, &mbs); + nwc = mbsrtowcs_l(s, (const char **)&mbp, n, &mbs, locale); free(f._bf._base); if (nwc == (size_t)-1) { errno = EILSEQ; @@ -90,3 +97,9 @@ return (ret); } +int +vswprintf(wchar_t * __restrict s, size_t n, const wchar_t * __restrict fmt, + __va_list ap) +{ + return vswprintf_l(s, n, __get_locale(), fmt, ap); +} Index: lib/libc/stdio/vsscanf.c =================================================================== --- lib/libc/stdio/vsscanf.c (revision 225653) +++ lib/libc/stdio/vsscanf.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * This code is derived from software contributed to Berkeley by * Donn Seeley at UUNET Technologies, Inc. * @@ -39,6 +44,7 @@ #include #include #include "local.h" +#include "xlocale_private.h" static int eofread(void *, char *, int); @@ -52,14 +58,21 @@ } int -vsscanf(const char * __restrict str, const char * __restrict fmt, - __va_list ap) +vsscanf_l(const char * __restrict str, locale_t locale, + const char * __restrict fmt, __va_list ap) { FILE f = FAKE_FILE; + FIX_LOCALE(locale); f._flags = __SRD; f._bf._base = f._p = (unsigned char *)str; f._bf._size = f._r = strlen(str); f._read = eofread; - return (__svfscanf(&f, fmt, ap)); + return (__svfscanf(&f, locale, fmt, ap)); } +int +vsscanf(const char * __restrict str, const char * __restrict fmt, + __va_list ap) +{ + return vsscanf_l(str, __get_locale(), fmt, ap); +} Index: lib/libc/stdio/snprintf.c =================================================================== --- lib/libc/stdio/snprintf.c (revision 225653) +++ lib/libc/stdio/snprintf.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * This code is derived from software contributed to Berkeley by * Chris Torek. * @@ -39,6 +44,7 @@ #include #include #include +#include "xlocale_private.h" #include "local.h" @@ -59,9 +65,34 @@ f._flags = __SWR | __SSTR; f._bf._base = f._p = (unsigned char *)str; f._bf._size = f._w = n; - ret = __vfprintf(&f, fmt, ap); + ret = __vfprintf(&f, __get_locale(), fmt, ap); if (on > 0) *f._p = '\0'; va_end(ap); return (ret); } +int +snprintf_l(char * __restrict str, size_t n, locale_t locale, + char const * __restrict fmt, ...) +{ + size_t on; + int ret; + va_list ap; + FILE f = FAKE_FILE; + FIX_LOCALE(locale); + + on = n; + if (n != 0) + n--; + if (n > INT_MAX) + n = INT_MAX; + va_start(ap, fmt); + f._flags = __SWR | __SSTR; + f._bf._base = f._p = (unsigned char *)str; + f._bf._size = f._w = n; + ret = __vfprintf(&f, locale, fmt, ap); + if (on > 0) + *f._p = '\0'; + va_end(ap); + return (ret); +} Index: lib/libc/stdio/ungetwc.c =================================================================== --- lib/libc/stdio/ungetwc.c (revision 225653) +++ lib/libc/stdio/ungetwc.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002-2004 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -37,19 +42,21 @@ #include "libc_private.h" #include "local.h" #include "mblocal.h" +#include "xlocale_private.h" /* * Non-MT-safe version. */ wint_t -__ungetwc(wint_t wc, FILE *fp) +__ungetwc(wint_t wc, FILE *fp, locale_t locale) { char buf[MB_LEN_MAX]; size_t len; + struct xlocale_ctype *l = XLOCALE_CTYPE(locale); if (wc == WEOF) return (WEOF); - if ((len = __wcrtomb(buf, wc, &fp->_mbstate)) == (size_t)-1) { + if ((len = l->__wcrtomb(buf, wc, &fp->_mbstate)) == (size_t)-1) { fp->_flags |= __SERR; return (WEOF); } @@ -64,14 +71,20 @@ * MT-safe version. */ wint_t -ungetwc(wint_t wc, FILE *fp) +ungetwc_l(wint_t wc, FILE *fp, locale_t locale) { wint_t r; + FIX_LOCALE(locale); FLOCKFILE(fp); ORIENT(fp, 1); - r = __ungetwc(wc, fp); + r = __ungetwc(wc, fp, locale); FUNLOCKFILE(fp); return (r); } +wint_t +ungetwc(wint_t wc, FILE *fp) +{ + return ungetwc_l(wc, fp, __get_locale()); +} Index: lib/libc/stdio/swprintf.c =================================================================== --- lib/libc/stdio/swprintf.c (revision 225653) +++ lib/libc/stdio/swprintf.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002 Tim J. Robbins * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -30,6 +35,7 @@ #include #include #include +#include int swprintf(wchar_t * __restrict s, size_t n, const wchar_t * __restrict fmt, ...) @@ -43,3 +49,16 @@ return (ret); } +int +swprintf_l(wchar_t * __restrict s, size_t n, locale_t locale, + const wchar_t * __restrict fmt, ...) +{ + int ret; + va_list ap; + + va_start(ap, fmt); + ret = vswprintf_l(s, n, locale, fmt, ap); + va_end(ap); + + return (ret); +} Index: lib/libc/stdio/wscanf.c =================================================================== --- lib/libc/stdio/wscanf.c (revision 225653) +++ lib/libc/stdio/wscanf.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002 Tim J. Robbins * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -30,6 +35,7 @@ #include #include #include +#include int wscanf(const wchar_t * __restrict fmt, ...) @@ -43,3 +49,15 @@ return (r); } +int +wscanf_l(locale_t locale, const wchar_t * __restrict fmt, ...) +{ + va_list ap; + int r; + + va_start(ap, fmt); + r = vfwscanf_l(stdin, locale, fmt, ap); + va_end(ap); + + return (r); +} Index: lib/libc/stdio/fscanf.c =================================================================== --- lib/libc/stdio/fscanf.c (revision 225653) +++ lib/libc/stdio/fscanf.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Chris Torek. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -42,6 +47,7 @@ #include "un-namespace.h" #include "libc_private.h" #include "local.h" +#include "xlocale_private.h" int fscanf(FILE * __restrict fp, char const * __restrict fmt, ...) @@ -51,8 +57,22 @@ va_start(ap, fmt); FLOCKFILE(fp); - ret = __svfscanf(fp, fmt, ap); + ret = __svfscanf(fp, __get_locale(), fmt, ap); va_end(ap); FUNLOCKFILE(fp); return (ret); } +int +fscanf_l(FILE * __restrict fp, locale_t locale, char const * __restrict fmt, ...) +{ + int ret; + va_list ap; + FIX_LOCALE(locale); + + va_start(ap, fmt); + FLOCKFILE(fp); + ret = __svfscanf(fp, locale, fmt, ap); + va_end(ap); + FUNLOCKFILE(fp); + return (ret); +} Index: lib/libc/stdio/fprintf.c =================================================================== --- lib/libc/stdio/fprintf.c (revision 225653) +++ lib/libc/stdio/fprintf.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Chris Torek. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -38,6 +43,7 @@ #include #include +#include "xlocale_private.h" int fprintf(FILE * __restrict fp, const char * __restrict fmt, ...) @@ -46,7 +52,19 @@ va_list ap; va_start(ap, fmt); - ret = vfprintf(fp, fmt, ap); + ret = vfprintf_l(fp, __get_locale(), fmt, ap); va_end(ap); return (ret); } +int +fprintf_l(FILE * __restrict fp, locale_t locale, const char * __restrict fmt, ...) +{ + int ret; + va_list ap; + FIX_LOCALE(locale); + + va_start(ap, fmt); + ret = vfprintf_l(fp, locale, fmt, ap); + va_end(ap); + return (ret); +} Index: lib/libc/stdio/vscanf.c =================================================================== --- lib/libc/stdio/vscanf.c (revision 225653) +++ lib/libc/stdio/vscanf.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Donn Seeley at UUNET Technologies, Inc. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -41,16 +46,26 @@ #include "un-namespace.h" #include "libc_private.h" #include "local.h" +#include "xlocale_private.h" int -vscanf(fmt, ap) +vscanf_l(locale, fmt, ap) + locale_t locale; const char * __restrict fmt; __va_list ap; { int retval; + FIX_LOCALE(locale); FLOCKFILE(stdin); - retval = __svfscanf(stdin, fmt, ap); + retval = __svfscanf(stdin, locale, fmt, ap); FUNLOCKFILE(stdin); return (retval); } +int +vscanf(fmt, ap) + const char * __restrict fmt; + __va_list ap; +{ + return vscanf_l(__get_locale(), fmt, ap); +} Index: lib/libc/stdio/printfcommon.h =================================================================== --- lib/libc/stdio/printfcommon.h (revision 225653) +++ lib/libc/stdio/printfcommon.h (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Chris Torek. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -79,14 +84,14 @@ * remain valid until io_flush() is called. */ static inline int -io_print(struct io_state *iop, const CHAR * __restrict ptr, int len) +io_print(struct io_state *iop, const CHAR * __restrict ptr, int len, locale_t locale) { iop->iov[iop->uio.uio_iovcnt].iov_base = (char *)ptr; iop->iov[iop->uio.uio_iovcnt].iov_len = len; iop->uio.uio_resid += len; if (++iop->uio.uio_iovcnt >= NIOV) - return (__sprint(iop->fp, &iop->uio)); + return (__sprint(iop->fp, &iop->uio, locale)); else return (0); } @@ -107,13 +112,14 @@ * or the zeroes array. */ static inline int -io_pad(struct io_state *iop, int howmany, const CHAR * __restrict with) +io_pad(struct io_state *iop, int howmany, const CHAR * __restrict with, + locale_t locale) { int n; while (howmany > 0) { n = (howmany >= PADSIZE) ? PADSIZE : howmany; - if (io_print(iop, with, n)) + if (io_print(iop, with, n, locale)) return (-1); howmany -= n; } @@ -126,7 +132,7 @@ */ static inline int io_printandpad(struct io_state *iop, const CHAR *p, const CHAR *ep, - int len, const CHAR * __restrict with) + int len, const CHAR * __restrict with, locale_t locale) { int p_len; @@ -134,19 +140,19 @@ if (p_len > len) p_len = len; if (p_len > 0) { - if (io_print(iop, p, p_len)) + if (io_print(iop, p, p_len, locale)) return (-1); } else { p_len = 0; } - return (io_pad(iop, len - p_len, with)); + return (io_pad(iop, len - p_len, with, locale)); } static inline int -io_flush(struct io_state *iop) +io_flush(struct io_state *iop, locale_t locale) { - return (__sprint(iop->fp, &iop->uio)); + return (__sprint(iop->fp, &iop->uio, locale)); } /* Index: lib/libc/stdio/sprintf.c =================================================================== --- lib/libc/stdio/sprintf.c (revision 225653) +++ lib/libc/stdio/sprintf.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Chris Torek. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -40,6 +45,7 @@ #include #include #include "local.h" +#include "xlocale_private.h" int sprintf(char * __restrict str, char const * __restrict fmt, ...) @@ -52,3 +58,16 @@ va_end(ap); return (ret); } +int +sprintf_l(char * __restrict str, locale_t locale, char const * __restrict fmt, + ...) +{ + int ret; + va_list ap; + FIX_LOCALE(locale); + + va_start(ap, fmt); + ret = vsprintf_l(str, locale, fmt, ap); + va_end(ap); + return (ret); +} Index: lib/libc/stdio/vprintf.c =================================================================== --- lib/libc/stdio/vprintf.c (revision 225653) +++ lib/libc/stdio/vprintf.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Chris Torek. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -37,10 +42,15 @@ __FBSDID("$FreeBSD$"); #include +#include int vprintf(const char * __restrict fmt, __va_list ap) { - return (vfprintf(stdout, fmt, ap)); } +int +vprintf_l(locale_t locale, const char * __restrict fmt, __va_list ap) +{ + return (vfprintf_l(stdout, locale, fmt, ap)); +} Index: lib/libc/stdio/wprintf.c =================================================================== --- lib/libc/stdio/wprintf.c (revision 225653) +++ lib/libc/stdio/wprintf.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002 Tim J. Robbins * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -30,6 +35,7 @@ #include #include #include +#include int wprintf(const wchar_t * __restrict fmt, ...) @@ -43,3 +49,15 @@ return (ret); } +int +wprintf_l(locale_t locale, const wchar_t * __restrict fmt, ...) +{ + int ret; + va_list ap; + + va_start(ap, fmt); + ret = vfwprintf_l(stdout, locale, fmt, ap); + va_end(ap); + + return (ret); +} Index: lib/libc/stdio/vfwprintf.c =================================================================== --- lib/libc/stdio/vfwprintf.c (revision 225653) +++ lib/libc/stdio/vfwprintf.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Chris Torek. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -65,10 +70,11 @@ #include "local.h" #include "fvwrite.h" #include "printflocal.h" +#include "xlocale_private.h" -static int __sprint(FILE *, struct __suio *); -static int __sbprintf(FILE *, const wchar_t *, va_list) __noinline; -static wint_t __xfputwc(wchar_t, FILE *); +static int __sprint(FILE *, struct __suio *, locale_t); +static int __sbprintf(FILE *, locale_t, const wchar_t *, va_list) __noinline; +static wint_t __xfputwc(wchar_t, FILE *, locale_t); static wchar_t *__mbsconv(char *, int); #define CHAR wchar_t @@ -85,28 +91,28 @@ static const mbstate_t initial_mbs; static inline wchar_t -get_decpt(void) +get_decpt(locale_t locale) { mbstate_t mbs; wchar_t decpt; int nconv; mbs = initial_mbs; - nconv = mbrtowc(&decpt, localeconv()->decimal_point, MB_CUR_MAX, &mbs); + nconv = mbrtowc(&decpt, localeconv_l(locale)->decimal_point, MB_CUR_MAX, &mbs); if (nconv == (size_t)-1 || nconv == (size_t)-2) decpt = '.'; /* failsafe */ return (decpt); } static inline wchar_t -get_thousep(void) +get_thousep(locale_t locale) { mbstate_t mbs; wchar_t thousep; int nconv; mbs = initial_mbs; - nconv = mbrtowc(&thousep, localeconv()->thousands_sep, + nconv = mbrtowc(&thousep, localeconv_l(locale)->thousands_sep, MB_CUR_MAX, &mbs); if (nconv == (size_t)-1 || nconv == (size_t)-2) thousep = '\0'; /* failsafe */ @@ -119,11 +125,11 @@ * of wide characters that will be printed. */ static int -grouping_init(struct grouping_state *gs, int ndigits) +grouping_init(struct grouping_state *gs, int ndigits, locale_t locale) { - gs->grouping = localeconv()->grouping; - gs->thousands_sep = get_thousep(); + gs->grouping = localeconv_l(locale)->grouping; + gs->thousands_sep = get_thousep(locale); gs->nseps = gs->nrepeats = 0; gs->lead = ndigits; @@ -145,11 +151,11 @@ */ static int grouping_print(struct grouping_state *gs, struct io_state *iop, - const CHAR *cp, const CHAR *ep) + const CHAR *cp, const CHAR *ep, locale_t locale) { const CHAR *cp0 = cp; - if (io_printandpad(iop, cp, ep, gs->lead, zeroes)) + if (io_printandpad(iop, cp, ep, gs->lead, zeroes, locale)) return (-1); cp += gs->lead; while (gs->nseps > 0 || gs->nrepeats > 0) { @@ -159,9 +165,9 @@ gs->grouping--; gs->nseps--; } - if (io_print(iop, &gs->thousands_sep, 1)) + if (io_print(iop, &gs->thousands_sep, 1, locale)) return (-1); - if (io_printandpad(iop, cp, ep, *gs->grouping, zeroes)) + if (io_printandpad(iop, cp, ep, *gs->grouping, zeroes, locale)) return (-1); cp += *gs->grouping; } @@ -180,7 +186,7 @@ * string eclipses the benefits of buffering. */ static int -__sprint(FILE *fp, struct __suio *uio) +__sprint(FILE *fp, struct __suio *uio, locale_t locale) { struct __siov *iov; wchar_t *p; @@ -191,7 +197,7 @@ p = (wchar_t *)iov->iov_base; len = iov->iov_len; for (i = 0; i < len; i++) { - if (__xfputwc(p[i], fp) == WEOF) + if (__xfputwc(p[i], fp, locale) == WEOF) return (-1); } } @@ -205,7 +211,7 @@ * worries about ungetc buffers and so forth. */ static int -__sbprintf(FILE *fp, const wchar_t *fmt, va_list ap) +__sbprintf(FILE *fp, locale_t locale, const wchar_t *fmt, va_list ap) { int ret; FILE fake; @@ -229,7 +235,7 @@ fake._lbfsize = 0; /* not actually used, but Just In Case */ /* do the work, then copy any error status */ - ret = __vfwprintf(&fake, fmt, ap); + ret = __vfwprintf(&fake, locale, fmt, ap); if (ret >= 0 && __fflush(&fake)) ret = WEOF; if (fake._flags & __SERR) @@ -242,7 +248,7 @@ * File must already be locked. */ static wint_t -__xfputwc(wchar_t wc, FILE *fp) +__xfputwc(wchar_t wc, FILE *fp, locale_t locale) { mbstate_t mbs; char buf[MB_LEN_MAX]; @@ -251,7 +257,7 @@ size_t len; if ((fp->_flags & __SSTR) == 0) - return (__fputwc(wc, fp)); + return (__fputwc(wc, fp, locale)); mbs = initial_mbs; if ((len = wcrtomb(buf, wc, &mbs)) == (size_t)-1) { @@ -343,21 +349,27 @@ * MT-safe version */ int -vfwprintf(FILE * __restrict fp, const wchar_t * __restrict fmt0, va_list ap) +vfwprintf_l(FILE * __restrict fp, locale_t locale, + const wchar_t * __restrict fmt0, va_list ap) { int ret; - + FIX_LOCALE(locale); FLOCKFILE(fp); /* optimise fprintf(stderr) (and other unbuffered Unix files) */ if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) && fp->_file >= 0) - ret = __sbprintf(fp, fmt0, ap); + ret = __sbprintf(fp, locale, fmt0, ap); else - ret = __vfwprintf(fp, fmt0, ap); + ret = __vfwprintf(fp, locale, fmt0, ap); FUNLOCKFILE(fp); return (ret); } +int +vfwprintf(FILE * __restrict fp, const wchar_t * __restrict fmt0, va_list ap) +{ + return vfwprintf_l(fp, __get_locale(), fmt0, ap); +} /* * The size of the buffer we use as scratch space for integer @@ -374,7 +386,7 @@ * Non-MT-safe version */ int -__vfwprintf(FILE *fp, const wchar_t *fmt0, va_list ap) +__vfwprintf(FILE *fp, locale_t locale, const wchar_t *fmt0, va_list ap) { wchar_t *fmt; /* format string */ wchar_t ch; /* character from fmt */ @@ -437,19 +449,19 @@ /* BEWARE, these `goto error' on error. */ #define PRINT(ptr, len) do { \ - if (io_print(&io, (ptr), (len))) \ + if (io_print(&io, (ptr), (len), locale)) \ goto error; \ } while (0) #define PAD(howmany, with) { \ - if (io_pad(&io, (howmany), (with))) \ + if (io_pad(&io, (howmany), (with), locale)) \ goto error; \ } #define PRINTANDPAD(p, ep, len, with) { \ - if (io_printandpad(&io, (p), (ep), (len), (with))) \ + if (io_printandpad(&io, (p), (ep), (len), (with), locale)) \ goto error; \ } #define FLUSH() { \ - if (io_flush(&io)) \ + if (io_flush(&io, locale)) \ goto error; \ } @@ -529,7 +541,7 @@ io_init(&io, fp); ret = 0; #ifndef NO_FLOATING_POINT - decimal_point = get_decpt(); + decimal_point = get_decpt(locale); #endif /* @@ -816,7 +828,7 @@ if (prec || flags & ALT) size += prec + 1; if ((flags & GROUPING) && expt > 0) - size += grouping_init(&gs, expt); + size += grouping_init(&gs, expt, locale); } break; #endif /* !NO_FLOATING_POINT */ @@ -955,7 +967,7 @@ if (size > BUF) /* should never happen */ abort(); if ((flags & GROUPING) && size != 0) - size += grouping_init(&gs, size); + size += grouping_init(&gs, size, locale); break; default: /* "%?" prints ?, unless ? is NUL */ if (ch == '\0') @@ -1018,7 +1030,7 @@ /* leading zeroes from decimal precision */ PAD(dprec - size, zeroes); if (gs.grouping) { - if (grouping_print(&gs, &io, cp, buf+BUF) < 0) + if (grouping_print(&gs, &io, cp, buf+BUF, locale) < 0) goto error; } else { PRINT(cp, size); @@ -1036,7 +1048,7 @@ } else { if (gs.grouping) { n = grouping_print(&gs, &io, - cp, convbuf + ndig); + cp, convbuf + ndig, locale); if (n < 0) goto error; cp += n; Index: lib/libc/stdio/vdprintf.c =================================================================== --- lib/libc/stdio/vdprintf.c (revision 225653) +++ lib/libc/stdio/vdprintf.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2009 David Schultz * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -35,6 +40,7 @@ #include "un-namespace.h" #include "local.h" +#include "xlocale_private.h" int vdprintf(int fd, const char * __restrict fmt, va_list ap) @@ -57,7 +63,7 @@ f._bf._base = buf; f._bf._size = sizeof(buf); - if ((ret = __vfprintf(&f, fmt, ap)) < 0) + if ((ret = __vfprintf(&f, __get_locale(), fmt, ap)) < 0) return (ret); return (__fflush(&f) ? EOF : ret); Index: lib/libc/stdio/vfprintf.c =================================================================== --- lib/libc/stdio/vfprintf.c (revision 225653) +++ lib/libc/stdio/vfprintf.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Chris Torek. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -57,6 +62,7 @@ #include #include +#include "xlocale_private.h" #include "un-namespace.h" #include "libc_private.h" @@ -64,8 +70,8 @@ #include "fvwrite.h" #include "printflocal.h" -static int __sprint(FILE *, struct __suio *); -static int __sbprintf(FILE *, const char *, va_list) __printflike(2, 0) +static int __sprint(FILE *, struct __suio *, locale_t); +static int __sbprintf(FILE *, locale_t, const char *, va_list) __printflike(3, 0) __noinline; static char *__wcsconv(wchar_t *, int); @@ -87,11 +93,11 @@ * of bytes that will be needed. */ static int -grouping_init(struct grouping_state *gs, int ndigits) +grouping_init(struct grouping_state *gs, int ndigits, locale_t loc) { struct lconv *locale; - locale = localeconv(); + locale = localeconv_l(loc); gs->grouping = locale->grouping; gs->thousands_sep = locale->thousands_sep; gs->thousep_len = strlen(gs->thousands_sep); @@ -116,11 +122,11 @@ */ static int grouping_print(struct grouping_state *gs, struct io_state *iop, - const CHAR *cp, const CHAR *ep) + const CHAR *cp, const CHAR *ep, locale_t locale) { const CHAR *cp0 = cp; - if (io_printandpad(iop, cp, ep, gs->lead, zeroes)) + if (io_printandpad(iop, cp, ep, gs->lead, zeroes, locale)) return (-1); cp += gs->lead; while (gs->nseps > 0 || gs->nrepeats > 0) { @@ -130,9 +136,9 @@ gs->grouping--; gs->nseps--; } - if (io_print(iop, gs->thousands_sep, gs->thousep_len)) + if (io_print(iop, gs->thousands_sep, gs->thousep_len, locale)) return (-1); - if (io_printandpad(iop, cp, ep, *gs->grouping, zeroes)) + if (io_printandpad(iop, cp, ep, *gs->grouping, zeroes, locale)) return (-1); cp += *gs->grouping; } @@ -146,7 +152,7 @@ * then reset it so that it can be reused. */ static int -__sprint(FILE *fp, struct __suio *uio) +__sprint(FILE *fp, struct __suio *uio, locale_t locale) { int err; @@ -166,7 +172,7 @@ * worries about ungetc buffers and so forth. */ static int -__sbprintf(FILE *fp, const char *fmt, va_list ap) +__sbprintf(FILE *fp, locale_t locale, const char *fmt, va_list ap) { int ret; FILE fake = FAKE_FILE; @@ -190,7 +196,7 @@ fake._lbfsize = 0; /* not actually used, but Just In Case */ /* do the work, then copy any error status */ - ret = __vfprintf(&fake, fmt, ap); + ret = __vfprintf(&fake, locale, fmt, ap); if (ret >= 0 && __fflush(&fake)) ret = EOF; if (fake._flags & __SERR) @@ -261,21 +267,27 @@ * MT-safe version */ int -vfprintf(FILE * __restrict fp, const char * __restrict fmt0, va_list ap) - +vfprintf_l(FILE * __restrict fp, locale_t locale, const char * __restrict fmt0, + va_list ap) { int ret; + FIX_LOCALE(locale); FLOCKFILE(fp); /* optimise fprintf(stderr) (and other unbuffered Unix files) */ if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) && fp->_file >= 0) - ret = __sbprintf(fp, fmt0, ap); + ret = __sbprintf(fp, locale, fmt0, ap); else - ret = __vfprintf(fp, fmt0, ap); + ret = __vfprintf(fp, locale, fmt0, ap); FUNLOCKFILE(fp); return (ret); } +int +vfprintf(FILE * __restrict fp, const char * __restrict fmt0, va_list ap) +{ + return vfprintf_l(fp, __get_locale(), fmt0, ap); +} /* * The size of the buffer we use as scratch space for integer @@ -292,7 +304,7 @@ * Non-MT-safe version */ int -__vfprintf(FILE *fp, const char *fmt0, va_list ap) +__vfprintf(FILE *fp, locale_t locale, const char *fmt0, va_list ap) { char *fmt; /* format string */ int ch; /* character from fmt */ @@ -357,19 +369,19 @@ /* BEWARE, these `goto error' on error. */ #define PRINT(ptr, len) { \ - if (io_print(&io, (ptr), (len))) \ + if (io_print(&io, (ptr), (len), locale)) \ goto error; \ } #define PAD(howmany, with) { \ - if (io_pad(&io, (howmany), (with))) \ + if (io_pad(&io, (howmany), (with), locale)) \ goto error; \ } #define PRINTANDPAD(p, ep, len, with) { \ - if (io_printandpad(&io, (p), (ep), (len), (with))) \ + if (io_printandpad(&io, (p), (ep), (len), (with), locale)) \ goto error; \ } #define FLUSH() { \ - if (io_flush(&io)) \ + if (io_flush(&io, locale)) \ goto error; \ } @@ -454,7 +466,7 @@ ret = 0; #ifndef NO_FLOATING_POINT dtoaresult = NULL; - decimal_point = localeconv()->decimal_point; + decimal_point = localeconv_l(locale)->decimal_point; /* The overwhelmingly common case is decpt_len == 1. */ decpt_len = (decimal_point[1] == '\0' ? 1 : strlen(decimal_point)); #endif @@ -750,7 +762,7 @@ if (prec || flags & ALT) size += prec + decpt_len; if ((flags & GROUPING) && expt > 0) - size += grouping_init(&gs, expt); + size += grouping_init(&gs, expt, locale); } break; #endif /* !NO_FLOATING_POINT */ @@ -887,7 +899,7 @@ if (size > BUF) /* should never happen */ abort(); if ((flags & GROUPING) && size != 0) - size += grouping_init(&gs, size); + size += grouping_init(&gs, size, locale); break; default: /* "%?" prints ?, unless ? is NUL */ if (ch == '\0') @@ -950,7 +962,7 @@ /* leading zeroes from decimal precision */ PAD(dprec - size, zeroes); if (gs.grouping) { - if (grouping_print(&gs, &io, cp, buf+BUF) < 0) + if (grouping_print(&gs, &io, cp, buf+BUF, locale) < 0) goto error; } else { PRINT(cp, size); @@ -968,7 +980,7 @@ } else { if (gs.grouping) { n = grouping_print(&gs, &io, - cp, dtoaend); + cp, dtoaend, locale); if (n < 0) goto error; cp += n; Index: lib/libc/stdio/local.h =================================================================== --- lib/libc/stdio/local.h (revision 225653) +++ lib/libc/stdio/local.h (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Chris Torek. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -37,6 +42,7 @@ #include #include #include +#include /* * Information local to this implementation of stdio, @@ -50,8 +56,8 @@ extern int _fseeko(FILE *, off_t, int, int); extern int __fflush(FILE *fp); extern void __fcloseall(void); -extern wint_t __fgetwc(FILE *); -extern wint_t __fputwc(wchar_t, FILE *); +extern wint_t __fgetwc(FILE *, locale_t); +extern wint_t __fputwc(wchar_t, FILE *, locale_t); extern int __sflush(FILE *); extern FILE *__sfp(void); extern int __slbexpand(FILE *, size_t); @@ -65,15 +71,15 @@ extern void __smakebuf(FILE *); extern int __swhatbuf(FILE *, size_t *, int *); extern int _fwalk(int (*)(FILE *)); -extern int __svfscanf(FILE *, const char *, __va_list); +extern int __svfscanf(FILE *, locale_t, const char *, __va_list); extern int __swsetup(FILE *); extern int __sflags(const char *, int *); extern int __ungetc(int, FILE *); -extern wint_t __ungetwc(wint_t, FILE *); -extern int __vfprintf(FILE *, const char *, __va_list); +extern wint_t __ungetwc(wint_t, FILE *, locale_t); +extern int __vfprintf(FILE *, locale_t, const char *, __va_list); extern int __vfscanf(FILE *, const char *, __va_list); -extern int __vfwprintf(FILE *, const wchar_t *, __va_list); -extern int __vfwscanf(FILE * __restrict, const wchar_t * __restrict, +extern int __vfwprintf(FILE *, locale_t, const wchar_t *, __va_list); +extern int __vfwscanf(FILE * __restrict, locale_t, const wchar_t * __restrict, __va_list); extern size_t __fread(void * __restrict buf, size_t size, size_t count, FILE * __restrict fp); Index: lib/libc/stdio/fwprintf.c =================================================================== --- lib/libc/stdio/fwprintf.c (revision 225653) +++ lib/libc/stdio/fwprintf.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002 Tim J. Robbins * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -30,6 +35,7 @@ #include #include #include +#include int fwprintf(FILE * __restrict fp, const wchar_t * __restrict fmt, ...) @@ -43,3 +49,15 @@ return (ret); } +int +fwprintf_l(FILE * __restrict fp, locale_t locale, const wchar_t * __restrict fmt, ...) +{ + int ret; + va_list ap; + + va_start(ap, fmt); + ret = vfwprintf_l(fp, locale, fmt, ap); + va_end(ap); + + return (ret); +} Index: lib/libc/stdio/fputwc.c =================================================================== --- lib/libc/stdio/fputwc.c (revision 225653) +++ lib/libc/stdio/fputwc.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002-2004 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -42,10 +47,11 @@ * Non-MT-safe version. */ wint_t -__fputwc(wchar_t wc, FILE *fp) +__fputwc(wchar_t wc, FILE *fp, locale_t locale) { char buf[MB_LEN_MAX]; size_t i, len; + struct xlocale_ctype *l = XLOCALE_CTYPE(locale); if (MB_CUR_MAX == 1 && wc > 0 && wc <= UCHAR_MAX) { /* @@ -56,7 +62,7 @@ *buf = (unsigned char)wc; len = 1; } else { - if ((len = __wcrtomb(buf, wc, &fp->_mbstate)) == (size_t)-1) { + if ((len = l->__wcrtomb(buf, wc, &fp->_mbstate)) == (size_t)-1) { fp->_flags |= __SERR; return (WEOF); } @@ -73,14 +79,20 @@ * MT-safe version. */ wint_t -fputwc(wchar_t wc, FILE *fp) +fputwc_l(wchar_t wc, FILE *fp, locale_t locale) { wint_t r; + FIX_LOCALE(locale); FLOCKFILE(fp); ORIENT(fp, 1); - r = __fputwc(wc, fp); + r = __fputwc(wc, fp, locale); FUNLOCKFILE(fp); return (r); } +wint_t +fputwc(wchar_t wc, FILE *fp) +{ + return fputwc_l(wc, fp, __get_locale()); +} Index: lib/libc/stdio/vsprintf.c =================================================================== --- lib/libc/stdio/vsprintf.c (revision 225653) +++ lib/libc/stdio/vsprintf.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Chris Torek. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -39,17 +44,25 @@ #include #include #include "local.h" +#include "xlocale_private.h" int -vsprintf(char * __restrict str, const char * __restrict fmt, __va_list ap) +vsprintf_l(char * __restrict str, locale_t locale, + const char * __restrict fmt, __va_list ap) { int ret; FILE f = FAKE_FILE; + FIX_LOCALE(locale); f._flags = __SWR | __SSTR; f._bf._base = f._p = (unsigned char *)str; f._bf._size = f._w = INT_MAX; - ret = __vfprintf(&f, fmt, ap); + ret = __vfprintf(&f, locale, fmt, ap); *f._p = 0; return (ret); } +int +vsprintf(char * __restrict str, const char * __restrict fmt, __va_list ap) +{ + return vsprintf_l(str, __get_locale(), fmt, ap); +} Index: lib/libc/stdio/vwprintf.c =================================================================== --- lib/libc/stdio/vwprintf.c (revision 225653) +++ lib/libc/stdio/vwprintf.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002 Tim J. Robbins * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -30,10 +35,15 @@ #include #include #include +#include int vwprintf(const wchar_t * __restrict fmt, va_list ap) { - return (vfwprintf(stdout, fmt, ap)); } +int +vwprintf_l(locale_t locale, const wchar_t * __restrict fmt, va_list ap) +{ + return (vfwprintf_l(stdout, locale, fmt, ap)); +} Index: lib/libc/stdio/fwscanf.c =================================================================== --- lib/libc/stdio/fwscanf.c (revision 225653) +++ lib/libc/stdio/fwscanf.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002 Tim J. Robbins * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -30,6 +35,7 @@ #include #include #include +#include int fwscanf(FILE * __restrict fp, const wchar_t * __restrict fmt, ...) @@ -43,3 +49,15 @@ return (r); } +int +fwscanf_l(FILE * __restrict fp, locale_t locale, const wchar_t * __restrict fmt, ...) +{ + va_list ap; + int r; + + va_start(ap, fmt); + r = vfwscanf_l(fp, locale, fmt, ap); + va_end(ap); + + return (r); +} Index: lib/libc/stdio/fputws.c =================================================================== --- lib/libc/stdio/fputws.c (revision 225653) +++ lib/libc/stdio/fputws.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002-2004 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -39,13 +44,15 @@ #include "mblocal.h" int -fputws(const wchar_t * __restrict ws, FILE * __restrict fp) +fputws_l(const wchar_t * __restrict ws, FILE * __restrict fp, locale_t locale) { size_t nbytes; char buf[BUFSIZ]; struct __suio uio; struct __siov iov; const wchar_t *wsp; + FIX_LOCALE(locale); + struct xlocale_ctype *l = XLOCALE_CTYPE(locale); FLOCKFILE(fp); ORIENT(fp, 1); @@ -56,7 +63,7 @@ iov.iov_base = buf; do { wsp = ws; - nbytes = __wcsnrtombs(buf, &wsp, SIZE_T_MAX, sizeof(buf), + nbytes = l->__wcsnrtombs(buf, &wsp, SIZE_T_MAX, sizeof(buf), &fp->_mbstate); if (nbytes == (size_t)-1) goto error; @@ -71,3 +78,9 @@ FUNLOCKFILE(fp); return (-1); } + +int +fputws(const wchar_t * __restrict ws, FILE * __restrict fp) +{ + return fputws_l(ws, fp, __get_locale()); +} Index: lib/libc/stdio/scanf.c =================================================================== --- lib/libc/stdio/scanf.c (revision 225653) +++ lib/libc/stdio/scanf.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Chris Torek. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -42,6 +47,7 @@ #include "un-namespace.h" #include "libc_private.h" #include "local.h" +#include "xlocale_private.h" int scanf(char const * __restrict fmt, ...) @@ -51,8 +57,22 @@ va_start(ap, fmt); FLOCKFILE(stdin); - ret = __svfscanf(stdin, fmt, ap); + ret = __svfscanf(stdin, __get_locale(), fmt, ap); FUNLOCKFILE(stdin); va_end(ap); return (ret); } +int +scanf_l(locale_t locale, char const * __restrict fmt, ...) +{ + int ret; + va_list ap; + FIX_LOCALE(locale); + + va_start(ap, fmt); + FLOCKFILE(stdin); + ret = __svfscanf(stdin, locale, fmt, ap); + FUNLOCKFILE(stdin); + va_end(ap); + return (ret); +} Index: lib/libc/stdio/swscanf.c =================================================================== --- lib/libc/stdio/swscanf.c (revision 225653) +++ lib/libc/stdio/swscanf.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002 Tim J. Robbins * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -30,6 +35,7 @@ #include #include #include +#include int swscanf(const wchar_t * __restrict str, const wchar_t * __restrict fmt, ...) @@ -43,3 +49,16 @@ return (r); } +int +swscanf_l(const wchar_t * __restrict str, locale_t locale, + const wchar_t * __restrict fmt, ...) +{ + va_list ap; + int r; + + va_start(ap, fmt); + r = vswscanf_l(str, locale, fmt, ap); + va_end(ap); + + return (r); +} Index: lib/libc/stdio/vwscanf.c =================================================================== --- lib/libc/stdio/vwscanf.c (revision 225653) +++ lib/libc/stdio/vwscanf.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002 Tim J. Robbins * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -30,10 +35,15 @@ #include #include #include +#include int vwscanf(const wchar_t * __restrict fmt, va_list ap) { - return (vfwscanf(stdin, fmt, ap)); } +int +vwscanf_l(locale_t locale, const wchar_t * __restrict fmt, va_list ap) +{ + return (vfwscanf_l(stdin, locale, fmt, ap)); +} Index: lib/libc/stdio/sscanf.c =================================================================== --- lib/libc/stdio/sscanf.c (revision 225653) +++ lib/libc/stdio/sscanf.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Chris Torek. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -39,6 +44,7 @@ #include #include #include +#include #include "local.h" int @@ -52,3 +58,15 @@ va_end(ap); return (ret); } +int +sscanf_l(const char * __restrict str, locale_t locale, + char const * __restrict fmt, ...) +{ + int ret; + va_list ap; + + va_start(ap, fmt); + ret = vsscanf_l(str, locale, fmt, ap); + va_end(ap); + return (ret); +} Index: lib/libc/stdio/fgetwc.c =================================================================== --- lib/libc/stdio/fgetwc.c (revision 225653) +++ lib/libc/stdio/fgetwc.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002-2004 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -36,31 +41,39 @@ #include "libc_private.h" #include "local.h" #include "mblocal.h" +#include "xlocale_private.h" /* * MT-safe version. */ wint_t -fgetwc(FILE *fp) +fgetwc_l(FILE *fp, locale_t locale) { wint_t r; + FIX_LOCALE(locale); FLOCKFILE(fp); ORIENT(fp, 1); - r = __fgetwc(fp); + r = __fgetwc(fp, locale); FUNLOCKFILE(fp); return (r); } +wint_t +fgetwc(FILE *fp) +{ + return fgetwc_l(fp, __get_locale()); +} /* * Non-MT-safe version. */ wint_t -__fgetwc(FILE *fp) +__fgetwc(FILE *fp, locale_t locale) { wchar_t wc; size_t nconv; + struct xlocale_ctype *l = XLOCALE_CTYPE(locale); if (fp->_r <= 0 && __srefill(fp)) return (WEOF); @@ -71,7 +84,7 @@ return (wc); } do { - nconv = __mbrtowc(&wc, fp->_p, fp->_r, &fp->_mbstate); + nconv = l->__mbrtowc(&wc, fp->_p, fp->_r, &fp->_mbstate); if (nconv == (size_t)-1) break; else if (nconv == (size_t)-2) Index: lib/libc/stdio/vfscanf.c =================================================================== --- lib/libc/stdio/vfscanf.c (revision 225653) +++ lib/libc/stdio/vfscanf.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * This code is derived from software contributed to Berkeley by * Chris Torek. * @@ -51,6 +56,7 @@ #include "collate.h" #include "libc_private.h" #include "local.h" +#include "xlocale_private.h" #ifndef NO_FLOATING_POINT #include @@ -95,11 +101,12 @@ static const u_char *__sccl(char *, const u_char *); #ifndef NO_FLOATING_POINT -static int parsefloat(FILE *, char *, char *); +static int parsefloat(FILE *, char *, char *, locale_t); #endif __weak_reference(__vfscanf, vfscanf); + /* * __vfscanf - MT-safe version */ @@ -109,16 +116,27 @@ int ret; FLOCKFILE(fp); - ret = __svfscanf(fp, fmt0, ap); + ret = __svfscanf(fp, __get_locale(), fmt0, ap); FUNLOCKFILE(fp); return (ret); } +int +vfscanf_l(FILE *fp, locale_t locale, char const *fmt0, va_list ap) +{ + int ret; + FIX_LOCALE(locale); + FLOCKFILE(fp); + ret = __svfscanf(fp, locale, fmt0, ap); + FUNLOCKFILE(fp); + return (ret); +} + /* * __svfscanf - non-MT-safe version of __vfscanf */ int -__svfscanf(FILE *fp, const char *fmt0, va_list ap) +__svfscanf(FILE *fp, locale_t locale, const char *fmt0, va_list ap) { const u_char *fmt = (const u_char *)fmt0; int c; /* character from format, or conversion */ @@ -455,8 +473,7 @@ !ccltab[wctob(*wcp)]) { while (n != 0) { n--; - __ungetc(buf[n], - fp); + __ungetc(buf[n], fp); } break; } @@ -555,8 +572,7 @@ if (iswspace(*wcp)) { while (n != 0) { n--; - __ungetc(buf[n], - fp); + __ungetc(buf[n], fp); } break; } @@ -733,9 +749,9 @@ *p = 0; if ((flags & UNSIGNED) == 0) - res = strtoimax(buf, (char **)NULL, base); + res = strtoimax_l(buf, (char **)NULL, base, locale); else - res = strtoumax(buf, (char **)NULL, base); + res = strtoumax_l(buf, (char **)NULL, base, locale); if (flags & POINTER) *va_arg(ap, void **) = (void *)(uintptr_t)res; @@ -766,17 +782,17 @@ /* scan a floating point number as if by strtod */ if (width == 0 || width > sizeof(buf) - 1) width = sizeof(buf) - 1; - if ((width = parsefloat(fp, buf, buf + width)) == 0) + if ((width = parsefloat(fp, buf, buf + width, locale)) == 0) goto match_failure; if ((flags & SUPPRESS) == 0) { if (flags & LONGDBL) { - long double res = strtold(buf, &p); + long double res = strtold_l(buf, &p, locale); *va_arg(ap, long double *) = res; } else if (flags & LONG) { - double res = strtod(buf, &p); + double res = strtod_l(buf, &p, locale); *va_arg(ap, double *) = res; } else { - float res = strtof(buf, &p); + float res = strtof_l(buf, &p, locale); *va_arg(ap, float *) = res; } nassigned++; @@ -805,6 +821,8 @@ const u_char *fmt; { int c, n, v, i; + struct xlocale_collate *table = + (struct xlocale_collate*)__get_locale()->components[XLC_COLLATE]; /* first `clear' the whole table */ c = *fmt++; /* first char hat => negated scanset */ @@ -858,8 +876,8 @@ */ n = *fmt; if (n == ']' - || (__collate_load_error ? n < c : - __collate_range_cmp (n, c) < 0 + || (table->__collate_load_error ? n < c : + __collate_range_cmp (table, n, c) < 0 ) ) { c = '-'; @@ -867,14 +885,14 @@ } fmt++; /* fill in the range */ - if (__collate_load_error) { + if (table->__collate_load_error) { do { tab[++c] = v; } while (c < n); } else { for (i = 0; i < 256; i ++) - if ( __collate_range_cmp (c, i) < 0 - && __collate_range_cmp (i, n) <= 0 + if ( __collate_range_cmp (table, c, i) < 0 + && __collate_range_cmp (table, i, n) <= 0 ) tab[i] = v; } @@ -908,7 +926,7 @@ #ifndef NO_FLOATING_POINT static int -parsefloat(FILE *fp, char *buf, char *end) +parsefloat(FILE *fp, char *buf, char *end, locale_t locale) { char *commit, *p; int infnanpos = 0, decptpos = 0; @@ -917,7 +935,7 @@ S_DIGITS, S_DECPT, S_FRAC, S_EXP, S_EXPDIGITS } state = S_START; unsigned char c; - const char *decpt = localeconv()->decimal_point; + const char *decpt = localeconv_l(locale)->decimal_point; _Bool gotmantdig = 0, ishex = 0; /* Index: lib/libc/stdio/fgetws.c =================================================================== --- lib/libc/stdio/fgetws.c (revision 225653) +++ lib/libc/stdio/fgetws.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002-2004 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -38,12 +43,14 @@ #include "mblocal.h" wchar_t * -fgetws(wchar_t * __restrict ws, int n, FILE * __restrict fp) +fgetws_l(wchar_t * __restrict ws, int n, FILE * __restrict fp, locale_t locale) { wchar_t *wsp; size_t nconv; const char *src; unsigned char *nl; + FIX_LOCALE(locale); + struct xlocale_ctype *l = XLOCALE_CTYPE(locale); FLOCKFILE(fp); ORIENT(fp, 1); @@ -60,7 +67,7 @@ do { src = fp->_p; nl = memchr(fp->_p, '\n', fp->_r); - nconv = __mbsnrtowcs(wsp, &src, + nconv = l->__mbsnrtowcs(wsp, &src, nl != NULL ? (nl - fp->_p + 1) : fp->_r, n - 1, &fp->_mbstate); if (nconv == (size_t)-1) @@ -86,7 +93,7 @@ if (wsp == ws) /* EOF */ goto error; - if (!__mbsinit(&fp->_mbstate)) + if (!l->__mbsinit(&fp->_mbstate)) /* Incomplete character */ goto error; *wsp = L'\0'; @@ -98,3 +105,8 @@ FUNLOCKFILE(fp); return (NULL); } +wchar_t * +fgetws(wchar_t * __restrict ws, int n, FILE * __restrict fp) +{ + return fgetws_l(ws, n, fp, __get_locale()); +} Index: lib/libc/stdio/vasprintf.c =================================================================== --- lib/libc/stdio/vasprintf.c (revision 225653) +++ lib/libc/stdio/vasprintf.c (working copy) @@ -4,6 +4,11 @@ * Copyright (c) 1997 Todd C. Miller * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -33,13 +38,15 @@ #include #include #include +#include "xlocale_private.h" #include "local.h" int -vasprintf(char **str, const char *fmt, __va_list ap) +vasprintf_l(char **str, locale_t locale, const char *fmt, __va_list ap) { FILE f = FAKE_FILE; int ret; + FIX_LOCALE(locale); f._flags = __SWR | __SSTR | __SALC; f._bf._base = f._p = malloc(128); @@ -49,7 +56,7 @@ return (-1); } f._bf._size = f._w = 127; /* Leave room for the NUL */ - ret = __vfprintf(&f, fmt, ap); + ret = __vfprintf(&f, locale, fmt, ap); if (ret < 0) { free(f._bf._base); *str = NULL; @@ -60,3 +67,8 @@ *str = (char *)f._bf._base; return (ret); } +int +vasprintf(char **str, const char *fmt, __va_list ap) +{ + return vasprintf_l(str, __get_locale(), fmt, ap); +} Index: lib/libc/stdio/vfwscanf.c =================================================================== --- lib/libc/stdio/vfwscanf.c (revision 225653) +++ lib/libc/stdio/vfwscanf.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Chris Torek. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -53,11 +58,8 @@ #include "libc_private.h" #include "local.h" +#include "xlocale_private.h" -#ifndef NO_FLOATING_POINT -#include -#endif - #define BUF 513 /* Maximum length of numeric string. */ /* @@ -96,7 +98,7 @@ #define CT_FLOAT 4 /* %[efgEFG] conversion */ #ifndef NO_FLOATING_POINT -static int parsefloat(FILE *, wchar_t *, wchar_t *); +static int parsefloat(FILE *, wchar_t *, wchar_t *, locale_t); #endif #define INCCL(_c) \ @@ -109,22 +111,30 @@ * MT-safe version. */ int -vfwscanf(FILE * __restrict fp, const wchar_t * __restrict fmt, va_list ap) +vfwscanf_l(FILE * __restrict fp, locale_t locale, + const wchar_t * __restrict fmt, va_list ap) { int ret; + FIX_LOCALE(locale); FLOCKFILE(fp); ORIENT(fp, 1); - ret = __vfwscanf(fp, fmt, ap); + ret = __vfwscanf(fp, locale, fmt, ap); FUNLOCKFILE(fp); return (ret); } +int +vfwscanf(FILE * __restrict fp, const wchar_t * __restrict fmt, va_list ap) +{ + return vfwscanf_l(fp, __get_locale(), fmt, ap); +} /* * Non-MT-safe version. */ int -__vfwscanf(FILE * __restrict fp, const wchar_t * __restrict fmt, va_list ap) +__vfwscanf(FILE * __restrict fp, locale_t locale, + const wchar_t * __restrict fmt, va_list ap) { wint_t c; /* character from format, or conversion */ size_t width; /* field width, or 0 */ @@ -159,11 +169,11 @@ if (c == 0) return (nassigned); if (iswspace(c)) { - while ((c = __fgetwc(fp)) != WEOF && - iswspace(c)) + while ((c = __fgetwc(fp, locale)) != WEOF && + iswspace_l(c, locale)) ; if (c != WEOF) - __ungetwc(c, fp); + __ungetwc(c, fp, locale); continue; } if (c != '%') @@ -178,10 +188,10 @@ switch (c) { case '%': literal: - if ((wi = __fgetwc(fp)) == WEOF) + if ((wi = __fgetwc(fp, locale)) == WEOF) goto input_failure; if (wi != c) { - __ungetwc(wi, fp); + __ungetwc(wi, fp, locale); goto input_failure; } nread++; @@ -341,11 +351,11 @@ * that suppress this. */ if ((flags & NOSKIP) == 0) { - while ((wi = __fgetwc(fp)) != WEOF && iswspace(wi)) + while ((wi = __fgetwc(fp, locale)) != WEOF && iswspace(wi)) nread++; if (wi == WEOF) goto input_failure; - __ungetwc(wi, fp); + __ungetwc(wi, fp, locale); } /* @@ -362,7 +372,7 @@ p = va_arg(ap, wchar_t *); n = 0; while (width-- != 0 && - (wi = __fgetwc(fp)) != WEOF) { + (wi = __fgetwc(fp, locale)) != WEOF) { if (!(flags & SUPPRESS)) *p++ = (wchar_t)wi; n++; @@ -378,7 +388,7 @@ n = 0; mbs = initial_mbs; while (width != 0 && - (wi = __fgetwc(fp)) != WEOF) { + (wi = __fgetwc(fp, locale)) != WEOF) { if (width >= MB_CUR_MAX && !(flags & SUPPRESS)) { nconv = wcrtomb(mbp, wi, &mbs); @@ -390,7 +400,7 @@ if (nconv == (size_t)-1) goto input_failure; if (nconv > width) { - __ungetwc(wi, fp); + __ungetwc(wi, fp, locale); break; } if (!(flags & SUPPRESS)) @@ -418,20 +428,20 @@ /* take only those things in the class */ if ((flags & SUPPRESS) && (flags & LONG)) { n = 0; - while ((wi = __fgetwc(fp)) != WEOF && + while ((wi = __fgetwc(fp, locale)) != WEOF && width-- != 0 && INCCL(wi)) n++; if (wi != WEOF) - __ungetwc(wi, fp); + __ungetwc(wi, fp, locale); if (n == 0) goto match_failure; } else if (flags & LONG) { p0 = p = va_arg(ap, wchar_t *); - while ((wi = __fgetwc(fp)) != WEOF && + while ((wi = __fgetwc(fp, locale)) != WEOF && width-- != 0 && INCCL(wi)) *p++ = (wchar_t)wi; if (wi != WEOF) - __ungetwc(wi, fp); + __ungetwc(wi, fp, locale); n = p - p0; if (n == 0) goto match_failure; @@ -442,7 +452,7 @@ mbp = va_arg(ap, char *); n = 0; mbs = initial_mbs; - while ((wi = __fgetwc(fp)) != WEOF && + while ((wi = __fgetwc(fp, locale)) != WEOF && width != 0 && INCCL(wi)) { if (width >= MB_CUR_MAX && !(flags & SUPPRESS)) { @@ -466,7 +476,7 @@ n++; } if (wi != WEOF) - __ungetwc(wi, fp); + __ungetwc(wi, fp, locale); if (!(flags & SUPPRESS)) { *mbp = 0; nassigned++; @@ -481,29 +491,29 @@ if (width == 0) width = (size_t)~0; if ((flags & SUPPRESS) && (flags & LONG)) { - while ((wi = __fgetwc(fp)) != WEOF && + while ((wi = __fgetwc(fp, locale)) != WEOF && width-- != 0 && !iswspace(wi)) nread++; if (wi != WEOF) - __ungetwc(wi, fp); + __ungetwc(wi, fp, locale); } else if (flags & LONG) { p0 = p = va_arg(ap, wchar_t *); - while ((wi = __fgetwc(fp)) != WEOF && + while ((wi = __fgetwc(fp, locale)) != WEOF && width-- != 0 && !iswspace(wi)) { *p++ = (wchar_t)wi; nread++; } if (wi != WEOF) - __ungetwc(wi, fp); + __ungetwc(wi, fp, locale); *p = '\0'; nassigned++; } else { if (!(flags & SUPPRESS)) mbp = va_arg(ap, char *); mbs = initial_mbs; - while ((wi = __fgetwc(fp)) != WEOF && + while ((wi = __fgetwc(fp, locale)) != WEOF && width != 0 && !iswspace(wi)) { if (width >= MB_CUR_MAX && @@ -528,7 +538,7 @@ nread++; } if (wi != WEOF) - __ungetwc(wi, fp); + __ungetwc(wi, fp, locale); if (!(flags & SUPPRESS)) { *mbp = 0; nassigned++; @@ -544,7 +554,7 @@ width = sizeof(buf) / sizeof(*buf) - 1; flags |= SIGNOK | NDIGITS | NZDIGITS; for (p = buf; width; width--) { - c = __fgetwc(fp); + c = __fgetwc(fp, locale); /* * Switch on the character; `goto ok' * if we accept it as a part of number. @@ -628,7 +638,7 @@ * for a number. Stop accumulating digits. */ if (c != WEOF) - __ungetwc(c, fp); + __ungetwc(c, fp, locale); break; ok: /* @@ -644,13 +654,13 @@ */ if (flags & NDIGITS) { if (p > buf) - __ungetwc(*--p, fp); + __ungetwc(*--p, fp, locale); goto match_failure; } c = p[-1]; if (c == 'x' || c == 'X') { --p; - __ungetwc(c, fp); + __ungetwc(c, fp, locale); } if ((flags & SUPPRESS) == 0) { uintmax_t res; @@ -691,7 +701,7 @@ if (width == 0 || width > sizeof(buf) / sizeof(*buf) - 1) width = sizeof(buf) / sizeof(*buf) - 1; - if ((width = parsefloat(fp, buf, buf + width)) == 0) + if ((width = parsefloat(fp, buf, buf + width, locale)) == 0) goto match_failure; if ((flags & SUPPRESS) == 0) { if (flags & LONGDBL) { @@ -720,7 +730,7 @@ #ifndef NO_FLOATING_POINT static int -parsefloat(FILE *fp, wchar_t *buf, wchar_t *end) +parsefloat(FILE *fp, wchar_t *buf, wchar_t *end, locale_t locale) { mbstate_t mbs; size_t nconv; @@ -751,7 +761,7 @@ commit = buf - 1; c = WEOF; for (p = buf; p < end; ) { - if ((c = __fgetwc(fp)) == WEOF) + if ((c = __fgetwc(fp, locale)) == WEOF) break; reswitch: switch (state) { @@ -871,9 +881,9 @@ parsedone: if (c != WEOF) - __ungetwc(c, fp); + __ungetwc(c, fp, locale); while (commit < --p) - __ungetwc(*p, fp); + __ungetwc(*p, fp, locale); *++commit = '\0'; return (commit - buf); } Index: lib/libc/stdio/asprintf.c =================================================================== --- lib/libc/stdio/asprintf.c (revision 225653) +++ lib/libc/stdio/asprintf.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Chris Torek. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -35,6 +40,7 @@ #include #include +#include int asprintf(char ** __restrict s, char const * __restrict fmt, ...) @@ -47,3 +53,15 @@ va_end(ap); return (ret); } +int +asprintf_l(char ** __restrict s, locale_t locale, char const * __restrict fmt, + ...) +{ + int ret; + va_list ap; + + va_start(ap, fmt); + ret = vasprintf_l(s, locale, fmt, ap); + va_end(ap); + return (ret); +} Index: lib/libc/stdio/vswscanf.c =================================================================== --- lib/libc/stdio/vswscanf.c (revision 225653) +++ lib/libc/stdio/vswscanf.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Donn Seeley at UUNET Technologies, Inc. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -46,6 +51,7 @@ #include #include #include "local.h" +#include "xlocale_private.h" static int eofread(void *, char *, int); @@ -57,8 +63,8 @@ } int -vswscanf(const wchar_t * __restrict str, const wchar_t * __restrict fmt, - va_list ap) +vswscanf_l(const wchar_t * __restrict str, locale_t locale, + const wchar_t * __restrict fmt, va_list ap) { static const mbstate_t initial; mbstate_t mbs; @@ -67,6 +73,7 @@ size_t mlen; int r; const wchar_t *strp; + FIX_LOCALE(locale); /* * XXX Convert the wide character string to multibyte, which @@ -76,7 +83,7 @@ return (EOF); mbs = initial; strp = str; - if ((mlen = wcsrtombs(mbstr, &strp, SIZE_T_MAX, &mbs)) == (size_t)-1) { + if ((mlen = wcsrtombs_l(mbstr, &strp, SIZE_T_MAX, &mbs, locale)) == (size_t)-1) { free(mbstr); return (EOF); } @@ -84,8 +91,14 @@ f._bf._base = f._p = (unsigned char *)mbstr; f._bf._size = f._r = mlen; f._read = eofread; - r = __vfwscanf(&f, fmt, ap); + r = __vfwscanf(&f, locale, fmt, ap); free(mbstr); return (r); } +int +vswscanf(const wchar_t * __restrict str, const wchar_t * __restrict fmt, + va_list ap) +{ + return vswscanf_l(str, __get_locale(), fmt, ap); +} Index: lib/libc/locale/collate.c =================================================================== --- lib/libc/locale/collate.c (revision 225653) +++ lib/libc/locale/collate.c (working copy) @@ -3,6 +3,16 @@ * at Electronni Visti IA, Kiev, Ukraine. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -44,24 +54,77 @@ #include "libc_private.h" -int __collate_load_error = 1; -int __collate_substitute_nontrivial; +/* + * To avoid modifying the original (single-threaded) code too much, we'll just + * define the old globals as fields inside the table. + * + * We also modify the collation table test functions to search the thread-local + * table first and the global table second. + */ +#define __collate_load_error (table->__collate_load_error) +#define __collate_substitute_nontrivial (table->__collate_substitute_nontrivial) +#define __collate_substitute_table_ptr (table->__collate_substitute_table_ptr) +#define __collate_char_pri_table_ptr (table->__collate_char_pri_table_ptr) +#define __collate_chain_pri_table (table->__collate_chain_pri_table) -u_char __collate_substitute_table[UCHAR_MAX + 1][STR_LEN]; -struct __collate_st_char_pri __collate_char_pri_table[UCHAR_MAX + 1]; -struct __collate_st_chain_pri *__collate_chain_pri_table; +struct xlocale_collate __xlocale_global_collate = { + {{0}, "C"}, 1, 0 +}; + +static struct xlocale_collate c_collate= { + {{0}, "C"}, 1, 0 +}; + void __collate_err(int ex, const char *f) __dead2; int +__collate_load_tables_l(const char *encoding, struct xlocale_collate *table); + +static void +destruct_collate(void *t) +{ + struct xlocale_collate *table = t; + if (__collate_chain_pri_table) { + free(__collate_chain_pri_table); + } + free(t); +} + +void * +__collate_load(const char *encoding, locale_t unused) +{ + if (strcmp(encoding, "C") == 0 || strcmp(encoding, "POSIX") == 0) { + return &c_collate; + } + struct xlocale_collate *table = calloc(sizeof(struct xlocale_collate), 1); + table->header.header.destructor = destruct_collate; + // FIXME: Make sure that _LDP_CACHE is never returned. We should be doing + // the caching outside of this section + if (__collate_load_tables_l(encoding, table) != _LDP_LOADED) { + xlocale_release(table); + return NULL; + } + return table; +} + +/** + * Load the collation tables for the specified encoding into the global table. + */ +int __collate_load_tables(const char *encoding) { + return __collate_load_tables_l(encoding, &__xlocale_global_collate); +} + +int +__collate_load_tables_l(const char *encoding, struct xlocale_collate *table) +{ FILE *fp; int i, saverr, chains; uint32_t u32; char strbuf[STR_LEN], buf[PATH_MAX]; void *TMP_substitute_table, *TMP_char_pri_table, *TMP_chain_pri_table; - static char collate_encoding[ENCODING_LEN + 1]; /* 'encoding' must be already checked. */ if (strcmp(encoding, "C") == 0 || strcmp(encoding, "POSIX") == 0) { @@ -69,18 +132,6 @@ return (_LDP_CACHE); } - /* - * If the locale name is the same as our cache, use the cache. - */ - if (strcmp(encoding, collate_encoding) == 0) { - __collate_load_error = 0; - return (_LDP_CACHE); - } - - /* - * Slurp the locale file into the cache. - */ - /* 'PathLocale' must be already set & checked. */ /* Range checking not needed, encoding has fixed size */ (void)strcpy(buf, _PathLocale); @@ -165,7 +216,6 @@ sizeof(*__collate_chain_pri_table), chains, fp); (void)fclose(fp); - (void)strcpy(collate_encoding, encoding); if (__collate_substitute_table_ptr != NULL) free(__collate_substitute_table_ptr); __collate_substitute_table_ptr = TMP_substitute_table; @@ -201,7 +251,7 @@ } u_char * -__collate_substitute(const u_char *s) +__collate_substitute(struct xlocale_collate *table, const u_char *s) { int dest_len, len, nlen; int delta = strlen(s); @@ -228,7 +278,7 @@ } void -__collate_lookup(const u_char *t, int *len, int *prim, int *sec) +__collate_lookup(struct xlocale_collate *table, const u_char *t, int *len, int *prim, int *sec) { struct __collate_st_chain_pri *p2; Index: lib/libc/locale/xlocale.c =================================================================== --- lib/libc/locale/xlocale.c (revision 0) +++ lib/libc/locale/xlocale.c (revision 0) @@ -0,0 +1,312 @@ +/*- + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by David Chisnall under sponsorship from + * the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions * are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include "libc_private.h" +#include "xlocale_private.h" + +/** + * Each locale loader declares a global component. This is used by setlocale() + * and also by xlocale with LC_GLOBAL_LOCALE.. + */ +extern struct xlocale_component __xlocale_global_collate; +extern struct xlocale_component __xlocale_global_ctype; +extern struct xlocale_component __xlocale_global_monetary; +extern struct xlocale_component __xlocale_global_numeric; +extern struct xlocale_component __xlocale_global_time; +extern struct xlocale_component __xlocale_global_messages; +/* + * Private functions in setlocale.c. + */ +const char * +__get_locale_env(int category); +int +__detect_path_locale(void); + +struct _xlocale __xlocale_global_locale = { + {0}, + { + &__xlocale_global_collate, + &__xlocale_global_ctype, + &__xlocale_global_monetary, + &__xlocale_global_numeric, + &__xlocale_global_time, + &__xlocale_global_messages + }, + 1, + 0, + 1, + 0 +}; + +static void*(*constructors[])(const char*, locale_t) = +{ + __collate_load, + __ctype_load, + __monetary_load, + __numeric_load, + __time_load, + __messages_load +}; + +static pthread_key_t locale_info_key; +static int fake_tls; +static locale_t thread_local_locale; + +static void init_key(void) +{ + pthread_key_create(&locale_info_key, xlocale_release); + pthread_setspecific(locale_info_key, (void*)42); + if (pthread_getspecific(locale_info_key) == (void*)42) { + pthread_setspecific(locale_info_key, 0); + } else { + fake_tls = 1; + } + __detect_path_locale(); +} + +static pthread_once_t once_control = PTHREAD_ONCE_INIT; + +static locale_t +get_thread_locale(void) +{ + _once(&once_control, init_key); + + return fake_tls ? thread_local_locale : + pthread_getspecific(locale_info_key); +} + +locale_t +__get_locale(void) +{ + locale_t l = get_thread_locale(); + return l ? l : &__xlocale_global_locale; + +} + +static void +set_thread_locale(locale_t loc) +{ + pthread_once(&once_control, init_key); + + if (NULL != loc) { + xlocale_retain((struct xlocale_refcounted*)loc); + } + locale_t old = pthread_getspecific(locale_info_key); + if ((NULL != old) && (loc != old)) { + xlocale_release((struct xlocale_refcounted*)old); + } + if (fake_tls) { + thread_local_locale = loc; + } else { + pthread_setspecific(locale_info_key, loc); + } +} + +/** + * Clean up a locale, once its reference count reaches zero. This function is + * called by xlocale_release(), it should not be called directly. + */ +static void +destruct_locale(void *l) +{ + locale_t loc = l; + for (int type=0 ; typecomponents[type]) { + xlocale_release(loc->components[type]); + } + } + if (loc->csym) { + free(loc->csym); + } + free(l); +} + +/** + * Allocates a new, uninitialised, locale. + */ +static locale_t +alloc_locale(void) +{ + locale_t new = calloc(sizeof(struct _xlocale), 1); + new->header.destructor = destruct_locale; + new->monetary_locale_changed = 1; + new->numeric_locale_changed = 1; + return new; +} +static void +copyflags(locale_t new, locale_t old) +{ + new->using_monetary_locale = old->using_monetary_locale; + new->using_numeric_locale = old->using_numeric_locale; + new->using_time_locale = old->using_time_locale; + new->using_messages_locale = old->using_messages_locale; +} + +static int dupcomponent(int type, locale_t base, locale_t new) +{ + /* Always copy from the global locale, since it has mutable components. */ + struct xlocale_component *src = base->components[type]; + if (&__xlocale_global_locale == base) { + new->components[type] = constructors[type](src->locale, new); + if (new->components[type]) { + strncpy(new->components[type]->locale, src->locale, ENCODING_LEN); + } + } else { + new->components[type] = xlocale_retain(base->components[type]); + } + return 0 != new->components[type]; +} + +/* + * Public interfaces. These are the five public functions described by the + * xlocale interface. + */ + +locale_t newlocale(int mask, const char *locale, locale_t base) +{ + int type; + const char *realLocale = locale; + int useenv = 0; + int success = 1; + + _once(&once_control, init_key); + + locale_t new = alloc_locale(); + if (NULL == new) { + return NULL; + } + + FIX_LOCALE(base); + copyflags(new, base); + + if (NULL == locale) { + realLocale = "C"; + } else if ('\0' == locale[0]) { + useenv = 1; + } + + for (type=0 ; typecomponents[type] = constructors[type](realLocale, new); + if (new->components[type]) { + strncpy(new->components[type]->locale, realLocale, ENCODING_LEN); + } else { + success = 0; + } + } else { + if (!dupcomponent(type, base, new)) { + success = 0; + } + } + mask >>= 1; + } + if (0 == success) { + xlocale_release(new); + new = NULL; + } + + return new; +} + +locale_t duplocale(locale_t base) +{ + locale_t new = alloc_locale(); + int type; + + _once(&once_control, init_key); + + if (NULL == new) { + return NULL; + } + + FIX_LOCALE(base); + copyflags(new, base); + + for (type=0 ; typecomponents[type]->locale; + } + mask >>= 1; + } + return NULL; +} + +/* + * Installs the specified locale_t as this thread's locale. + */ +locale_t uselocale(locale_t loc) +{ + locale_t old = get_thread_locale(); + if (NULL != loc) { + if (LC_GLOBAL_LOCALE == loc) { + loc = NULL; + } + set_thread_locale(loc); + } + return old ? old : LC_GLOBAL_LOCALE; +} + Index: lib/libc/locale/ascii.c =================================================================== --- lib/libc/locale/ascii.c (revision 225653) +++ lib/libc/locale/ascii.c (working copy) @@ -6,6 +6,11 @@ * This code is derived from software contributed to Berkeley by * Paul Borman at Krystal Technologies. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -56,17 +61,17 @@ size_t, size_t, mbstate_t * __restrict); int -_ascii_init(_RuneLocale *rl) +_ascii_init(struct xlocale_ctype *l,_RuneLocale *rl) { - __mbrtowc = _ascii_mbrtowc; - __mbsinit = _ascii_mbsinit; - __mbsnrtowcs = _ascii_mbsnrtowcs; - __wcrtomb = _ascii_wcrtomb; - __wcsnrtombs = _ascii_wcsnrtombs; - _CurrentRuneLocale = rl; - __mb_cur_max = 1; - __mb_sb_limit = 128; + l->__mbrtowc = _ascii_mbrtowc; + l->__mbsinit = _ascii_mbsinit; + l->__mbsnrtowcs = _ascii_mbsnrtowcs; + l->__wcrtomb = _ascii_wcrtomb; + l->__wcsnrtombs = _ascii_wcsnrtombs; + l->runes = rl; + l->__mb_cur_max = 1; + l->__mb_sb_limit = 128; return(0); } Index: lib/libc/locale/collate.h =================================================================== --- lib/libc/locale/collate.h (revision 225653) +++ lib/libc/locale/collate.h (working copy) @@ -3,6 +3,11 @@ * at Electronni Visti IA, Kiev, Ukraine. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -33,6 +38,7 @@ #include #include #include +#include "xlocale_private.h" #define STR_LEN 10 #define TABLE_SIZE 100 @@ -47,20 +53,26 @@ int prim, sec; }; -extern int __collate_load_error; -extern int __collate_substitute_nontrivial; #define __collate_substitute_table (*__collate_substitute_table_ptr) -extern u_char __collate_substitute_table[UCHAR_MAX + 1][STR_LEN]; #define __collate_char_pri_table (*__collate_char_pri_table_ptr) -extern struct __collate_st_char_pri __collate_char_pri_table[UCHAR_MAX + 1]; -extern struct __collate_st_chain_pri *__collate_chain_pri_table; +struct xlocale_collate { + struct xlocale_component header; + int __collate_load_error; + int __collate_substitute_nontrivial; + + u_char (*__collate_substitute_table_ptr)[UCHAR_MAX + 1][STR_LEN]; + struct __collate_st_char_pri (*__collate_char_pri_table_ptr)[UCHAR_MAX + 1]; + struct __collate_st_chain_pri *__collate_chain_pri_table; +}; + + __BEGIN_DECLS u_char *__collate_strdup(u_char *); -u_char *__collate_substitute(const u_char *); +u_char *__collate_substitute(struct xlocale_collate *, const u_char *); int __collate_load_tables(const char *); -void __collate_lookup(const u_char *, int *, int *, int *); -int __collate_range_cmp(int, int); +void __collate_lookup(struct xlocale_collate *, const u_char *, int *, int *, int *); +int __collate_range_cmp(struct xlocale_collate *, int, int); #ifdef COLLATE_DEBUG void __collate_print_tables(void); #endif Index: lib/libc/locale/wcstoumax.c =================================================================== --- lib/libc/locale/wcstoumax.c (revision 225653) +++ lib/libc/locale/wcstoumax.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -41,19 +46,21 @@ #include #include #include +#include "xlocale_private.h" /* * Convert a wide character string to a uintmax_t integer. */ uintmax_t -wcstoumax(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, - int base) +wcstoumax_l(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, + int base, locale_t locale) { const wchar_t *s; uintmax_t acc; wchar_t c; uintmax_t cutoff; int neg, any, cutlim; + FIX_LOCALE(locale); /* * See strtoimax for comments as to the logic used. @@ -61,7 +68,7 @@ s = nptr; do { c = *s++; - } while (iswspace(c)); + } while (iswspace_l(c, locale)); if (c == L'-') { neg = 1; c = *s++; @@ -86,8 +93,8 @@ cutlim = UINTMAX_MAX % base; for ( ; ; c = *s++) { #ifdef notyet - if (iswdigit(c)) - c = digittoint(c); + if (iswdigit_l(c, locale)) + c = digittoint_l(c, locale); else #endif if (c >= L'0' && c <= L'9') @@ -120,3 +127,9 @@ *endptr = (wchar_t *)(any ? s - 1 : nptr); return (acc); } +uintmax_t +wcstoumax(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, + int base) +{ + return wcstoumax_l(nptr, endptr, base, __get_locale()); +} Index: lib/libc/locale/mbtowc.c =================================================================== --- lib/libc/locale/mbtowc.c (revision 225653) +++ lib/libc/locale/mbtowc.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002-2004 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -32,19 +37,24 @@ #include "mblocal.h" int -mbtowc(wchar_t * __restrict pwc, const char * __restrict s, size_t n) +mbtowc_l(wchar_t * __restrict pwc, const char * __restrict s, size_t n, locale_t locale) { static const mbstate_t initial; - static mbstate_t mbs; size_t rval; + FIX_LOCALE(locale); if (s == NULL) { /* No support for state dependent encodings. */ - mbs = initial; + locale->mbtowc = initial; return (0); } - rval = __mbrtowc(pwc, s, n, &mbs); + rval = XLOCALE_CTYPE(locale)->__mbrtowc(pwc, s, n, &locale->mbtowc); if (rval == (size_t)-1 || rval == (size_t)-2) return (-1); return ((int)rval); } +int +mbtowc(wchar_t * __restrict pwc, const char * __restrict s, size_t n) +{ + return mbtowc_l(pwc, s, n, __get_locale()); +} Index: lib/libc/locale/wcstoul.c =================================================================== --- lib/libc/locale/wcstoul.c (revision 225653) +++ lib/libc/locale/wcstoul.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -35,18 +40,21 @@ #include #include #include +#include "xlocale_private.h" /* * Convert a wide character string to an unsigned long integer. */ unsigned long -wcstoul(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, int base) +wcstoul_l(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, + int base, locale_t locale) { const wchar_t *s; unsigned long acc; wchar_t c; unsigned long cutoff; int neg, any, cutlim; + FIX_LOCALE(locale); /* * See strtol for comments as to the logic used. @@ -54,7 +62,7 @@ s = nptr; do { c = *s++; - } while (iswspace(c)); + } while (iswspace_l(c, locale)); if (c == L'-') { neg = 1; c = *s++; @@ -79,8 +87,8 @@ cutlim = ULONG_MAX % base; for ( ; ; c = *s++) { #ifdef notyet - if (iswdigit(c)) - c = digittoint(c); + if (iswdigit_l(c, locale)) + c = digittoint_l(c, locale); else #endif if (c >= L'0' && c <= L'9') @@ -113,3 +121,8 @@ *endptr = (wchar_t *)(any ? s - 1 : nptr); return (acc); } +unsigned long +wcstoul(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, int base) +{ + return wcstoul_l(nptr, endptr, base, __get_locale()); +} Index: lib/libc/locale/gb2312.c =================================================================== --- lib/libc/locale/gb2312.c (revision 225653) +++ lib/libc/locale/gb2312.c (working copy) @@ -3,6 +3,11 @@ * Copyright (c) 2003 David Xu * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -35,8 +40,6 @@ #include #include "mblocal.h" -extern int __mb_sb_limit; - static size_t _GB2312_mbrtowc(wchar_t * __restrict, const char * __restrict, size_t, mbstate_t * __restrict); static int _GB2312_mbsinit(const mbstate_t *); @@ -49,15 +52,15 @@ } _GB2312State; int -_GB2312_init(_RuneLocale *rl) +_GB2312_init(struct xlocale_ctype *l, _RuneLocale *rl) { - _CurrentRuneLocale = rl; - __mbrtowc = _GB2312_mbrtowc; - __wcrtomb = _GB2312_wcrtomb; - __mbsinit = _GB2312_mbsinit; - __mb_cur_max = 2; - __mb_sb_limit = 128; + l->runes = rl; + l->__mbrtowc = _GB2312_mbrtowc; + l->__wcrtomb = _GB2312_wcrtomb; + l->__mbsinit = _GB2312_mbsinit; + l->__mb_cur_max = 2; + l->__mb_sb_limit = 128; return (0); } Index: lib/libc/locale/Symbol.map =================================================================== --- lib/libc/locale/Symbol.map (revision 225653) +++ lib/libc/locale/Symbol.map (working copy) @@ -99,6 +99,98 @@ iswctype; wctype; wcwidth; + newlocale; + duplocale; + freelocale; + querylocale; + uselocale; + __getCurrentRuneLocale; + btowc_l; + localeconv_l; + mblen_l; + mbrlen_l; + mbrtowc_l; + mbsinit_l; + mbsnrtowcs_l; + mbsrtowcs_l; + mbstowcs_l; + mbtowc_l; + nl_langinfo_l; + strcoll_l; + strfmon_l; + strftime_l; + strptime_l; + strxfrm_l; + wcrtomb_l; + wcscoll_l; + wcsnrtombs_l; + wcsrtombs_l; + wcstombs_l; + wcsxfrm_l; + wctob_l; + wctomb_l; + ___tolower_l; + ___toupper_l; + ___runetype_l; + digittoint_l; + isalnum_l; + isalpha_l; + isblank_l; + iscntrl_l; + isdigit_l; + isgraph_l; + ishexnumber_l; + isideogram_l; + islower_l; + isnumber_l; + isphonogram_l; + isprint_l; + ispunct_l; + isrune_l; + isspace_l; + isspecial_l; + isupper_l; + isxdigit_l; + tolower_l; + toupper_l; + iswalnum_l; + iswalpha_l; + iswblank_l; + iswcntrl_l; + iswdigit_l; + iswgraph_l; + iswhexnumber_l; + iswideogram_l; + iswlower_l; + iswnumber_l; + iswphonogram_l; + iswprint_l; + iswpunct_l; + iswrune_l; + iswspace_l; + iswspecial_l; + iswupper_l; + iswxdigit_l; + towlower_l; + towupper_l; + iswctype_l; + wctype_l; + nextwctype_l; + ___mb_cur_max; + ___mb_cur_max_l; + towctrans_l; + wctrans_l; + wcsftime_l; + wcstod_l; + wcstof_l; + wcstoimax_l; + wcstol_l; + wcstold_l; + wcstoll_l; + wcstoul_l; + wcstoull_l; + wcstoumax_l; + __runes_for_locale; }; FBSDprivate_1.0 { Index: lib/libc/locale/mblocal.h =================================================================== --- lib/libc/locale/mblocal.h (revision 225653) +++ lib/libc/locale/mblocal.h (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2004 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -30,35 +35,45 @@ #define _MBLOCAL_H_ #include +#include "xlocale_private.h" + /* - * Rune initialization function prototypes. + * Conversion function pointers for current encoding. */ -int _none_init(_RuneLocale *); -int _ascii_init(_RuneLocale *); -int _UTF8_init(_RuneLocale *); -int _EUC_init(_RuneLocale *); -int _GB18030_init(_RuneLocale *); -int _GB2312_init(_RuneLocale *); -int _GBK_init(_RuneLocale *); -int _BIG5_init(_RuneLocale *); -int _MSKanji_init(_RuneLocale *); +struct xlocale_ctype { + struct xlocale_component header; + _RuneLocale *runes; + size_t (*__mbrtowc)(wchar_t * __restrict, const char * __restrict, + size_t, mbstate_t * __restrict); + int (*__mbsinit)(const mbstate_t *); + size_t (*__mbsnrtowcs)(wchar_t * __restrict, const char ** __restrict, + size_t, size_t, mbstate_t * __restrict); + size_t (*__wcrtomb)(char * __restrict, wchar_t, mbstate_t * __restrict); + size_t (*__wcsnrtombs)(char * __restrict, const wchar_t ** __restrict, + size_t, size_t, mbstate_t * __restrict); + int __mb_cur_max; + int __mb_sb_limit; +}; +#define XLOCALE_CTYPE(x) ((struct xlocale_ctype*)(x)->components[XLC_CTYPE]) +extern struct xlocale_ctype __xlocale_global_ctype; /* - * Conversion function pointers for current encoding. + * Rune initialization function prototypes. */ -extern size_t (*__mbrtowc)(wchar_t * __restrict, const char * __restrict, - size_t, mbstate_t * __restrict); -extern int (*__mbsinit)(const mbstate_t *); -extern size_t (*__mbsnrtowcs)(wchar_t * __restrict, const char ** __restrict, - size_t, size_t, mbstate_t * __restrict); -extern size_t (*__wcrtomb)(char * __restrict, wchar_t, mbstate_t * __restrict); -extern size_t (*__wcsnrtombs)(char * __restrict, const wchar_t ** __restrict, - size_t, size_t, mbstate_t * __restrict); +int _none_init(struct xlocale_ctype *, _RuneLocale *); +int _ascii_init(struct xlocale_ctype *, _RuneLocale *); +int _UTF8_init(struct xlocale_ctype *, _RuneLocale *); +int _EUC_init(struct xlocale_ctype *, _RuneLocale *); +int _GB18030_init(struct xlocale_ctype *, _RuneLocale *); +int _GB2312_init(struct xlocale_ctype *, _RuneLocale *); +int _GBK_init(struct xlocale_ctype *, _RuneLocale *); +int _BIG5_init(struct xlocale_ctype *, _RuneLocale *); +int _MSKanji_init(struct xlocale_ctype *, _RuneLocale *); extern size_t __mbsnrtowcs_std(wchar_t * __restrict, const char ** __restrict, - size_t, size_t, mbstate_t * __restrict); + size_t, size_t, mbstate_t * __restrict); extern size_t __wcsnrtombs_std(char * __restrict, const wchar_t ** __restrict, - size_t, size_t, mbstate_t * __restrict); + size_t, size_t, mbstate_t * __restrict); #endif /* _MBLOCAL_H_ */ Index: lib/libc/locale/DESIGN.xlocale =================================================================== --- lib/libc/locale/DESIGN.xlocale (revision 0) +++ lib/libc/locale/DESIGN.xlocale (revision 0) @@ -0,0 +1,157 @@ +Design of xlocale +================= + +The xlocale APIs come from Darwin, although a subset is now part of POSIX 2008. +They fall into two broad categories: + +- Manipulation of per-thread locales (POSIX) +- Locale-aware functions taking an explicit locale argument (Darwin) + +This document describes the implementation of these APIs for FreeBSD. + +Goals +----- + +The overall goal of this implementation is to be compatible with the Darwin +version. Additionally, it should include minimal changes to the existing +locale code. A lot of the existing locale code originates with 4BSD or earlier +and has had over a decade of testing. Replacing this code, unless absolutely +necessary, gives us the potential for more bugs without much benefit. + +With this in mind, various libc-private functions have been modified to take a +locale_t parameter. This causes a compiler error if they are accidentally +called without a locale. This approach was taken, rather than adding _l +variants of these functions, to make it harder for accidental uses of the +global-locale versions to slip in. + +Locale Objects +-------------- + +A locale is encapsulated in a `locale_t`, which is an opaque type: a pointer to +a `struct _xlocale`. The name `_xlocale` is unfortunate, as it does not fit +well with existing conventions, but is used because this is the name the Darwin +implementation gives to this structure and so may be used by existing (bad) code. + +This structure should include all of the information corresponding to a locale. +A locale_t is almost immutable after creation. There are no functions that modify it, +and it can therefore be used without locking. It is the responsibility of the +caller to ensure that a locale is not deallocated during a call that uses it. + +Each locale contains a number of components, one for each of the categories +supported by `setlocale()`. These are likewise immutable after creation. This +differs from the Darwin implementation, which includes a deprecated +`setinvalidrune()` function that can modify the rune locale. + +The exception to these mutability rules is a set of `mbstate_t` flags stored +with each locale. These are used by various functions that previously had a +static local `mbstate_t` variable. + +The components are reference counted, and so can be aliased between locale +objects. This makes copying locales very cheap. + +The Global Locale +----------------- + +All locales and locale components are reference counted. The global locale, +however, is special. It, and all of its components, are static and so no +malloc() memory is required when using a single locale. + +This means that threads using the global locale are subject to the same +constraints as with the pre-xlocale libc. Calls to any locale-aware functions +in threads using the global locale, while modifying the global locale, have +undefined behaviour. + +Because of this, we have to ensure that we always copy the components of the +global locale, rather than alias them. + +It would be cleaner to simply remove the special treatment of the global locale +and have a locale_t lazily allocated for the global context. This would cost a +little more `malloc()` memory, so is not done in the initial version. + +Caching +------- + +The existing locale implementation included several ad-hoc caching layers. +None of these were thread safe. Caching is only really of use for supporting +the pattern where the locale is briefly changed to something and then changed +back. + +The current xlocale implementation removes the caching entirely. This pattern +is not one that should be encouraged. If you need to make some calls with a +modified locale, then you should use the _l suffix versions of the calls, +rather than switch the global locale. If you do need to temporarily switch the +locale and then switch it back, `uselocale()` provides a way of doing this very +easily: It returns the old locale, which can then be passed to a subsequent +call to `uselocale()` to restore it, without the need to load any locale data +from the disk. + +If, in the future, it is determined that caching is beneficial, it can be added +quite easily in xlocale.c. Given, however, that any locale-aware call is going +to be a preparation for presenting data to the user, and so is invariably going +to be part of an I/O operation, this seems like a case of premature +optimisation. + +localeconv +---------- + +The `localeconv()` function is an exception to the immutable-after-creation +rule. In the classic implementation, this function returns a pointer to some +global storage, which is initialised with the data from the current locale. +This is not possible in a multithreaded environment, with multiple locales. + +Instead, each locale contains a `struct lconv` that is lazily initialised on +calls to `localeconv()`. This is not protected by any locking, however this is +still safe on any machine where word-sized stores are atomic: two concurrent +calls will write the same data into the structure. + +Explicit Locale Calls +--------------------- + +A large number of functions have been modified to take an explicit `locale_t` +parameter. The old APIs are then reimplemented with a call to `__get_locale()` +to supply the `locale_t` parameter. This is in line with the Darwin public +APIs, but also simplifies the modifications to these functions. The +`__get_locale()` function is now the only way to access the current locale +within libc. All of the old globals have gone, so there is now a linker error +if any functions attempt to use them. + +The ctype.h functions are a little different. These are not implemented in +terms of their locale-aware versions, for performance reasons. Each of these +is implemented as a short inline function. + +Differences to Darwin APIs +-------------------------- + +`strtoq_l()` and `strtouq_l() `are not provided. These are extensions to +deprecated functions - we should not be encouraging people to use deprecated +interfaces. + +Locale Placeholders +------------------- + +The pointer values 0 and -1 have special meanings as `locale_t` values. Any +public function that accepts a `locale_t` parameter must use the `FIX_LOCALE()` +macro on it before using it. For efficiency, this can be emitted in functions +which *only* use their locale parameter as an argument to another public +function, as the callee will do the `FIX_LOCALE()` itself. + +Potential Improvements +---------------------- + +Currently, the current rune set is accessed via a function call. This makes it +fairly expensive to use any of the ctype.h functions. We could improve this +quite a lot by storing the rune locale data in a __thread-qualified variable. + +Several of the existing FreeBSD locale-aware functions appear to be wrong. For +example, most of the `strto*()` family should probably use `digittoint_l()`, +but instead they assume ASCII. These will break if using a character encoding +that does not put numbers and the letters A-F in the same location as ASCII. +Some functions, like `strcoll()` only work on single-byte encodings. No +attempt has been made to fix existing limitations in the libc functions other +than to add support for xlocale. + +Intuitively, setting a thread-local locale should ensure that all locale-aware +functions can be used safely from that thread. In fact, this is not the case +in either this implementation or the Darwin one. You must call `duplocale()` +or `newlocale()` before calling `uselocale()`. This is a bit ugly, and it +would be better if libc ensure that every thread had its own locale object. Index: lib/libc/locale/mbsrtowcs.c =================================================================== --- lib/libc/locale/mbsrtowcs.c (revision 225653) +++ lib/libc/locale/mbsrtowcs.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002-2004 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -34,12 +39,17 @@ #include "mblocal.h" size_t +mbsrtowcs_l(wchar_t * __restrict dst, const char ** __restrict src, size_t len, + mbstate_t * __restrict ps, locale_t locale) +{ + FIX_LOCALE(locale); + if (ps == NULL) + ps = &locale->mbsrtowcs; + return (XLOCALE_CTYPE(locale)->__mbsnrtowcs(dst, src, SIZE_T_MAX, len, ps)); +} +size_t mbsrtowcs(wchar_t * __restrict dst, const char ** __restrict src, size_t len, mbstate_t * __restrict ps) { - static mbstate_t mbs; - - if (ps == NULL) - ps = &mbs; - return (__mbsnrtowcs(dst, src, SIZE_T_MAX, len, ps)); + return mbsrtowcs_l(dst, src, len, ps, __get_locale()); } Index: lib/libc/locale/utf8.c =================================================================== --- lib/libc/locale/utf8.c (revision 225653) +++ lib/libc/locale/utf8.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002-2004 Tim J. Robbins * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -55,22 +60,22 @@ } _UTF8State; int -_UTF8_init(_RuneLocale *rl) +_UTF8_init(struct xlocale_ctype *l, _RuneLocale *rl) { - __mbrtowc = _UTF8_mbrtowc; - __wcrtomb = _UTF8_wcrtomb; - __mbsinit = _UTF8_mbsinit; - __mbsnrtowcs = _UTF8_mbsnrtowcs; - __wcsnrtombs = _UTF8_wcsnrtombs; - _CurrentRuneLocale = rl; - __mb_cur_max = 6; + l->__mbrtowc = _UTF8_mbrtowc; + l->__wcrtomb = _UTF8_wcrtomb; + l->__mbsinit = _UTF8_mbsinit; + l->__mbsnrtowcs = _UTF8_mbsnrtowcs; + l->__wcsnrtombs = _UTF8_wcsnrtombs; + l->runes = rl; + l->__mb_cur_max = 6; /* * UCS-4 encoding used as the internal representation, so * slots 0x0080-0x00FF are occuped and must be excluded * from the single byte ctype by setting the limit. */ - __mb_sb_limit = 128; + l->__mb_sb_limit = 128; return (0); } Index: lib/libc/locale/collcmp.c =================================================================== --- lib/libc/locale/collcmp.c (revision 225653) +++ lib/libc/locale/collcmp.c (working copy) @@ -2,6 +2,11 @@ * Copyright (C) 1996 by Andrey A. Chernov, Moscow, Russia. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -28,17 +33,20 @@ __FBSDID("$FreeBSD$"); #include +#include #include "collate.h" /* * Compare two characters using collate */ -int __collate_range_cmp(int c1, int c2) +int __collate_range_cmp(struct xlocale_collate *table, int c1, int c2) { static char s1[2], s2[2]; s1[0] = c1; s2[0] = c2; - return (strcoll(s1, s2)); + struct _xlocale l = {{0}}; + l.components[XLC_COLLATE] = (struct xlocale_component *)table; + return (strcoll_l(s1, s2, &l)); } Index: lib/libc/locale/Makefile.inc =================================================================== --- lib/libc/locale/Makefile.inc (revision 225653) +++ lib/libc/locale/Makefile.inc (working copy) @@ -5,7 +5,7 @@ .PATH: ${.CURDIR}/${LIBC_ARCH}/locale ${.CURDIR}/locale SRCS+= ascii.c big5.c btowc.c collate.c collcmp.c euc.c fix_grouping.c \ - gb18030.c gb2312.c gbk.c isctype.c iswctype.c \ + gb18030.c gb2312.c gbk.c ctype.c isctype.c iswctype.c \ ldpart.c lmessages.c lmonetary.c lnumeric.c localeconv.c mblen.c \ mbrlen.c \ mbrtowc.c mbsinit.c mbsnrtowcs.c \ @@ -20,7 +20,8 @@ wcstoimax.c wcstol.c wcstold.c wcstoll.c \ wcstombs.c \ wcstoul.c wcstoull.c wcstoumax.c wctob.c wctomb.c wctrans.c wctype.c \ - wcwidth.c + wcwidth.c\ + xlocale.c SYM_MAPS+=${.CURDIR}/locale/Symbol.map Index: lib/libc/locale/wcstof.c =================================================================== --- lib/libc/locale/wcstof.c (revision 225653) +++ lib/libc/locale/wcstof.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002, 2003 Tim J. Robbins * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -30,12 +35,14 @@ #include #include #include +#include "xlocale_private.h" /* * See wcstod() for comments as to the logic used. */ float -wcstof(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr) +wcstof_l(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, + locale_t locale) { static const mbstate_t initial; mbstate_t mbs; @@ -43,13 +50,14 @@ char *buf, *end; const wchar_t *wcp; size_t len; + FIX_LOCALE(locale); - while (iswspace(*nptr)) + while (iswspace_l(*nptr, locale)) nptr++; wcp = nptr; mbs = initial; - if ((len = wcsrtombs(NULL, &wcp, 0, &mbs)) == (size_t)-1) { + if ((len = wcsrtombs_l(NULL, &wcp, 0, &mbs, locale)) == (size_t)-1) { if (endptr != NULL) *endptr = (wchar_t *)nptr; return (0.0); @@ -57,9 +65,9 @@ if ((buf = malloc(len + 1)) == NULL) return (0.0); mbs = initial; - wcsrtombs(buf, &wcp, len + 1, &mbs); + wcsrtombs_l(buf, &wcp, len + 1, &mbs, locale); - val = strtof(buf, &end); + val = strtof_l(buf, &end, locale); if (endptr != NULL) *endptr = (wchar_t *)nptr + (end - buf); @@ -68,3 +76,8 @@ return (val); } +float +wcstof(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr) +{ + return wcstof_l(nptr, endptr, __get_locale()); +} Index: lib/libc/locale/localeconv.3 =================================================================== --- lib/libc/locale/localeconv.3 (revision 225653) +++ lib/libc/locale/localeconv.3 (working copy) @@ -44,6 +44,9 @@ .In locale.h .Ft struct lconv * .Fn localeconv "void" +.In xlocale.h +.Ft struct lconv * +.Fn localeconv_l "locale_t locale" .Sh DESCRIPTION The .Fn localeconv @@ -196,6 +199,11 @@ A .Dv CHAR_MAX result similarly denotes an unavailable value. +.Pp +The +.Fn localeconv_l +function takes an explicit locale parameter. For more information, see +.Xr xlocale 3 . .Sh RETURN VALUES The .Fn localeconv @@ -204,6 +212,13 @@ .Xr setlocale 3 or .Fn localeconv . +The return value for +.Fn localeconv_l +is stored with the locale. It will remain valid until a subsequent call to +.Xr freelocale 3 . +If a thread-local locale is in effect then the return value from +.Fn localeconv +will remain valid until the locale is destroyed. .Sh ERRORS No errors are defined. .Sh SEE ALSO Index: lib/libc/locale/mbsinit.c =================================================================== --- lib/libc/locale/mbsinit.c (revision 225653) +++ lib/libc/locale/mbsinit.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002-2004 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -31,8 +36,13 @@ #include "mblocal.h" int +mbsinit_l(const mbstate_t *ps, locale_t locale) +{ + FIX_LOCALE(locale); + return (XLOCALE_CTYPE(locale)->__mbsinit(ps)); +} +int mbsinit(const mbstate_t *ps) { - - return (__mbsinit(ps)); + return mbsinit_l(ps, __get_locale()); } Index: lib/libc/locale/wcwidth.c =================================================================== --- lib/libc/locale/wcwidth.c (revision 225653) +++ lib/libc/locale/wcwidth.c (working copy) @@ -10,6 +10,11 @@ * This code is derived from software contributed to Berkeley by * Paul Borman at Krystal Technologies. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -39,12 +44,18 @@ __FBSDID("$FreeBSD$"); #include +#include +#include #undef wcwidth int wcwidth(wchar_t wc) { - return (__wcwidth(wc)); } +int +wcwidth_l(wchar_t wc, locale_t locale) +{ + return (__wcwidth_l(wc, locale)); +} Index: lib/libc/locale/setlocale.c =================================================================== --- lib/libc/locale/setlocale.c (revision 225653) +++ lib/libc/locale/setlocale.c (working copy) @@ -95,7 +95,7 @@ static char *currentlocale(void); static char *loadlocale(int); -static const char *__get_locale_env(int); +const char *__get_locale_env(int); char * setlocale(category, locale) @@ -278,13 +278,14 @@ if (func(new) != _LDP_ERROR) { (void)strcpy(old, new); + (void)strcpy(__xlocale_global_locale.components[category-1]->locale, new); return (old); } return (NULL); } -static const char * +const char * __get_locale_env(category) int category; { Index: lib/libc/locale/runetype.c =================================================================== --- lib/libc/locale/runetype.c (revision 225653) +++ lib/libc/locale/runetype.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Paul Borman at Krystal Technologies. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -36,12 +41,15 @@ #include #include #include +#include +#include "mblocal.h" unsigned long -___runetype(__ct_rune_t c) +___runetype_l(__ct_rune_t c, locale_t locale) { size_t lim; - _RuneRange *rr = &_CurrentRuneLocale->__runetype_ext; + FIX_LOCALE(locale); + _RuneRange *rr = &(XLOCALE_CTYPE(locale)->runes->__runetype_ext); _RuneEntry *base, *re; if (c < 0 || c == EOF) @@ -64,3 +72,18 @@ return(0L); } +unsigned long +___runetype(__ct_rune_t c) +{ + return ___runetype_l(c, __get_locale()); +} + +int ___mb_cur_max(void) +{ + return XLOCALE_CTYPE(__get_locale())->__mb_cur_max; +} +int ___mb_cur_max_l(locale_t locale) +{ + FIX_LOCALE(locale); + return XLOCALE_CTYPE(locale)->__mb_cur_max; +} Index: lib/libc/locale/btowc.c =================================================================== --- lib/libc/locale/btowc.c (revision 225653) +++ lib/libc/locale/btowc.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002, 2003 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -32,12 +37,13 @@ #include "mblocal.h" wint_t -btowc(int c) +btowc_l(int c, locale_t l) { static const mbstate_t initial; mbstate_t mbs = initial; char cc; wchar_t wc; + FIX_LOCALE(l); if (c == EOF) return (WEOF); @@ -47,7 +53,12 @@ * counts. */ cc = (char)c; - if (__mbrtowc(&wc, &cc, 1, &mbs) > 1) + if (XLOCALE_CTYPE(l)->__mbrtowc(&wc, &cc, 1, &mbs) > 1) return (WEOF); return (wc); } +wint_t +btowc(int c) +{ + return btowc_l(c, __get_locale()); +} Index: lib/libc/locale/mbrlen.c =================================================================== --- lib/libc/locale/mbrlen.c (revision 225653) +++ lib/libc/locale/mbrlen.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002-2004 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -31,11 +36,16 @@ #include "mblocal.h" size_t -mbrlen(const char * __restrict s, size_t n, mbstate_t * __restrict ps) +mbrlen_l(const char * __restrict s, size_t n, mbstate_t * __restrict ps, locale_t locale) { - static mbstate_t mbs; - + FIX_LOCALE(locale); if (ps == NULL) - ps = &mbs; - return (__mbrtowc(NULL, s, n, ps)); + ps = &locale->mbrlen; + return (XLOCALE_CTYPE(locale)->__mbrtowc(NULL, s, n, ps)); } + +size_t +mbrlen(const char * __restrict s, size_t n, mbstate_t * __restrict ps) +{ + return mbrlen_l(s, n, ps, __get_locale()); +} Index: lib/libc/locale/lmessages.c =================================================================== --- lib/libc/locale/lmessages.c (revision 225653) +++ lib/libc/locale/lmessages.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2001 Alexey Zelkin * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -36,6 +41,14 @@ #define LCMESSAGES_SIZE_MIN \ (offsetof(struct lc_messages_T, yesstr) / sizeof(char *)) +struct xlocale_messages { + struct xlocale_component header; + char *buffer; + struct lc_messages_T locale; +}; + +struct xlocale_messages __xlocale_global_messages; + static char empty[] = ""; static const struct lc_messages_T _C_messages_locale = { @@ -45,33 +58,55 @@ "no" /* nostr */ }; -static struct lc_messages_T _messages_locale; -static int _messages_using_locale; -static char *_messages_locale_buf; +static void destruct_messages(void *v) +{ + struct xlocale_messages *l = v; + if (l->buffer) + free(l->buffer); + free(l); +} -int -__messages_load_locale(const char *name) +static int +messages_load_locale(struct xlocale_messages *loc, int *using_locale, const char *name) { int ret; + struct lc_messages_T *l = &loc->locale; - ret = __part_load_locale(name, &_messages_using_locale, - &_messages_locale_buf, "LC_MESSAGES", + ret = __part_load_locale(name, using_locale, + &loc->buffer, "LC_MESSAGES", LCMESSAGES_SIZE_FULL, LCMESSAGES_SIZE_MIN, - (const char **)&_messages_locale); + (const char **)l); if (ret == _LDP_LOADED) { - if (_messages_locale.yesstr == NULL) - _messages_locale.yesstr = empty; - if (_messages_locale.nostr == NULL) - _messages_locale.nostr = empty; + if (l->yesstr == NULL) + l->yesstr = empty; + if (l->nostr == NULL) + l->nostr = empty; } return (ret); } +int +__messages_load_locale(const char *name) +{ + return messages_load_locale(&__xlocale_global_messages, + &__xlocale_global_locale.using_messages_locale, name); +} +void * +__messages_load(const char *name, locale_t l) +{ + struct xlocale_messages *new = calloc(sizeof(struct xlocale_messages), 1); + new->header.header.destructor = destruct_messages; + if (messages_load_locale(new, &l->using_messages_locale, name) == _LDP_ERROR) { + xlocale_release(new); + return NULL; + } + return new; +} struct lc_messages_T * -__get_current_messages_locale(void) +__get_current_messages_locale(locale_t loc) { - return (_messages_using_locale - ? &_messages_locale + return (loc->using_messages_locale + ? &((struct xlocale_messages *)loc->components[XLC_MESSAGES])->locale : (struct lc_messages_T *)&_C_messages_locale); } Index: lib/libc/locale/big5.c =================================================================== --- lib/libc/locale/big5.c (revision 225653) +++ lib/libc/locale/big5.c (working copy) @@ -6,6 +6,11 @@ * This code is derived from software contributed to Berkeley by * Paul Borman at Krystal Technologies. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -62,15 +67,15 @@ } _BIG5State; int -_BIG5_init(_RuneLocale *rl) +_BIG5_init(struct xlocale_ctype *l, _RuneLocale *rl) { - __mbrtowc = _BIG5_mbrtowc; - __wcrtomb = _BIG5_wcrtomb; - __mbsinit = _BIG5_mbsinit; - _CurrentRuneLocale = rl; - __mb_cur_max = 2; - __mb_sb_limit = 128; + l->__mbrtowc = _BIG5_mbrtowc; + l->__wcrtomb = _BIG5_wcrtomb; + l->__mbsinit = _BIG5_mbsinit; + l->runes = rl; + l->__mb_cur_max = 2; + l->__mb_sb_limit = 128; return (0); } Index: lib/libc/locale/lmessages.h =================================================================== --- lib/libc/locale/lmessages.h (revision 225653) +++ lib/libc/locale/lmessages.h (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2000, 2001 Alexey Zelkin * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -29,6 +34,8 @@ #ifndef _LMESSAGES_H_ #define _LMESSAGES_H_ +#include "xlocale_private.h" + struct lc_messages_T { const char *yesexpr; const char *noexpr; @@ -36,7 +43,7 @@ const char *nostr; }; -struct lc_messages_T *__get_current_messages_locale(void); +struct lc_messages_T *__get_current_messages_locale(locale_t); int __messages_load_locale(const char *); #endif /* !_LMESSAGES_H_ */ Index: lib/libc/locale/duplocale.3 =================================================================== --- lib/libc/locale/duplocale.3 (revision 0) +++ lib/libc/locale/duplocale.3 (revision 0) @@ -0,0 +1,76 @@ +.\" Copyright (c) 2011 The FreeBSD Foundation +.\" All rights reserved. +.\" +.\" This documentation was written by David Chisnall under sponsorship from +.\" the FreeBSD Foundation. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.Dd September 17 2011 +.Dt DUPLOCALE 3 +.Os +.Sh NAME +.Nm duplocale +.Nd duplicate an locale +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.In xlocale.h +.Ft locale_t +.Fn duplocale "locale_t locale" +.Sh DESCRIPTION +Duplicates an existing +.Fa locale_t +returning a new +.Fa locale_t +that refers to the same locale values but has independent internal state. +Various functions, such as +.Xr mblen 3 +require presistent state. These functions formerly used static variables and +calls to them from multiple threads had undefined behavior. They now use +fields in the +.Fa locale_t +associated with the current thread by +.Xr uselocale 3 . +These calls are therefore only thread safe on threads with a unique per-thread +locale. +.Pt +The locale returned by this call must be freed with +.Xr freelocale 3 . +.Sh BUGS +Ideally, +.Xr uselocale 3 +should make a copy of the +.Fa locale_t +implicitly to ensure thread safety, and a copy of the global locale should be +installed lazily on each thread. The FreeBSD implementation does not do this, +for compatibility with Darwin. +.Sh SEE ALSO +.Xr freelocale 3 , +.Xr localeconv 3 , +.Xr newlocale 3 , +.Xr querylocale 3 , +.Xr uselocale 3 , +.Xr xlocale 3 +.Sh STANDARDS +This function, conforms to +.St -p1003.1-2008 Index: lib/libc/locale/uselocale.3 =================================================================== --- lib/libc/locale/uselocale.3 (revision 0) +++ lib/libc/locale/uselocale.3 (revision 0) @@ -0,0 +1,60 @@ +.\" Copyright (c) 2011 The FreeBSD Foundation +.\" All rights reserved. +.\" +.\" This documentation was written by David Chisnall under sponsorship from +.\" the FreeBSD Foundation. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)ctype.3 8.1 (Berkeley) 6/4/93 +.\" $FreeBSD: head/lib/libc/locale/ctype.3 196820 2009-09-04 07:44:58Z des $ +.\" +.Dd September 17 2011 +.Dt USELOCALE 3 +.Os +.Sh NAME +.Nm uselocale +.Nd Sets a thread-local locale. +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.In xlocale.h +.Ft locale_t +.Fn uselocale "locale_t locale" +.Sh DESCRIPTION +Specifies the locale for this thread to use. Specifying +.Fa LC_GLOBAL_LOCALE +disables the per-thread locale, while NULL returns the current locale without +setting a new one. +.Sh RETURN VALUES +Returns the previous locale, or LC_GLOBAL_LOCALE if this thread has no locale +associated with it. +.Sh SEE ALSO +.Xr duplocale 3 , +.Xr freelocale 3 , +.Xr localeconv 3 , +.Xr newlocale 3 , +.Xr querylocale 3 , +.Xr xlocale 3 +.Sh STANDARDS +This function, conforms to +.St -p1003.1-2008 Index: lib/libc/locale/freelocale.3 =================================================================== --- lib/libc/locale/freelocale.3 (revision 0) +++ lib/libc/locale/freelocale.3 (revision 0) @@ -0,0 +1,60 @@ +.\" Copyright (c) 2011 The FreeBSD Foundation +.\" All rights reserved. +.\" +.\" This documentation was written by David Chisnall under sponsorship from +.\" the FreeBSD Foundation. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.Dd September 17 2011 +.Dt FREELOCALE 3 +.Os +.Sh NAME +.Nm freelocale +.Nd Frees a locale created with +.Xr duplocale 3 +or +.Xr newlocale 3 . +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.In xlocale.h +.Ft int +.Fn freelocale "locale_t locale" +.Sh DESCRIPTION +Frees a +.Fa locale_t . +This relinquishes any resources held exclusively by this locale. Note that +locales share reference-counted components, so a call to this function is not +guaranteed to free all of the components. +.Sh RETURN VALUES +Returns 0 on success or -1 on error. +.Sh SEE ALSO +.Xr duplocale 3 , +.Xr localeconv 3 , +.Xr newlocale 3 , +.Xr querylocale 3 , +.Xr uselocale 3 , +.Xr xlocale 3 +.Sh STANDARDS +This function, conforms to +.St -p1003.1-2008 . Index: lib/libc/locale/wcsrtombs.c =================================================================== --- lib/libc/locale/wcsrtombs.c (revision 225653) +++ lib/libc/locale/wcsrtombs.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002-2004 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -34,12 +39,18 @@ #include "mblocal.h" size_t +wcsrtombs_l(char * __restrict dst, const wchar_t ** __restrict src, size_t len, + mbstate_t * __restrict ps, locale_t locale) +{ + FIX_LOCALE(locale); + if (ps == NULL) + ps = &locale->wcsrtombs; + return (XLOCALE_CTYPE(locale)->__wcsnrtombs(dst, src, SIZE_T_MAX, len, ps)); +} + +size_t wcsrtombs(char * __restrict dst, const wchar_t ** __restrict src, size_t len, mbstate_t * __restrict ps) { - static mbstate_t mbs; - - if (ps == NULL) - ps = &mbs; - return (__wcsnrtombs(dst, src, SIZE_T_MAX, len, ps)); + return wcsrtombs_l(dst, src, len, ps, __get_locale()); } Index: lib/libc/locale/localeconv.c =================================================================== --- lib/libc/locale/localeconv.c (revision 225653) +++ lib/libc/locale/localeconv.c (working copy) @@ -3,6 +3,11 @@ * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -48,25 +53,24 @@ * lconv structure are computed only when the monetary or numeric * locale has been changed. */ -int __mlocale_changed = 1; -int __nlocale_changed = 1; /* * Return the current locale conversion. */ struct lconv * -localeconv() +localeconv_l(locale_t loc) { - static struct lconv ret; + FIX_LOCALE(loc); + struct lconv *ret = &loc->lconv; - if (__mlocale_changed) { + if (loc->monetary_locale_changed) { /* LC_MONETARY part */ struct lc_monetary_T * mptr; -#define M_ASSIGN_STR(NAME) (ret.NAME = (char*)mptr->NAME) -#define M_ASSIGN_CHAR(NAME) (ret.NAME = mptr->NAME[0]) +#define M_ASSIGN_STR(NAME) (ret->NAME = (char*)mptr->NAME) +#define M_ASSIGN_CHAR(NAME) (ret->NAME = mptr->NAME[0]) - mptr = __get_current_monetary_locale(); + mptr = __get_current_monetary_locale(loc); M_ASSIGN_STR(int_curr_symbol); M_ASSIGN_STR(currency_symbol); M_ASSIGN_STR(mon_decimal_point); @@ -88,21 +92,26 @@ M_ASSIGN_CHAR(int_n_sep_by_space); M_ASSIGN_CHAR(int_p_sign_posn); M_ASSIGN_CHAR(int_n_sign_posn); - __mlocale_changed = 0; + loc->monetary_locale_changed = 0; } - if (__nlocale_changed) { + if (loc->numeric_locale_changed) { /* LC_NUMERIC part */ struct lc_numeric_T * nptr; -#define N_ASSIGN_STR(NAME) (ret.NAME = (char*)nptr->NAME) +#define N_ASSIGN_STR(NAME) (ret->NAME = (char*)nptr->NAME) - nptr = __get_current_numeric_locale(); + nptr = __get_current_numeric_locale(loc); N_ASSIGN_STR(decimal_point); N_ASSIGN_STR(thousands_sep); N_ASSIGN_STR(grouping); - __nlocale_changed = 0; + loc->numeric_locale_changed = 0; } - return (&ret); + return ret; } +struct lconv * +localeconv(void) +{ + return localeconv_l(__get_locale()); +} Index: lib/libc/locale/wcsnrtombs.c =================================================================== --- lib/libc/locale/wcsnrtombs.c (revision 225653) +++ lib/libc/locale/wcsnrtombs.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002-2004 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -34,16 +39,22 @@ #include "mblocal.h" size_t +wcsnrtombs_l(char * __restrict dst, const wchar_t ** __restrict src, size_t nwc, + size_t len, mbstate_t * __restrict ps, locale_t locale) +{ + FIX_LOCALE(locale); + if (ps == NULL) + ps = &locale->wcsnrtombs; + return (XLOCALE_CTYPE(locale)->__wcsnrtombs(dst, src, nwc, len, ps)); +} +size_t wcsnrtombs(char * __restrict dst, const wchar_t ** __restrict src, size_t nwc, size_t len, mbstate_t * __restrict ps) { - static mbstate_t mbs; - - if (ps == NULL) - ps = &mbs; - return (__wcsnrtombs(dst, src, nwc, len, ps)); + return wcsnrtombs_l(dst, src, nwc, len, ps, __get_locale()); } + size_t __wcsnrtombs_std(char * __restrict dst, const wchar_t ** __restrict src, size_t nwc, size_t len, mbstate_t * __restrict ps) @@ -53,13 +64,14 @@ const wchar_t *s; size_t nbytes; size_t nb; + struct xlocale_ctype *l = XLOCALE_CTYPE(__get_locale()); s = *src; nbytes = 0; if (dst == NULL) { while (nwc-- > 0) { - if ((nb = __wcrtomb(buf, *s, ps)) == (size_t)-1) + if ((nb = l->__wcrtomb(buf, *s, ps)) == (size_t)-1) /* Invalid character - wcrtomb() sets errno. */ return ((size_t)-1); else if (*s == L'\0') @@ -73,7 +85,7 @@ while (len > 0 && nwc-- > 0) { if (len > (size_t)MB_CUR_MAX) { /* Enough space to translate in-place. */ - if ((nb = __wcrtomb(dst, *s, ps)) == (size_t)-1) { + if ((nb = l->__wcrtomb(dst, *s, ps)) == (size_t)-1) { *src = s; return ((size_t)-1); } @@ -86,7 +98,7 @@ * character is too long for the buffer. */ mbsbak = *ps; - if ((nb = __wcrtomb(buf, *s, ps)) == (size_t)-1) { + if ((nb = l->__wcrtomb(buf, *s, ps)) == (size_t)-1) { *src = s; return ((size_t)-1); } Index: lib/libc/locale/gbk.c =================================================================== --- lib/libc/locale/gbk.c (revision 225653) +++ lib/libc/locale/gbk.c (working copy) @@ -6,6 +6,11 @@ * This code is derived from software contributed to Berkeley by * Paul Borman at Krystal Technologies. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -55,15 +60,15 @@ } _GBKState; int -_GBK_init(_RuneLocale *rl) +_GBK_init(struct xlocale_ctype *l, _RuneLocale *rl) { - __mbrtowc = _GBK_mbrtowc; - __wcrtomb = _GBK_wcrtomb; - __mbsinit = _GBK_mbsinit; - _CurrentRuneLocale = rl; - __mb_cur_max = 2; - __mb_sb_limit = 128; + l->__mbrtowc = _GBK_mbrtowc; + l->__wcrtomb = _GBK_wcrtomb; + l->__mbsinit = _GBK_mbsinit; + l->runes = rl; + l->__mb_cur_max = 2; + l->__mb_sb_limit = 128; return (0); } Index: lib/libc/locale/querylocale.3 =================================================================== --- lib/libc/locale/querylocale.3 (revision 0) +++ lib/libc/locale/querylocale.3 (revision 0) @@ -0,0 +1,55 @@ +.\" Copyright (c) 2011 The FreeBSD Foundation +.\" All rights reserved. +.\" +.\" This documentation was written by David Chisnall under sponsorship from +.\" the FreeBSD Foundation. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.Dd September 17 2011 +.Dt QUERYLOCALE 3 +.Os +.Sh NAME +.Nm querylocale +.Nd Look up the locale name for a specified category. +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.In xlocale.h +.Ft const char * +.Fn querylocale "int mask" "locale_t locale" +.Sh DESCRIPTION +Returns the name of the locale for the category specified by +.Fa mask. +This possible values for the mask are the same as those in +.Xr newlocale 3 . If more than one bit in the mask is set, the returned value +is undefined. +.Sh SEE ALSO +.Xr duplocale 3 , +.Xr freelocale 3 , +.Xr localeconv 3 , +.Xr newlocale 3 , +.Xr uselocale 3 , +.Xr xlocale 3 +.Sh STANDARDS +This function, conforms to +.St -p1003.1-2008 Index: lib/libc/locale/wctype.c =================================================================== --- lib/libc/locale/wctype.c (revision 225653) +++ lib/libc/locale/wctype.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -30,17 +35,27 @@ #include #include #include +#include #undef iswctype int iswctype(wint_t wc, wctype_t charclass) { - return (__istype(wc, charclass)); } +int +iswctype_l(wint_t wc, wctype_t charclass, locale_t locale) +{ + return __istype_l(wc, charclass, locale); +} +/* + * IMPORTANT: The 0 in the call to this function in wctype() must be changed to + * __get_locale() if wctype_l() ie ever modified to actually use the locale + * parameter. + */ wctype_t -wctype(const char *property) +wctype_l(const char *property, locale_t locale) { static const struct { const char *name; @@ -72,3 +87,8 @@ return (props[i].mask); } + +wctype_t wctype(const char *property) +{ + return wctype_l(property, 0); +} Index: lib/libc/locale/lnumeric.c =================================================================== --- lib/libc/locale/lnumeric.c (revision 225653) +++ lib/libc/locale/lnumeric.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2000, 2001 Alexey Zelkin * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -32,7 +37,6 @@ #include "ldpart.h" #include "lnumeric.h" -extern int __nlocale_changed; extern const char *__fix_locale_grouping_str(const char *); #define LCNUMERIC_SIZE (sizeof(struct lc_numeric_T) / sizeof(char *)) @@ -45,37 +49,67 @@ numempty /* grouping */ }; -static struct lc_numeric_T _numeric_locale; -static int _numeric_using_locale; -static char *_numeric_locale_buf; +static void +destruct_numeric(void *v) +{ + struct xlocale_numeric *l = v; + if (l->buffer) + free(l->buffer); + free(l); +} -int -__numeric_load_locale(const char *name) +struct xlocale_numeric __xlocale_global_numeric; + +static int +numeric_load_locale(struct xlocale_numeric *loc, int *using_locale, int *changed, + const char *name) { int ret; + struct lc_numeric_T *l = &loc->locale; - ret = __part_load_locale(name, &_numeric_using_locale, - &_numeric_locale_buf, "LC_NUMERIC", + ret = __part_load_locale(name, using_locale, + &loc->buffer, "LC_NUMERIC", LCNUMERIC_SIZE, LCNUMERIC_SIZE, - (const char **)&_numeric_locale); + (const char**)l); if (ret != _LDP_ERROR) - __nlocale_changed = 1; + *changed= 1; if (ret == _LDP_LOADED) { /* Can't be empty according to C99 */ - if (*_numeric_locale.decimal_point == '\0') - _numeric_locale.decimal_point = + if (*l->decimal_point == '\0') + l->decimal_point = _C_numeric_locale.decimal_point; - _numeric_locale.grouping = - __fix_locale_grouping_str(_numeric_locale.grouping); + l->grouping = + __fix_locale_grouping_str(l->grouping); } return (ret); } +int +__numeric_load_locale(const char *name) +{ + return numeric_load_locale(&__xlocale_global_numeric, + &__xlocale_global_locale.using_numeric_locale, + &__xlocale_global_locale.numeric_locale_changed, name); +} +void * +__numeric_load(const char *name, locale_t l) +{ + struct xlocale_numeric *new = calloc(sizeof(struct xlocale_numeric), 1); + new->header.header.destructor = destruct_numeric; + if (numeric_load_locale(new, &l->using_numeric_locale, + &l->numeric_locale_changed, name) == _LDP_ERROR) + { + xlocale_release(new); + return NULL; + } + return new; +} + struct lc_numeric_T * -__get_current_numeric_locale(void) +__get_current_numeric_locale(locale_t loc) { - return (_numeric_using_locale - ? &_numeric_locale + return (loc->using_numeric_locale + ? &((struct xlocale_numeric *)loc->components[XLC_NUMERIC])->locale : (struct lc_numeric_T *)&_C_numeric_locale); } Index: lib/libc/locale/wcstoimax.c =================================================================== --- lib/libc/locale/wcstoimax.c (revision 225653) +++ lib/libc/locale/wcstoimax.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -41,19 +46,21 @@ #include #include #include +#include "xlocale_private.h" /* * Convert a wide character string to an intmax_t integer. */ intmax_t -wcstoimax(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, - int base) +wcstoimax_l(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, + int base, locale_t locale) { const wchar_t *s; uintmax_t acc; wchar_t c; uintmax_t cutoff; int neg, any, cutlim; + FIX_LOCALE(locale); /* * See strtoimax for comments as to the logic used. @@ -61,7 +68,7 @@ s = nptr; do { c = *s++; - } while (iswspace(c)); + } while (iswspace_l(c, locale)); if (c == L'-') { neg = 1; c = *s++; @@ -88,8 +95,8 @@ cutoff /= base; for ( ; ; c = *s++) { #ifdef notyet - if (iswdigit(c)) - c = digittoint(c); + if (iswdigit_l(c, locale)) + c = digittoint_l(c, locale); else #endif if (c >= L'0' && c <= L'9') @@ -122,3 +129,9 @@ *endptr = (wchar_t *)(any ? s - 1 : nptr); return (acc); } +intmax_t +wcstoimax(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, + int base) +{ + return wcstoimax_l(nptr, endptr, base, __get_locale()); +} Index: lib/libc/locale/lnumeric.h =================================================================== --- lib/libc/locale/lnumeric.h (revision 225653) +++ lib/libc/locale/lnumeric.h (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2000, 2001 Alexey Zelkin * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -28,14 +33,20 @@ #ifndef _LNUMERIC_H_ #define _LNUMERIC_H_ +#include "xlocale_private.h" struct lc_numeric_T { const char *decimal_point; const char *thousands_sep; const char *grouping; }; +struct xlocale_numeric { + struct xlocale_component header; + char *buffer; + struct lc_numeric_T locale; +}; -struct lc_numeric_T *__get_current_numeric_locale(void); +struct lc_numeric_T *__get_current_numeric_locale(locale_t loc); int __numeric_load_locale(const char *); #endif /* !_LNUMERIC_H_ */ Index: lib/libc/locale/wctomb.c =================================================================== --- lib/libc/locale/wctomb.c (revision 225653) +++ lib/libc/locale/wctomb.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002-2004 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -32,18 +37,23 @@ #include "mblocal.h" int -wctomb(char *s, wchar_t wchar) +wctomb_l(char *s, wchar_t wchar, locale_t locale) { static const mbstate_t initial; - static mbstate_t mbs; size_t rval; + FIX_LOCALE(locale); if (s == NULL) { /* No support for state dependent encodings. */ - mbs = initial; + locale->wctomb = initial; return (0); } - if ((rval = __wcrtomb(s, wchar, &mbs)) == (size_t)-1) + if ((rval = XLOCALE_CTYPE(locale)->__wcrtomb(s, wchar, &locale->wctomb)) == (size_t)-1) return (-1); return ((int)rval); } +int +wctomb(char *s, wchar_t wchar) +{ + return wctomb_l(s, wchar, __get_locale()); +} Index: lib/libc/locale/toupper.c =================================================================== --- lib/libc/locale/toupper.c (revision 225653) +++ lib/libc/locale/toupper.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Paul Borman at Krystal Technologies. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -36,13 +41,17 @@ #include #include #include +#include +#include "mblocal.h" __ct_rune_t -___toupper(c) +___toupper_l(c, l) __ct_rune_t c; + locale_t l; { size_t lim; - _RuneRange *rr = &_CurrentRuneLocale->__mapupper_ext; + FIX_LOCALE(l); + _RuneRange *rr = &XLOCALE_CTYPE(l)->runes->__maplower_ext; _RuneEntry *base, *re; if (c < 0 || c == EOF) @@ -53,7 +62,9 @@ for (lim = rr->__nranges; lim != 0; lim >>= 1) { re = base + (lim >> 1); if (re->__min <= c && c <= re->__max) + { return (re->__map + c - re->__min); + } else if (c > re->__max) { base = re + 1; lim--; @@ -62,3 +73,9 @@ return(c); } +__ct_rune_t +___toupper(c) + __ct_rune_t c; +{ + return ___toupper_l(c, __get_locale()); +} Index: lib/libc/locale/wcstombs.c =================================================================== --- lib/libc/locale/wcstombs.c (revision 225653) +++ lib/libc/locale/wcstombs.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002-2004 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -33,13 +38,21 @@ #include "mblocal.h" size_t -wcstombs(char * __restrict s, const wchar_t * __restrict pwcs, size_t n) +wcstombs_l(char * __restrict s, const wchar_t * __restrict pwcs, size_t n, + locale_t locale) { static const mbstate_t initial; mbstate_t mbs; const wchar_t *pwcsp; + FIX_LOCALE(locale); mbs = initial; pwcsp = pwcs; - return (__wcsnrtombs(s, &pwcsp, SIZE_T_MAX, n, &mbs)); + return (XLOCALE_CTYPE(locale)->__wcsnrtombs(s, &pwcsp, SIZE_T_MAX, n, &mbs)); } +size_t +wcstombs(char * __restrict s, const wchar_t * __restrict pwcs, size_t n) +{ + return wcstombs_l(s, pwcs, n, __get_locale()); +} + Index: lib/libc/locale/wcstoull.c =================================================================== --- lib/libc/locale/wcstoull.c (revision 225653) +++ lib/libc/locale/wcstoull.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -41,19 +46,21 @@ #include #include #include +#include "xlocale_private.h" /* * Convert a wide character string to an unsigned long long integer. */ unsigned long long -wcstoull(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, - int base) +wcstoull_l(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, + int base, locale_t locale) { const wchar_t *s; unsigned long long acc; wchar_t c; unsigned long long cutoff; int neg, any, cutlim; + FIX_LOCALE(locale); /* * See strtoull for comments as to the logic used. @@ -61,7 +68,7 @@ s = nptr; do { c = *s++; - } while (iswspace(c)); + } while (iswspace_l(c, locale)); if (c == L'-') { neg = 1; c = *s++; @@ -86,8 +93,8 @@ cutlim = ULLONG_MAX % base; for ( ; ; c = *s++) { #ifdef notyet - if (iswdigit(c)) - c = digittoint(c); + if (iswdigit_l(c, locale)) + c = digittoint_l(c, locale); else #endif if (c >= L'0' && c <= L'9') @@ -120,3 +127,9 @@ *endptr = (wchar_t *)(any ? s - 1 : nptr); return (acc); } +unsigned long long +wcstoull(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, + int base) +{ + return wcstoull_l(nptr, endptr, base, __get_locale()); +} Index: lib/libc/locale/euc.c =================================================================== --- lib/libc/locale/euc.c (revision 225653) +++ lib/libc/locale/euc.c (working copy) @@ -6,6 +6,11 @@ * This code is derived from software contributed to Berkeley by * Paul Borman at Krystal Technologies. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -70,7 +75,7 @@ } _EucState; int -_EUC_init(_RuneLocale *rl) +_EUC_init(struct xlocale_ctype *l, _RuneLocale *rl) { _EucInfo *ei; int x, new__mb_cur_max; @@ -113,12 +118,12 @@ } rl->__variable = ei; rl->__variable_len = sizeof(_EucInfo); - _CurrentRuneLocale = rl; - __mb_cur_max = new__mb_cur_max; - __mbrtowc = _EUC_mbrtowc; - __wcrtomb = _EUC_wcrtomb; - __mbsinit = _EUC_mbsinit; - __mb_sb_limit = 256; + l->runes = rl; + l->__mb_cur_max = new__mb_cur_max; + l->__mbrtowc = _EUC_mbrtowc; + l->__wcrtomb = _EUC_wcrtomb; + l->__mbsinit = _EUC_mbsinit; + l->__mb_sb_limit = 256; return (0); } Index: lib/libc/locale/wctob.c =================================================================== --- lib/libc/locale/wctob.c (revision 225653) +++ lib/libc/locale/wctob.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002-2004 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -33,13 +38,19 @@ #include "mblocal.h" int -wctob(wint_t c) +wctob_l(wint_t c, locale_t locale) { static const mbstate_t initial; mbstate_t mbs = initial; char buf[MB_LEN_MAX]; + FIX_LOCALE(locale); - if (c == WEOF || __wcrtomb(buf, c, &mbs) != 1) + if (c == WEOF || XLOCALE_CTYPE(locale)->__wcrtomb(buf, c, &mbs) != 1) return (EOF); return ((unsigned char)*buf); } +int +wctob(wint_t c) +{ + return wctob_l(c, __get_locale()); +} Index: lib/libc/locale/wcstold.c =================================================================== --- lib/libc/locale/wcstold.c (revision 225653) +++ lib/libc/locale/wcstold.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002, 2003 Tim J. Robbins * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -30,26 +35,32 @@ #include #include #include +#include "xlocale_private.h" /* * See wcstod() for comments as to the logic used. */ long double -wcstold(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr) +wcstold_l(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, + locale_t locale) { static const mbstate_t initial; mbstate_t mbs; long double val; char *buf, *end; - const wchar_t *wcp; + const wchar_t *wcp = nptr; size_t len; + size_t spaces = 0; + FIX_LOCALE(locale); - while (iswspace(*nptr)) - nptr++; + while (iswspace_l(*wcp, locale)) { + wcp++; + spaces++; + } wcp = nptr; mbs = initial; - if ((len = wcsrtombs(NULL, &wcp, 0, &mbs)) == (size_t)-1) { + if ((len = wcsrtombs_l(NULL, &wcp, 0, &mbs, locale)) == (size_t)-1) { if (endptr != NULL) *endptr = (wchar_t *)nptr; return (0.0); @@ -57,14 +68,23 @@ if ((buf = malloc(len + 1)) == NULL) return (0.0); mbs = initial; - wcsrtombs(buf, &wcp, len + 1, &mbs); + wcsrtombs_l(buf, &wcp, len + 1, &mbs, locale); - val = strtold(buf, &end); + val = strtold_l(buf, &end, locale); - if (endptr != NULL) + if (endptr != NULL) { + /* XXX Assume each wide char is one byte. */ *endptr = (wchar_t *)nptr + (end - buf); + if (buf != end) + *endptr += spaces; + } free(buf); return (val); } +long double +wcstold(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr) +{ + return wcstold_l(nptr, endptr, __get_locale()); +} Index: lib/libc/locale/wctrans.c =================================================================== --- lib/libc/locale/wctrans.c (revision 225653) +++ lib/libc/locale/wctrans.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -30,6 +35,7 @@ #include #include #include +#include "xlocale_private.h" enum { _WCT_ERROR = 0, @@ -38,15 +44,14 @@ }; wint_t -towctrans(wint_t wc, wctrans_t desc) +towctrans_l(wint_t wc, wctrans_t desc, locale_t locale) { - switch (desc) { case _WCT_TOLOWER: - wc = towlower(wc); + wc = towlower_l(wc, locale); break; case _WCT_TOUPPER: - wc = towupper(wc); + wc = towupper_l(wc, locale); break; case _WCT_ERROR: default: @@ -56,9 +61,18 @@ return (wc); } +wint_t +towctrans(wint_t wc, wctrans_t desc) +{ + return towctrans_l(wc, desc, __get_locale()); +} +/* + * wctrans() calls this will a 0 locale. If this is ever modified to actually + * use the locale, wctrans() must be modified to call __get_locale(). + */ wctrans_t -wctrans(const char *charclass) +wctrans_l(const char *charclass, locale_t locale) { struct { const char *name; @@ -78,3 +92,10 @@ errno = EINVAL; return (ccls[i].trans); } + +wctrans_t +wctrans(const char *charclass) +{ + return wctrans_l(charclass, 0); +} + Index: lib/libc/locale/gb18030.c =================================================================== --- lib/libc/locale/gb18030.c (revision 225653) +++ lib/libc/locale/gb18030.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002-2004 Tim J. Robbins * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -39,8 +44,6 @@ #include #include "mblocal.h" -extern int __mb_sb_limit; - static size_t _GB18030_mbrtowc(wchar_t * __restrict, const char * __restrict, size_t, mbstate_t * __restrict); static int _GB18030_mbsinit(const mbstate_t *); @@ -53,15 +56,15 @@ } _GB18030State; int -_GB18030_init(_RuneLocale *rl) +_GB18030_init(struct xlocale_ctype *l, _RuneLocale *rl) { - __mbrtowc = _GB18030_mbrtowc; - __wcrtomb = _GB18030_wcrtomb; - __mbsinit = _GB18030_mbsinit; - _CurrentRuneLocale = rl; - __mb_cur_max = 4; - __mb_sb_limit = 128; + l->__mbrtowc = _GB18030_mbrtowc; + l->__wcrtomb = _GB18030_wcrtomb; + l->__mbsinit = _GB18030_mbsinit; + l->runes = rl; + l->__mb_cur_max = 4; + l->__mb_sb_limit = 128; return (0); } Index: lib/libc/locale/nl_langinfo.c =================================================================== --- lib/libc/locale/nl_langinfo.c (revision 225653) +++ lib/libc/locale/nl_langinfo.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2001, 2003 Alexey Zelkin * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -41,15 +46,16 @@ #define _REL(BASE) ((int)item-BASE) char * -nl_langinfo(nl_item item) +nl_langinfo_l(nl_item item, locale_t loc) { - char *ret, *s, *cs; - static char *csym = NULL; + char *ret, *cs; + const char *s; + FIX_LOCALE(loc); switch (item) { case CODESET: ret = ""; - if ((s = setlocale(LC_CTYPE, NULL)) != NULL) { + if ((s = querylocale(LC_CTYPE_MASK, loc)) != NULL) { if ((cs = strchr(s, '.')) != NULL) ret = cs + 1; else if (strcmp(s, "C") == 0 || @@ -58,46 +64,46 @@ } break; case D_T_FMT: - ret = (char *) __get_current_time_locale()->c_fmt; + ret = (char *) __get_current_time_locale(loc)->c_fmt; break; case D_FMT: - ret = (char *) __get_current_time_locale()->x_fmt; + ret = (char *) __get_current_time_locale(loc)->x_fmt; break; case T_FMT: - ret = (char *) __get_current_time_locale()->X_fmt; + ret = (char *) __get_current_time_locale(loc)->X_fmt; break; case T_FMT_AMPM: - ret = (char *) __get_current_time_locale()->ampm_fmt; + ret = (char *) __get_current_time_locale(loc)->ampm_fmt; break; case AM_STR: - ret = (char *) __get_current_time_locale()->am; + ret = (char *) __get_current_time_locale(loc)->am; break; case PM_STR: - ret = (char *) __get_current_time_locale()->pm; + ret = (char *) __get_current_time_locale(loc)->pm; break; case DAY_1: case DAY_2: case DAY_3: case DAY_4: case DAY_5: case DAY_6: case DAY_7: - ret = (char*) __get_current_time_locale()->weekday[_REL(DAY_1)]; + ret = (char*) __get_current_time_locale(loc)->weekday[_REL(DAY_1)]; break; case ABDAY_1: case ABDAY_2: case ABDAY_3: case ABDAY_4: case ABDAY_5: case ABDAY_6: case ABDAY_7: - ret = (char*) __get_current_time_locale()->wday[_REL(ABDAY_1)]; + ret = (char*) __get_current_time_locale(loc)->wday[_REL(ABDAY_1)]; break; case MON_1: case MON_2: case MON_3: case MON_4: case MON_5: case MON_6: case MON_7: case MON_8: case MON_9: case MON_10: case MON_11: case MON_12: - ret = (char*) __get_current_time_locale()->month[_REL(MON_1)]; + ret = (char*) __get_current_time_locale(loc)->month[_REL(MON_1)]; break; case ABMON_1: case ABMON_2: case ABMON_3: case ABMON_4: case ABMON_5: case ABMON_6: case ABMON_7: case ABMON_8: case ABMON_9: case ABMON_10: case ABMON_11: case ABMON_12: - ret = (char*) __get_current_time_locale()->mon[_REL(ABMON_1)]; + ret = (char*) __get_current_time_locale(loc)->mon[_REL(ABMON_1)]; break; case ALTMON_1: case ALTMON_2: case ALTMON_3: case ALTMON_4: case ALTMON_5: case ALTMON_6: case ALTMON_7: case ALTMON_8: case ALTMON_9: case ALTMON_10: case ALTMON_11: case ALTMON_12: ret = (char*) - __get_current_time_locale()->alt_month[_REL(ALTMON_1)]; + __get_current_time_locale(loc)->alt_month[_REL(ALTMON_1)]; break; case ERA: /* XXX: need to be implemented */ @@ -120,16 +126,16 @@ ret = ""; break; case RADIXCHAR: - ret = (char*) __get_current_numeric_locale()->decimal_point; + ret = (char*) __get_current_numeric_locale(loc)->decimal_point; break; case THOUSEP: - ret = (char*) __get_current_numeric_locale()->thousands_sep; + ret = (char*) __get_current_numeric_locale(loc)->thousands_sep; break; case YESEXPR: - ret = (char*) __get_current_messages_locale()->yesexpr; + ret = (char*) __get_current_messages_locale(loc)->yesexpr; break; case NOEXPR: - ret = (char*) __get_current_messages_locale()->noexpr; + ret = (char*) __get_current_messages_locale(loc)->noexpr; break; /* * YESSTR and NOSTR items marked with LEGACY are available, but not @@ -137,45 +143,51 @@ * they're subject to remove in future specification editions. */ case YESSTR: /* LEGACY */ - ret = (char*) __get_current_messages_locale()->yesstr; + ret = (char*) __get_current_messages_locale(loc)->yesstr; break; case NOSTR: /* LEGACY */ - ret = (char*) __get_current_messages_locale()->nostr; + ret = (char*) __get_current_messages_locale(loc)->nostr; break; /* * SUSv2 special formatted currency string */ case CRNCYSTR: ret = ""; - cs = (char*) __get_current_monetary_locale()->currency_symbol; + cs = (char*) __get_current_monetary_locale(loc)->currency_symbol; if (*cs != '\0') { - char pos = localeconv()->p_cs_precedes; + char pos = localeconv_l(loc)->p_cs_precedes; - if (pos == localeconv()->n_cs_precedes) { + if (pos == localeconv_l(loc)->n_cs_precedes) { char psn = '\0'; if (pos == CHAR_MAX) { - if (strcmp(cs, __get_current_monetary_locale()->mon_decimal_point) == 0) + if (strcmp(cs, __get_current_monetary_locale(loc)->mon_decimal_point) == 0) psn = '.'; } else psn = pos ? '-' : '+'; if (psn != '\0') { int clen = strlen(cs); - if ((csym = reallocf(csym, clen + 2)) != NULL) { - *csym = psn; - strcpy(csym + 1, cs); - ret = csym; + if ((loc->csym = reallocf(loc->csym, clen + 2)) != NULL) { + *loc->csym = psn; + strcpy(loc->csym + 1, cs); + ret = loc->csym; } } } } break; case D_MD_ORDER: /* FreeBSD local extension */ - ret = (char *) __get_current_time_locale()->md_order; + ret = (char *) __get_current_time_locale(loc)->md_order; break; default: ret = ""; } return (ret); } + +char * +nl_langinfo(nl_item item) +{ + return nl_langinfo_l(item, __get_locale()); +} Index: lib/libc/locale/table.c =================================================================== --- lib/libc/locale/table.c (revision 225653) +++ lib/libc/locale/table.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Paul Borman at Krystal Technologies. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -41,7 +46,7 @@ #include #include "mblocal.h" -_RuneLocale _DefaultRuneLocale = { +const _RuneLocale _DefaultRuneLocale = { _RUNE_MAGIC_1, "NONE", NULL, @@ -245,5 +250,14 @@ }, }; -_RuneLocale *_CurrentRuneLocale = &_DefaultRuneLocale; +#undef _CurrentRuneLocale +_RuneLocale *_CurrentRuneLocale = (_RuneLocale*)&_DefaultRuneLocale; +_RuneLocale * +__runes_for_locale(locale_t locale, int *mb_sb_limit) +{ + FIX_LOCALE(locale); + struct xlocale_ctype *c = XLOCALE_CTYPE(locale); + *mb_sb_limit = c->__mb_sb_limit; + return c->runes; +} Index: lib/libc/locale/wcstoll.c =================================================================== --- lib/libc/locale/wcstoll.c (revision 225653) +++ lib/libc/locale/wcstoll.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -41,18 +46,21 @@ #include #include #include +#include "xlocale_private.h" /* * Convert a wide character string to a long long integer. */ long long -wcstoll(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, int base) +wcstoll_l(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, + int base, locale_t locale) { const wchar_t *s; unsigned long long acc; wchar_t c; unsigned long long cutoff; int neg, any, cutlim; + FIX_LOCALE(locale); /* * See strtoll for comments as to the logic used. @@ -60,7 +68,7 @@ s = nptr; do { c = *s++; - } while (iswspace(c)); + } while (iswspace_l(c, locale)); if (c == L'-') { neg = 1; c = *s++; @@ -87,8 +95,8 @@ cutoff /= base; for ( ; ; c = *s++) { #ifdef notyet - if (iswdigit(c)) - c = digittoint(c); + if (iswdigit_l(c, locale)) + c = digittoint_l(c, locale); else #endif if (c >= L'0' && c <= L'9') @@ -121,3 +129,8 @@ *endptr = (wchar_t *)(any ? s - 1 : nptr); return (acc); } +long long +wcstoll(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, int base) +{ + return wcstoll_l(nptr, endptr, base, __get_locale()); +} Index: lib/libc/locale/tolower.c =================================================================== --- lib/libc/locale/tolower.c (revision 225653) +++ lib/libc/locale/tolower.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Paul Borman at Krystal Technologies. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -36,13 +41,17 @@ #include #include #include +#include +#include "mblocal.h" __ct_rune_t -___tolower(c) +___tolower_l(c, l) __ct_rune_t c; + locale_t l; { size_t lim; - _RuneRange *rr = &_CurrentRuneLocale->__maplower_ext; + FIX_LOCALE(l); + _RuneRange *rr = &XLOCALE_CTYPE(l)->runes->__maplower_ext; _RuneEntry *base, *re; if (c < 0 || c == EOF) @@ -62,3 +71,9 @@ return(c); } +__ct_rune_t +___tolower(c) + __ct_rune_t c; +{ + return ___tolower_l(c, __get_locale()); +} Index: lib/libc/locale/mskanji.c =================================================================== --- lib/libc/locale/mskanji.c (revision 225653) +++ lib/libc/locale/mskanji.c (working copy) @@ -6,6 +6,11 @@ * (C) Sin'ichiro MIYATANI / Phase One, Inc * May 12, 1995 * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -60,15 +65,15 @@ } _MSKanjiState; int -_MSKanji_init(_RuneLocale *rl) +_MSKanji_init(struct xlocale_ctype *l, _RuneLocale *rl) { - __mbrtowc = _MSKanji_mbrtowc; - __wcrtomb = _MSKanji_wcrtomb; - __mbsinit = _MSKanji_mbsinit; - _CurrentRuneLocale = rl; - __mb_cur_max = 2; - __mb_sb_limit = 256; + l->__mbrtowc = _MSKanji_mbrtowc; + l->__wcrtomb = _MSKanji_wcrtomb; + l->__mbsinit = _MSKanji_mbsinit; + l->runes = rl; + l->__mb_cur_max = 2; + l->__mb_sb_limit = 256; return (0); } Index: lib/libc/locale/mblen.c =================================================================== --- lib/libc/locale/mblen.c (revision 225653) +++ lib/libc/locale/mblen.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002-2004 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -32,19 +37,25 @@ #include "mblocal.h" int -mblen(const char *s, size_t n) +mblen_l(const char *s, size_t n, locale_t locale) { static const mbstate_t initial; - static mbstate_t mbs; size_t rval; + FIX_LOCALE(locale); if (s == NULL) { /* No support for state dependent encodings. */ - mbs = initial; + locale->mblen = initial; return (0); } - rval = __mbrtowc(NULL, s, n, &mbs); + rval = XLOCALE_CTYPE(locale)->__mbrtowc(NULL, s, n, &locale->mblen); if (rval == (size_t)-1 || rval == (size_t)-2) return (-1); return ((int)rval); } + +int +mblen(const char *s, size_t n) +{ + return mblen_l(s, n, __get_locale()); +} Index: lib/libc/locale/none.c =================================================================== --- lib/libc/locale/none.c (revision 225653) +++ lib/libc/locale/none.c (working copy) @@ -6,6 +6,11 @@ * This code is derived from software contributed to Berkeley by * Paul Borman at Krystal Technologies. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -64,17 +69,17 @@ int __mb_sb_limit = 256; /* Expected to be <= _CACHED_RUNES */ int -_none_init(_RuneLocale *rl) +_none_init(struct xlocale_ctype *l, _RuneLocale *rl) { - __mbrtowc = _none_mbrtowc; - __mbsinit = _none_mbsinit; - __mbsnrtowcs = _none_mbsnrtowcs; - __wcrtomb = _none_wcrtomb; - __wcsnrtombs = _none_wcsnrtombs; - _CurrentRuneLocale = rl; - __mb_cur_max = 1; - __mb_sb_limit = 256; + l->__mbrtowc = _none_mbrtowc; + l->__mbsinit = _none_mbsinit; + l->__mbsnrtowcs = _none_mbsnrtowcs; + l->__wcrtomb = _none_wcrtomb; + l->__wcsnrtombs = _none_wcsnrtombs; + l->runes = rl; + l->__mb_cur_max = 1; + l->__mb_sb_limit = 256; return(0); } @@ -192,3 +197,14 @@ size_t (*__wcsnrtombs)(char * __restrict, const wchar_t ** __restrict, size_t, size_t, mbstate_t * __restrict) = _none_wcsnrtombs; +struct xlocale_ctype __xlocale_global_ctype = { + {{0}, "C"}, + (_RuneLocale*)&_DefaultRuneLocale, + _none_mbrtowc, + _none_mbsinit, + _none_mbsnrtowcs, + _none_wcrtomb, + _none_wcsnrtombs, + 1, /* __mb_cur_max, */ + 256 /* __mb_sb_limit */ +}; Index: lib/libc/locale/mbstowcs.c =================================================================== --- lib/libc/locale/mbstowcs.c (revision 225653) +++ lib/libc/locale/mbstowcs.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002-2004 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -33,13 +38,19 @@ #include "mblocal.h" size_t -mbstowcs(wchar_t * __restrict pwcs, const char * __restrict s, size_t n) +mbstowcs_l(wchar_t * __restrict pwcs, const char * __restrict s, size_t n, locale_t locale) { static const mbstate_t initial; mbstate_t mbs; const char *sp; + FIX_LOCALE(locale); mbs = initial; sp = s; - return (__mbsnrtowcs(pwcs, &sp, SIZE_T_MAX, n, &mbs)); + return (XLOCALE_CTYPE(locale)->__mbsnrtowcs(pwcs, &sp, SIZE_T_MAX, n, &mbs)); } +size_t +mbstowcs(wchar_t * __restrict pwcs, const char * __restrict s, size_t n) +{ + return mbstowcs_l(pwcs, s, n, __get_locale()); +} Index: lib/libc/locale/wcstod.c =================================================================== --- lib/libc/locale/wcstod.c (revision 225653) +++ lib/libc/locale/wcstod.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002 Tim J. Robbins * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -30,6 +35,7 @@ #include #include #include +#include "xlocale_private.h" /* * Convert a string to a double-precision number. @@ -41,17 +47,22 @@ * for at least the digits, radix character and letters. */ double -wcstod(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr) +wcstod_l(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, + locale_t locale) { static const mbstate_t initial; mbstate_t mbs; double val; char *buf, *end; - const wchar_t *wcp; + const wchar_t *wcp = nptr; size_t len; + size_t spaces = 0; + FIX_LOCALE(locale); - while (iswspace(*nptr)) - nptr++; + while (iswspace_l(*wcp, locale)) { + wcp++; + spaces++; + } /* * Convert the supplied numeric wide char. string to multibyte. @@ -63,9 +74,8 @@ * duplicates a lot of strtod()'s functionality and slows down the * most common cases. */ - wcp = nptr; mbs = initial; - if ((len = wcsrtombs(NULL, &wcp, 0, &mbs)) == (size_t)-1) { + if ((len = wcsrtombs_l(NULL, &wcp, 0, &mbs, locale)) == (size_t)-1) { if (endptr != NULL) *endptr = (wchar_t *)nptr; return (0.0); @@ -73,10 +83,10 @@ if ((buf = malloc(len + 1)) == NULL) return (0.0); mbs = initial; - wcsrtombs(buf, &wcp, len + 1, &mbs); + wcsrtombs_l(buf, &wcp, len + 1, &mbs, locale); /* Let strtod() do most of the work for us. */ - val = strtod(buf, &end); + val = strtod_l(buf, &end, locale); /* * We only know where the number ended in the _multibyte_ @@ -84,11 +94,20 @@ * where it ended, count multibyte characters to find the * corresponding position in the wide char string. */ - if (endptr != NULL) + if (endptr != NULL) { /* XXX Assume each wide char is one byte. */ *endptr = (wchar_t *)nptr + (end - buf); + if (buf != end) + *endptr += spaces; + } + free(buf); return (val); } +double +wcstod(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr) +{ + return wcstod_l(nptr, endptr, __get_locale()); +} Index: lib/libc/locale/setrunelocale.c =================================================================== --- lib/libc/locale/setrunelocale.c (revision 225653) +++ lib/libc/locale/setrunelocale.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Paul Borman at Krystal Technologies. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -49,68 +54,46 @@ extern _RuneLocale *_Read_RuneMagi(FILE *); -static int __setrunelocale(const char *); +static int __setrunelocale(struct xlocale_ctype *l, const char *); +#define __collate_load_error (table->__collate_load_error) +#define __collate_substitute_nontrivial (table->__collate_substitute_nontrivial) +#define __collate_substitute_table_ptr (table->__collate_substitute_table_ptr) +#define __collate_char_pri_table_ptr (table->__collate_char_pri_table_ptr) +#define __collate_chain_pri_table (table->__collate_chain_pri_table) + + +static void destruct_ctype(void *v) +{ + struct xlocale_ctype *l = v; + if (strcmp(l->runes->__encoding, "EUC") == 0) + free(l->runes->__variable); + if (&_DefaultRuneLocale != l->runes) + free(l->runes); + free(l); +} +_RuneLocale *__getCurrentRuneLocale(void) +{ + return XLOCALE_CTYPE(__get_locale())->runes; +} + static int -__setrunelocale(const char *encoding) +__setrunelocale(struct xlocale_ctype *l, const char *encoding) { FILE *fp; char name[PATH_MAX]; _RuneLocale *rl; int saverr, ret; - size_t (*old__mbrtowc)(wchar_t * __restrict, - const char * __restrict, size_t, mbstate_t * __restrict); - size_t (*old__wcrtomb)(char * __restrict, wchar_t, - mbstate_t * __restrict); - int (*old__mbsinit)(const mbstate_t *); - size_t (*old__mbsnrtowcs)(wchar_t * __restrict, - const char ** __restrict, size_t, size_t, mbstate_t * __restrict); - size_t (*old__wcsnrtombs)(char * __restrict, - const wchar_t ** __restrict, size_t, size_t, - mbstate_t * __restrict); - static char ctype_encoding[ENCODING_LEN + 1]; - static _RuneLocale *CachedRuneLocale; - static int Cached__mb_cur_max; - static int Cached__mb_sb_limit; - static size_t (*Cached__mbrtowc)(wchar_t * __restrict, - const char * __restrict, size_t, mbstate_t * __restrict); - static size_t (*Cached__wcrtomb)(char * __restrict, wchar_t, - mbstate_t * __restrict); - static int (*Cached__mbsinit)(const mbstate_t *); - static size_t (*Cached__mbsnrtowcs)(wchar_t * __restrict, - const char ** __restrict, size_t, size_t, mbstate_t * __restrict); - static size_t (*Cached__wcsnrtombs)(char * __restrict, - const wchar_t ** __restrict, size_t, size_t, - mbstate_t * __restrict); + struct xlocale_ctype saved = *l; /* * The "C" and "POSIX" locale are always here. */ if (strcmp(encoding, "C") == 0 || strcmp(encoding, "POSIX") == 0) { - (void) _none_init(&_DefaultRuneLocale); + (void) _none_init(l, (_RuneLocale*)&_DefaultRuneLocale); return (0); } - /* - * If the locale name is the same as our cache, use the cache. - */ - if (CachedRuneLocale != NULL && - strcmp(encoding, ctype_encoding) == 0) { - _CurrentRuneLocale = CachedRuneLocale; - __mb_cur_max = Cached__mb_cur_max; - __mb_sb_limit = Cached__mb_sb_limit; - __mbrtowc = Cached__mbrtowc; - __mbsinit = Cached__mbsinit; - __mbsnrtowcs = Cached__mbsnrtowcs; - __wcrtomb = Cached__wcrtomb; - __wcsnrtombs = Cached__wcsnrtombs; - return (0); - } - - /* - * Slurp the locale file into the cache. - */ - /* Range checking not needed, encoding length already checked before */ (void) strcpy(name, _PathLocale); (void) strcat(name, "/"); @@ -127,63 +110,47 @@ } (void)fclose(fp); - old__mbrtowc = __mbrtowc; - old__mbsinit = __mbsinit; - old__mbsnrtowcs = __mbsnrtowcs; - old__wcrtomb = __wcrtomb; - old__wcsnrtombs = __wcsnrtombs; + l->__mbrtowc = NULL; + l->__mbsinit = NULL; + l->__mbsnrtowcs = __mbsnrtowcs_std; + l->__wcrtomb = NULL; + l->__wcsnrtombs = __wcsnrtombs_std; - __mbrtowc = NULL; - __mbsinit = NULL; - __mbsnrtowcs = __mbsnrtowcs_std; - __wcrtomb = NULL; - __wcsnrtombs = __wcsnrtombs_std; - rl->__sputrune = NULL; rl->__sgetrune = NULL; if (strcmp(rl->__encoding, "NONE") == 0) - ret = _none_init(rl); + ret = _none_init(l, rl); else if (strcmp(rl->__encoding, "ASCII") == 0) - ret = _ascii_init(rl); + ret = _ascii_init(l, rl); else if (strcmp(rl->__encoding, "UTF-8") == 0) - ret = _UTF8_init(rl); + ret = _UTF8_init(l, rl); else if (strcmp(rl->__encoding, "EUC") == 0) - ret = _EUC_init(rl); + ret = _EUC_init(l, rl); else if (strcmp(rl->__encoding, "GB18030") == 0) - ret = _GB18030_init(rl); + ret = _GB18030_init(l, rl); else if (strcmp(rl->__encoding, "GB2312") == 0) - ret = _GB2312_init(rl); + ret = _GB2312_init(l, rl); else if (strcmp(rl->__encoding, "GBK") == 0) - ret = _GBK_init(rl); + ret = _GBK_init(l, rl); else if (strcmp(rl->__encoding, "BIG5") == 0) - ret = _BIG5_init(rl); + ret = _BIG5_init(l, rl); else if (strcmp(rl->__encoding, "MSKanji") == 0) - ret = _MSKanji_init(rl); + ret = _MSKanji_init(l, rl); else ret = EFTYPE; if (ret == 0) { - if (CachedRuneLocale != NULL) { - /* See euc.c */ - if (strcmp(CachedRuneLocale->__encoding, "EUC") == 0) - free(CachedRuneLocale->__variable); - free(CachedRuneLocale); + /* Free the old runes if it exists. */ + /* FIXME: The "EUC" check here is a hideous abstraction violation. */ + if ((saved.runes != &_DefaultRuneLocale) && (saved.runes)) { + if (strcmp(saved.runes->__encoding, "EUC") == 0) { + free(saved.runes->__variable); + } + free(saved.runes); } - CachedRuneLocale = _CurrentRuneLocale; - Cached__mb_cur_max = __mb_cur_max; - Cached__mb_sb_limit = __mb_sb_limit; - Cached__mbrtowc = __mbrtowc; - Cached__mbsinit = __mbsinit; - Cached__mbsnrtowcs = __mbsnrtowcs; - Cached__wcrtomb = __wcrtomb; - Cached__wcsnrtombs = __wcsnrtombs; - (void)strcpy(ctype_encoding, encoding); } else { - __mbrtowc = old__mbrtowc; - __mbsinit = old__mbsinit; - __mbsnrtowcs = old__mbsnrtowcs; - __wcrtomb = old__wcrtomb; - __wcsnrtombs = old__wcsnrtombs; + /* Restore the saved version if this failed. */ + memcpy(l, &saved, sizeof(struct xlocale_ctype)); free(rl); } @@ -193,12 +160,24 @@ int __wrap_setrunelocale(const char *locale) { - int ret = __setrunelocale(locale); + int ret = __setrunelocale(&__xlocale_global_ctype, locale); if (ret != 0) { errno = ret; return (_LDP_ERROR); } + __mb_cur_max = __xlocale_global_ctype.__mb_cur_max; + __mb_sb_limit = __xlocale_global_ctype.__mb_sb_limit; return (_LDP_LOADED); } - +void *__ctype_load(const char *locale, locale_t unused) +{ + struct xlocale_ctype *l = calloc(sizeof(struct xlocale_ctype), 1); + l->header.header.destructor = destruct_ctype; + if (__setrunelocale(l, locale)) + { + free(l); + return NULL; + } + return l; +} Index: lib/libc/locale/lmonetary.c =================================================================== --- lib/libc/locale/lmonetary.c (revision 225653) +++ lib/libc/locale/lmonetary.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2000, 2001 Alexey Zelkin * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -34,7 +39,6 @@ #include "ldpart.h" #include "lmonetary.h" -extern int __mlocale_changed; extern const char * __fix_locale_grouping_str(const char *); #define LCMONETARY_SIZE_FULL (sizeof(struct lc_monetary_T) / sizeof(char *)) @@ -69,9 +73,7 @@ numempty /* int_n_sign_posn */ }; -static struct lc_monetary_T _monetary_locale; -static int _monetary_using_locale; -static char *_monetary_locale_buf; +struct xlocale_monetary __xlocale_global_monetary; static char cnv(const char *str) @@ -83,23 +85,34 @@ return ((char)i); } -int -__monetary_load_locale(const char *name) +static void +destruct_monetary(void *v) { + struct xlocale_monetary *l = v; + if (l->buffer) + free(l->buffer); + free(l); +} + +static int +monetary_load_locale_l(struct xlocale_monetary *loc, int *using_locale, + int *changed, const char *name) +{ int ret; + struct lc_monetary_T *l = &loc->locale; - ret = __part_load_locale(name, &_monetary_using_locale, - &_monetary_locale_buf, "LC_MONETARY", + ret = __part_load_locale(name, using_locale, + &loc->buffer, "LC_MONETARY", LCMONETARY_SIZE_FULL, LCMONETARY_SIZE_MIN, - (const char **)&_monetary_locale); + (const char **)l); if (ret != _LDP_ERROR) - __mlocale_changed = 1; + *changed = 1; if (ret == _LDP_LOADED) { - _monetary_locale.mon_grouping = - __fix_locale_grouping_str(_monetary_locale.mon_grouping); + l->mon_grouping = + __fix_locale_grouping_str(l->mon_grouping); -#define M_ASSIGN_CHAR(NAME) (((char *)_monetary_locale.NAME)[0] = \ - cnv(_monetary_locale.NAME)) +#define M_ASSIGN_CHAR(NAME) (((char *)l->NAME)[0] = \ + cnv(l->NAME)) M_ASSIGN_CHAR(int_frac_digits); M_ASSIGN_CHAR(frac_digits); @@ -117,9 +130,9 @@ */ #define M_ASSIGN_ICHAR(NAME) \ do { \ - if (_monetary_locale.int_##NAME == NULL) \ - _monetary_locale.int_##NAME = \ - _monetary_locale.NAME; \ + if (l->int_##NAME == NULL) \ + l->int_##NAME = \ + l->NAME; \ else \ M_ASSIGN_CHAR(int_##NAME); \ } while (0) @@ -133,12 +146,32 @@ } return (ret); } +int +__monetary_load_locale(const char *name) +{ + return monetary_load_locale_l(&__xlocale_global_monetary, + &__xlocale_global_locale.using_monetary_locale, + &__xlocale_global_locale.monetary_locale_changed, name); +} +void* __monetary_load(const char *name, locale_t l) +{ + struct xlocale_monetary *new = calloc(sizeof(struct xlocale_monetary), 1); + new->header.header.destructor = destruct_monetary; + if (monetary_load_locale_l(new, &l->using_monetary_locale, + &l->monetary_locale_changed, name) == _LDP_ERROR) + { + xlocale_release(new); + return NULL; + } + return new; +} + struct lc_monetary_T * -__get_current_monetary_locale(void) +__get_current_monetary_locale(locale_t loc) { - return (_monetary_using_locale - ? &_monetary_locale + return (loc->using_monetary_locale + ? &((struct xlocale_monetary*)loc->components[XLC_MONETARY])->locale : (struct lc_monetary_T *)&_C_monetary_locale); } Index: lib/libc/locale/nextwctype.c =================================================================== --- lib/libc/locale/nextwctype.c (revision 225653) +++ lib/libc/locale/nextwctype.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2004 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -30,12 +35,15 @@ #include #include #include +#include "mblocal.h" wint_t -nextwctype(wint_t wc, wctype_t wct) +nextwctype_l(wint_t wc, wctype_t wct, locale_t locale) { size_t lim; - _RuneRange *rr = &_CurrentRuneLocale->__runetype_ext; + FIX_LOCALE(locale); + _RuneLocale *runes = XLOCALE_CTYPE(locale)->runes; + _RuneRange *rr = &runes->__runetype_ext; _RuneEntry *base, *re; int noinc; @@ -43,7 +51,7 @@ if (wc < _CACHED_RUNES) { wc++; while (wc < _CACHED_RUNES) { - if (_CurrentRuneLocale->__runetype[wc] & wct) + if (runes->__runetype[wc] & wct) return (wc); wc++; } @@ -88,3 +96,8 @@ } return (-1); } +wint_t +nextwctype(wint_t wc, wctype_t wct) +{ + return nextwctype_l(wc, wct, __get_locale()); +} Index: lib/libc/locale/wcstol.c =================================================================== --- lib/libc/locale/wcstol.c (revision 225653) +++ lib/libc/locale/wcstol.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -35,18 +40,21 @@ #include #include #include +#include "xlocale_private.h" /* * Convert a string to a long integer. */ long -wcstol(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, int base) +wcstol_l(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, int + base, locale_t locale) { const wchar_t *s; unsigned long acc; wchar_t c; unsigned long cutoff; int neg, any, cutlim; + FIX_LOCALE(locale); /* * See strtol for comments as to the logic used. @@ -54,7 +62,7 @@ s = nptr; do { c = *s++; - } while (iswspace(c)); + } while (iswspace_l(c, locale)); if (c == '-') { neg = 1; c = *s++; @@ -81,8 +89,8 @@ cutoff /= base; for ( ; ; c = *s++) { #ifdef notyet - if (iswdigit(c)) - c = digittoint(c); + if (iswdigit_l(c, locale)) + c = digittoint_l(c, locale); else #endif if (c >= L'0' && c <= L'9') @@ -115,3 +123,8 @@ *endptr = (wchar_t *)(any ? s - 1 : nptr); return (acc); } +long +wcstol(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, int base) +{ + return wcstol_l(nptr, endptr, base, __get_locale()); +} Index: lib/libc/locale/wcrtomb.c =================================================================== --- lib/libc/locale/wcrtomb.c (revision 225653) +++ lib/libc/locale/wcrtomb.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002-2004 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -31,11 +36,17 @@ #include "mblocal.h" size_t -wcrtomb(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps) +wcrtomb_l(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps, + locale_t locale) { - static mbstate_t mbs; - + FIX_LOCALE(locale); if (ps == NULL) - ps = &mbs; - return (__wcrtomb(s, wc, ps)); + ps = &locale->wcrtomb; + return (XLOCALE_CTYPE(locale)->__wcrtomb(s, wc, ps)); } + +size_t +wcrtomb(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps) +{ + return wcrtomb_l(s, wc, ps, __get_locale()); +} Index: lib/libc/locale/lmonetary.h =================================================================== --- lib/libc/locale/lmonetary.h (revision 225653) +++ lib/libc/locale/lmonetary.h (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2000, 2001 Alexey Zelkin * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -28,6 +33,7 @@ #ifndef _LMONETARY_H_ #define _LMONETARY_H_ +#include "xlocale_private.h" struct lc_monetary_T { const char *int_curr_symbol; @@ -52,8 +58,13 @@ const char *int_p_sign_posn; const char *int_n_sign_posn; }; +struct xlocale_monetary { + struct xlocale_component header; + char *buffer; + struct lc_monetary_T locale; +}; -struct lc_monetary_T *__get_current_monetary_locale(void); +struct lc_monetary_T *__get_current_monetary_locale(locale_t loc); int __monetary_load_locale(const char *); #endif /* !_LMONETARY_H_ */ Index: lib/libc/locale/wcsftime.c =================================================================== --- lib/libc/locale/wcsftime.c (revision 225653) +++ lib/libc/locale/wcsftime.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002 Tim J. Robbins * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -32,6 +37,7 @@ #include #include #include +#include "xlocale_private.h" /* * Convert date and time to a wide-character string. @@ -47,8 +53,9 @@ * format specifications in the format string. */ size_t -wcsftime(wchar_t * __restrict wcs, size_t maxsize, - const wchar_t * __restrict format, const struct tm * __restrict timeptr) +wcsftime_l(wchar_t * __restrict wcs, size_t maxsize, + const wchar_t * __restrict format, const struct tm * __restrict timeptr, + locale_t locale) { static const mbstate_t initial; mbstate_t mbs; @@ -57,6 +64,7 @@ const wchar_t *formatp; size_t n, sflen; int sverrno; + FIX_LOCALE(locale); sformat = dst = NULL; @@ -66,13 +74,13 @@ */ mbs = initial; formatp = format; - sflen = wcsrtombs(NULL, &formatp, 0, &mbs); + sflen = wcsrtombs_l(NULL, &formatp, 0, &mbs, locale); if (sflen == (size_t)-1) goto error; if ((sformat = malloc(sflen + 1)) == NULL) goto error; mbs = initial; - wcsrtombs(sformat, &formatp, sflen + 1, &mbs); + wcsrtombs_l(sformat, &formatp, sflen + 1, &mbs, locale); /* * Allocate memory for longest multibyte sequence that will fit @@ -87,11 +95,11 @@ } if ((dst = malloc(maxsize * MB_CUR_MAX)) == NULL) goto error; - if (strftime(dst, maxsize, sformat, timeptr) == 0) + if (strftime_l(dst, maxsize, sformat, timeptr, locale) == 0) goto error; dstp = dst; mbs = initial; - n = mbsrtowcs(wcs, &dstp, maxsize, &mbs); + n = mbsrtowcs_l(wcs, &dstp, maxsize, &mbs, locale); if (n == (size_t)-2 || n == (size_t)-1 || dstp != NULL) goto error; @@ -106,3 +114,9 @@ errno = sverrno; return (0); } +size_t +wcsftime(wchar_t * __restrict wcs, size_t maxsize, + const wchar_t * __restrict format, const struct tm * __restrict timeptr) +{ + return wcsftime_l(wcs, maxsize, format, timeptr, __get_locale()); +} Index: lib/libc/locale/xlocale_private.h =================================================================== --- lib/libc/locale/xlocale_private.h (revision 0) +++ lib/libc/locale/xlocale_private.h (revision 0) @@ -0,0 +1,199 @@ +/*- + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by David Chisnall under sponsorship from + * the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions * are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _XLOCALE_PRIVATE__H_ +#define _XLOCALE_PRIVATE__H_ + +#include +#include +#include +#include +#include "setlocale.h" + +enum { + XLC_COLLATE = 0, + XLC_CTYPE, + XLC_MONETARY, + XLC_NUMERIC, + XLC_TIME, + XLC_MESSAGES, + XLC_LAST +}; + + +/** + * Header used for objects that are reference counted. Objects may optionally + * have a destructor associated, which is responsible for destroying the + * structure. Global / static versions of the structure should have no + * destructor set - they can then have their reference counts manipulated as + * normal, but will not do anything with them. + * + * The header stores a retain count - objects are assumed to have a reference + * count of 1 when they are created, but the retain count is 0. When the + * retain count is less than 0, they are freed. + */ +struct xlocale_refcounted { + /** Number of references to this component. */ + long retain_count; + /** Function used to destroy this component, if one is required*/ + void(*destructor)(void*); +}; +/** + * Header for a locale component. All locale components must begin with this + * header. + */ +struct xlocale_component { + struct xlocale_refcounted header; + /** Name of the locale used for this component. */ + char locale[ENCODING_LEN+1]; +}; + +/** + * xlocale structure, stores per-thread locale information. + * + * Note: We could save a few bytes by using a bitfield for the flags at the end + * of this structure. I imagine that most programs will not have more than + * half a dozen locales though, so this doesn't seem worthwhile. + */ +struct _xlocale { + struct xlocale_refcounted header; + /** Components for the locale. */ + struct xlocale_component *components[XLC_LAST]; + /** Flag indicating if components[XLC_MONETARY] has changed since the last + * call to localeconv_l() with this locale. */ + int monetary_locale_changed; + /** Flag indicating whether this locale is actually using a locale for + * LC_MONETARY (1), or if it should use the C default instead (0). */ + int using_monetary_locale; + /** Flag indicating if components[XLC_NUMERIC] has changed since the last + * call to localeconv_l() with this locale. */ + int numeric_locale_changed; + /** Flag indicating whether this locale is actually using a locale for + * LC_NUMERIC (1), or if it should use the C default instead (0). */ + int using_numeric_locale; + /** Flag indicating whether this locale is actually using a locale for + * LC_TIME (1), or if it should use the C default instead (0). */ + int using_time_locale; + /** Flag indicating whether this locale is actually using a locale for + * LC_MESSAGES (1), or if it should use the C default instead (0). */ + int using_messages_locale; + /** The structure to be returned from localeconv_l() for this locale. */ + struct lconv lconv; + /** Persistent state used by mblen() calls. */ + __mbstate_t mblen; + /** Persistent state used by mbrlen() calls. */ + __mbstate_t mbrlen; + /** Persistent state used by mbrtowc() calls. */ + __mbstate_t mbrtowc; + /** Persistent state used by mbsnrtowcs() calls. */ + __mbstate_t mbsnrtowcs; + /** Persistent state used by mbsrtowcs() calls. */ + __mbstate_t mbsrtowcs; + /** Persistent state used by mbtowc() calls. */ + __mbstate_t mbtowc; + /** Persistent state used by wcrtomb() calls. */ + __mbstate_t wcrtomb; + /** Persistent state used by wcsnrtombs() calls. */ + __mbstate_t wcsnrtombs; + /** Persistent state used by wcsrtombs() calls. */ + __mbstate_t wcsrtombs; + /** Persistent state used by wctomb() calls. */ + __mbstate_t wctomb; + /** Buffer used by nl_langinfo_l() */ + char *csym; +}; + +/** + * Increments the reference count of a reference-counted structure. + */ +__attribute__((unused)) static void* +xlocale_retain(void *val) +{ + struct xlocale_refcounted *obj = val; + __sync_fetch_and_add(&(obj->retain_count), 1); + return val; +} +/** + * Decrements the reference count of a reference-counted structure, freeing it + * if this is the last reference, calling its destructor if it has one. + */ +__attribute__((unused)) static void +xlocale_release(void *val) +{ + struct xlocale_refcounted *obj = val; + long count = __sync_sub_and_fetch(&(obj->retain_count), 1); + if (count < 0) + { + if (0 != obj->destructor) + { + obj->destructor(obj); + } + } +} + +/** + * Load functions. Each takes the name of a locale and a pointer to the data + * to be initialised as arguments. Two special values are allowed for the + */ +extern void* __collate_load(const char*, locale_t); +extern void* __ctype_load(const char*, locale_t); +extern void* __messages_load(const char*, locale_t); +extern void* __monetary_load(const char*, locale_t); +extern void* __numeric_load(const char*, locale_t); +extern void* __time_load(const char*, locale_t); + +extern struct _xlocale __xlocale_global_locale; + +/** + * Returns the current locale for this thread, or the global locale if none is + * set. The caller does not have to free the locale. The return value from + * this call is not guaranteed to remain valid after the locale changes. As + * such, this should only be called within libc functions. + */ +locale_t __get_locale(void); + +/** + * Two magic values are allowed for locale_t objects. NULL and -1. This + * function maps those to the real locales that they represent. + */ +static inline locale_t get_real_locale(locale_t locale) +{ + switch ((intptr_t)locale) + { + case 0: return &__xlocale_global_locale; + case -1: return __get_locale(); + default: return locale; + } +} + +/** + * Replace a plaecholder locale with the real global or thread-local locale_t. + */ +#define FIX_LOCALE(l) (l = get_real_locale(l)) + +#endif Index: lib/libc/locale/newlocale.3 =================================================================== --- lib/libc/locale/newlocale.3 (revision 0) +++ lib/libc/locale/newlocale.3 (revision 0) @@ -0,0 +1,108 @@ +.\" Copyright (c) 2011 The FreeBSD Foundation +.\" All rights reserved. +.\" +.\" This documentation was written by David Chisnall under sponsorship from +.\" the FreeBSD Foundation. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.Dd September 17 2011 +.Dt newlocale 3 +.Os +.Sh NAME +.Nm newlocale +.Nd Creates a new locale +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.In xlocale +.Ft +.Fn newlocale "int mask" "const char * locale" "locale_t base" +.Sh DESCRIPTION +Creates a new locale, inheriting some properties from an existing locale. The +.Fa mask +defines the components that the new locale will have set to the locale with the +name specified in the +.Fa locale +parameter. Any other components will be inherited from +.Fa base . +.Pt +The +.Fa mask +is either +.Fa LC_ALL_MASK, +indicating all possible locale components, or the logical OR of some +combination of the following: +.Bl -tag -width "LC_MESSAGES_MASK" -offset indent +.It LC_COLLATE_MASK +The locale for string collation routines. This controls alphabetic ordering in +.Xr strcoll 3 + and +.Xr strxfrm 3 . +.It LC_CTYPE_MASK +The locale for the +.Xr ctype 3 +and +.Xr multibyte 3 +functions. This controls recognition of upper and lower case, alpha- betic or +non-alphabetic characters, and so on. +.It LC_MESSAGES_MASK +Set a locale for message catalogs, see +.Xr catopen 3 +function. +.It LC_MONETARY_MASK +Set a locale for formatting monetary values; this affects +the +.Xr localeconv 3 +function. +.It LC_NUMERIC_MASK +Set a locale for formatting numbers. This controls the for- +matting of decimal points in input and output of floating +point numbers in functions such as +.Xr printf 3 +and +.Xr scanf 3 , +as well as values returned by +.Xr localeconv 3 . +.It LC_TIME_MASK +Set a locale for formatting dates and times using the +.Xr strftime 3 +function. +.El + +This function uses the same rules for loading locale components as +.Xr setlocale 3 . +.Sh RETURN VALUES +Returns a new, valid, +.Fa locale_t +or NULL if an error occurs. You must free the returned locale with +.Xr freelocale 3 . +.Sh SEE ALSO +.Xr duplocale 3 , +.Xr freelocale 3 , +.Xr localeconv 3 , +.Xr querylocale 3 , +.Xr uselocale 3 , +.Xr xlocale 3 +.Sh STANDARDS +This function, conforms to +.St -p1003.1-2008 Index: lib/libc/locale/mbsnrtowcs.c =================================================================== --- lib/libc/locale/mbsnrtowcs.c (revision 225653) +++ lib/libc/locale/mbsnrtowcs.c (working copy) @@ -1,6 +1,11 @@ /*- * Copyright (c) 2002-2004 Tim J. Robbins. + * + * Copyright (c) 2011 The FreeBSD Foundation * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -34,14 +39,19 @@ #include "mblocal.h" size_t +mbsnrtowcs_l(wchar_t * __restrict dst, const char ** __restrict src, + size_t nms, size_t len, mbstate_t * __restrict ps, locale_t locale) +{ + FIX_LOCALE(locale); + if (ps == NULL) + ps = &locale->mbsnrtowcs; + return (XLOCALE_CTYPE(locale)->__mbsnrtowcs(dst, src, nms, len, ps)); +} +size_t mbsnrtowcs(wchar_t * __restrict dst, const char ** __restrict src, size_t nms, size_t len, mbstate_t * __restrict ps) { - static mbstate_t mbs; - - if (ps == NULL) - ps = &mbs; - return (__mbsnrtowcs(dst, src, nms, len, ps)); + return mbsnrtowcs_l(dst, src, nms, len, ps, __get_locale()); } size_t @@ -52,13 +62,14 @@ size_t nchr; wchar_t wc; size_t nb; + struct xlocale_ctype *ct = XLOCALE_CTYPE(__get_locale()); s = *src; nchr = 0; if (dst == NULL) { for (;;) { - if ((nb = __mbrtowc(&wc, s, nms, ps)) == (size_t)-1) + if ((nb = ct->__mbrtowc(&wc, s, nms, ps)) == (size_t)-1) /* Invalid sequence - mbrtowc() sets errno. */ return ((size_t)-1); else if (nb == 0 || nb == (size_t)-2) @@ -71,7 +82,7 @@ } while (len-- > 0) { - if ((nb = __mbrtowc(dst, s, nms, ps)) == (size_t)-1) { + if ((nb = ct->__mbrtowc(dst, s, nms, ps)) == (size_t)-1) { *src = s; return ((size_t)-1); } else if (nb == (size_t)-2) { Index: lib/libc/locale/xlocale.3 =================================================================== --- lib/libc/locale/xlocale.3 (revision 0) +++ lib/libc/locale/xlocale.3 (revision 0) @@ -0,0 +1,265 @@ +.\" Copyright (c) 2011 The FreeBSD Foundation +.\" All rights reserved. +.\" +.\" This documentation was written by David Chisnall under sponsorship from +.\" the FreeBSD Foundation. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.Dd September 17 2011 +.Dt XLOCALE 3 +.Os +.Sh NAME +.Nm xlocale +.Nd Thread-safe extended locale support. +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.In xlocale.h +.Sh DESCRIPTION +The extended locale support includes a set of functions for setting +thread-local locales, as well convenience functions for performing locale-aware +calls with a specified locale. +.Pp +The core of the xlocale API is the +.Fa locale_t +type. This is an opqaue type encapsulating a locale. Instances of this can be +either set as the locale for a specific thread or passed directly to the +.Fa _l +suffixed variants of various standard C functions. Two special +.Fa locale_t +values are available: +.Bl -bullet -offset indent +.It +NULL refers to the current locale for the thread, or to the global locale if no +locale has been set for this thread. +.It +LC_GLOBAL_LOCALE refers to the global locale. +.El +.Pp +The global locale is the locale set with the +.Xr setlocale 3 +function. +.Sh CAVEATS +The +.Xr setlocale 3 +function, and others in the family, refer to the global locale. Other +functions that depend on the locale, however, will take the thread-local locale +if one has been set. This means that the idiom of setting the locale using +.Xr setlocale 3 , +calling a locale-dependent function, and then restoring the locale will not +have the expected behavior if the current thread has had a locale set using +.Xr uselocale 3 . +You should avoid this idiom and prefer to use the +.Fa _l +suffixed versions instead. +.Sh SEE ALSO +.Xr duplocale 3 , +.Xr freelocale 3 , +.Xr localeconv 3 , +.Xr newlocale 3 , +.Xr querylocale 3 , +.Xr uselocale 3 , +.Sh CONVENIENCE FUNCTIONS +The xlocale API includes a number of +.Fa _l +suffixed convenience functions. These are variants of standard C functions +that have been modified to take an explicit +.Fa locale_t +parameter as the final argument or, in the case of variadic functions, as an +additional argument directly before the format string. +.Pp +These functions are exposed by including +.In xlocale.h +.Em after +including the relevant headers for the standard variant. For example, the +.Xr strtol_l 3 +function is exposed by including +.In xlocale.h +after +.In stdlib.h , +which defines +.Xr strtol 3 . +.Pp +For reference, a complete list of the locale-aware functions that are available +in this form, along with the headers that expose them, is provided here: +.Pp +.Bl -tag -width " " +.It In wctype.h +.Xr iswalnum_l 3 , +.Xr iswalpha_l 3 , +.Xr iswcntrl_l 3 , +.Xr iswctype_l 3 , +.Xr iswdigit_l 3 , +.Xr iswgraph_l 3 , +.Xr iswlower_l 3 , +.Xr iswprint_l 3 , +.Xr iswpunct_l 3 , +.Xr iswspace_l 3 , +.Xr iswupper_l 3 , +.Xr iswxdigit_l 3 , +.Xr towlower_l 3 , +.Xr towupper_l 3 , +.Xr wctype_l 3 , +.It In ctype.h +.Xr digittoint_l 3 , +.Xr isalnum_l 3 , +.Xr isalpha_l 3 , +.Xr isblank_l 3 , +.Xr iscntrl_l 3 , +.Xr isdigit_l 3 , +.Xr isgraph_l 3 , +.Xr ishexnumber_l 3 , +.Xr isideogram_l 3 , +.Xr islower_l 3 , +.Xr isnumber_l 3 , +.Xr isphonogram_l 3 , +.Xr isprint_l 3 , +.Xr ispunct_l 3 , +.Xr isrune_l 3 , +.Xr isspace_l 3 , +.Xr isspecial_l 3 , +.Xr isupper_l 3 , +.Xr isxdigit_l 3 , +.Xr tolower_l 3 , +.Xr toupper_l 3 +.It In inttypes.h +.Xr strtoimax_l 3 , +.Xr strtoumax_l 3 , +.Xr wcstoimax_l 3 , +.Xr wcstoumax_l 3 +.It In langinfo.h +.Xr nl_langinfo_l 3 +.It In monetary.h +.Xr strfmon_l 3 +.It In stdio.h +.Xr asprintf_l 3 , +.Xr fprintf_l 3 , +.Xr fscanf_l 3 , +.Xr printf_l 3 , +.Xr scanf_l 3 , +.Xr snprintf_l 3 , +.Xr sprintf_l 3 , +.Xr sscanf_l 3 , +.Xr vasprintf_l 3 , +.Xr vfprintf_l 3 , +.Xr vfscanf_l 3 , +.Xr vprintf_l 3 , +.Xr vscanf_l 3 , +.Xr vsnprintf_l 3 , +.Xr vsprintf_l 3 , +.Xr vsscanf_l 3 +.It In stdlib.h +.Xr atof_l 3 , +.Xr atoi_l 3 , +.Xr atol_l 3 , +.Xr atoll_l 3 , +.Xr mblen_l 3 , +.Xr mbstowcs_l 3 , +.Xr mbtowc_l 3 , +.Xr strtod_l 3 , +.Xr strtof_l 3 , +.Xr strtol_l 3 , +.Xr strtold_l 3 , +.Xr strtoll_l 3 , +.Xr strtoq_l 3 , +.Xr strtoul_l 3 , +.Xr strtoull_l 3 , +.Xr strtouq_l 3 , +.Xr wcstombs_l 3 , +.Xr wctomb_l 3 +.It In string.h +.Xr strcoll_l 3 , +.Xr strxfrm_l 3 , +.Xr strcasecmp_l 3 , +.Xr strcasestr_l 3 , +.Xr strncasecmp_l 3 +.It In time.h +.Xr strftime_l 3 +.Xr strptime_l 3 +.It In wchar.h +.Xr btowc_l 3 , +.Xr fgetwc_l 3 , +.Xr fgetws_l 3 , +.Xr fputwc_l 3 , +.Xr fputws_l 3 , +.Xr fwprintf_l 3 , +.Xr fwscanf_l 3 , +.Xr getwc_l 3 , +.Xr getwchar_l 3 , +.Xr mbrlen_l 3 , +.Xr mbrtowc_l 3 , +.Xr mbsinit_l 3 , +.Xr mbsnrtowcs_l 3 , +.Xr mbsrtowcs_l 3 , +.Xr putwc_l 3 , +.Xr putwchar_l 3 , +.Xr swprintf_l 3 , +.Xr swscanf_l 3 , +.Xr ungetwc_l 3 , +.Xr vfwprintf_l 3 , +.Xr vfwscanf_l 3 , +.Xr vswprintf_l 3 , +.Xr vswscanf_l 3 , +.Xr vwprintf_l 3 , +.Xr vwscanf_l 3 , +.Xr wcrtomb_l 3 , +.Xr wcscoll_l 3 , +.Xr wcsftime_l 3 , +.Xr wcsnrtombs_l 3 , +.Xr wcsrtombs_l 3 , +.Xr wcstod_l 3 , +.Xr wcstof_l 3 , +.Xr wcstol_l 3 , +.Xr wcstold_l 3 , +.Xr wcstoll_l 3 , +.Xr wcstoul_l 3 , +.Xr wcstoull_l 3 , +.Xr wcswidth_l 3 , +.Xr wcsxfrm_l 3 , +.Xr wctob_l 3 , +.Xr wcwidth_l 3 , +.Xr wprintf_l 3 , +.Xr wscanf_l 3 +.It In wctype.h +.Xr iswblank_l 3 , +.Xr iswhexnumber_l 3 , +.Xr iswideogram_l 3 , +.Xr iswnumber_l 3 , +.Xr iswphonogram_l 3 , +.Xr iswrune_l 3 , +.Xr iswspecial_l 3 , +.Xr nextwctype_l 3 , +.Xr towctrans_l 3 , +.Xr wctrans_l 3 +.It In xlocale.h +.Xr localeconv_l 3 +.El +.Sh STANDARDS +The functions +conform to +.St -p1003.1-2008 . +.Sh HISTORY +The xlocale APIs first appeared in Darwin 8.0. This implementation was +written by David Chisnall, under sponsorship from the FreeBSD Foundation and +first appeared in +.Fx 9.1 . Index: lib/libc/locale/mbrtowc.c =================================================================== --- lib/libc/locale/mbrtowc.c (revision 225653) +++ lib/libc/locale/mbrtowc.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002-2004 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -31,12 +36,18 @@ #include "mblocal.h" size_t +mbrtowc_l(wchar_t * __restrict pwc, const char * __restrict s, + size_t n, mbstate_t * __restrict ps, locale_t locale) +{ + FIX_LOCALE(locale); + if (ps == NULL) + ps = &locale->mbrtowc; + return (XLOCALE_CTYPE(locale)->__mbrtowc(pwc, s, n, ps)); +} + +size_t mbrtowc(wchar_t * __restrict pwc, const char * __restrict s, size_t n, mbstate_t * __restrict ps) { - static mbstate_t mbs; - - if (ps == NULL) - ps = &mbs; - return (__mbrtowc(pwc, s, n, ps)); + return mbrtowc_l(pwc, s, n, ps, __get_locale()); } Index: lib/libc/locale/ctype.c =================================================================== --- lib/libc/locale/ctype.c (revision 0) +++ lib/libc/locale/ctype.c (revision 0) @@ -0,0 +1,31 @@ +/*- + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by David Chisnall under sponsorship from + * the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions * are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#define _XLOCALE_INLINE +#include +#include +#include Index: lib/libc/stdtime/timelocal.h =================================================================== --- lib/libc/stdtime/timelocal.h (revision 225653) +++ lib/libc/stdtime/timelocal.h (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1997-2002 FreeBSD Project. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -28,6 +33,7 @@ #ifndef _TIMELOCAL_H_ #define _TIMELOCAL_H_ +#include "xlocale_private.h" /* * Private header file for the strftime and strptime localization @@ -49,7 +55,7 @@ const char *ampm_fmt; }; -struct lc_time_T *__get_current_time_locale(void); +struct lc_time_T *__get_current_time_locale(locale_t); int __time_load_locale(const char *); #endif /* !_TIMELOCAL_H_ */ Index: lib/libc/stdtime/strptime.c =================================================================== --- lib/libc/stdtime/strptime.c (revision 225653) +++ lib/libc/stdtime/strptime.c (working copy) @@ -22,6 +22,11 @@ /* * Copyright (c) 1994 Powerdog Industries. All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -72,19 +77,20 @@ #include "libc_private.h" #include "timelocal.h" -static char * _strptime(const char *, const char *, struct tm *, int *); +static char * _strptime(const char *, const char *, struct tm *, int *, locale_t); #define asizeof(a) (sizeof (a) / sizeof ((a)[0])) static char * -_strptime(const char *buf, const char *fmt, struct tm *tm, int *GMTp) +_strptime(const char *buf, const char *fmt, struct tm *tm, int *GMTp, + locale_t locale) { char c; const char *ptr; int i, len; int Ealternative, Oalternative; - struct lc_time_T *tptr = __get_current_time_locale(); + struct lc_time_T *tptr = __get_current_time_locale(locale); ptr = fmt; while (*ptr != 0) { @@ -94,8 +100,8 @@ c = *ptr++; if (c != '%') { - if (isspace((unsigned char)c)) - while (*buf != 0 && isspace((unsigned char)*buf)) + if (isspace_l((unsigned char)c, locale)) + while (*buf != 0 && isspace_l((unsigned char)*buf, locale)) buf++; else if (c != *buf++) return 0; @@ -114,18 +120,18 @@ break; case '+': - buf = _strptime(buf, tptr->date_fmt, tm, GMTp); + buf = _strptime(buf, tptr->date_fmt, tm, GMTp, locale); if (buf == 0) return 0; break; case 'C': - if (!isdigit((unsigned char)*buf)) + if (!isdigit_l((unsigned char)*buf, locale)) return 0; /* XXX This will break for 3-digit centuries. */ len = 2; - for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { + for (i = 0; len && *buf != 0 && isdigit_l((unsigned char)*buf, locale); buf++) { i *= 10; i += *buf - '0'; len--; @@ -137,13 +143,13 @@ break; case 'c': - buf = _strptime(buf, tptr->c_fmt, tm, GMTp); + buf = _strptime(buf, tptr->c_fmt, tm, GMTp, locale); if (buf == 0) return 0; break; case 'D': - buf = _strptime(buf, "%m/%d/%y", tm, GMTp); + buf = _strptime(buf, "%m/%d/%y", tm, GMTp, locale); if (buf == 0) return 0; break; @@ -161,47 +167,47 @@ goto label; case 'F': - buf = _strptime(buf, "%Y-%m-%d", tm, GMTp); + buf = _strptime(buf, "%Y-%m-%d", tm, GMTp, locale); if (buf == 0) return 0; break; case 'R': - buf = _strptime(buf, "%H:%M", tm, GMTp); + buf = _strptime(buf, "%H:%M", tm, GMTp, locale); if (buf == 0) return 0; break; case 'r': - buf = _strptime(buf, tptr->ampm_fmt, tm, GMTp); + buf = _strptime(buf, tptr->ampm_fmt, tm, GMTp, locale); if (buf == 0) return 0; break; case 'T': - buf = _strptime(buf, "%H:%M:%S", tm, GMTp); + buf = _strptime(buf, "%H:%M:%S", tm, GMTp, locale); if (buf == 0) return 0; break; case 'X': - buf = _strptime(buf, tptr->X_fmt, tm, GMTp); + buf = _strptime(buf, tptr->X_fmt, tm, GMTp, locale); if (buf == 0) return 0; break; case 'x': - buf = _strptime(buf, tptr->x_fmt, tm, GMTp); + buf = _strptime(buf, tptr->x_fmt, tm, GMTp, locale); if (buf == 0) return 0; break; case 'j': - if (!isdigit((unsigned char)*buf)) + if (!isdigit_l((unsigned char)*buf, locale)) return 0; len = 3; - for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { + for (i = 0; len && *buf != 0 && isdigit_l((unsigned char)*buf, locale); buf++) { i *= 10; i += *buf - '0'; len--; @@ -214,14 +220,14 @@ case 'M': case 'S': - if (*buf == 0 || isspace((unsigned char)*buf)) + if (*buf == 0 || isspace_l((unsigned char)*buf, locale)) break; - if (!isdigit((unsigned char)*buf)) + if (!isdigit_l((unsigned char)*buf, locale)) return 0; len = 2; - for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { + for (i = 0; len && *buf != 0 && isdigit_l((unsigned char)*buf, locale); buf++) { i *= 10; i += *buf - '0'; len--; @@ -237,8 +243,8 @@ tm->tm_sec = i; } - if (*buf != 0 && isspace((unsigned char)*buf)) - while (*ptr != 0 && !isspace((unsigned char)*ptr)) + if (*buf != 0 && isspace_l((unsigned char)*buf, locale)) + while (*ptr != 0 && !isspace_l((unsigned char)*ptr, locale)) ptr++; break; @@ -254,11 +260,11 @@ * XXX The %l specifier may gobble one too many * digits if used incorrectly. */ - if (!isdigit((unsigned char)*buf)) + if (!isdigit_l((unsigned char)*buf, locale)) return 0; len = 2; - for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { + for (i = 0; len && *buf != 0 && isdigit_l((unsigned char)*buf, locale); buf++) { i *= 10; i += *buf - '0'; len--; @@ -271,8 +277,8 @@ tm->tm_hour = i; - if (*buf != 0 && isspace((unsigned char)*buf)) - while (*ptr != 0 && !isspace((unsigned char)*ptr)) + if (*buf != 0 && isspace_l((unsigned char)*buf, locale)) + while (*ptr != 0 && !isspace_l((unsigned char)*ptr, locale)) ptr++; break; @@ -282,7 +288,7 @@ * specifiers. */ len = strlen(tptr->am); - if (strncasecmp(buf, tptr->am, len) == 0) { + if (strncasecmp_l(buf, tptr->am, len, locale) == 0) { if (tm->tm_hour > 12) return 0; if (tm->tm_hour == 12) @@ -292,7 +298,7 @@ } len = strlen(tptr->pm); - if (strncasecmp(buf, tptr->pm, len) == 0) { + if (strncasecmp_l(buf, tptr->pm, len, locale) == 0) { if (tm->tm_hour > 12) return 0; if (tm->tm_hour != 12) @@ -307,12 +313,12 @@ case 'a': for (i = 0; i < asizeof(tptr->weekday); i++) { len = strlen(tptr->weekday[i]); - if (strncasecmp(buf, tptr->weekday[i], - len) == 0) + if (strncasecmp_l(buf, tptr->weekday[i], + len, locale) == 0) break; len = strlen(tptr->wday[i]); - if (strncasecmp(buf, tptr->wday[i], - len) == 0) + if (strncasecmp_l(buf, tptr->wday[i], + len, locale) == 0) break; } if (i == asizeof(tptr->weekday)) @@ -330,11 +336,11 @@ * point to calculate a real value, so just check the * range for now. */ - if (!isdigit((unsigned char)*buf)) + if (!isdigit_l((unsigned char)*buf, locale)) return 0; len = 2; - for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { + for (i = 0; len && *buf != 0 && isdigit_l((unsigned char)*buf, locale); buf++) { i *= 10; i += *buf - '0'; len--; @@ -342,13 +348,13 @@ if (i > 53) return 0; - if (*buf != 0 && isspace((unsigned char)*buf)) - while (*ptr != 0 && !isspace((unsigned char)*ptr)) + if (*buf != 0 && isspace_l((unsigned char)*buf, locale)) + while (*ptr != 0 && !isspace_l((unsigned char)*ptr, locale)) ptr++; break; case 'w': - if (!isdigit((unsigned char)*buf)) + if (!isdigit_l((unsigned char)*buf, locale)) return 0; i = *buf - '0'; @@ -357,8 +363,8 @@ tm->tm_wday = i; - if (*buf != 0 && isspace((unsigned char)*buf)) - while (*ptr != 0 && !isspace((unsigned char)*ptr)) + if (*buf != 0 && isspace_l((unsigned char)*buf, locale)) + while (*ptr != 0 && !isspace_l((unsigned char)*ptr, locale)) ptr++; break; @@ -372,11 +378,11 @@ * XXX The %e specifier may gobble one too many * digits if used incorrectly. */ - if (!isdigit((unsigned char)*buf)) + if (!isdigit_l((unsigned char)*buf, locale)) return 0; len = 2; - for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { + for (i = 0; len && *buf != 0 && isdigit_l((unsigned char)*buf, locale); buf++) { i *= 10; i += *buf - '0'; len--; @@ -386,8 +392,8 @@ tm->tm_mday = i; - if (*buf != 0 && isspace((unsigned char)*buf)) - while (*ptr != 0 && !isspace((unsigned char)*ptr)) + if (*buf != 0 && isspace_l((unsigned char)*buf, locale)) + while (*ptr != 0 && !isspace_l((unsigned char)*ptr, locale)) ptr++; break; @@ -398,15 +404,15 @@ if (Oalternative) { if (c == 'B') { len = strlen(tptr->alt_month[i]); - if (strncasecmp(buf, + if (strncasecmp_l(buf, tptr->alt_month[i], - len) == 0) + len, locale) == 0) break; } } else { len = strlen(tptr->month[i]); - if (strncasecmp(buf, tptr->month[i], - len) == 0) + if (strncasecmp_l(buf, tptr->month[i], + len, locale) == 0) break; } } @@ -417,8 +423,8 @@ if (i == asizeof(tptr->month) && !Oalternative) { for (i = 0; i < asizeof(tptr->month); i++) { len = strlen(tptr->mon[i]); - if (strncasecmp(buf, tptr->mon[i], - len) == 0) + if (strncasecmp_l(buf, tptr->mon[i], + len, locale) == 0) break; } } @@ -430,11 +436,11 @@ break; case 'm': - if (!isdigit((unsigned char)*buf)) + if (!isdigit_l((unsigned char)*buf, locale)) return 0; len = 2; - for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { + for (i = 0; len && *buf != 0 && isdigit_l((unsigned char)*buf, locale); buf++) { i *= 10; i += *buf - '0'; len--; @@ -444,8 +450,8 @@ tm->tm_mon = i - 1; - if (*buf != 0 && isspace((unsigned char)*buf)) - while (*ptr != 0 && !isspace((unsigned char)*ptr)) + if (*buf != 0 && isspace_l((unsigned char)*buf, locale)) + while (*ptr != 0 && !isspace_l((unsigned char)*ptr, locale)) ptr++; break; @@ -458,7 +464,7 @@ sverrno = errno; errno = 0; - n = strtol(buf, &cp, 10); + n = strtol_l(buf, &cp, 10, locale); if (errno == ERANGE || (long)(t = n) != n) { errno = sverrno; return 0; @@ -472,14 +478,14 @@ case 'Y': case 'y': - if (*buf == 0 || isspace((unsigned char)*buf)) + if (*buf == 0 || isspace_l((unsigned char)*buf, locale)) break; - if (!isdigit((unsigned char)*buf)) + if (!isdigit_l((unsigned char)*buf, locale)) return 0; len = (c == 'Y') ? 4 : 2; - for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { + for (i = 0; len && *buf != 0 && isdigit_l((unsigned char)*buf, locale); buf++) { i *= 10; i += *buf - '0'; len--; @@ -493,8 +499,8 @@ tm->tm_year = i; - if (*buf != 0 && isspace((unsigned char)*buf)) - while (*ptr != 0 && !isspace((unsigned char)*ptr)) + if (*buf != 0 && isspace_l((unsigned char)*buf, locale)) + while (*ptr != 0 && !isspace_l((unsigned char)*ptr, locale)) ptr++; break; @@ -503,7 +509,7 @@ const char *cp; char *zonestr; - for (cp = buf; *cp && isupper((unsigned char)*cp); ++cp) {/*empty*/} + for (cp = buf; *cp && isupper_l((unsigned char)*cp, locale); ++cp) {/*empty*/} if (cp - buf) { zonestr = alloca(cp - buf + 1); strncpy(zonestr, buf, cp - buf); @@ -537,7 +543,7 @@ buf++; i = 0; for (len = 4; len > 0; len--) { - if (isdigit((unsigned char)*buf)) { + if (isdigit_l((unsigned char)*buf, locale)) { i *= 10; i += *buf - '0'; buf++; @@ -557,14 +563,15 @@ char * -strptime(const char * __restrict buf, const char * __restrict fmt, - struct tm * __restrict tm) +strptime_l(const char * __restrict buf, const char * __restrict fmt, + struct tm * __restrict tm, locale_t loc) { char *ret; int gmt; + FIX_LOCALE(loc); gmt = 0; - ret = _strptime(buf, fmt, tm, &gmt); + ret = _strptime(buf, fmt, tm, &gmt, loc); if (ret && gmt) { time_t t = timegm(tm); localtime_r(&t, tm); @@ -572,3 +579,9 @@ return (ret); } +char * +strptime(const char * __restrict buf, const char * __restrict fmt, + struct tm * __restrict tm) +{ + return strptime_l(buf, fmt, tm, __get_locale()); +} Index: lib/libc/stdtime/timelocal.c =================================================================== --- lib/libc/stdtime/timelocal.c (revision 225653) +++ lib/libc/stdtime/timelocal.c (working copy) @@ -3,6 +3,11 @@ * Copyright (c) 1997 FreeBSD Inc. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -33,10 +38,14 @@ #include "ldpart.h" #include "timelocal.h" -static struct lc_time_T _time_locale; -static int _time_using_locale; -static char *time_locale_buf; +struct xlocale_time { + struct xlocale_component header; + char *buffer; + struct lc_time_T locale; +}; +struct xlocale_time __xlocale_global_time; + #define LCTIME_SIZE (sizeof(struct lc_time_T) / sizeof(char *)) static const struct lc_time_T _C_time_locale = { @@ -99,19 +108,47 @@ "%I:%M:%S %p" }; +static void destruct_time(void *v) +{ + struct xlocale_time *l = v; + if (l->buffer) + free(l->buffer); + free(l); +} + +#include struct lc_time_T * -__get_current_time_locale(void) +__get_current_time_locale(locale_t loc) { - return (_time_using_locale - ? &_time_locale + return (loc->using_time_locale + ? &((struct xlocale_time *)loc->components[XLC_TIME])->locale : (struct lc_time_T *)&_C_time_locale); } +static int +time_load_locale(struct xlocale_time *l, int *using_locale, const char *name) +{ + struct lc_time_T *time_locale = &l->locale; + return (__part_load_locale(name, using_locale, + &l->buffer, "LC_TIME", + LCTIME_SIZE, LCTIME_SIZE, + (const char **)time_locale)); +} int __time_load_locale(const char *name) { - return (__part_load_locale(name, &_time_using_locale, - &time_locale_buf, "LC_TIME", - LCTIME_SIZE, LCTIME_SIZE, - (const char **)&_time_locale)); + return time_load_locale(&__xlocale_global_time, + &__xlocale_global_locale.using_time_locale, name); } +extern void* __time_load(const char* name, locale_t loc) +{ + struct xlocale_time *new = calloc(sizeof(struct xlocale_time), 1); + new->header.header.destructor = destruct_time; + if (time_load_locale(new, &loc->using_time_locale, name) == _LDP_ERROR) + { + xlocale_release(new); + return NULL; + } + return new; +} + Index: lib/libc/stdtime/strftime.c =================================================================== --- lib/libc/stdtime/strftime.c (revision 225653) +++ lib/libc/stdtime/strftime.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1989 The Regents of the University of California. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms are permitted * provided that the above copyright notice and this paragraph are * duplicated in all such forms and that any documentation, @@ -43,7 +48,7 @@ static char * _add(const char *, char *, const char *); static char * _conv(int, const char *, char *, const char *); static char * _fmt(const char *, const struct tm *, char *, const char *, - int *); + int *, locale_t); static char * _yconv(int, int, int, int, char *, const char *); extern char * tzname[]; @@ -82,29 +87,30 @@ }; size_t -strftime(char * __restrict s, size_t maxsize, const char * __restrict format, - const struct tm * __restrict t) +strftime_l(char * __restrict s, size_t maxsize, const char * __restrict format, + const struct tm * __restrict t, locale_t loc) { char * p; int warn; + FIX_LOCALE(loc); tzset(); warn = IN_NONE; - p = _fmt(((format == NULL) ? "%c" : format), t, s, s + maxsize, &warn); + p = _fmt(((format == NULL) ? "%c" : format), t, s, s + maxsize, &warn, loc); #ifndef NO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU if (warn != IN_NONE && getenv(YEAR_2000_NAME) != NULL) { - (void) fprintf(stderr, "\n"); + (void) fprintf_l(stderr, loc, "\n"); if (format == NULL) - (void) fprintf(stderr, "NULL strftime format "); - else (void) fprintf(stderr, "strftime format \"%s\" ", + (void) fprintf_l(stderr, loc, "NULL strftime format "); + else (void) fprintf_l(stderr, loc, "strftime format \"%s\" ", format); - (void) fprintf(stderr, "yields only two digits of years in "); + (void) fprintf_l(stderr, loc, "yields only two digits of years in "); if (warn == IN_SOME) - (void) fprintf(stderr, "some locales"); + (void) fprintf_l(stderr, loc, "some locales"); else if (warn == IN_THIS) - (void) fprintf(stderr, "the current locale"); - else (void) fprintf(stderr, "all locales"); - (void) fprintf(stderr, "\n"); + (void) fprintf_l(stderr, loc, "the current locale"); + else (void) fprintf_l(stderr, loc, "all locales"); + (void) fprintf_l(stderr, loc, "\n"); } #endif /* !defined NO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU */ if (p == s + maxsize) @@ -113,16 +119,24 @@ return p - s; } +size_t +strftime(char * __restrict s, size_t maxsize, const char * __restrict format, + const struct tm * __restrict t) +{ + return strftime_l(s, maxsize, format, t, __get_locale()); +} + static char * -_fmt(format, t, pt, ptlim, warnp) +_fmt(format, t, pt, ptlim, warnp, loc) const char * format; const struct tm * const t; char * pt; const char * const ptlim; int * warnp; +locale_t loc; { int Ealternative, Oalternative, PadIndex; - struct lc_time_T *tptr = __get_current_time_locale(); + struct lc_time_T *tptr = __get_current_time_locale(loc); for ( ; *format; ++format) { if (*format == '%') { @@ -175,7 +189,7 @@ { int warn2 = IN_SOME; - pt = _fmt(tptr->c_fmt, t, pt, ptlim, &warn2); + pt = _fmt(tptr->c_fmt, t, pt, ptlim, &warn2, loc); if (warn2 == IN_ALL) warn2 = IN_THIS; if (warn2 > *warnp) @@ -183,7 +197,7 @@ } continue; case 'D': - pt = _fmt("%m/%d/%y", t, pt, ptlim, warnp); + pt = _fmt("%m/%d/%y", t, pt, ptlim, warnp, loc); continue; case 'd': pt = _conv(t->tm_mday, fmt_padding[PAD_FMT_DAYOFMONTH][PadIndex], @@ -216,7 +230,7 @@ fmt_padding[PAD_FMT_SDAYOFMONTH][PadIndex], pt, ptlim); continue; case 'F': - pt = _fmt("%Y-%m-%d", t, pt, ptlim, warnp); + pt = _fmt("%Y-%m-%d", t, pt, ptlim, warnp, loc); continue; case 'H': pt = _conv(t->tm_hour, fmt_padding[PAD_FMT_HMS][PadIndex], @@ -285,11 +299,11 @@ pt, ptlim); continue; case 'R': - pt = _fmt("%H:%M", t, pt, ptlim, warnp); + pt = _fmt("%H:%M", t, pt, ptlim, warnp, loc); continue; case 'r': pt = _fmt(tptr->ampm_fmt, t, pt, ptlim, - warnp); + warnp, loc); continue; case 'S': pt = _conv(t->tm_sec, fmt_padding[PAD_FMT_HMS][PadIndex], @@ -313,7 +327,7 @@ } continue; case 'T': - pt = _fmt("%H:%M:%S", t, pt, ptlim, warnp); + pt = _fmt("%H:%M:%S", t, pt, ptlim, warnp, loc); continue; case 't': pt = _add("\t", pt, ptlim); @@ -428,7 +442,7 @@ ** "date as dd-bbb-YYYY" ** (ado, 1993-05-24) */ - pt = _fmt("%e-%b-%Y", t, pt, ptlim, warnp); + pt = _fmt("%e-%b-%Y", t, pt, ptlim, warnp, loc); continue; case 'W': pt = _conv((t->tm_yday + DAYSPERWEEK - @@ -441,13 +455,13 @@ pt = _conv(t->tm_wday, "%d", pt, ptlim); continue; case 'X': - pt = _fmt(tptr->X_fmt, t, pt, ptlim, warnp); + pt = _fmt(tptr->X_fmt, t, pt, ptlim, warnp, loc); continue; case 'x': { int warn2 = IN_SOME; - pt = _fmt(tptr->x_fmt, t, pt, ptlim, &warn2); + pt = _fmt(tptr->x_fmt, t, pt, ptlim, &warn2, loc); if (warn2 == IN_ALL) warn2 = IN_THIS; if (warn2 > *warnp) @@ -534,7 +548,7 @@ continue; case '+': pt = _fmt(tptr->date_fmt, t, pt, ptlim, - warnp); + warnp, loc); continue; case '-': if (PadIndex != PAD_DEFAULT) Index: lib/libc/gen/glob.c =================================================================== --- lib/libc/gen/glob.c (revision 225653) +++ lib/libc/gen/glob.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Guido van Rossum. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -751,6 +756,8 @@ { int ok, negate_range; Char c, k; + struct xlocale_collate *table = + (struct xlocale_collate*)__get_locale()->components[XLC_COLLATE]; while (pat < patend) { c = *pat++; @@ -775,10 +782,10 @@ ++pat; while (((c = *pat++) & M_MASK) != M_END) if ((*pat & M_MASK) == M_RNG) { - if (__collate_load_error ? + if (table->__collate_load_error ? CHAR(c) <= CHAR(k) && CHAR(k) <= CHAR(pat[1]) : - __collate_range_cmp(CHAR(c), CHAR(k)) <= 0 - && __collate_range_cmp(CHAR(k), CHAR(pat[1])) <= 0 + __collate_range_cmp(table, CHAR(c), CHAR(k)) <= 0 + && __collate_range_cmp(table, CHAR(k), CHAR(pat[1])) <= 0 ) ok = 1; pat += 2; Index: lib/libc/gen/fnmatch.c =================================================================== --- lib/libc/gen/fnmatch.c (revision 225653) +++ lib/libc/gen/fnmatch.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Guido van Rossum. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -222,6 +227,8 @@ wchar_t c, c2; size_t pclen; const char *origpat; + struct xlocale_collate *table = + (struct xlocale_collate*)__get_locale()->components[XLC_COLLATE]; /* * A bracket expression starting with an unquoted circumflex @@ -276,10 +283,10 @@ if (flags & FNM_CASEFOLD) c2 = towlower(c2); - if (__collate_load_error ? + if (table->__collate_load_error ? c <= test && test <= c2 : - __collate_range_cmp(c, test) <= 0 - && __collate_range_cmp(test, c2) <= 0 + __collate_range_cmp(table, c, test) <= 0 + && __collate_range_cmp(table, test, c2) <= 0 ) ok = 1; } else if (c == test) Index: lib/libc/regex/regcomp.c =================================================================== --- lib/libc/regex/regcomp.c (revision 225653) +++ lib/libc/regex/regcomp.c (working copy) @@ -3,9 +3,19 @@ * Copyright (c) 1992, 1993, 1994 * The Regents of the University of California. All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * This code is derived from software contributed to Berkeley by * Henry Spencer. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -730,6 +740,8 @@ char c; wint_t start, finish; wint_t i; + struct xlocale_collate *table = + (struct xlocale_collate*)__get_locale()->components[XLC_COLLATE]; /* classify what we've got */ switch ((MORE()) ? PEEK() : '\0') { @@ -778,14 +790,14 @@ if (start == finish) CHadd(p, cs, start); else { - if (__collate_load_error) { + if (table->__collate_load_error) { (void)REQUIRE((uch)start <= (uch)finish, REG_ERANGE); CHaddrange(p, cs, start, finish); } else { - (void)REQUIRE(__collate_range_cmp(start, finish) <= 0, REG_ERANGE); + (void)REQUIRE(__collate_range_cmp(table, start, finish) <= 0, REG_ERANGE); for (i = 0; i <= UCHAR_MAX; i++) { - if ( __collate_range_cmp(start, i) <= 0 - && __collate_range_cmp(i, finish) <= 0 + if ( __collate_range_cmp(table, start, i) <= 0 + && __collate_range_cmp(table, i, finish) <= 0 ) CHadd(p, cs, i); } Index: lib/libc/Makefile =================================================================== --- lib/libc/Makefile (revision 225653) +++ lib/libc/Makefile (working copy) @@ -3,6 +3,9 @@ SHLIBDIR?= /lib +DEBUG_CFLAGS+=-g +CFLAGS+=-g + .include # Pick the current architecture directory for libc. In general, this is @@ -36,6 +39,7 @@ CFLAGS+=${CANCELPOINTS_CFLAGS} .endif + # # Only link with static libgcc.a (no libgcc_eh.a). # Index: lib/libc/gdtoa/machdep_ldisd.c =================================================================== --- lib/libc/gdtoa/machdep_ldisd.c (revision 225653) +++ lib/libc/gdtoa/machdep_ldisd.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2003 David Schultz * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -34,10 +39,10 @@ __FBSDID("$FreeBSD$"); #include "gdtoaimp.h" +#undef strtold_l long double -strtold(const char * __restrict s, char ** __restrict sp) +strtold_l(const char * __restrict s, char ** __restrict sp, locale_t locale) { - - return strtod(s, sp); + return __strtod_l(s, sp, locale); } Index: lib/libc/gdtoa/machdep_ldisx.c =================================================================== --- lib/libc/gdtoa/machdep_ldisx.c (revision 225653) +++ lib/libc/gdtoa/machdep_ldisx.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2003 David Schultz * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -38,10 +43,11 @@ #include "gdtoaimp.h" long double -strtold(const char * __restrict s, char ** __restrict sp) +strtold_l(const char * __restrict s, char ** __restrict sp, locale_t locale) { long double result; + FIX_LOCALE(locale); - strtorx(s, sp, FLT_ROUNDS, &result); + strtorx_l(s, sp, FLT_ROUNDS, &result, locale); return result; } Index: lib/libc/gdtoa/machdep_ldisQ.c =================================================================== --- lib/libc/gdtoa/machdep_ldisQ.c (revision 225653) +++ lib/libc/gdtoa/machdep_ldisQ.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2003 David Schultz * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -38,10 +43,10 @@ #include "gdtoaimp.h" long double -strtold(const char * __restrict s, char ** __restrict sp) +strtold_l(const char * __restrict s, char ** __restrict sp, locale_t locale) { long double result; - strtorQ(s, sp, FLT_ROUNDS, &result); + strtorQ_l(s, sp, FLT_ROUNDS, &result, locale); return result; } Index: lib/libc/string/strcasecmp.c =================================================================== --- lib/libc/string/strcasecmp.c (revision 225653) +++ lib/libc/string/strcasecmp.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1987, 1993 * The Regents of the University of California. All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -35,36 +40,50 @@ #include #include +#include "xlocale_private.h" typedef unsigned char u_char; int -strcasecmp(const char *s1, const char *s2) +strcasecmp_l(const char *s1, const char *s2, locale_t locale) { const u_char *us1 = (const u_char *)s1, *us2 = (const u_char *)s2; + FIX_LOCALE(locale); - while (tolower(*us1) == tolower(*us2++)) + while (tolower_l(*us1, locale) == tolower_l(*us2++, locale)) if (*us1++ == '\0') return (0); - return (tolower(*us1) - tolower(*--us2)); + return (tolower_l(*us1, locale) - tolower_l(*--us2, locale)); } +int +strcasecmp(const char *s1, const char *s2) +{ + return strcasecmp_l(s1, s2, __get_locale()); +} int -strncasecmp(const char *s1, const char *s2, size_t n) +strncasecmp_l(const char *s1, const char *s2, size_t n, locale_t locale) { + FIX_LOCALE(locale); if (n != 0) { const u_char *us1 = (const u_char *)s1, *us2 = (const u_char *)s2; do { - if (tolower(*us1) != tolower(*us2++)) - return (tolower(*us1) - tolower(*--us2)); + if (tolower_l(*us1, locale) != tolower_l(*us2++, locale)) + return (tolower_l(*us1, locale) - tolower_l(*--us2, locale)); if (*us1++ == '\0') break; } while (--n != 0); } return (0); } + +int +strncasecmp(const char *s1, const char *s2, size_t n) +{ + return strncasecmp_l(s1, s2, n, __get_locale()); +} Index: lib/libc/string/wcscoll.c =================================================================== --- lib/libc/string/wcscoll.c (revision 225653) +++ lib/libc/string/wcscoll.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002 Tim J. Robbins * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -41,12 +46,15 @@ * with extended character sets. */ int -wcscoll(const wchar_t *ws1, const wchar_t *ws2) +wcscoll_l(const wchar_t *ws1, const wchar_t *ws2, locale_t locale) { char *mbs1, *mbs2; int diff, sverrno; + FIX_LOCALE(locale); + struct xlocale_collate *table = + (struct xlocale_collate*)locale->components[XLC_COLLATE]; - if (__collate_load_error || MB_CUR_MAX > 1) + if (table->__collate_load_error || MB_CUR_MAX > 1) /* * Locale has no special collating order, could not be * loaded, or has an extended character set; do a fast binary @@ -67,7 +75,7 @@ return (wcscmp(ws1, ws2)); } - diff = strcoll(mbs1, mbs2); + diff = strcoll_l(mbs1, mbs2, locale); sverrno = errno; free(mbs1); free(mbs2); @@ -76,6 +84,12 @@ return (diff); } +int +wcscoll(const wchar_t *ws1, const wchar_t *ws2) +{ + return wcscoll_l(ws1, ws2, __get_locale()); +} + static char * __mbsdup(const wchar_t *ws) { Index: lib/libc/string/wcswidth.c =================================================================== --- lib/libc/string/wcswidth.c (revision 225653) +++ lib/libc/string/wcswidth.c (working copy) @@ -10,6 +10,11 @@ * This code is derived from software contributed to Berkeley by * Paul Borman at Krystal Technologies. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -39,19 +44,26 @@ __FBSDID("$FreeBSD$"); #include +#include "xlocale_private.h" int -wcswidth(const wchar_t *pwcs, size_t n) +wcswidth_l(const wchar_t *pwcs, size_t n, locale_t locale) { wchar_t wc; int len, l; + FIX_LOCALE(locale); len = 0; while (n-- > 0 && (wc = *pwcs++) != L'\0') { - if ((l = wcwidth(wc)) < 0) + if ((l = wcwidth_l(wc, locale)) < 0) return (-1); len += l; } return (len); } +int +wcswidth(const wchar_t *pwcs, size_t n) +{ + return wcswidth_l(pwcs, n, __get_locale()); +} Index: lib/libc/string/Symbol.map =================================================================== --- lib/libc/string/Symbol.map (revision 225653) +++ lib/libc/string/Symbol.map (working copy) @@ -75,6 +75,11 @@ wmemcpy; wmemmove; wmemset; + strcasecmp_l; + strcasestr_l; + strncasecmp_l; + wcswidth_l; + wcwidth_l; }; FBSD_1.1 { Index: lib/libc/string/strcoll.c =================================================================== --- lib/libc/string/strcoll.c (revision 225653) +++ lib/libc/string/strcoll.c (working copy) @@ -3,6 +3,11 @@ * at Electronni Visti IA, Kiev, Ukraine. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -32,21 +37,26 @@ #include #include "collate.h" +#include + int -strcoll(const char *s, const char *s2) +strcoll_l(const char *s, const char *s2, locale_t locale) { int len, len2, prim, prim2, sec, sec2, ret, ret2; const char *t, *t2; char *tt, *tt2; + FIX_LOCALE(locale); + struct xlocale_collate *table = + (struct xlocale_collate*)locale->components[XLC_COLLATE]; - if (__collate_load_error) + if (table->__collate_load_error) return strcmp(s, s2); len = len2 = 1; ret = ret2 = 0; - if (__collate_substitute_nontrivial) { - t = tt = __collate_substitute(s); - t2 = tt2 = __collate_substitute(s2); + if (table->__collate_substitute_nontrivial) { + t = tt = __collate_substitute(table, s); + t2 = tt2 = __collate_substitute(table, s2); } else { tt = tt2 = NULL; t = s; @@ -55,11 +65,11 @@ while(*t && *t2) { prim = prim2 = 0; while(*t && !prim) { - __collate_lookup(t, &len, &prim, &sec); + __collate_lookup(table, t, &len, &prim, &sec); t += len; } while(*t2 && !prim2) { - __collate_lookup(t2, &len2, &prim2, &sec2); + __collate_lookup(table, t2, &len2, &prim2, &sec2); t2 += len2; } if(!prim || !prim2) @@ -83,3 +93,10 @@ return ret; } + +int +strcoll(const char *s, const char *s2) +{ + return strcoll_l(s, s2, __get_locale()); +} + Index: lib/libc/string/wcsxfrm.c =================================================================== --- lib/libc/string/wcsxfrm.c (revision 225653) +++ lib/libc/string/wcsxfrm.c (working copy) @@ -3,6 +3,11 @@ * at Electronni Visti IA, Kiev, Ukraine. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -43,11 +48,14 @@ * the logic used. */ size_t -wcsxfrm(wchar_t * __restrict dest, const wchar_t * __restrict src, size_t len) +wcsxfrm_l(wchar_t * __restrict dest, const wchar_t * __restrict src, size_t len, locale_t locale) { int prim, sec, l; size_t slen; char *mbsrc, *s, *ss; + FIX_LOCALE(locale); + struct xlocale_collate *table = + (struct xlocale_collate*)locale->components[XLC_COLLATE]; if (*src == L'\0') { if (len != 0) @@ -55,7 +63,7 @@ return (0); } - if (__collate_load_error || MB_CUR_MAX > 1) { + if (table->__collate_load_error || MB_CUR_MAX > 1) { slen = wcslen(src); if (len > 0) { if (slen < len) @@ -71,10 +79,10 @@ mbsrc = __mbsdup(src); slen = 0; prim = sec = 0; - ss = s = __collate_substitute(mbsrc); + ss = s = __collate_substitute(table, mbsrc); while (*s != '\0') { while (*s != '\0' && prim == 0) { - __collate_lookup(s, &l, &prim, &sec); + __collate_lookup(table, s, &l, &prim, &sec); s += l; } if (prim != 0) { @@ -93,6 +101,11 @@ return (slen); } +size_t +wcsxfrm(wchar_t * __restrict dest, const wchar_t * __restrict src, size_t len) +{ + return wcsxfrm_l(dest, src, len, __get_locale()); +} static char * __mbsdup(const wchar_t *ws) Index: lib/libc/string/strcasestr.c =================================================================== --- lib/libc/string/strcasestr.c (revision 225653) +++ lib/libc/string/strcasestr.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Chris Torek. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -35,26 +40,33 @@ #include #include +#include "xlocale_private.h" /* * Find the first occurrence of find in s, ignore case. */ char * -strcasestr(const char *s, const char *find) +strcasestr_l(const char *s, const char *find, locale_t locale) { char c, sc; size_t len; + FIX_LOCALE(locale); if ((c = *find++) != 0) { - c = tolower((unsigned char)c); + c = tolower_l((unsigned char)c, locale); len = strlen(find); do { do { if ((sc = *s++) == 0) return (NULL); - } while ((char)tolower((unsigned char)sc) != c); - } while (strncasecmp(s, find, len) != 0); + } while ((char)tolower_l((unsigned char)sc, locale) != c); + } while (strncasecmp_l(s, find, len, locale) != 0); s--; } return ((char *)s); } +char * +strcasestr(const char *s, const char *find) +{ + return strcasestr_l(s, find, __get_locale()); +} Index: lib/libc/string/strxfrm.c =================================================================== --- lib/libc/string/strxfrm.c (revision 225653) +++ lib/libc/string/strxfrm.c (working copy) @@ -3,6 +3,11 @@ * at Electronni Visti IA, Kiev, Ukraine. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -33,11 +38,22 @@ #include "collate.h" size_t +strxfrm_l(char * __restrict dest, const char * __restrict src, size_t len, locale_t loc); +size_t strxfrm(char * __restrict dest, const char * __restrict src, size_t len) { + return strxfrm_l(dest, src, len, __get_locale()); +} + +size_t +strxfrm_l(char * __restrict dest, const char * __restrict src, size_t len, locale_t locale) +{ int prim, sec, l; size_t slen; char *s, *ss; + FIX_LOCALE(locale); + struct xlocale_collate *table = + (struct xlocale_collate*)locale->components[XLC_COLLATE]; if (!*src) { if (len > 0) @@ -45,15 +61,15 @@ return 0; } - if (__collate_load_error) + if (table->__collate_load_error) return strlcpy(dest, src, len); slen = 0; prim = sec = 0; - ss = s = __collate_substitute(src); + ss = s = __collate_substitute(table, src); while (*s) { while (*s && !prim) { - __collate_lookup(s, &l, &prim, &sec); + __collate_lookup(table, s, &l, &prim, &sec); s += l; } if (prim) { Index: sys/amd64/include/_stdint.h =================================================================== --- sys/amd64/include/_stdint.h (revision 225653) +++ sys/amd64/include/_stdint.h (working copy) @@ -150,8 +150,8 @@ #define PTRDIFF_MAX INT64_MAX /* Limits of sig_atomic_t. */ -#define SIG_ATOMIC_MIN INT32_MIN -#define SIG_ATOMIC_MAX INT32_MAX +#define SIG_ATOMIC_MIN LONG_MIN +#define SIG_ATOMIC_MAX LONG_MAX /* Limit of size_t. */ #define SIZE_MAX UINT64_MAX Index: sys/sys/cdefs.h =================================================================== --- sys/sys/cdefs.h (revision 225653) +++ sys/sys/cdefs.h (working copy) @@ -253,6 +253,17 @@ #define __LONG_LONG_SUPPORTED #endif +/* C++11 exposes a load of C99 stuff */ +#if __cplusplus >= 201103L +# define __LONG_LONG_SUPPORTED +# ifndef __STDC_LIMIT_MACROS +# define __STDC_LIMIT_MACROS +# endif +# ifndef __STDC_CONSTANT_MACROS +# define __STDC_CONSTANT_MACROS +# endif +#endif + /* * GCC 2.95 provides `__restrict' as an extension to C90 to support the * C99-specific `restrict' type qualifier. We happen to use `__restrict' as --Apple-Mail=_D1FEC970-512C-409C-B503-1C81695F7BCD-- From owner-freebsd-hackers@FreeBSD.ORG Wed Sep 21 22:43:46 2011 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id B50D2106566B; Wed, 21 Sep 2011 22:43:46 +0000 (UTC) (envelope-from lacombar@gmail.com) Received: from mail-ww0-f50.google.com (mail-ww0-f50.google.com [74.125.82.50]) by mx1.freebsd.org (Postfix) with ESMTP id 225108FC12; Wed, 21 Sep 2011 22:43:45 +0000 (UTC) Received: by wwe3 with SMTP id 3so1286857wwe.31 for ; Wed, 21 Sep 2011 15:43:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=mime-version:in-reply-to:references:date:message-id:subject:from:to :cc:content-type:content-transfer-encoding; bh=5/uOl3OpreKoXCE17MzYpJIcKASzPGSE4ZFS31UsSlg=; b=lqyyxfaAJEzS+9LbNHznKDliHkBAmlde9TdZH56uwN/Z2ThEKocFvWZAFGRt5aGZ9M 39YmWIWjnJDfLDAGMDxNkx6Zc2O/Uk3hARBs/7HoFWyqlUSWJWD05vydXnvjaSo9Xy5e e2tKhgrgHH69bR/a6mKizZQiszArkuINXvNwM= MIME-Version: 1.0 Received: by 10.216.172.75 with SMTP id s53mr2830581wel.38.1316645025269; Wed, 21 Sep 2011 15:43:45 -0700 (PDT) Received: by 10.180.95.169 with HTTP; Wed, 21 Sep 2011 15:43:45 -0700 (PDT) In-Reply-To: References: Date: Wed, 21 Sep 2011 18:43:45 -0400 Message-ID: From: Arnaud Lacombe To: "K. Macy" Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable Cc: FreeBSD Hackers Subject: Re: buf_ring(9) API precisions X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 21 Sep 2011 22:43:46 -0000 Hi, On Mon, Sep 19, 2011 at 8:46 AM, K. Macy wrote: > If the value lags next by one then it is ours. This rule applies to > all callers so the rule holds consistently. > I think you do not understand what I mean, which is that the following: while (br->br_prod_tail !=3D prod_head) cpu_spinwait(); br->br_prod_bufs++; br->br_prod_bytes +=3D nbytes; br->br_prod_tail =3D prod_next; critical_exit(); at runtime, can be seen, memory-wise as: while (br->br_prod_tail !=3D prod_head) cpu_spinwait(); br->br_prod_tail =3D prod_next; br->br_prod_bufs++; br->br_prod_bytes +=3D nbytes; critical_exit(); That is, there is no memory barrier to enforce completion of the load/increment/store/load/load/addition/store operations before updating what other thread spin on. Yes, `br_prod_tail' is marked `volatile', but there is no guarantee that it will not be re-ordered wrt. non-volatile write (to `br_prod_bufs' and `br_prod_bytes'). - Arnaud > On Mon, Sep 19, 2011 at 5:53 AM, Arnaud Lacombe wrot= e: >> Hi, >> >> On Fri, Sep 16, 2011 at 10:41 AM, K. Macy wrote: >>> On Fri, Sep 16, 2011 at 3:02 AM, Arnaud Lacombe wr= ote: >>>> Hi, >>>> >>>> On Wed, Sep 14, 2011 at 10:53 PM, Arnaud Lacombe = wrote: >>>>> Hi Kip, >>>>> >>>>> I've got a few question about the buf_ring(9) API. >>>>> >>>>> 1) what means the 'drbr_' prefix. I can guess the two last letter, 'b= ' >>>>> and 'r', for Buffer Ring, but what about 'd' and 'r' ? >>>>> >>>>> 2) in `sys/sys/buf_ring.h', you defined 'struct buf_ring' as: >>>>> >>>>> struct buf_ring { >>>>> =A0 =A0 =A0 =A0volatile uint32_t =A0 =A0 =A0 br_prod_head; >>>>> =A0 =A0 =A0 =A0volatile uint32_t =A0 =A0 =A0 br_prod_tail; >>>>> =A0 =A0 =A0 =A0int =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 br_prod_si= ze; >>>>> =A0 =A0 =A0 =A0int =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 br_prod_ma= sk; >>>>> =A0 =A0 =A0 =A0uint64_t =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0br_drops; >>>>> =A0 =A0 =A0 =A0uint64_t =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0br_prod_bufs; >>>>> =A0 =A0 =A0 =A0uint64_t =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0br_prod_bytes; >>>> shouldn't those 3 fields be updated atomically, especially on 32bits >>>> platforms ? That might pose a problem as, AFAIK, FreeBSD do not have >>>> MI 64bits atomics operations... >>> >>> Between the point at which br_prod_tail =3D=3D prod_head and when we >>> update br_prod_tail to point to prod_next we are the exclusive owners >>> of the fields in buf_ring. That is why we wait for any other >>> enqueueing threads to update br_prod_tail to point to prod_head before >>> continuing. >>> >> How do you enforce ordering ? I do not see anything particular >> forbidding the `br->br_prod_tail' to be committed first, leading other >> thread to believe they have access to the statistics, while the other >> thread has not yet committed its change. >> >> Thanks, >> =A0- Arnaud >> >>> Cheers >>> >>> =A0 =A0 =A0 =A0/* >>> =A0 =A0 =A0 =A0 * If there are other enqueues in progress >>> =A0 =A0 =A0 =A0 * that preceeded us, we need to wait for them >>> =A0 =A0 =A0 =A0 * to complete >>> =A0 =A0 =A0 =A0 */ >>> =A0 =A0 =A0 =A0while (br->br_prod_tail !=3D prod_head) >>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0cpu_spinwait(); >>> =A0 =A0 =A0 =A0br->br_prod_bufs++; >>> =A0 =A0 =A0 =A0br->br_prod_bytes +=3D nbytes; >>> =A0 =A0 =A0 =A0br->br_prod_tail =3D prod_next; >>> =A0 =A0 =A0 =A0critical_exit(); >>> >> > From owner-freebsd-hackers@FreeBSD.ORG Thu Sep 22 19:05:37 2011 Return-Path: Delivered-To: hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 20774106564A for ; Thu, 22 Sep 2011 19:05:37 +0000 (UTC) (envelope-from uqs@spoerlein.net) Received: from acme.spoerlein.net (acme.spoerlein.net [IPv6:2a01:4f8:131:23c2::1]) by mx1.freebsd.org (Postfix) with ESMTP id AE9EA8FC12 for ; Thu, 22 Sep 2011 19:05:36 +0000 (UTC) Received: from localhost (acme.spoerlein.net [IPv6:2a01:4f8:131:23c2::1]) by acme.spoerlein.net (8.14.4/8.14.4) with ESMTP id p8MJ5Ze3073428 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES128-SHA bits=128 verify=NO) for ; Thu, 22 Sep 2011 21:05:35 +0200 (CEST) (envelope-from uqs@spoerlein.net) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=spoerlein.net; s=dkim200908; t=1316718335; bh=+qHJ+qBAhB/gkM2qEkLELVC8jbtoKkM57hQ2XAT3XxY=; h=Date:From:To:Subject:Message-ID:References:MIME-Version: Content-Type:In-Reply-To; b=DOSeeuSMzeGz1CGHtW84FCYjVbGTFERivc+xDr4GtS+UQvEzzkzz5w4jTvVtIZAdP OFYdY53GJKBxRk9ihR2z5IRHtJEV4hkLVw6uqqXnZckC6DRLVwN1uGTE7smp9k0Kjn s/DJw24eCfYfBPiA32yq0N0qCHp2JwvXTstdh4fA= Date: Thu, 22 Sep 2011 21:05:35 +0200 From: Ulrich =?utf-8?B?U3DDtnJsZWlu?= To: hackers@freebsd.org Message-ID: <20110922190535.GR26743@acme.spoerlein.net> Mail-Followup-To: hackers@freebsd.org References: <4E712D11.7040202@FreeBSD.org> <4E75B67E.1000802@FreeBSD.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <4E75B67E.1000802@FreeBSD.org> User-Agent: Mutt/1.5.21 (2010-09-15) Cc: Subject: Re: Fwd: my git development snapshot(s) X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 22 Sep 2011 19:05:37 -0000 On Sun, 2011-09-18 at 12:14:38 +0300, Andriy Gapon wrote: > > Just decided to follow the global trends and trying to throw all of my > local/private changes at you in hope that the "crowd-sourcing magic" might > somehow happen :-) This seems definitely easier than carefully producing the > patch files and keeping them up-to-date. > > So, my newly cloned gitorious repository: > https://gitorious.org/~avg/freebsd/avgbsd > > And the first branch of interest: > https://gitorious.org/~avg/freebsd/avgbsd/commits/devel-20110915 I'll throw mine in as well: https://github.com/uqs/freebsd-head/branches If you did the rsync from repos.freebsd.your.org, then you simply: $ git remote add uqs git://github.com/uqs/freebsd-head.git $ git fetch uqs and you can look at the remote branches uqs/* to see bits of it. Cheers, Uli From owner-freebsd-hackers@FreeBSD.ORG Thu Sep 22 19:52:45 2011 Return-Path: Delivered-To: hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 3987C106566C; Thu, 22 Sep 2011 19:52:45 +0000 (UTC) (envelope-from lacombar@gmail.com) Received: from mail-ww0-f50.google.com (mail-ww0-f50.google.com [74.125.82.50]) by mx1.freebsd.org (Postfix) with ESMTP id 9AD418FC12; Thu, 22 Sep 2011 19:52:44 +0000 (UTC) Received: by wwe3 with SMTP id 3so2558998wwe.31 for ; Thu, 22 Sep 2011 12:52:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=mime-version:in-reply-to:references:date:message-id:subject:from:to :cc:content-type:content-transfer-encoding; bh=OQpArRAFRswInYvVG6JBaRSDjes2tk8BvjuBZt/UBvY=; b=dgXfV/NggeMY+wdIImbq/FcnzS2OrE0ER799SFwSyz7PMj2kME/GKzKvG7M5VgA4gG lj11Q8okvroVVHpJbJiWoX3YDmjq1uGlnkt5vdeITJ8/nE9FbH0pM8W065PYoKujNtgi HWOL4l88vLabtgtzTWmampXE7QMJBnhahg75o= MIME-Version: 1.0 Received: by 10.227.135.141 with SMTP id n13mr1061421wbt.53.1316721163350; Thu, 22 Sep 2011 12:52:43 -0700 (PDT) Received: by 10.180.95.169 with HTTP; Thu, 22 Sep 2011 12:52:43 -0700 (PDT) In-Reply-To: <20110922190535.GR26743@acme.spoerlein.net> References: <4E712D11.7040202@FreeBSD.org> <4E75B67E.1000802@FreeBSD.org> <20110922190535.GR26743@acme.spoerlein.net> Date: Thu, 22 Sep 2011 15:52:43 -0400 Message-ID: From: Arnaud Lacombe To: hackers@freebsd.org Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable Cc: Fabien Thomas Subject: Re: Fwd: my git development snapshot(s) X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 22 Sep 2011 19:52:45 -0000 Hi, On Thu, Sep 22, 2011 at 3:05 PM, Ulrich Sp=F6rlein wrot= e: > On Sun, 2011-09-18 at 12:14:38 +0300, Andriy Gapon wrote: >> >> Just decided to follow the global trends and trying to throw all of my >> local/private changes at you in hope that the "crowd-sourcing magic" mig= ht >> somehow happen :-) =A0This seems definitely easier than carefully produc= ing the >> patch files and keeping them up-to-date. >> >> So, my newly cloned gitorious repository: >> https://gitorious.org/~avg/freebsd/avgbsd >> >> And the first branch of interest: >> https://gitorious.org/~avg/freebsd/avgbsd/commits/devel-20110915 > > I'll throw mine in as well: > > https://github.com/uqs/freebsd-head/branches > is that the same as tree as Fabien's, or a new snapshot ? If not, couldn't we agree to have all the same tree in order to ease code sharing between all of them ? I see there is already a https://github.com/freebsd/freebsd tree, which seem different than Fabien's tree on github. It really look like The FreeBSD Project (https://github.com/freebsd/) is not able to provide consistency. Thanks, - Arnaud > If you did the rsync from repos.freebsd.your.org, then you simply: > > $ git remote add uqs git://github.com/uqs/freebsd-head.git > $ git fetch uqs > > and you can look at the remote branches uqs/* to see bits of it. > > Cheers, > Uli > _______________________________________________ > freebsd-hackers@freebsd.org mailing list > http://lists.freebsd.org/mailman/listinfo/freebsd-hackers > To unsubscribe, send any mail to "freebsd-hackers-unsubscribe@freebsd.org= " > From owner-freebsd-hackers@FreeBSD.ORG Thu Sep 22 21:26:04 2011 Return-Path: Delivered-To: hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 8125E106566C; Thu, 22 Sep 2011 21:26:04 +0000 (UTC) (envelope-from uqs@spoerlein.net) Received: from acme.spoerlein.net (acme.spoerlein.net [IPv6:2a01:4f8:131:23c2::1]) by mx1.freebsd.org (Postfix) with ESMTP id F19CA8FC14; Thu, 22 Sep 2011 21:26:03 +0000 (UTC) Received: from localhost (acme.spoerlein.net [IPv6:2a01:4f8:131:23c2::1]) by acme.spoerlein.net (8.14.4/8.14.4) with ESMTP id p8MLQ2ZP076579 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES128-SHA bits=128 verify=NO); Thu, 22 Sep 2011 23:26:02 +0200 (CEST) (envelope-from uqs@spoerlein.net) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=spoerlein.net; s=dkim200908; t=1316726763; bh=gidan7GdW8R3oXir012oCA9TVXwviY3w7nCOmVnJGGM=; h=Date:From:To:Cc:Subject:Message-ID:References:MIME-Version: Content-Type:Content-Transfer-Encoding:In-Reply-To; b=AdAZGNsIRKB65X5mfLyaKRheU2s7PFDgnGHXbSiCZDIFX/Jc7u5Z0AiA4MJaqJuyD jWZtiH9ey1KfsVbXBqRMFGX3VPxCpkNX/xbVQns8B73mUFczXqBwB8JJhBDoKO0GEY t/ebi1iCF15AghC/CcukIFcO2RJpfmMudw52EPUk= Date: Thu, 22 Sep 2011 23:26:02 +0200 From: Ulrich =?utf-8?B?U3DDtnJsZWlu?= To: Arnaud Lacombe Message-ID: <20110922212602.GS26743@acme.spoerlein.net> Mail-Followup-To: Arnaud Lacombe , hackers@freebsd.org, Fabien Thomas References: <4E712D11.7040202@FreeBSD.org> <4E75B67E.1000802@FreeBSD.org> <20110922190535.GR26743@acme.spoerlein.net> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: User-Agent: Mutt/1.5.21 (2010-09-15) Cc: hackers@freebsd.org, Fabien Thomas Subject: Re: Fwd: my git development snapshot(s) X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 22 Sep 2011 21:26:04 -0000 On Thu, 2011-09-22 at 15:52:43 -0400, Arnaud Lacombe wrote: > Hi, > > On Thu, Sep 22, 2011 at 3:05 PM, Ulrich Spörlein wrote: > > On Sun, 2011-09-18 at 12:14:38 +0300, Andriy Gapon wrote: > >> > >> Just decided to follow the global trends and trying to throw all of my > >> local/private changes at you in hope that the "crowd-sourcing magic" might > >> somehow happen :-)  This seems definitely easier than carefully producing the > >> patch files and keeping them up-to-date. > >> > >> So, my newly cloned gitorious repository: > >> https://gitorious.org/~avg/freebsd/avgbsd > >> > >> And the first branch of interest: > >> https://gitorious.org/~avg/freebsd/avgbsd/commits/devel-20110915 > > > > I'll throw mine in as well: > > > > https://github.com/uqs/freebsd-head/branches > > > is that the same as tree as Fabien's, or a new snapshot ? > > If not, couldn't we agree to have all the same tree in order to ease > code sharing between all of them ? > > I see there is already a https://github.com/freebsd/freebsd tree, > which seem different than Fabien's tree on github. It really look like > The FreeBSD Project (https://github.com/freebsd/) is not able to > provide consistency. The freebsd-head tree is the same that everybody in the world can get by simply running git svn clone against the FreeBSD subversion server (you'd need a lot of patience, though). It's also available from git.freebsd.your.org and on code.google.com (except that Google's git backend sucks ass). Fabien's tree is cut off at an arbitrary date and if you happen to choose a different date, well you cannot merge any branches with that repository. http://wiki.freebsd.org/GitWorkflow Uli From owner-freebsd-hackers@FreeBSD.ORG Thu Sep 22 22:19:45 2011 Return-Path: Delivered-To: hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 1D40C106564A; Thu, 22 Sep 2011 22:19:45 +0000 (UTC) (envelope-from lacombar@gmail.com) Received: from mail-wy0-f182.google.com (mail-wy0-f182.google.com [74.125.82.182]) by mx1.freebsd.org (Postfix) with ESMTP id 687DC8FC0C; Thu, 22 Sep 2011 22:19:43 +0000 (UTC) Received: by wyj26 with SMTP id 26so466683wyj.13 for ; Thu, 22 Sep 2011 15:19:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=mime-version:in-reply-to:references:date:message-id:subject:from:to :content-type:content-transfer-encoding; bh=rTZe52nQUJxqYRDTDvI1bFEhaiRgI89QmQH7ktmjWHY=; b=Eqji8x1n2O97SKF5cHNpSfKmexjbT4skfu9pNMRmA/01NOVHtWOdbLp9r3U6ItQ+0+ bp1d/IqRWPqw/nQIy//yy16GhpIv3Duz7G66gxFGoWTXdx4ly/O5yi8ZQBR9pcDp/q/K VsdzwkzhwYdwFXG8udPDbQz6nB/lYDX4lDb5E= MIME-Version: 1.0 Received: by 10.227.135.141 with SMTP id n13mr1203378wbt.53.1316729982988; Thu, 22 Sep 2011 15:19:42 -0700 (PDT) Received: by 10.180.95.169 with HTTP; Thu, 22 Sep 2011 15:19:42 -0700 (PDT) In-Reply-To: <20110922212602.GS26743@acme.spoerlein.net> References: <4E712D11.7040202@FreeBSD.org> <4E75B67E.1000802@FreeBSD.org> <20110922190535.GR26743@acme.spoerlein.net> <20110922212602.GS26743@acme.spoerlein.net> Date: Thu, 22 Sep 2011 18:19:42 -0400 Message-ID: From: Arnaud Lacombe To: hackers@freebsd.org, Fabien Thomas Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable Cc: Subject: Re: Fwd: my git development snapshot(s) X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 22 Sep 2011 22:19:45 -0000 Hi, On Thu, Sep 22, 2011 at 5:26 PM, Ulrich Sp=F6rlein wrot= e: > On Thu, 2011-09-22 at 15:52:43 -0400, Arnaud Lacombe wrote: >> Hi, >> >> On Thu, Sep 22, 2011 at 3:05 PM, Ulrich Sp=F6rlein w= rote: >> > On Sun, 2011-09-18 at 12:14:38 +0300, Andriy Gapon wrote: >> >> >> >> Just decided to follow the global trends and trying to throw all of m= y >> >> local/private changes at you in hope that the "crowd-sourcing magic" = might >> >> somehow happen :-) =A0This seems definitely easier than carefully pro= ducing the >> >> patch files and keeping them up-to-date. >> >> >> >> So, my newly cloned gitorious repository: >> >> https://gitorious.org/~avg/freebsd/avgbsd >> >> >> >> And the first branch of interest: >> >> https://gitorious.org/~avg/freebsd/avgbsd/commits/devel-20110915 >> > >> > I'll throw mine in as well: >> > >> > https://github.com/uqs/freebsd-head/branches >> > >> is that the same as tree as Fabien's, or a new snapshot ? >> >> If not, couldn't we agree to have all the same tree in order to ease >> code sharing between all of them ? >> >> I see there is already a https://github.com/freebsd/freebsd tree, >> which seem different than Fabien's tree on github. It really look like >> The FreeBSD Project (https://github.com/freebsd/) is not able to >> provide consistency. > > The freebsd-head tree is the same that everybody in the world can get by > simply running git svn clone against the FreeBSD subversion server > (you'd need a lot of patience, though). > > It's also available from git.freebsd.your.org and on code.google.com > (except that Google's git backend sucks ass). > > Fabien's tree is cut off at an arbitrary date and if you happen to > choose a different date, well you cannot merge any branches with that > repository. > ok, so Fabien's tree is the one duplicating the work :) looks like for years I used the wrong one and better have to switch to the tree from github to get the full history. Fabien, if the size is the only matter of your tree, shouldn't you just create a shallow tree from the common tree ? At least, hashes will match up to a given point. You may also want to clean the branches to only keep releng/, stable/, releases/ and head/. - Arnaud From owner-freebsd-hackers@FreeBSD.ORG Fri Sep 23 13:01:34 2011 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 41C801065675 for ; Fri, 23 Sep 2011 13:01:34 +0000 (UTC) (envelope-from geoffrey.levand@mail.ru) Received: from f44.mail.ru (f44.mail.ru [217.69.129.100]) by mx1.freebsd.org (Postfix) with ESMTP id B20FE8FC12 for ; Fri, 23 Sep 2011 13:01:33 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=mail.ru; s=mail; h=Message-Id:Content-Type:Reply-To:Date:Mime-Version:Subject:To:From; bh=o/NyVCi19LzqRTVdyLDlT7oUZHVIDzE73ah30V/5rpc=; b=RyModCcjHvFBa+x4TdKIF2g0yan/VKm/XSwF93YaJasvkhNNj/V3EOEHxaI0ZnrjlUO+3HcnvEFVTceYNKL/joM9mju2MVgrNsSmxP/N8XLW+0s1e/5qAwzw1a3nih6C; Received: from mail by f44.mail.ru with local id 1R75Nj-00066m-00 for freebsd-hackers@freebsd.org; Fri, 23 Sep 2011 17:01:31 +0400 Received: from [217.228.3.213] by e.mail.ru with HTTP; Fri, 23 Sep 2011 17:01:31 +0400 From: =?UTF-8?B?Z2VvZmZyZXkgbGV2YW5k?= To: freebsd-hackers@freebsd.org Mime-Version: 1.0 X-Mailer: mPOP Web-Mail 2.19 X-Originating-IP: [217.228.3.213] Date: Fri, 23 Sep 2011 17:01:31 +0400 X-Priority: Message-Id: X-Spam: Not detected X-Mras: Ok Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: base64 X-Content-Filtered-By: Mailman/MimeDel 2.1.5 Subject: CAM framework for FLASH devices X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list Reply-To: =?UTF-8?B?Z2VvZmZyZXkgbGV2YW5k?= List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 23 Sep 2011 13:01:34 -0000 CiAKICAKICAKQ291bGQgQ0FNIGZyYW1ld29yayBiZSB1c2VkIGZvciBkZXZpY2VzIHdoaWNoIGRv IG5vdCBzdXBwb3J0IFNDU0kgb3IgQVRBIGNvbW1hbmRzIG5hdGl2ZWx5LCBlLmcuIEZMQVNIIGRl dmljZXMgPwpJIGRpZG4ndCBmaW5kIGFueSBleGFtcGxlcyBmb3IgdGhpcyBjYXNlLgpJJ20gZGV2 ZWxvcGluZyBQUzMgZmxhc2ggZGV2aWNlIGRyaXZlci4gT3IgaXMgZGlzayBmcmFtZXdvcmsgYmV0 dGVyIGluIHRoaXMgY2FzZSA/CkkgdXNlZCBDQU0gZm9yIFBTMyBDRFJPTSBkcml2ZXIgYnV0IGl0 IHN1cHBvcnRzIFNDU0kgY29tbWFuZHMgbmF0aXZlbHkgYW5kCmkgbGlrZWQgaXQgdmVyeSBtdWNo IHNvIGkgd291bGQgbGlrZSB0byB1c2UgaXQgZm9yIEZMQVNIIGRldmljZXMgdG9vLgoKICAKLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLQo= From owner-freebsd-hackers@FreeBSD.ORG Fri Sep 23 14:44:28 2011 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 185D7106564A for ; Fri, 23 Sep 2011 14:44:28 +0000 (UTC) (envelope-from doconnor@gsoft.com.au) Received: from cain.gsoft.com.au (cain.gsoft.com.au [203.31.81.10]) by mx1.freebsd.org (Postfix) with ESMTP id 932F88FC12 for ; Fri, 23 Sep 2011 14:44:26 +0000 (UTC) Received: from ur.dons.net.au (ppp118-210-8-217.lns20.adl2.internode.on.net [118.210.8.217]) (authenticated bits=0) by cain.gsoft.com.au (8.14.4/8.14.3) with ESMTP id p8NEiFwG069676 (version=TLSv1/SSLv3 cipher=AES128-SHA bits=128 verify=NO); Sat, 24 Sep 2011 00:14:22 +0930 (CST) (envelope-from doconnor@gsoft.com.au) Mime-Version: 1.0 (Apple Message framework v1244.3) Content-Type: text/plain; charset=us-ascii From: "Daniel O'Connor" In-Reply-To: Date: Sat, 24 Sep 2011 00:14:15 +0930 Content-Transfer-Encoding: quoted-printable Message-Id: References: To: geoffrey levand X-Mailer: Apple Mail (2.1244.3) X-Spam-Score: 2.162 (**) BAYES_00,KHOP_DYNAMIC,RDNS_DYNAMIC X-Scanned-By: MIMEDefang 2.67 on 203.31.81.10 Cc: freebsd-hackers@freebsd.org Subject: Re: CAM framework for FLASH devices X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 23 Sep 2011 14:44:28 -0000 On 23/09/2011, at 22:31, geoffrey levand wrote: > Could CAM framework be used for devices which do not support SCSI or = ATA commands natively, e.g. FLASH devices ? > I didn't find any examples for this case. > I'm developing PS3 flash device driver. Or is disk framework better in = this case ? > I used CAM for PS3 CDROM driver but it supports SCSI commands natively = and > i liked it very much so i would like to use it for FLASH devices too. I don't think so - I think you want a GEOM class, e.g... http://osdir.com/ml/freebsd-geom/2009-04/msg00008.html (I haven't really looked in detail though..) -- Daniel O'Connor software and network engineer for Genesis Software - http://www.gsoft.com.au "The nice thing about standards is that there are so many of them to choose from." -- Andrew Tanenbaum GPG Fingerprint - 5596 B766 97C0 0E94 4347 295E E593 DC20 7B3F CE8C From owner-freebsd-hackers@FreeBSD.ORG Fri Sep 23 13:18:20 2011 Return-Path: Delivered-To: hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 5B9F7106567A for ; Fri, 23 Sep 2011 13:18:20 +0000 (UTC) (envelope-from geoffrey.levand@mail.ru) Received: from fallback4.mail.ru (fallback4.mail.ru [94.100.176.42]) by mx1.freebsd.org (Postfix) with ESMTP id 109BD8FC1E for ; Fri, 23 Sep 2011 13:18:19 +0000 (UTC) Received: from f95.mail.ru (f95.mail.ru [217.69.129.118]) by fallback4.mail.ru (mPOP.Fallback_MX) with ESMTP id 366844B500BA for ; Fri, 23 Sep 2011 16:59:57 +0400 (MSD) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=mail.ru; s=mail; h=Message-Id:Content-Type:Reply-To:Date:Mime-Version:Subject:To:From; bh=PghcehP9YtmD+tTJjce99NDhRlLlxZOgs1EWg3dRDrE=; b=ibtfkrgXQ1Qgw7E1JBDp4KXTdepwu+krYjPQ8jP+GP3suO1klBZVa9Z073/8RoHaz0WIhtChbODIJhFhDOFMdjKtyZwfoCGZ1E4s52KEVyKfAAcbOjVJJxDAZFyf/FUh; Received: from mail by f95.mail.ru with local id 1R75MB-0006VA-00 for hackers@freebsd.org; Fri, 23 Sep 2011 16:59:55 +0400 Received: from [217.228.1.143] by e.mail.ru with HTTP; Fri, 23 Sep 2011 16:59:55 +0400 From: =?UTF-8?B?Z2VvZmZyZXkgbGV2YW5k?= To: hackers@freebsd.org Mime-Version: 1.0 X-Mailer: mPOP Web-Mail 2.19 X-Originating-IP: [217.228.1.143] Date: Fri, 23 Sep 2011 16:59:55 +0400 X-Priority: Message-Id: X-Spam: Not detected X-Mras: Ok X-Mailman-Approved-At: Fri, 23 Sep 2011 15:23:08 +0000 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: base64 X-Content-Filtered-By: Mailman/MimeDel 2.1.5 Cc: Subject: CAM framework for FLASH devices X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list Reply-To: =?UTF-8?B?Z2VvZmZyZXkgbGV2YW5k?= List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 23 Sep 2011 13:18:20 -0000 Q291bGQgQ0FNIGZyYW1ld29yayBiZSB1c2VkIGZvciBkZXZpY2VzIHdoaWNoIGRvIG5vdCBzdXBw b3J0IFNDU0kgb3IgQVRBIGNvbW1hbmRzIG5hdGl2ZWx5LCBlLmcuIEZMQVNIIGRldmljZXMgPwpJ IGRpZG4ndCBmaW5kIGFueSBleGFtcGxlcyBmb3IgdGhpcyBjYXNlLgpJJ20gZGV2ZWxvcGluZyBQ UzMgZmxhc2ggZGV2aWNlIGRyaXZlci4gT3IgaXMgZGlzayBmcmFtZXdvcmsgYmV0dGVyIGluIHRo aXMgY2FzZSA/CkkgdXNlZCBDQU0gZm9yIFBTMyBDRFJPTSBkcml2ZXIgYnV0IGl0IHN1cHBvcnRz IFNDU0kgY29tbWFuZHMgbmF0aXZlbHkgYW5kCmkgbGlrZWQgaXQgdmVyeSBtdWNoIHNvIGkgd291 bGQgbGlrZSB0byB1c2UgaXQgZm9yIEZMQVNIIGRldmljZXMgdG9vLgo= From owner-freebsd-hackers@FreeBSD.ORG Fri Sep 23 15:54:20 2011 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 0AB24106566C for ; Fri, 23 Sep 2011 15:54:20 +0000 (UTC) (envelope-from geoffrey.levand@mail.ru) Received: from f261.mail.ru (f261.mail.ru [217.69.128.182]) by mx1.freebsd.org (Postfix) with ESMTP id 79E218FC13 for ; Fri, 23 Sep 2011 15:54:19 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=mail.ru; s=mail; h=Message-Id:Content-Transfer-Encoding:Content-Type:Reply-To:In-Reply-To:References:Date:Mime-Version:Subject:Cc:To:From; bh=6egS6jhY2dDMaSB9icJAOiTxF9lpHgE031snv8lyH9Y=; b=bz0yKIShycAU6meYOU8Gc7C98o3nrB07vVJuKhY0zzczg4kJgJSToygwOjh57FO3cWxs/CEqOmg1BABW7xsEPnZbhB7idNm3WnC/1Y05vHPuxcSmwUQpzdDTbLX1DFpp; Received: from mail by f261.mail.ru with local id 1R784i-0002jw-00; Fri, 23 Sep 2011 19:54:04 +0400 Received: from [109.193.222.154] by e.mail.ru with HTTP; Fri, 23 Sep 2011 19:54:04 +0400 From: =?UTF-8?B?Z2VvZmZyZXkgbGV2YW5k?= To: =?UTF-8?B?RGFuaWVsIE8nQ29ubm9y?= Mime-Version: 1.0 X-Mailer: mPOP Web-Mail 2.19 X-Originating-IP: [109.193.222.154] Date: Fri, 23 Sep 2011 19:54:04 +0400 References: In-Reply-To: X-Priority: Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: base64 Message-Id: X-Spam: Not detected X-Mras: Ok Cc: freebsd-hackers@freebsd.org Subject: Re[2]: CAM framework for FLASH devices X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list Reply-To: =?UTF-8?B?Z2VvZmZyZXkgbGV2YW5k?= List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 23 Sep 2011 15:54:20 -0000 VGhlIGludGVyZmFjZSB0byB0aGUgUFMzIGZsYXNoIGRldmljZSBpcyBOT1QgbGlrZSBub3JtYWwg Tk9SL05BTkQgZmxhc2ggaW50ZXJmYWNlcy4KVGhlIGludGVyZmFjZSB0byB0aGUgUFMzIEZMQVNI IGlzIGFic3RyYWN0ZWQgYnkgdGhlIGh5cGVydmlzb3IgYW5kIGl0IGxvb2tzIGxpa2UgSEREIHRv IEZyZWVCU0QgYnV0IGhhcyBzZXZlcmFsIGxvZ2ljYWwgdW5pdHMgbGlrZSBTQ1NJIGRldmljZXMu IFRoZSBmbGFzaCBkZXZpY2Ugc3VwcG9ydHMgd3JpdGUsIHJlYWQgYW5kIGZsdXNoIG9wZXJhdGlv bi4gU2VjdG9yIHNpemUgaXMgNTEyIGJ5dGUuIEJ1dCBpdCBkb2Vzbid0IHN1cHBvcnQgYW55IEFU QSBvciBTQ1NJIGNvbW1hbmRzIGV4Y2VwdCBmbHVzaC4KCgoyMyDRgdC10L3RgtGP0LHRgNGPIDIw MTEsIDE4OjQ1INC+0YIgIkRhbmllbCBPJ0Nvbm5vciIgPGRvY29ubm9yQGdzb2Z0LmNvbS5hdT46 Cj4gCj4gT24gMjMvMDkvMjAxMSwgYXQgMjI6MzEsIGdlb2ZmcmV5IGxldmFuZCB3cm90ZToKPiA+ IENvdWxkIENBTSBmcmFtZXdvcmsgYmUgdXNlZCBmb3IgZGV2aWNlcyB3aGljaCBkbyBub3Qgc3Vw cG9ydCBTQ1NJIG9yIEFUQSBjb21tYW5kcyBuYXRpdmVseSwgZS5nLiBGTEFTSCBkZXZpY2VzID8K PiA+IEkgZGlkbid0IGZpbmQgYW55IGV4YW1wbGVzIGZvciB0aGlzIGNhc2UuCj4gPiBJJ20gZGV2 ZWxvcGluZyBQUzMgZmxhc2ggZGV2aWNlIGRyaXZlci4gT3IgaXMgZGlzayBmcmFtZXdvcmsgYmV0 dGVyIGluIHRoaXMgY2FzZSA/Cj4gPiBJIHVzZWQgQ0FNIGZvciBQUzMgQ0RST00gZHJpdmVyIGJ1 dCBpdCBzdXBwb3J0cyBTQ1NJIGNvbW1hbmRzIG5hdGl2ZWx5IGFuZAo+ID4gaSBsaWtlZCBpdCB2 ZXJ5IG11Y2ggc28gaSB3b3VsZCBsaWtlIHRvIHVzZSBpdCBmb3IgRkxBU0ggZGV2aWNlcyB0b28u Cj4gCj4gSSBkb24ndCB0aGluayBzbyAtIEkgdGhpbmsgeW91IHdhbnQgYSBHRU9NIGNsYXNzLCBl LmcuLi4KPiBodHRwOi8vb3NkaXIuY29tL21sL2ZyZWVic2QtZ2VvbS8yMDA5LTA0L21zZzAwMDA4 Lmh0bWwKPiAKPiAoSSBoYXZlbid0IHJlYWxseSBsb29rZWQgaW4gZGV0YWlsIHRob3VnaC4uKQo+ IAo+IC0tCj4gRGFuaWVsIE8nQ29ubm9yIHNvZnR3YXJlIGFuZCBuZXR3b3JrIGVuZ2luZWVyCj4g Zm9yIEdlbmVzaXMgU29mdHdhcmUgLSBodHRwOi8vd3d3Lmdzb2Z0LmNvbS5hdQo+ICJUaGUgbmlj ZSB0aGluZyBhYm91dCBzdGFuZGFyZHMgaXMgdGhhdCB0aGVyZQo+IGFyZSBzbyBtYW55IG9mIHRo ZW0gdG8gY2hvb3NlIGZyb20uIgo+ICAgLS0gQW5kcmV3IFRhbmVuYmF1bQo+IEdQRyBGaW5nZXJw cmludCAtIDU1OTYgQjc2NiA5N0MwIDBFOTQgNDM0NyAyOTVFIEU1OTMgREMyMCA3QjNGIENFOEMK PiAKPiBfX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fXwo+IGZy ZWVic2QtaGFja2Vyc0BmcmVlYnNkLm9yZyBtYWlsaW5nIGxpc3QKPiBodHRwOi8vbGlzdHMuZnJl ZWJzZC5vcmcvbWFpbG1hbi9saXN0aW5mby9mcmVlYnNkLWhhY2tlcnMKPiBUbyB1bnN1YnNjcmli ZSwgc2VuZCBhbnkgbWFpbCB0byAiZnJlZWJzZC1oYWNrZXJzLXVuc3Vic2NyaWJlQGZyZWVic2Qu b3JnIgo+IA== From owner-freebsd-hackers@FreeBSD.ORG Fri Sep 23 19:06:28 2011 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id DD124106566C; Fri, 23 Sep 2011 19:06:28 +0000 (UTC) (envelope-from jilles@stack.nl) Received: from mx1.stack.nl (relay04.stack.nl [IPv6:2001:610:1108:5010::107]) by mx1.freebsd.org (Postfix) with ESMTP id 783CB8FC14; Fri, 23 Sep 2011 19:06:28 +0000 (UTC) Received: from turtle.stack.nl (turtle.stack.nl [IPv6:2001:610:1108:5010::132]) by mx1.stack.nl (Postfix) with ESMTP id 8BC901DD77B; Fri, 23 Sep 2011 21:06:26 +0200 (CEST) Received: by turtle.stack.nl (Postfix, from userid 1677) id 741981756C; Fri, 23 Sep 2011 21:06:26 +0200 (CEST) Date: Fri, 23 Sep 2011 21:06:26 +0200 From: Jilles Tjoelker To: Ivan Voras Message-ID: <20110923190626.GA61562@stack.nl> References: MIME-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: User-Agent: Mutt/1.5.21 (2010-09-15) Cc: freebsd-hackers@freebsd.org, geoffrey levand Subject: Re: Re[2]: Sharing device driver between kernel and user space X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 23 Sep 2011 19:06:28 -0000 On Wed, Sep 21, 2011 at 04:23:28PM +0200, Ivan Voras wrote: > On 21 September 2011 16:09, geoffrey levand wrote: > > Sure i can use the synchronization primitives, the problem is that > > the response to a request sent to PS3 VUART port is not available > > immediately, and i have to disallow kernel access to the PS3 VUART > > while i'm waiting for the response in user space. I send request > > with write syscall from user space and wait for response with read > > syscall. In the period of time between sending request and receiving > > response i could receive some other packets from VUART port, e.g. > > some kind of event notification,  i have to skip them. But kernel > > should not interfer until i get my response. So i would need to > > lock out the kernel during this time. I think i found a good > > solution for this problem, just use a IOCTL which tells kernel > > device driver to stop processing kernel requests and events, > > something like SET_USER_MODE. After that i can use it in user > > space. Perhaps it is better to lock out kernel activity (and further opens) while userland has the device open. In any case, a close should probably release the device (possibly after some sort of cleanup), so that a crash of the userland program does not necessitate a reboot before the device can be used again. > Have you read sema(9)? sema(9) is best avoided in new code. It is not used much in existing code, and it would be useful to be able to remove some day in order to reduce redundancy in the provided synchronization primitives. Instead, see mutex(9) and condvar(9). The implementation of sema(9) is not very optimized, using a mutex and a condition variable. (This is unlike the userland sem_post(3) and friends which only require a single atomic op in the uncontested case, except for named semaphores in 8.x and earlier.) > Or if returning EBUSY is acceptable when the resource is in use by > $whatever, maybe you just need a boolean variable. -- Jilles Tjoelker From owner-freebsd-hackers@FreeBSD.ORG Fri Sep 23 19:14:31 2011 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 2D257106564A; Fri, 23 Sep 2011 19:14:31 +0000 (UTC) (envelope-from geoffrey.levand@mail.ru) Received: from f186.mail.ru (f186.mail.ru [217.69.129.199]) by mx1.freebsd.org (Postfix) with ESMTP id A3AA78FC13; Fri, 23 Sep 2011 19:14:30 +0000 (UTC) Received: from mail by f186.mail.ru with local id 1R7BCc-0003L9-00; Fri, 23 Sep 2011 23:14:26 +0400 Received: from [109.193.222.154] by e.mail.ru with HTTP; Fri, 23 Sep 2011 23:14:26 +0400 From: =?UTF-8?B?Z2VvZmZyZXkgbGV2YW5k?= To: =?UTF-8?B?SmlsbGVzIFRqb2Vsa2Vy?= Mime-Version: 1.0 X-Mailer: mPOP Web-Mail 2.19 X-Originating-IP: [109.193.222.154] Date: Fri, 23 Sep 2011 23:14:26 +0400 References: <20110923190626.GA61562@stack.nl> In-Reply-To: <20110923190626.GA61562@stack.nl> X-Priority: Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: base64 Message-Id: X-Spam: Not detected X-Mras: Ok Cc: freebsd-hackers@freebsd.org, =?UTF-8?B?SXZhbiBWb3Jhcw==?= Subject: Re[4]: Sharing device driver between kernel and user space X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list Reply-To: =?UTF-8?B?Z2VvZmZyZXkgbGV2YW5k?= List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 23 Sep 2011 19:14:31 -0000 VGhhbmtzIGZvciB5b3VyIHJlc3BvbnNlcy4KVGhlIG9uZSB3aXRoIG9wZW4vY2xvc2Ugc2VlbXMg dG8gYmUgdGhlIG1vc3QgcmVhc29uYWJsZS4KCgoyMyDRgdC10L3RgtGP0LHRgNGPIDIwMTEsIDIz OjA2INC+0YIgSmlsbGVzIFRqb2Vsa2VyIDxqaWxsZXNAc3RhY2submw+Ogo+IE9uIFdlZCwgU2Vw IDIxLCAyMDExIGF0IDA0OjIzOjI4UE0gKzAyMDAsIEl2YW4gVm9yYXMgd3JvdGU6Cj4gPiBPbiAy MSBTZXB0ZW1iZXIgMjAxMSAxNjowOSwgZ2VvZmZyZXkgbGV2YW5kIDxnZW9mZnJleS5sZXZhbmRA bWFpbC5ydT4gd3JvdGU6Cj4gPiA+IFN1cmUgaSBjYW4gdXNlIHRoZSBzeW5jaHJvbml6YXRpb24g cHJpbWl0aXZlcywgdGhlIHByb2JsZW0gaXMgdGhhdAo+ID4gPiB0aGUgcmVzcG9uc2UgdG8gYSBy ZXF1ZXN0IHNlbnQgdG8gUFMzIFZVQVJUIHBvcnQgaXMgbm90IGF2YWlsYWJsZQo+ID4gPiBpbW1l ZGlhdGVseSwgYW5kIGkgaGF2ZSB0byBkaXNhbGxvdyBrZXJuZWwgYWNjZXNzIHRvIHRoZSBQUzMg VlVBUlQKPiA+ID4gd2hpbGUgaSdtIHdhaXRpbmcgZm9yIHRoZSByZXNwb25zZSBpbiB1c2VyIHNw YWNlLiBJIHNlbmQgcmVxdWVzdAo+ID4gPiB3aXRoIHdyaXRlIHN5c2NhbGwgZnJvbSB1c2VyIHNw YWNlIGFuZCB3YWl0IGZvciByZXNwb25zZSB3aXRoIHJlYWQKPiA+ID4gc3lzY2FsbC4gSW4gdGhl IHBlcmlvZCBvZiB0aW1lIGJldHdlZW4gc2VuZGluZyByZXF1ZXN0IGFuZCByZWNlaXZpbmcKPiA+ ID4gcmVzcG9uc2UgaSBjb3VsZCByZWNlaXZlIHNvbWUgb3RoZXIgcGFja2V0cyBmcm9tIFZVQVJU IHBvcnQsIGUuZy4KPiA+ID4gc29tZSBraW5kIG9mIGV2ZW50IG5vdGlmaWNhdGlvbiwgwqBpIGhh dmUgdG8gc2tpcCB0aGVtLiBCdXQga2VybmVsCj4gPiA+IHNob3VsZCBub3QgaW50ZXJmZXIgdW50 aWwgaSBnZXQgbXkgcmVzcG9uc2UuICBTbyBpIHdvdWxkIG5lZWQgdG8KPiA+ID4gbG9jayBvdXQg dGhlIGtlcm5lbCBkdXJpbmcgdGhpcyB0aW1lLiBJIHRoaW5rIGkgZm91bmQgYSBnb29kCj4gPiA+ IHNvbHV0aW9uIGZvciB0aGlzIHByb2JsZW0sIGp1c3QgdXNlIGEgSU9DVEwgd2hpY2ggdGVsbHMg a2VybmVsCj4gPiA+IGRldmljZSBkcml2ZXIgdG8gc3RvcCBwcm9jZXNzaW5nIGtlcm5lbCByZXF1 ZXN0cyBhbmQgZXZlbnRzLAo+ID4gPiBzb21ldGhpbmcgbGlrZSBTRVRfVVNFUl9NT0RFLiAgQWZ0 ZXIgdGhhdCBpIGNhbiB1c2UgaXQgaW4gdXNlcgo+ID4gPiBzcGFjZS4KPiAKPiBQZXJoYXBzIGl0 IGlzIGJldHRlciB0byBsb2NrIG91dCBrZXJuZWwgYWN0aXZpdHkgKGFuZCBmdXJ0aGVyIG9wZW5z KQo+IHdoaWxlIHVzZXJsYW5kIGhhcyB0aGUgZGV2aWNlIG9wZW4uCj4gCj4gSW4gYW55IGNhc2Us IGEgY2xvc2Ugc2hvdWxkIHByb2JhYmx5IHJlbGVhc2UgdGhlIGRldmljZSAocG9zc2libHkgYWZ0 ZXIKPiBzb21lIHNvcnQgb2YgY2xlYW51cCksIHNvIHRoYXQgYSBjcmFzaCBvZiB0aGUgdXNlcmxh bmQgcHJvZ3JhbSBkb2VzIG5vdAo+IG5lY2Vzc2l0YXRlIGEgcmVib290IGJlZm9yZSB0aGUgZGV2 aWNlIGNhbiBiZSB1c2VkIGFnYWluLgo+IAo+ID4gSGF2ZSB5b3UgcmVhZCBzZW1hKDkpPwo+IAo+ IHNlbWEoOSkgaXMgYmVzdCBhdm9pZGVkIGluIG5ldyBjb2RlLiBJdCBpcyBub3QgdXNlZCBtdWNo IGluIGV4aXN0aW5nCj4gY29kZSwgYW5kIGl0IHdvdWxkIGJlIHVzZWZ1bCB0byBiZSBhYmxlIHRv IHJlbW92ZSBzb21lIGRheSBpbiBvcmRlciB0bwo+IHJlZHVjZSByZWR1bmRhbmN5IGluIHRoZSBw cm92aWRlZCBzeW5jaHJvbml6YXRpb24gcHJpbWl0aXZlcy4KPiAKPiBJbnN0ZWFkLCBzZWUgbXV0 ZXgoOSkgYW5kIGNvbmR2YXIoOSkuCj4gCj4gVGhlIGltcGxlbWVudGF0aW9uIG9mIHNlbWEoOSkg aXMgbm90IHZlcnkgb3B0aW1pemVkLCB1c2luZyBhIG11dGV4IGFuZCBhCj4gY29uZGl0aW9uIHZh cmlhYmxlLiAoVGhpcyBpcyB1bmxpa2UgdGhlIHVzZXJsYW5kIHNlbV9wb3N0KDMpIGFuZCBmcmll bmRzCj4gd2hpY2ggb25seSByZXF1aXJlIGEgc2luZ2xlIGF0b21pYyBvcCBpbiB0aGUgdW5jb250 ZXN0ZWQgY2FzZSwgZXhjZXB0Cj4gZm9yIG5hbWVkIHNlbWFwaG9yZXMgaW4gOC54IGFuZCBlYXJs aWVyLikKPiAKPiA+IE9yIGlmIHJldHVybmluZyBFQlVTWSBpcyBhY2NlcHRhYmxlIHdoZW4gdGhl IHJlc291cmNlIGlzIGluIHVzZSBieQo+ID4gJHdoYXRldmVyLCBtYXliZSB5b3UganVzdCBuZWVk IGEgYm9vbGVhbiB2YXJpYWJsZS4KPiAKPiAtLQo+IEppbGxlcyBUam9lbGtlcgo+IA== From owner-freebsd-hackers@FreeBSD.ORG Sat Sep 24 02:36:44 2011 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id B023C106566C for ; Sat, 24 Sep 2011 02:36:44 +0000 (UTC) (envelope-from doconnor@gsoft.com.au) Received: from cain.gsoft.com.au (cain.gsoft.com.au [203.31.81.10]) by mx1.freebsd.org (Postfix) with ESMTP id 3492D8FC0A for ; Sat, 24 Sep 2011 02:36:43 +0000 (UTC) Received: from ur.dons.net.au (ppp118-210-8-217.lns20.adl2.internode.on.net [118.210.8.217]) (authenticated bits=0) by cain.gsoft.com.au (8.14.4/8.14.3) with ESMTP id p8O2aX7V029176 (version=TLSv1/SSLv3 cipher=AES128-SHA bits=128 verify=NO); Sat, 24 Sep 2011 12:06:40 +0930 (CST) (envelope-from doconnor@gsoft.com.au) Mime-Version: 1.0 (Apple Message framework v1244.3) Content-Type: text/plain; charset=us-ascii From: "Daniel O'Connor" In-Reply-To: Date: Sat, 24 Sep 2011 12:06:33 +0930 Content-Transfer-Encoding: quoted-printable Message-Id: <584637B2-1335-499D-A26A-E9072AB4EDAC@gsoft.com.au> References: To: geoffrey levand X-Mailer: Apple Mail (2.1244.3) X-Spam-Score: 2.162 (**) BAYES_00,KHOP_DYNAMIC,RDNS_DYNAMIC X-Scanned-By: MIMEDefang 2.67 on 203.31.81.10 Cc: FreeBSD Mailing List Subject: Re: CAM framework for FLASH devices X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 24 Sep 2011 02:36:44 -0000 On 24/09/2011, at 1:24, geoffrey levand wrote: > The interface to the PS3 flash device is NOT like normal NOR/NAND = flash interfaces. > The interface to the PS3 FLASH is abstracted by the hypervisor and it = looks like HDD to FreeBSD but has several logical units like SCSI = devices. The flash device supports write, read and flush operation. = Sector size is 512 byte. But it doesn't support any ATA or SCSI commands = except flush. >=20 I think you could use make_dev() etc.. although I haven't used it :) -- Daniel O'Connor software and network engineer for Genesis Software - http://www.gsoft.com.au "The nice thing about standards is that there are so many of them to choose from." -- Andrew Tanenbaum GPG Fingerprint - 5596 B766 97C0 0E94 4347 295E E593 DC20 7B3F CE8C From owner-freebsd-hackers@FreeBSD.ORG Sat Sep 24 08:56:10 2011 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 3AD55106564A for ; Sat, 24 Sep 2011 08:56:10 +0000 (UTC) (envelope-from kmacybsd@gmail.com) Received: from mail-vx0-f182.google.com (mail-vx0-f182.google.com [209.85.220.182]) by mx1.freebsd.org (Postfix) with ESMTP id E6F638FC15 for ; Sat, 24 Sep 2011 08:56:09 +0000 (UTC) Received: by vcbf13 with SMTP id f13so2564709vcb.13 for ; Sat, 24 Sep 2011 01:56:09 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=mime-version:sender:in-reply-to:references:date :x-google-sender-auth:message-id:subject:from:to:cc:content-type :content-transfer-encoding; bh=Py2Q3TEfO47GRqK4hndfnfbdMEiWC+jEVpA4El9Vnks=; b=eT2VyASeH7+dr7To9rWfYh6WqTtqtqMtJ4CCRrwXvp1RpJVC4SBBg80s/xUY3cVxl2 E93DVuavIeTslEYjKAObEhUPGuioXW1fX5vq7T4LF63Wyeemdhp1/VapbouJqqA/TW1c uyHnaDRIQ1zV2qeiOXs7RNE5BuCAn9p8dLqsM= MIME-Version: 1.0 Received: by 10.52.96.166 with SMTP id dt6mr4332317vdb.345.1316854569170; Sat, 24 Sep 2011 01:56:09 -0700 (PDT) Sender: kmacybsd@gmail.com Received: by 10.52.113.202 with HTTP; Sat, 24 Sep 2011 01:56:08 -0700 (PDT) In-Reply-To: References: Date: Sat, 24 Sep 2011 10:56:08 +0200 X-Google-Sender-Auth: PSAKzBNNfWE-y8FmvrXyBB4aTP8 Message-ID: From: "K. Macy" To: Arnaud Lacombe Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable Cc: FreeBSD Hackers Subject: Re: buf_ring(9) API precisions X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 24 Sep 2011 08:56:10 -0000 You're right. A write memory barrier is needed there. Thanks On Thu, Sep 22, 2011 at 12:43 AM, Arnaud Lacombe wrote= : > Hi, > > On Mon, Sep 19, 2011 at 8:46 AM, K. Macy wrote: >> If the value lags next by one then it is ours. This rule applies to >> all callers so the rule holds consistently. >> > I think you do not understand what I mean, which is that the following: > > =A0 =A0 =A0 while (br->br_prod_tail !=3D prod_head) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 cpu_spinwait(); > =A0 =A0 =A0 br->br_prod_bufs++; > =A0 =A0 =A0 br->br_prod_bytes +=3D nbytes; > =A0 =A0 =A0 br->br_prod_tail =3D prod_next; > =A0 =A0 =A0 critical_exit(); > > at runtime, can be seen, memory-wise as: > > =A0 =A0 =A0 while (br->br_prod_tail !=3D prod_head) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 cpu_spinwait(); > =A0 =A0 =A0 br->br_prod_tail =3D prod_next; > =A0 =A0 =A0 br->br_prod_bufs++; > =A0 =A0 =A0 br->br_prod_bytes +=3D nbytes; > =A0 =A0 =A0 critical_exit(); > > That is, there is no memory barrier to enforce completion of the > load/increment/store/load/load/addition/store operations before > updating what other thread spin on. Yes, `br_prod_tail' is marked > `volatile', but there is no guarantee that it will not be re-ordered > wrt. non-volatile write (to `br_prod_bufs' and `br_prod_bytes'). > > =A0- Arnaud > >> On Mon, Sep 19, 2011 at 5:53 AM, Arnaud Lacombe wro= te: >>> Hi, >>> >>> On Fri, Sep 16, 2011 at 10:41 AM, K. Macy wrote: >>>> On Fri, Sep 16, 2011 at 3:02 AM, Arnaud Lacombe w= rote: >>>>> Hi, >>>>> >>>>> On Wed, Sep 14, 2011 at 10:53 PM, Arnaud Lacombe = wrote: >>>>>> Hi Kip, >>>>>> >>>>>> I've got a few question about the buf_ring(9) API. >>>>>> >>>>>> 1) what means the 'drbr_' prefix. I can guess the two last letter, '= b' >>>>>> and 'r', for Buffer Ring, but what about 'd' and 'r' ? >>>>>> >>>>>> 2) in `sys/sys/buf_ring.h', you defined 'struct buf_ring' as: >>>>>> >>>>>> struct buf_ring { >>>>>> =A0 =A0 =A0 =A0volatile uint32_t =A0 =A0 =A0 br_prod_head; >>>>>> =A0 =A0 =A0 =A0volatile uint32_t =A0 =A0 =A0 br_prod_tail; >>>>>> =A0 =A0 =A0 =A0int =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 br_prod_s= ize; >>>>>> =A0 =A0 =A0 =A0int =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 br_prod_m= ask; >>>>>> =A0 =A0 =A0 =A0uint64_t =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0br_drops; >>>>>> =A0 =A0 =A0 =A0uint64_t =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0br_prod_bufs; >>>>>> =A0 =A0 =A0 =A0uint64_t =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0br_prod_bytes= ; >>>>> shouldn't those 3 fields be updated atomically, especially on 32bits >>>>> platforms ? That might pose a problem as, AFAIK, FreeBSD do not have >>>>> MI 64bits atomics operations... >>>> >>>> Between the point at which br_prod_tail =3D=3D prod_head and when we >>>> update br_prod_tail to point to prod_next we are the exclusive owners >>>> of the fields in buf_ring. That is why we wait for any other >>>> enqueueing threads to update br_prod_tail to point to prod_head before >>>> continuing. >>>> >>> How do you enforce ordering ? I do not see anything particular >>> forbidding the `br->br_prod_tail' to be committed first, leading other >>> thread to believe they have access to the statistics, while the other >>> thread has not yet committed its change. >>> >>> Thanks, >>> =A0- Arnaud >>> >>>> Cheers >>>> >>>> =A0 =A0 =A0 =A0/* >>>> =A0 =A0 =A0 =A0 * If there are other enqueues in progress >>>> =A0 =A0 =A0 =A0 * that preceeded us, we need to wait for them >>>> =A0 =A0 =A0 =A0 * to complete >>>> =A0 =A0 =A0 =A0 */ >>>> =A0 =A0 =A0 =A0while (br->br_prod_tail !=3D prod_head) >>>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0cpu_spinwait(); >>>> =A0 =A0 =A0 =A0br->br_prod_bufs++; >>>> =A0 =A0 =A0 =A0br->br_prod_bytes +=3D nbytes; >>>> =A0 =A0 =A0 =A0br->br_prod_tail =3D prod_next; >>>> =A0 =A0 =A0 =A0critical_exit(); >>>> >>> >> >