Initial revision
This commit is contained in:
258
src/lib9/LICENSE
Normal file
258
src/lib9/LICENSE
Normal file
@@ -0,0 +1,258 @@
|
||||
The Plan 9 software is provided under the terms of the
|
||||
Lucent Public License, Version 1.02, reproduced below,
|
||||
with the following exceptions:
|
||||
|
||||
1. No right is granted to create derivative works of or
|
||||
to redistribute (other than with the Plan 9 Operating System)
|
||||
the screen imprinter fonts identified in subdirectory
|
||||
/lib/font/bit/lucida and printer fonts (Lucida Sans Unicode, Lucida
|
||||
Sans Italic, Lucida Sans Demibold, Lucida Typewriter, Lucida Sans
|
||||
Typewriter83), identified in subdirectory /sys/lib/postscript/font.
|
||||
These directories contain material copyrights by B&H Inc. and Y&Y Inc.
|
||||
|
||||
2. The printer fonts identified in subdirectory /sys/lib/ghostscript/font
|
||||
are subject to the GNU GPL, reproduced in the file /LICENSE.gpl.
|
||||
|
||||
3. The ghostscript program in the subdirectory /sys/src/cmd/gs is
|
||||
covered by the Aladdin Free Public License, reproduced in the file
|
||||
/LICENSE.afpl.
|
||||
|
||||
===================================================================
|
||||
|
||||
Lucent Public License Version 1.02
|
||||
|
||||
THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS PUBLIC
|
||||
LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE
|
||||
PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
|
||||
|
||||
1. DEFINITIONS
|
||||
|
||||
"Contribution" means:
|
||||
|
||||
a. in the case of Lucent Technologies Inc. ("LUCENT"), the Original
|
||||
Program, and
|
||||
b. in the case of each Contributor,
|
||||
|
||||
i. changes to the Program, and
|
||||
ii. additions to the Program;
|
||||
|
||||
where such changes and/or additions to the Program were added to the
|
||||
Program by such Contributor itself or anyone acting on such
|
||||
Contributor's behalf, and the Contributor explicitly consents, in
|
||||
accordance with Section 3C, to characterization of the changes and/or
|
||||
additions as Contributions.
|
||||
|
||||
"Contributor" means LUCENT and any other entity that has Contributed a
|
||||
Contribution to the Program.
|
||||
|
||||
"Distributor" means a Recipient that distributes the Program,
|
||||
modifications to the Program, or any part thereof.
|
||||
|
||||
"Licensed Patents" mean patent claims licensable by a Contributor
|
||||
which are necessarily infringed by the use or sale of its Contribution
|
||||
alone or when combined with the Program.
|
||||
|
||||
"Original Program" means the original version of the software
|
||||
accompanying this Agreement as released by LUCENT, including source
|
||||
code, object code and documentation, if any.
|
||||
|
||||
"Program" means the Original Program and Contributions or any part
|
||||
thereof
|
||||
|
||||
"Recipient" means anyone who receives the Program under this
|
||||
Agreement, including all Contributors.
|
||||
|
||||
2. GRANT OF RIGHTS
|
||||
|
||||
a. Subject to the terms of this Agreement, each Contributor hereby
|
||||
grants Recipient a non-exclusive, worldwide, royalty-free copyright
|
||||
license to reproduce, prepare derivative works of, publicly display,
|
||||
publicly perform, distribute and sublicense the Contribution of such
|
||||
Contributor, if any, and such derivative works, in source code and
|
||||
object code form.
|
||||
|
||||
b. Subject to the terms of this Agreement, each Contributor hereby
|
||||
grants Recipient a non-exclusive, worldwide, royalty-free patent
|
||||
license under Licensed Patents to make, use, sell, offer to sell,
|
||||
import and otherwise transfer the Contribution of such Contributor, if
|
||||
any, in source code and object code form. The patent license granted
|
||||
by a Contributor shall also apply to the combination of the
|
||||
Contribution of that Contributor and the Program if, at the time the
|
||||
Contribution is added by the Contributor, such addition of the
|
||||
Contribution causes such combination to be covered by the Licensed
|
||||
Patents. The patent license granted by a Contributor shall not apply
|
||||
to (i) any other combinations which include the Contribution, nor to
|
||||
(ii) Contributions of other Contributors. No hardware per se is
|
||||
licensed hereunder.
|
||||
|
||||
c. Recipient understands that although each Contributor grants the
|
||||
licenses to its Contributions set forth herein, no assurances are
|
||||
provided by any Contributor that the Program does not infringe the
|
||||
patent or other intellectual property rights of any other entity. Each
|
||||
Contributor disclaims any liability to Recipient for claims brought by
|
||||
any other entity based on infringement of intellectual property rights
|
||||
or otherwise. As a condition to exercising the rights and licenses
|
||||
granted hereunder, each Recipient hereby assumes sole responsibility
|
||||
to secure any other intellectual property rights needed, if any. For
|
||||
example, if a third party patent license is required to allow
|
||||
Recipient to distribute the Program, it is Recipient's responsibility
|
||||
to acquire that license before distributing the Program.
|
||||
|
||||
d. Each Contributor represents that to its knowledge it has sufficient
|
||||
copyright rights in its Contribution, if any, to grant the copyright
|
||||
license set forth in this Agreement.
|
||||
|
||||
3. REQUIREMENTS
|
||||
|
||||
A. Distributor may choose to distribute the Program in any form under
|
||||
this Agreement or under its own license agreement, provided that:
|
||||
|
||||
a. it complies with the terms and conditions of this Agreement;
|
||||
|
||||
b. if the Program is distributed in source code or other tangible
|
||||
form, a copy of this Agreement or Distributor's own license agreement
|
||||
is included with each copy of the Program; and
|
||||
|
||||
c. if distributed under Distributor's own license agreement, such
|
||||
license agreement:
|
||||
|
||||
i. effectively disclaims on behalf of all Contributors all warranties
|
||||
and conditions, express and implied, including warranties or
|
||||
conditions of title and non-infringement, and implied warranties or
|
||||
conditions of merchantability and fitness for a particular purpose;
|
||||
ii. effectively excludes on behalf of all Contributors all liability
|
||||
for damages, including direct, indirect, special, incidental and
|
||||
consequential damages, such as lost profits; and
|
||||
iii. states that any provisions which differ from this Agreement are
|
||||
offered by that Contributor alone and not by any other party.
|
||||
|
||||
B. Each Distributor must include the following in a conspicuous
|
||||
location in the Program:
|
||||
|
||||
Copyright (C) 2003, Lucent Technologies Inc. and others. All Rights
|
||||
Reserved.
|
||||
|
||||
C. In addition, each Contributor must identify itself as the
|
||||
originator of its Contribution in a manner that reasonably allows
|
||||
subsequent Recipients to identify the originator of the Contribution.
|
||||
Also, each Contributor must agree that the additions and/or changes
|
||||
are intended to be a Contribution. Once a Contribution is contributed,
|
||||
it may not thereafter be revoked.
|
||||
|
||||
4. COMMERCIAL DISTRIBUTION
|
||||
|
||||
Commercial distributors of software may accept certain
|
||||
responsibilities with respect to end users, business partners and the
|
||||
like. While this license is intended to facilitate the commercial use
|
||||
of the Program, the Distributor who includes the Program in a
|
||||
commercial product offering should do so in a manner which does not
|
||||
create potential liability for Contributors. Therefore, if a
|
||||
Distributor includes the Program in a commercial product offering,
|
||||
such Distributor ("Commercial Distributor") hereby agrees to defend
|
||||
and indemnify every Contributor ("Indemnified Contributor") against
|
||||
any losses, damages and costs (collectively"Losses") arising from
|
||||
claims, lawsuits and other legal actions brought by a third party
|
||||
against the Indemnified Contributor to the extent caused by the acts
|
||||
or omissions of such Commercial Distributor in connection with its
|
||||
distribution of the Program in a commercial product offering. The
|
||||
obligations in this section do not apply to any claims or Losses
|
||||
relating to any actual or alleged intellectual property infringement.
|
||||
In order to qualify, an Indemnified Contributor must: a) promptly
|
||||
notify the Commercial Distributor in writing of such claim, and b)
|
||||
allow the Commercial Distributor to control, and cooperate with the
|
||||
Commercial Distributor in, the defense and any related settlement
|
||||
negotiations. The Indemnified Contributor may participate in any such
|
||||
claim at its own expense.
|
||||
|
||||
For example, a Distributor might include the Program in a commercial
|
||||
product offering, Product X. That Distributor is then a Commercial
|
||||
Distributor. If that Commercial Distributor then makes performance
|
||||
claims, or offers warranties related to Product X, those performance
|
||||
claims and warranties are such Commercial Distributor's responsibility
|
||||
alone. Under this section, the Commercial Distributor would have to
|
||||
defend claims against the Contributors related to those performance
|
||||
claims and warranties, and if a court requires any Contributor to pay
|
||||
any damages as a result, the Commercial Distributor must pay those
|
||||
damages.
|
||||
|
||||
5. NO WARRANTY
|
||||
|
||||
EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS
|
||||
PROVIDED ON AN"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
|
||||
WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY
|
||||
OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely
|
||||
responsible for determining the appropriateness of using and
|
||||
distributing the Program and assumes all risks associated with its
|
||||
exercise of rights under this Agreement, including but not limited to
|
||||
the risks and costs of program errors, compliance with applicable
|
||||
laws, damage to or loss of data, programs or equipment, and
|
||||
unavailability or interruption of operations.
|
||||
|
||||
6. DISCLAIMER OF LIABILITY
|
||||
|
||||
EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR
|
||||
ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING
|
||||
WITHOUT LIMITATION LOST PROFITS), 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 OR
|
||||
DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
|
||||
HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
7. EXPORT CONTROL
|
||||
|
||||
Recipient agrees that Recipient alone is responsible for compliance
|
||||
with the United States export administration regulations (and the
|
||||
export control laws and regulation of any other countries).
|
||||
|
||||
8. GENERAL
|
||||
|
||||
If any provision of this Agreement is invalid or unenforceable under
|
||||
applicable law, it shall not affect the validity or enforceability of
|
||||
the remainder of the terms of this Agreement, and without further
|
||||
action by the parties hereto, such provision shall be reformed to the
|
||||
minimum extent necessary to make such provision valid and enforceable.
|
||||
|
||||
If Recipient institutes patent litigation against a Contributor with
|
||||
respect to a patent applicable to software (including a cross-claim or
|
||||
counterclaim in a lawsuit), then any patent licenses granted by that
|
||||
Contributor to such Recipient under this Agreement shall terminate as
|
||||
of the date such litigation is filed. In addition, if Recipient
|
||||
institutes patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Program
|
||||
itself (excluding combinations of the Program with other software or
|
||||
hardware) infringes such Recipient's patent(s), then such Recipient's
|
||||
rights granted under Section 2(b) shall terminate as of the date such
|
||||
litigation is filed.
|
||||
|
||||
All Recipient's rights under this Agreement shall terminate if it
|
||||
fails to comply with any of the material terms or conditions of this
|
||||
Agreement and does not cure such failure in a reasonable period of
|
||||
time after becoming aware of such noncompliance. If all Recipient's
|
||||
rights under this Agreement terminate, Recipient agrees to cease use
|
||||
and distribution of the Program as soon as reasonably practicable.
|
||||
However, Recipient's obligations under this Agreement and any licenses
|
||||
granted by Recipient relating to the Program shall continue and
|
||||
survive.
|
||||
|
||||
LUCENT may publish new versions (including revisions) of this
|
||||
Agreement from time to time. Each new version of the Agreement will be
|
||||
given a distinguishing version number. The Program (including
|
||||
Contributions) may always be distributed subject to the version of the
|
||||
Agreement under which it was received. In addition, after a new
|
||||
version of the Agreement is published, Contributor may elect to
|
||||
distribute the Program (including its Contributions) under the new
|
||||
version. No one other than LUCENT has the right to modify this
|
||||
Agreement. Except as expressly stated in Sections 2(a) and 2(b) above,
|
||||
Recipient receives no rights or licenses to the intellectual property
|
||||
of any Contributor under this Agreement, whether expressly, by
|
||||
implication, estoppel or otherwise. All rights in the Program not
|
||||
expressly granted under this Agreement are reserved.
|
||||
|
||||
This Agreement is governed by the laws of the State of New York and
|
||||
the intellectual property laws of the United States of America. No
|
||||
party to this Agreement will bring a legal action under this Agreement
|
||||
more than one year after the cause of action arose. Each party waives
|
||||
its rights to a jury trial in any resulting litigation.
|
||||
|
||||
6
src/lib9/Make.Darwin-PowerMacintosh
Normal file
6
src/lib9/Make.Darwin-PowerMacintosh
Normal file
@@ -0,0 +1,6 @@
|
||||
CC=gcc
|
||||
CFLAGS+=-Wall -Wno-missing-braces -Wno-parentheses -Wno-switch -O2 -g -c -I. -I${PREFIX}/include
|
||||
O=o
|
||||
AR=ar
|
||||
ARFLAGS=rvc
|
||||
NAN=nan64.$O
|
||||
7
src/lib9/Make.FreeBSD-386
Normal file
7
src/lib9/Make.FreeBSD-386
Normal file
@@ -0,0 +1,7 @@
|
||||
CC=gcc
|
||||
CFLAGS+=-Wall -Wno-missing-braces -Wno-parentheses -Wno-switch -O2 -g -c -I. -I$(PREFIX)/include
|
||||
O=o
|
||||
AR=ar
|
||||
ARFLAGS=rvc
|
||||
NAN=nan64.$O # default, can be overriden by Make.$(SYSNAME)
|
||||
NAN=nan64.$O
|
||||
6
src/lib9/Make.HP-UX-9000
Normal file
6
src/lib9/Make.HP-UX-9000
Normal file
@@ -0,0 +1,6 @@
|
||||
CC=cc
|
||||
CFLAGS=-O -c -Ae -I.
|
||||
O=o
|
||||
AR=ar
|
||||
ARFLAGS=rvc
|
||||
NAN=nan64.$O
|
||||
7
src/lib9/Make.Linux-386
Normal file
7
src/lib9/Make.Linux-386
Normal file
@@ -0,0 +1,7 @@
|
||||
CC=gcc
|
||||
CFLAGS+=-Wall -Wno-missing-braces -Wno-parentheses -Wno-switch -O2 -g -c -I.
|
||||
O=o
|
||||
AR=ar
|
||||
ARFLAGS=rvc
|
||||
NAN=nan64.$O # default, can be overriden by Make.$(SYSNAME)
|
||||
NAN=nan64.$O
|
||||
7
src/lib9/Make.NetBSD-386
Normal file
7
src/lib9/Make.NetBSD-386
Normal file
@@ -0,0 +1,7 @@
|
||||
CC=gcc
|
||||
CFLAGS+=-Wall -Wno-missing-braces -Wno-parentheses -Wno-switch -O2 -g -c -I. -I$(PREFIX)/include
|
||||
O=o
|
||||
AR=ar
|
||||
ARFLAGS=rvc
|
||||
NAN=nan64.$O # default, can be overriden by Make.$(SYSNAME)
|
||||
NAN=nan64.$O
|
||||
6
src/lib9/Make.OSF1-alpha
Normal file
6
src/lib9/Make.OSF1-alpha
Normal file
@@ -0,0 +1,6 @@
|
||||
CC=cc
|
||||
CFLAGS+=-g -c -I.
|
||||
O=o
|
||||
AR=ar
|
||||
ARFLAGS=rvc
|
||||
NAN=nan64.$O
|
||||
2
src/lib9/Make.SunOS-sun4u
Normal file
2
src/lib9/Make.SunOS-sun4u
Normal file
@@ -0,0 +1,2 @@
|
||||
include Make.SunOS-sun4u-$(CC)
|
||||
NAN=nan64.$O
|
||||
6
src/lib9/Make.SunOS-sun4u-cc
Normal file
6
src/lib9/Make.SunOS-sun4u-cc
Normal file
@@ -0,0 +1,6 @@
|
||||
CC=cc
|
||||
CFLAGS+=-g -c -I. -O
|
||||
O=o
|
||||
AR=ar
|
||||
ARFLAGS=rvc
|
||||
NAN=nan64.$O
|
||||
6
src/lib9/Make.SunOS-sun4u-gcc
Normal file
6
src/lib9/Make.SunOS-sun4u-gcc
Normal file
@@ -0,0 +1,6 @@
|
||||
CC=gcc
|
||||
CFLAGS+=-Wall -Wno-missing-braces -Wno-parentheses -Wno-switch -O2 -g -c
|
||||
O=o
|
||||
AR=ar
|
||||
ARFLAGS=rvc
|
||||
NAN=nan64.$O
|
||||
120
src/lib9/Makefile
Normal file
120
src/lib9/Makefile
Normal file
@@ -0,0 +1,120 @@
|
||||
|
||||
# this works in gnu make
|
||||
SYSNAME:=${shell uname}
|
||||
OBJTYPE:=${shell uname -m | sed 's;i.86;386;; s;/.*;;; s; ;;g'}
|
||||
|
||||
# this works in bsd make
|
||||
SYSNAME!=uname
|
||||
OBJTYPE!=uname -m | sed 's;i.86;386;; s;/.*;;; s; ;;g'
|
||||
|
||||
# the gnu rules will mess up bsd but not vice versa,
|
||||
# hence the gnu rules come first.
|
||||
|
||||
include Make.$(SYSNAME)-$(OBJTYPE)
|
||||
|
||||
PREFIX=/usr/local
|
||||
|
||||
NUKEFILES=
|
||||
|
||||
TGZFILES=
|
||||
|
||||
LIB=lib9.a
|
||||
VERSION=2.0
|
||||
PORTPLACE=devel/lib9
|
||||
NAME=lib9
|
||||
|
||||
OFILES=\
|
||||
_exits.$O\
|
||||
argv0.$O\
|
||||
await.$O\
|
||||
encodefmt.$O\
|
||||
errstr.$O\
|
||||
exits.$O\
|
||||
ffork-$(SYSNAME).$O\
|
||||
getcallerpc-$(OBJTYPE).$O\
|
||||
getfields.$O\
|
||||
lock.$O\
|
||||
malloctag.$O\
|
||||
mallocz.$O\
|
||||
nrand.$O\
|
||||
qlock.$O\
|
||||
readn.$O\
|
||||
rendez.$O\
|
||||
strecpy.$O\
|
||||
sysfatal.$O\
|
||||
tas-$(OBJTYPE).$O\
|
||||
tokenize.$O\
|
||||
u16.$O\
|
||||
u32.$O\
|
||||
u64.$O\
|
||||
wait.$O\
|
||||
werrstr.$O\
|
||||
|
||||
HFILES=\
|
||||
lib9.h\
|
||||
|
||||
all: $(LIB)
|
||||
|
||||
install: $(LIB)
|
||||
test -d $(PREFIX)/man/man3 || mkdir $(PREFIX)/man/man3
|
||||
# install -m 0644 lib9.3 $(PREFIX)/man/man3/lib9.3
|
||||
install -m 0644 lib9.h $(PREFIX)/include/lib9.h
|
||||
install -m 0644 $(LIB) $(PREFIX)/lib/$(LIB)
|
||||
|
||||
test: $(LIB) test.$O
|
||||
$(CC) -o test test.$O $(LIB) -L$(PREFIX)/lib -lfmt -lutf
|
||||
|
||||
testfork: $(LIB) testfork.$O
|
||||
$(CC) -o testfork testfork.$O $(LIB) -L$(PREFIX)/lib -lfmt -lutf
|
||||
|
||||
$(LIB): $(OFILES)
|
||||
$(AR) $(ARFLAGS) $(LIB) $(OFILES)
|
||||
|
||||
NUKEFILES+=$(LIB)
|
||||
.c.$O:
|
||||
$(CC) $(CFLAGS) -I$(PREFIX)/include $*.c
|
||||
|
||||
%.$O: %.c
|
||||
$(CC) $(CFLAGS) -I$(PREFIX)/include $*.c
|
||||
|
||||
|
||||
$(OFILES): $(HFILES)
|
||||
|
||||
tgz:
|
||||
rm -rf $(NAME)-$(VERSION)
|
||||
mkdir $(NAME)-$(VERSION)
|
||||
cp Makefile Make.* README LICENSE NOTICE *.[ch137] rpm.spec bundle.ports $(TGZFILES) $(NAME)-$(VERSION)
|
||||
tar cf - $(NAME)-$(VERSION) | gzip >$(NAME)-$(VERSION).tgz
|
||||
rm -rf $(NAME)-$(VERSION)
|
||||
|
||||
clean:
|
||||
rm -f $(OFILES) $(LIB)
|
||||
|
||||
nuke:
|
||||
rm -f $(OFILES) *.tgz *.rpm $(NUKEFILES)
|
||||
|
||||
rpm:
|
||||
make tgz
|
||||
cp $(NAME)-$(VERSION).tgz /usr/src/RPM/SOURCES
|
||||
rpm -ba rpm.spec
|
||||
cp /usr/src/RPM/SRPMS/$(NAME)-$(VERSION)-1.src.rpm .
|
||||
cp /usr/src/RPM/RPMS/i586/$(NAME)-$(VERSION)-1.i586.rpm .
|
||||
scp *.rpm rsc@amsterdam.lcs.mit.edu:public_html/software
|
||||
|
||||
PORTDIR=/usr/ports/$(PORTPLACE)
|
||||
|
||||
ports:
|
||||
make tgz
|
||||
rm -rf $(PORTDIR)
|
||||
mkdir $(PORTDIR)
|
||||
cp $(NAME)-$(VERSION).tgz /usr/ports/distfiles
|
||||
cat bundle.ports | (cd $(PORTDIR) && awk '$$1=="---" && $$3=="---" { ofile=$$2; next} {if(ofile) print >ofile}')
|
||||
(cd $(PORTDIR); make makesum)
|
||||
(cd $(PORTDIR); make)
|
||||
(cd $(PORTDIR); /usr/local/bin/portlint)
|
||||
rm -rf $(PORTDIR)/work
|
||||
shar `find $(PORTDIR)` > ports.shar
|
||||
(cd $(PORTDIR); tar cf - *) | gzip >$(NAME)-$(VERSION)-ports.tgz
|
||||
scp *.tgz rsc@amsterdam.lcs.mit.edu:public_html/software
|
||||
|
||||
.phony: all clean nuke install tgz rpm ports
|
||||
49
src/lib9/Makefile.MID
Normal file
49
src/lib9/Makefile.MID
Normal file
@@ -0,0 +1,49 @@
|
||||
LIB=lib9.a
|
||||
VERSION=2.0
|
||||
PORTPLACE=devel/lib9
|
||||
NAME=lib9
|
||||
|
||||
OFILES=\
|
||||
_exits.$O\
|
||||
argv0.$O\
|
||||
await.$O\
|
||||
encodefmt.$O\
|
||||
errstr.$O\
|
||||
exits.$O\
|
||||
ffork-$(SYSNAME).$O\
|
||||
getcallerpc-$(OBJTYPE).$O\
|
||||
getfields.$O\
|
||||
lock.$O\
|
||||
malloctag.$O\
|
||||
mallocz.$O\
|
||||
nrand.$O\
|
||||
qlock.$O\
|
||||
readn.$O\
|
||||
rendez.$O\
|
||||
strecpy.$O\
|
||||
sysfatal.$O\
|
||||
tas-$(OBJTYPE).$O\
|
||||
tokenize.$O\
|
||||
u16.$O\
|
||||
u32.$O\
|
||||
u64.$O\
|
||||
wait.$O\
|
||||
werrstr.$O\
|
||||
|
||||
HFILES=\
|
||||
lib9.h\
|
||||
|
||||
all: $(LIB)
|
||||
|
||||
install: $(LIB)
|
||||
test -d $(PREFIX)/man/man3 || mkdir $(PREFIX)/man/man3
|
||||
# install -m 0644 lib9.3 $(PREFIX)/man/man3/lib9.3
|
||||
install -m 0644 lib9.h $(PREFIX)/include/lib9.h
|
||||
install -m 0644 $(LIB) $(PREFIX)/lib/$(LIB)
|
||||
|
||||
test: $(LIB) test.$O
|
||||
$(CC) -o test test.$O $(LIB) -L$(PREFIX)/lib -lfmt -lutf
|
||||
|
||||
testfork: $(LIB) testfork.$O
|
||||
$(CC) -o testfork testfork.$O $(LIB) -L$(PREFIX)/lib -lfmt -lutf
|
||||
|
||||
9
src/lib9/_exits.c
Normal file
9
src/lib9/_exits.c
Normal file
@@ -0,0 +1,9 @@
|
||||
#include <lib9.h>
|
||||
|
||||
void
|
||||
_exits(char *s)
|
||||
{
|
||||
if(s && *s)
|
||||
_exit(1);
|
||||
_exit(0);
|
||||
}
|
||||
4
src/lib9/argv0.c
Normal file
4
src/lib9/argv0.c
Normal file
@@ -0,0 +1,4 @@
|
||||
#include <lib9.h>
|
||||
|
||||
char *argv0;
|
||||
|
||||
105
src/lib9/await.c
Normal file
105
src/lib9/await.c
Normal file
@@ -0,0 +1,105 @@
|
||||
#include <signal.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/time.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <lib9.h>
|
||||
|
||||
static struct {
|
||||
int sig;
|
||||
char *str;
|
||||
} tab[] = {
|
||||
SIGHUP, "hangup",
|
||||
SIGINT, "interrupt",
|
||||
SIGQUIT, "quit",
|
||||
SIGILL, "sys: trap: illegal instruction",
|
||||
SIGTRAP, "sys: trace trap",
|
||||
SIGABRT, "sys: abort",
|
||||
#ifdef SIGEMT
|
||||
SIGEMT, "sys: emulate instruction executed",
|
||||
#endif
|
||||
SIGFPE, "sys: fp: trap",
|
||||
SIGKILL, "sys: kill",
|
||||
SIGBUS, "sys: bus error",
|
||||
SIGSEGV, "sys: segmentation violation",
|
||||
SIGALRM, "alarm",
|
||||
SIGTERM, "kill",
|
||||
SIGURG, "sys: urgent condition on socket",
|
||||
SIGSTOP, "sys: stop",
|
||||
SIGTSTP, "sys: tstp",
|
||||
SIGCONT, "sys: cont",
|
||||
SIGCHLD, "sys: child",
|
||||
SIGTTIN, "sys: ttin",
|
||||
SIGTTOU, "sys: ttou",
|
||||
SIGIO, "sys: i/o possible on fd",
|
||||
SIGXCPU, "sys: cpu time limit exceeded",
|
||||
SIGXFSZ, "sys: file size limit exceeded",
|
||||
SIGVTALRM, "sys: virtual time alarm",
|
||||
SIGPROF, "sys: profiling timer alarm",
|
||||
SIGWINCH, "sys: window size change",
|
||||
#ifdef SIGINFO
|
||||
SIGINFO, "sys: status request",
|
||||
#endif
|
||||
SIGUSR1, "sys: usr1",
|
||||
SIGUSR2, "sys: usr2",
|
||||
};
|
||||
|
||||
static char*
|
||||
_p9sigstr(int sig, char *tmp)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i=0; i<nelem(tab); i++)
|
||||
if(tab[i].sig == sig)
|
||||
return tab[i].str;
|
||||
sprint(tmp, "sys: signal %d", sig);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/*
|
||||
static int
|
||||
_p9strsig(char *s)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i=0; i<nelem(tab); i++)
|
||||
if(strcmp(s, tab[i].str) == 0)
|
||||
return tab[i].sig;
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
|
||||
int
|
||||
await(char *str, int n)
|
||||
{
|
||||
int pid, status, cd;
|
||||
struct rusage ru;
|
||||
char buf[128], tmp[64];
|
||||
ulong u, s;
|
||||
|
||||
for(;;){
|
||||
pid = wait3(&status, 0, &ru);
|
||||
if(pid < 0)
|
||||
return -1;
|
||||
u = ru.ru_utime.tv_sec*1000+((ru.ru_utime.tv_usec+500)/1000);
|
||||
s = ru.ru_stime.tv_sec*1000+((ru.ru_stime.tv_usec+500)/1000);
|
||||
if(WIFEXITED(status)){
|
||||
status = WEXITSTATUS(status);
|
||||
if(status)
|
||||
snprint(buf, sizeof buf, "%d %lu %lu %lu %d", pid, u, s, u+s, status);
|
||||
else
|
||||
snprint(buf, sizeof buf, "%d %lu %lu %lu ''", pid, u, s, u+s);
|
||||
strecpy(str, str+n, buf);
|
||||
return strlen(str);
|
||||
}
|
||||
if(WIFSIGNALED(status)){
|
||||
cd = WCOREDUMP(status);
|
||||
USED(cd);
|
||||
snprint(buf, sizeof buf, "%d %lu %lu %lu '%s'", pid, u, s, u+s, _p9sigstr(WTERMSIG(status), tmp));
|
||||
strecpy(str, str+n, buf);
|
||||
return strlen(str);
|
||||
}
|
||||
}
|
||||
}
|
||||
69
src/lib9/encodefmt.c
Normal file
69
src/lib9/encodefmt.c
Normal file
@@ -0,0 +1,69 @@
|
||||
#include <lib9.h>
|
||||
|
||||
int
|
||||
encodefmt(Fmt *f)
|
||||
{
|
||||
char *out;
|
||||
char *buf;
|
||||
int len;
|
||||
int ilen;
|
||||
int rv;
|
||||
uchar *b;
|
||||
char obuf[64]; // rsc optimization
|
||||
|
||||
if(!(f->flags&FmtPrec) || f->prec < 1)
|
||||
goto error;
|
||||
|
||||
b = va_arg(f->args, uchar*);
|
||||
|
||||
ilen = f->prec;
|
||||
f->prec = 0;
|
||||
f->flags &= ~FmtPrec;
|
||||
switch(f->r){
|
||||
case '<':
|
||||
len = (8*ilen+4)/5 + 3;
|
||||
break;
|
||||
case '[':
|
||||
len = (8*ilen+5)/6 + 4;
|
||||
break;
|
||||
case 'H':
|
||||
len = 2*ilen + 1;
|
||||
break;
|
||||
default:
|
||||
goto error;
|
||||
}
|
||||
|
||||
if(len > sizeof(obuf)){
|
||||
buf = malloc(len);
|
||||
if(buf == nil)
|
||||
goto error;
|
||||
} else
|
||||
buf = obuf;
|
||||
|
||||
// convert
|
||||
out = buf;
|
||||
switch(f->r){
|
||||
case '<':
|
||||
rv = enc32(out, len, b, ilen);
|
||||
break;
|
||||
case '[':
|
||||
rv = enc64(out, len, b, ilen);
|
||||
break;
|
||||
case 'H':
|
||||
rv = enc16(out, len, b, ilen);
|
||||
break;
|
||||
default:
|
||||
rv = -1;
|
||||
break;
|
||||
}
|
||||
if(rv < 0)
|
||||
goto error;
|
||||
|
||||
fmtstrcpy(f, buf);
|
||||
if(buf != obuf)
|
||||
free(buf);
|
||||
return 0;
|
||||
|
||||
error:
|
||||
return fmtstrcpy(f, "<encodefmt>");
|
||||
}
|
||||
68
src/lib9/errstr.c
Normal file
68
src/lib9/errstr.c
Normal file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* We assume there's only one error buffer for the whole system.
|
||||
* If you use ffork, you need to provide a _syserrstr. Since most
|
||||
* people will use libthread (which provides a _syserrstr), this is
|
||||
* okay.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <lib9.h>
|
||||
|
||||
enum
|
||||
{
|
||||
EPLAN9 = 0x19283745,
|
||||
};
|
||||
|
||||
char *(*_syserrstr)(void);
|
||||
static char xsyserr[ERRMAX];
|
||||
static char*
|
||||
getsyserr(void)
|
||||
{
|
||||
char *s;
|
||||
|
||||
s = nil;
|
||||
if(_syserrstr)
|
||||
s = (*_syserrstr)();
|
||||
if(s == nil)
|
||||
s = xsyserr;
|
||||
return s;
|
||||
}
|
||||
|
||||
int
|
||||
errstr(char *err, uint n)
|
||||
{
|
||||
char tmp[ERRMAX];
|
||||
char *syserr;
|
||||
|
||||
syserr = getsyserr();
|
||||
if(errno != EPLAN9)
|
||||
strcpy(syserr, strerror(errno));
|
||||
|
||||
strecpy(tmp, tmp+ERRMAX, syserr);
|
||||
strecpy(syserr, syserr+ERRMAX, err);
|
||||
strecpy(err, err+n, tmp);
|
||||
errno = EPLAN9;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
rerrstr(char *err, uint n)
|
||||
{
|
||||
char *syserr;
|
||||
|
||||
syserr = getsyserr();
|
||||
if(errno != EPLAN9)
|
||||
strcpy(syserr, strerror(errno));
|
||||
strecpy(err, err+n, syserr);
|
||||
}
|
||||
|
||||
/* replaces __errfmt in libfmt */
|
||||
|
||||
int
|
||||
__errfmt(Fmt *f)
|
||||
{
|
||||
if(errno == EPLAN9)
|
||||
return fmtstrcpy(f, getsyserr());
|
||||
return fmtstrcpy(f, strerror(errno));
|
||||
}
|
||||
10
src/lib9/exits.c
Normal file
10
src/lib9/exits.c
Normal file
@@ -0,0 +1,10 @@
|
||||
#include <lib9.h>
|
||||
|
||||
void
|
||||
exits(char *s)
|
||||
{
|
||||
if(s && *s)
|
||||
exit(1);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
33
src/lib9/ffork-FreeBSD.c
Normal file
33
src/lib9/ffork-FreeBSD.c
Normal file
@@ -0,0 +1,33 @@
|
||||
#include <lib9.h>
|
||||
|
||||
extern int __isthreaded;
|
||||
int
|
||||
ffork(int flags, void(*fn)(void*), void *arg)
|
||||
{
|
||||
void *p;
|
||||
|
||||
__isthreaded = 1;
|
||||
p = malloc(16384);
|
||||
if(p == nil)
|
||||
return -1;
|
||||
memset(p, 0xFE, 16384);
|
||||
return rfork_thread(RFPROC|flags, (char*)p+16000, (int(*)(void*))fn, arg);
|
||||
}
|
||||
|
||||
/*
|
||||
* For FreeBSD libc.
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
volatile long access_lock;
|
||||
volatile long lock_owner;
|
||||
volatile char *fname;
|
||||
volatile int lineno;
|
||||
} spinlock_t;
|
||||
|
||||
void
|
||||
_spinlock(spinlock_t *lk)
|
||||
{
|
||||
lock((Lock*)&lk->access_lock);
|
||||
}
|
||||
|
||||
39
src/lib9/ffork-Linux.c
Normal file
39
src/lib9/ffork-Linux.c
Normal file
@@ -0,0 +1,39 @@
|
||||
#include <sched.h>
|
||||
#include <signal.h>
|
||||
#include <lib9.h>
|
||||
|
||||
int fforkstacksize = 16384;
|
||||
|
||||
int
|
||||
ffork(int flags, void (*fn)(void*), void *arg)
|
||||
{
|
||||
char *p;
|
||||
int cloneflag, pid;
|
||||
|
||||
p = malloc(fforkstacksize);
|
||||
if(p == nil)
|
||||
return -1;
|
||||
cloneflag = 0;
|
||||
flags &= ~RFPROC;
|
||||
if(flags&RFMEM){
|
||||
cloneflag |= CLONE_VM;
|
||||
flags &= ~RFMEM;
|
||||
}
|
||||
if(!(flags&RFFDG))
|
||||
cloneflag |= CLONE_FILES;
|
||||
else
|
||||
flags &= ~RFFDG;
|
||||
if(!(flags&RFNOWAIT))
|
||||
cloneflag |= SIGCHLD;
|
||||
else
|
||||
flags &= ~RFNOWAIT;
|
||||
if(flags){
|
||||
fprint(2, "unknown rfork flags %x\n", flags);
|
||||
return -1;
|
||||
}
|
||||
pid = clone((int(*)(void*))fn, p+fforkstacksize-16, cloneflag, arg);
|
||||
if(pid < 0)
|
||||
free(p);
|
||||
return pid;
|
||||
}
|
||||
|
||||
7
src/lib9/getcallerpc-386.c
Normal file
7
src/lib9/getcallerpc-386.c
Normal file
@@ -0,0 +1,7 @@
|
||||
#include <lib9.h>
|
||||
|
||||
ulong
|
||||
getcallerpc(void *x)
|
||||
{
|
||||
return (((ulong*)(x))[-1]);
|
||||
}
|
||||
36
src/lib9/getfields.c
Normal file
36
src/lib9/getfields.c
Normal file
@@ -0,0 +1,36 @@
|
||||
#include <lib9.h>
|
||||
|
||||
int
|
||||
getfields(char *str, char **args, int max, int mflag, char *set)
|
||||
{
|
||||
Rune r;
|
||||
int nr, intok, narg;
|
||||
|
||||
if(max <= 0)
|
||||
return 0;
|
||||
|
||||
narg = 0;
|
||||
args[narg] = str;
|
||||
if(!mflag)
|
||||
narg++;
|
||||
intok = 0;
|
||||
for(;; str += nr) {
|
||||
nr = chartorune(&r, str);
|
||||
if(r == 0)
|
||||
break;
|
||||
if(utfrune(set, r)) {
|
||||
if(narg >= max)
|
||||
break;
|
||||
*str = 0;
|
||||
intok = 0;
|
||||
args[narg] = str + nr;
|
||||
if(!mflag)
|
||||
narg++;
|
||||
} else {
|
||||
if(!intok && mflag)
|
||||
narg++;
|
||||
intok = 1;
|
||||
}
|
||||
}
|
||||
return narg;
|
||||
}
|
||||
246
src/lib9/lib9.h
Normal file
246
src/lib9/lib9.h
Normal file
@@ -0,0 +1,246 @@
|
||||
/*
|
||||
* Lib9 is miscellany from the Plan 9 C library that doesn't
|
||||
* fit into libutf or into libfmt, but is still missing from traditional
|
||||
* Unix C libraries.
|
||||
*/
|
||||
#ifndef _LIB9H_
|
||||
#define _LIB9H_ 1
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <fcntl.h>
|
||||
#include <assert.h>
|
||||
|
||||
#ifndef _FMTH_
|
||||
# include <fmt.h>
|
||||
#endif
|
||||
|
||||
#define nil ((void*)0)
|
||||
#define nelem(x) (sizeof(x)/sizeof((x)[0]))
|
||||
|
||||
#define _NEEDUCHAR 1
|
||||
#define _NEEDUSHORT 1
|
||||
#define _NEEDUINT 1
|
||||
#define _NEEDULONG 1
|
||||
|
||||
#if defined(__linux__)
|
||||
# include <sys/types.h>
|
||||
# if defined(__USE_MISC)
|
||||
# undef _NEEDUSHORT
|
||||
# undef _NEEDUINT
|
||||
# undef _NEEDULONG
|
||||
# endif
|
||||
#endif
|
||||
#if defined(__FreeBSD__)
|
||||
# include <sys/types.h>
|
||||
# if !defined(_POSIX_SOURCE)
|
||||
# undef _NEEDUSHORT
|
||||
# undef _NEEDUINT
|
||||
# endif
|
||||
#endif
|
||||
|
||||
typedef signed char schar;
|
||||
typedef unsigned int u32int;
|
||||
#ifdef _NEEDUCHAR
|
||||
typedef unsigned char uchar;
|
||||
#endif
|
||||
#ifdef _NEEDUSHORT
|
||||
typedef unsigned short ushort;
|
||||
#endif
|
||||
#ifdef _NEEDUINT
|
||||
typedef unsigned int uint;
|
||||
#endif
|
||||
#ifdef _NEEDULONG
|
||||
typedef unsigned long ulong;
|
||||
#endif
|
||||
typedef unsigned long long uvlong;
|
||||
typedef long long vlong;
|
||||
|
||||
/* rfork to create new process running fn(arg) */
|
||||
|
||||
#if defined(__FreeBSD__)
|
||||
#undef RFFDG
|
||||
#undef RFNOTEG
|
||||
#undef RFPROC
|
||||
#undef RFMEM
|
||||
#undef RFNOWAIT
|
||||
#undef RFCFDG
|
||||
#endif
|
||||
|
||||
enum
|
||||
{
|
||||
/* RFNAMEG = (1<<0), */
|
||||
/* RFENVG = (1<<1), */
|
||||
RFFDG = (1<<2),
|
||||
RFNOTEG = (1<<3),
|
||||
RFPROC = (1<<4),
|
||||
RFMEM = (1<<5),
|
||||
RFNOWAIT = (1<<6),
|
||||
/* RFCNAMEG = (1<<10), */
|
||||
/* RFCENVG = (1<<11), */
|
||||
RFCFDG = (1<<12),
|
||||
/* RFREND = (1<<13), */
|
||||
/* RFNOMNT = (1<<14) */
|
||||
};
|
||||
extern int ffork(int, void(*)(void*), void*);
|
||||
|
||||
/* wait for processes */
|
||||
#define wait _p9wait
|
||||
typedef struct Waitmsg Waitmsg;
|
||||
struct Waitmsg
|
||||
{
|
||||
int pid; /* of loved one */
|
||||
ulong time[3]; /* of loved one & descendants */
|
||||
char *msg;
|
||||
};
|
||||
extern int await(char*, int);
|
||||
extern Waitmsg* wait(void);
|
||||
|
||||
/* synchronization */
|
||||
typedef struct Lock Lock;
|
||||
struct Lock
|
||||
{
|
||||
int val;
|
||||
};
|
||||
|
||||
extern int _tas(void*);
|
||||
extern void lock(Lock*);
|
||||
extern void unlock(Lock*);
|
||||
extern int canlock(Lock*);
|
||||
|
||||
typedef struct QLp QLp;
|
||||
struct QLp
|
||||
{
|
||||
int inuse;
|
||||
QLp *next;
|
||||
int state;
|
||||
};
|
||||
|
||||
typedef struct QLock QLock;
|
||||
struct QLock
|
||||
{
|
||||
Lock lock;
|
||||
int locked;
|
||||
QLp *head;
|
||||
QLp *tail;
|
||||
};
|
||||
|
||||
extern void qlock(QLock*);
|
||||
extern void qunlock(QLock*);
|
||||
extern int canqlock(QLock*);
|
||||
extern void _qlockinit(ulong (*)(ulong, ulong));
|
||||
|
||||
typedef struct RWLock RWLock;
|
||||
struct RWLock
|
||||
{
|
||||
Lock lock;
|
||||
int readers;
|
||||
int writer;
|
||||
QLp *head;
|
||||
QLp *tail;
|
||||
};
|
||||
|
||||
extern void rlock(RWLock*);
|
||||
extern void runlock(RWLock*);
|
||||
extern int canrlock(RWLock*);
|
||||
extern void wlock(RWLock*);
|
||||
extern void wunlock(RWLock*);
|
||||
extern int canwlock(RWLock*);
|
||||
|
||||
typedef struct Rendez Rendez;
|
||||
struct Rendez
|
||||
{
|
||||
QLock *l;
|
||||
QLp *head;
|
||||
QLp *tail;
|
||||
};
|
||||
|
||||
extern void rsleep(Rendez*);
|
||||
extern int rwakeup(Rendez*);
|
||||
extern int rwakeupall(Rendez*);
|
||||
|
||||
extern ulong rendezvous(ulong, ulong);
|
||||
|
||||
/* one of a kind */
|
||||
extern void sysfatal(char*, ...);
|
||||
extern int nrand(int);
|
||||
extern void setmalloctag(void*, ulong);
|
||||
extern void setrealloctag(void*, ulong);
|
||||
extern void *mallocz(ulong, int);
|
||||
extern long readn(int, void*, long);
|
||||
extern void exits(char*);
|
||||
extern void _exits(char*);
|
||||
extern ulong getcallerpc(void*);
|
||||
|
||||
/* string routines */
|
||||
extern char* strecpy(char*, char*, char*);
|
||||
extern int tokenize(char*, char**, int);
|
||||
extern int cistrncmp(char*, char*, int);
|
||||
extern int cistrcmp(char*, char*);
|
||||
extern char* cistrstr(char*, char*);
|
||||
extern int getfields(char*, char**, int, int, char*);
|
||||
extern int gettokens(char *, char **, int, char *);
|
||||
|
||||
/* formatting helpers */
|
||||
extern int dec64(uchar*, int, char*, int);
|
||||
extern int enc64(char*, int, uchar*, int);
|
||||
extern int dec32(uchar*, int, char*, int);
|
||||
extern int enc32(char*, int, uchar*, int);
|
||||
extern int dec16(uchar*, int, char*, int);
|
||||
extern int enc16(char*, int, uchar*, int);
|
||||
extern int encodefmt(Fmt*);
|
||||
|
||||
/* error string */
|
||||
enum
|
||||
{
|
||||
ERRMAX = 128
|
||||
};
|
||||
extern void rerrstr(char*, uint);
|
||||
extern void werrstr(char*, ...);
|
||||
extern int errstr(char*, uint);
|
||||
|
||||
/* compiler directives on plan 9 */
|
||||
#define USED(x) if(x){}else{}
|
||||
#define SET(x) ((x)=0)
|
||||
|
||||
/* command line */
|
||||
extern char *argv0;
|
||||
#define ARGBEGIN for((argv0||(argv0=*argv)),argv++,argc--;\
|
||||
argv[0] && argv[0][0]=='-' && argv[0][1];\
|
||||
argc--, argv++) {\
|
||||
char *_args, *_argt;\
|
||||
Rune _argc;\
|
||||
_args = &argv[0][1];\
|
||||
if(_args[0]=='-' && _args[1]==0){\
|
||||
argc--; argv++; break;\
|
||||
}\
|
||||
_argc = 0;\
|
||||
while(*_args && (_args += chartorune(&_argc, _args)))\
|
||||
switch(_argc)
|
||||
#define ARGEND SET(_argt);USED(_argt);USED(_argc);USED(_args);}USED(argv);USED(argc);
|
||||
#define ARGF() (_argt=_args, _args="",\
|
||||
(*_argt? _argt: argv[1]? (argc--, *++argv): 0))
|
||||
#define EARGF(x) (_argt=_args, _args="",\
|
||||
(*_argt? _argt: argv[1]? (argc--, *++argv): ((x), abort(), (char*)0)))
|
||||
|
||||
#define ARGC() _argc
|
||||
|
||||
#define OREAD O_RDONLY
|
||||
#define OWRITE O_WRONLY
|
||||
#define AEXIST 0
|
||||
#define AREAD 4
|
||||
#define AWRITE 2
|
||||
#define AEXEC 1
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _LIB9H_ */
|
||||
54
src/lib9/lock.c
Normal file
54
src/lib9/lock.c
Normal file
@@ -0,0 +1,54 @@
|
||||
#include <unistd.h>
|
||||
#include <sched.h>
|
||||
#include <lib9.h>
|
||||
|
||||
int _ntas;
|
||||
static int
|
||||
_xtas(void *v)
|
||||
{
|
||||
int x;
|
||||
|
||||
_ntas++;
|
||||
x = _tas(v);
|
||||
if(x == 0 || x == 0xCAFEBABE)
|
||||
return x;
|
||||
fprint(2, "%d: tas %p got %ux\n", getpid(), v, x);
|
||||
abort();
|
||||
}
|
||||
|
||||
int
|
||||
canlock(Lock *l)
|
||||
{
|
||||
return !_xtas(&l->val);
|
||||
}
|
||||
|
||||
void
|
||||
unlock(Lock *l)
|
||||
{
|
||||
l->val = 0;
|
||||
}
|
||||
|
||||
void
|
||||
lock(Lock *lk)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* once fast */
|
||||
if(!_xtas(&lk->val))
|
||||
return;
|
||||
/* a thousand times pretty fast */
|
||||
for(i=0; i<1000; i++){
|
||||
if(!_xtas(&lk->val))
|
||||
return;
|
||||
sched_yield();
|
||||
}
|
||||
/* now nice and slow */
|
||||
for(i=0; i<1000; i++){
|
||||
if(!_xtas(&lk->val))
|
||||
return;
|
||||
usleep(100*1000);
|
||||
}
|
||||
/* take your time */
|
||||
while(_xtas(&lk->val))
|
||||
usleep(1000*1000);
|
||||
}
|
||||
15
src/lib9/malloctag.c
Normal file
15
src/lib9/malloctag.c
Normal file
@@ -0,0 +1,15 @@
|
||||
#include <lib9.h>
|
||||
|
||||
void
|
||||
setmalloctag(void *v, ulong t)
|
||||
{
|
||||
USED(v);
|
||||
USED(t);
|
||||
}
|
||||
|
||||
void
|
||||
setrealloctag(void *v, ulong t)
|
||||
{
|
||||
USED(v);
|
||||
USED(t);
|
||||
}
|
||||
14
src/lib9/mallocz.c
Normal file
14
src/lib9/mallocz.c
Normal file
@@ -0,0 +1,14 @@
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <lib9.h>
|
||||
|
||||
void*
|
||||
mallocz(unsigned long n, int clr)
|
||||
{
|
||||
void *v;
|
||||
|
||||
v = malloc(n);
|
||||
if(clr && v)
|
||||
memset(v, 0, n);
|
||||
return v;
|
||||
}
|
||||
2
src/lib9/mkfile
Normal file
2
src/lib9/mkfile
Normal file
@@ -0,0 +1,2 @@
|
||||
<../libutf/mkfile
|
||||
|
||||
17
src/lib9/nrand.c
Normal file
17
src/lib9/nrand.c
Normal file
@@ -0,0 +1,17 @@
|
||||
#include <lib9.h>
|
||||
|
||||
#define MASK 0x7fffffffL
|
||||
|
||||
int
|
||||
nrand(int n)
|
||||
{
|
||||
long slop, v;
|
||||
|
||||
if(n < 0)
|
||||
return n;
|
||||
slop = MASK % n;
|
||||
do
|
||||
v = lrand();
|
||||
while(v <= slop);
|
||||
return v % n;
|
||||
}
|
||||
360
src/lib9/qlock.c
Normal file
360
src/lib9/qlock.c
Normal file
@@ -0,0 +1,360 @@
|
||||
#include <lib9.h>
|
||||
|
||||
static struct {
|
||||
QLp *p;
|
||||
QLp x[1024];
|
||||
} ql = {
|
||||
ql.x
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
Queuing,
|
||||
QueuingR,
|
||||
QueuingW,
|
||||
Sleeping,
|
||||
};
|
||||
|
||||
static ulong (*_rendezvousp)(ulong, ulong) = rendezvous;
|
||||
|
||||
/* this gets called by the thread library ONLY to get us to use its rendezvous */
|
||||
void
|
||||
_qlockinit(ulong (*r)(ulong, ulong))
|
||||
{
|
||||
_rendezvousp = r;
|
||||
}
|
||||
|
||||
/* find a free shared memory location to queue ourselves in */
|
||||
static QLp*
|
||||
getqlp(void)
|
||||
{
|
||||
QLp *p, *op;
|
||||
|
||||
op = ql.p;
|
||||
for(p = op+1; ; p++){
|
||||
if(p == &ql.x[nelem(ql.x)])
|
||||
p = ql.x;
|
||||
if(p == op)
|
||||
abort();
|
||||
if(_tas(&(p->inuse)) == 0){
|
||||
ql.p = p;
|
||||
p->next = nil;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
void
|
||||
qlock(QLock *q)
|
||||
{
|
||||
QLp *p, *mp;
|
||||
|
||||
lock(&q->lock);
|
||||
if(!q->locked){
|
||||
q->locked = 1;
|
||||
unlock(&q->lock);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* chain into waiting list */
|
||||
mp = getqlp();
|
||||
p = q->tail;
|
||||
if(p == nil)
|
||||
q->head = mp;
|
||||
else
|
||||
p->next = mp;
|
||||
q->tail = mp;
|
||||
mp->state = Queuing;
|
||||
unlock(&q->lock);
|
||||
|
||||
/* wait */
|
||||
while((*_rendezvousp)((ulong)mp, 1) == ~0)
|
||||
;
|
||||
mp->inuse = 0;
|
||||
}
|
||||
|
||||
void
|
||||
qunlock(QLock *q)
|
||||
{
|
||||
QLp *p;
|
||||
|
||||
lock(&q->lock);
|
||||
p = q->head;
|
||||
if(p != nil){
|
||||
/* wakeup head waiting process */
|
||||
q->head = p->next;
|
||||
if(q->head == nil)
|
||||
q->tail = nil;
|
||||
unlock(&q->lock);
|
||||
while((*_rendezvousp)((ulong)p, 0x12345) == ~0)
|
||||
;
|
||||
return;
|
||||
}
|
||||
q->locked = 0;
|
||||
unlock(&q->lock);
|
||||
}
|
||||
|
||||
int
|
||||
canqlock(QLock *q)
|
||||
{
|
||||
if(!canlock(&q->lock))
|
||||
return 0;
|
||||
if(!q->locked){
|
||||
q->locked = 1;
|
||||
unlock(&q->lock);
|
||||
return 1;
|
||||
}
|
||||
unlock(&q->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
rlock(RWLock *q)
|
||||
{
|
||||
QLp *p, *mp;
|
||||
|
||||
lock(&q->lock);
|
||||
if(q->writer == 0 && q->head == nil){
|
||||
/* no writer, go for it */
|
||||
q->readers++;
|
||||
unlock(&q->lock);
|
||||
return;
|
||||
}
|
||||
|
||||
mp = getqlp();
|
||||
p = q->tail;
|
||||
if(p == 0)
|
||||
q->head = mp;
|
||||
else
|
||||
p->next = mp;
|
||||
q->tail = mp;
|
||||
mp->next = nil;
|
||||
mp->state = QueuingR;
|
||||
unlock(&q->lock);
|
||||
|
||||
/* wait in kernel */
|
||||
while((*_rendezvousp)((ulong)mp, 1) == ~0)
|
||||
;
|
||||
mp->inuse = 0;
|
||||
}
|
||||
|
||||
int
|
||||
canrlock(RWLock *q)
|
||||
{
|
||||
lock(&q->lock);
|
||||
if (q->writer == 0 && q->head == nil) {
|
||||
/* no writer; go for it */
|
||||
q->readers++;
|
||||
unlock(&q->lock);
|
||||
return 1;
|
||||
}
|
||||
unlock(&q->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
runlock(RWLock *q)
|
||||
{
|
||||
QLp *p;
|
||||
|
||||
lock(&q->lock);
|
||||
if(q->readers <= 0)
|
||||
abort();
|
||||
p = q->head;
|
||||
if(--(q->readers) > 0 || p == nil){
|
||||
unlock(&q->lock);
|
||||
return;
|
||||
}
|
||||
|
||||
/* start waiting writer */
|
||||
if(p->state != QueuingW)
|
||||
abort();
|
||||
q->head = p->next;
|
||||
if(q->head == 0)
|
||||
q->tail = 0;
|
||||
q->writer = 1;
|
||||
unlock(&q->lock);
|
||||
|
||||
/* wakeup waiter */
|
||||
while((*_rendezvousp)((ulong)p, 0) == ~0)
|
||||
;
|
||||
}
|
||||
|
||||
void
|
||||
wlock(RWLock *q)
|
||||
{
|
||||
QLp *p, *mp;
|
||||
|
||||
lock(&q->lock);
|
||||
if(q->readers == 0 && q->writer == 0){
|
||||
/* noone waiting, go for it */
|
||||
q->writer = 1;
|
||||
unlock(&q->lock);
|
||||
return;
|
||||
}
|
||||
|
||||
/* wait */
|
||||
p = q->tail;
|
||||
mp = getqlp();
|
||||
if(p == nil)
|
||||
q->head = mp;
|
||||
else
|
||||
p->next = mp;
|
||||
q->tail = mp;
|
||||
mp->next = nil;
|
||||
mp->state = QueuingW;
|
||||
unlock(&q->lock);
|
||||
|
||||
/* wait in kernel */
|
||||
while((*_rendezvousp)((ulong)mp, 1) == ~0)
|
||||
;
|
||||
mp->inuse = 0;
|
||||
}
|
||||
|
||||
int
|
||||
canwlock(RWLock *q)
|
||||
{
|
||||
lock(&q->lock);
|
||||
if (q->readers == 0 && q->writer == 0) {
|
||||
/* no one waiting; go for it */
|
||||
q->writer = 1;
|
||||
unlock(&q->lock);
|
||||
return 1;
|
||||
}
|
||||
unlock(&q->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
wunlock(RWLock *q)
|
||||
{
|
||||
QLp *p;
|
||||
|
||||
lock(&q->lock);
|
||||
if(q->writer == 0)
|
||||
abort();
|
||||
p = q->head;
|
||||
if(p == nil){
|
||||
q->writer = 0;
|
||||
unlock(&q->lock);
|
||||
return;
|
||||
}
|
||||
if(p->state == QueuingW){
|
||||
/* start waiting writer */
|
||||
q->head = p->next;
|
||||
if(q->head == nil)
|
||||
q->tail = nil;
|
||||
unlock(&q->lock);
|
||||
while((*_rendezvousp)((ulong)p, 0) == ~0)
|
||||
;
|
||||
return;
|
||||
}
|
||||
|
||||
if(p->state != QueuingR)
|
||||
abort();
|
||||
|
||||
/* wake waiting readers */
|
||||
while(q->head != nil && q->head->state == QueuingR){
|
||||
p = q->head;
|
||||
q->head = p->next;
|
||||
q->readers++;
|
||||
while((*_rendezvousp)((ulong)p, 0) == ~0)
|
||||
;
|
||||
}
|
||||
if(q->head == nil)
|
||||
q->tail = nil;
|
||||
q->writer = 0;
|
||||
unlock(&q->lock);
|
||||
}
|
||||
|
||||
void
|
||||
rsleep(Rendez *r)
|
||||
{
|
||||
QLp *t, *me;
|
||||
|
||||
if(!r->l)
|
||||
abort();
|
||||
lock(&r->l->lock);
|
||||
/* we should hold the qlock */
|
||||
if(!r->l->locked)
|
||||
abort();
|
||||
|
||||
/* add ourselves to the wait list */
|
||||
me = getqlp();
|
||||
me->state = Sleeping;
|
||||
if(r->head == nil)
|
||||
r->head = me;
|
||||
else
|
||||
r->tail->next = me;
|
||||
me->next = nil;
|
||||
r->tail = me;
|
||||
|
||||
/* pass the qlock to the next guy */
|
||||
t = r->l->head;
|
||||
if(t){
|
||||
r->l->head = t->next;
|
||||
if(r->l->head == nil)
|
||||
r->l->tail = nil;
|
||||
unlock(&r->l->lock);
|
||||
while((*_rendezvousp)((ulong)t, 0x12345) == ~0)
|
||||
;
|
||||
}else{
|
||||
r->l->locked = 0;
|
||||
unlock(&r->l->lock);
|
||||
}
|
||||
|
||||
/* wait for a wakeup */
|
||||
while((*_rendezvousp)((ulong)me, 0x23456) == ~0)
|
||||
;
|
||||
me->inuse = 0;
|
||||
if(!r->l->locked)
|
||||
abort();
|
||||
}
|
||||
|
||||
int
|
||||
rwakeup(Rendez *r)
|
||||
{
|
||||
QLp *t;
|
||||
|
||||
/*
|
||||
* take off wait and put on front of queue
|
||||
* put on front so guys that have been waiting will not get starved
|
||||
*/
|
||||
|
||||
if(!r->l)
|
||||
abort();
|
||||
lock(&r->l->lock);
|
||||
if(!r->l->locked)
|
||||
abort();
|
||||
|
||||
t = r->head;
|
||||
if(t == nil){
|
||||
unlock(&r->l->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
r->head = t->next;
|
||||
if(r->head == nil)
|
||||
r->tail = nil;
|
||||
|
||||
t->next = r->l->head;
|
||||
r->l->head = t;
|
||||
if(r->l->tail == nil)
|
||||
r->l->tail = t;
|
||||
|
||||
t->state = Queuing;
|
||||
unlock(&r->l->lock);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
rwakeupall(Rendez *r)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i=0; rwakeup(r); i++)
|
||||
;
|
||||
return i;
|
||||
}
|
||||
89
src/lib9/rand.c
Normal file
89
src/lib9/rand.c
Normal file
@@ -0,0 +1,89 @@
|
||||
#include <lib9.h>
|
||||
|
||||
/*
|
||||
* algorithm by
|
||||
* D. P. Mitchell & J. A. Reeds
|
||||
*/
|
||||
|
||||
#define LEN 607
|
||||
#define TAP 273
|
||||
#define MASK 0x7fffffffL
|
||||
#define A 48271
|
||||
#define M 2147483647
|
||||
#define Q 44488
|
||||
#define R 3399
|
||||
#define NORM (1.0/(1.0+MASK))
|
||||
|
||||
static ulong rng_vec[LEN];
|
||||
static ulong* rng_tap = rng_vec;
|
||||
static ulong* rng_feed = 0;
|
||||
static Lock lk;
|
||||
|
||||
static void
|
||||
isrand(long seed)
|
||||
{
|
||||
long lo, hi, x;
|
||||
int i;
|
||||
|
||||
rng_tap = rng_vec;
|
||||
rng_feed = rng_vec+LEN-TAP;
|
||||
seed = seed%M;
|
||||
if(seed < 0)
|
||||
seed += M;
|
||||
if(seed == 0)
|
||||
seed = 89482311;
|
||||
x = seed;
|
||||
/*
|
||||
* Initialize by x[n+1] = 48271 * x[n] mod (2**31 - 1)
|
||||
*/
|
||||
for(i = -20; i < LEN; i++) {
|
||||
hi = x / Q;
|
||||
lo = x % Q;
|
||||
x = A*lo - R*hi;
|
||||
if(x < 0)
|
||||
x += M;
|
||||
if(i >= 0)
|
||||
rng_vec[i] = x;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
srand(long seed)
|
||||
{
|
||||
lock(&lk);
|
||||
isrand(seed);
|
||||
unlock(&lk);
|
||||
}
|
||||
|
||||
long
|
||||
lrand(void)
|
||||
{
|
||||
ulong x;
|
||||
|
||||
lock(&lk);
|
||||
|
||||
rng_tap--;
|
||||
if(rng_tap < rng_vec) {
|
||||
if(rng_feed == 0) {
|
||||
isrand(1);
|
||||
rng_tap--;
|
||||
}
|
||||
rng_tap += LEN;
|
||||
}
|
||||
rng_feed--;
|
||||
if(rng_feed < rng_vec)
|
||||
rng_feed += LEN;
|
||||
x = (*rng_feed + *rng_tap) & MASK;
|
||||
*rng_feed = x;
|
||||
|
||||
unlock(&lk);
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
int
|
||||
rand(void)
|
||||
{
|
||||
return lrand() & 0x7fff;
|
||||
}
|
||||
|
||||
21
src/lib9/readn.c
Normal file
21
src/lib9/readn.c
Normal file
@@ -0,0 +1,21 @@
|
||||
#include <lib9.h>
|
||||
|
||||
long
|
||||
readn(int f, void *av, long n)
|
||||
{
|
||||
char *a;
|
||||
long m, t;
|
||||
|
||||
a = av;
|
||||
t = 0;
|
||||
while(t < n){
|
||||
m = read(f, a+t, n-t);
|
||||
if(m <= 0){
|
||||
if(t == 0)
|
||||
return m;
|
||||
break;
|
||||
}
|
||||
t += m;
|
||||
}
|
||||
return t;
|
||||
}
|
||||
180
src/lib9/rendez.c
Normal file
180
src/lib9/rendez.c
Normal file
@@ -0,0 +1,180 @@
|
||||
/*
|
||||
NAME
|
||||
rendezvous - user level process synchronization
|
||||
|
||||
SYNOPSIS
|
||||
ulong rendezvous(ulong tag, ulong value)
|
||||
|
||||
DESCRIPTION
|
||||
The rendezvous system call allows two processes to synchro-
|
||||
nize and exchange a value. In conjunction with the shared
|
||||
memory system calls (see segattach(2) and fork(2)), it
|
||||
enables parallel programs to control their scheduling.
|
||||
|
||||
Two processes wishing to synchronize call rendezvous with a
|
||||
common tag, typically an address in memory they share. One
|
||||
process will arrive at the rendezvous first; it suspends
|
||||
execution until a second arrives. When a second process
|
||||
meets the rendezvous the value arguments are exchanged
|
||||
between the processes and returned as the result of the
|
||||
respective rendezvous system calls. Both processes are
|
||||
awakened when the rendezvous succeeds.
|
||||
|
||||
The set of tag values which two processes may use to
|
||||
rendezvous-their tag space-is inherited when a process
|
||||
forks, unless RFREND is set in the argument to rfork; see
|
||||
fork(2).
|
||||
|
||||
If a rendezvous is interrupted the return value is ~0, so
|
||||
that value should not be used in normal communication.
|
||||
|
||||
* This simulates rendezvous with shared memory, pause, and SIGUSR1.
|
||||
*/
|
||||
|
||||
#include <signal.h>
|
||||
#include <lib9.h>
|
||||
|
||||
enum
|
||||
{
|
||||
VOUSHASH = 257,
|
||||
};
|
||||
|
||||
typedef struct Vous Vous;
|
||||
struct Vous
|
||||
{
|
||||
Vous *link;
|
||||
Lock lk;
|
||||
int pid;
|
||||
ulong val;
|
||||
ulong tag;
|
||||
};
|
||||
|
||||
static void
|
||||
ign(int x)
|
||||
{
|
||||
USED(x);
|
||||
}
|
||||
|
||||
void /*__attribute__((constructor))*/
|
||||
ignusr1(void)
|
||||
{
|
||||
signal(SIGUSR1, ign);
|
||||
}
|
||||
|
||||
static Vous vouspool[2048];
|
||||
static int nvousused;
|
||||
static Vous *vousfree;
|
||||
static Vous *voushash[VOUSHASH];
|
||||
static Lock vouslock;
|
||||
|
||||
static Vous*
|
||||
getvous(void)
|
||||
{
|
||||
Vous *v;
|
||||
|
||||
if(vousfree){
|
||||
v = vousfree;
|
||||
vousfree = v->link;
|
||||
}else if(nvousused < nelem(vouspool))
|
||||
v = &vouspool[nvousused++];
|
||||
else
|
||||
abort();
|
||||
return v;
|
||||
}
|
||||
|
||||
static void
|
||||
putvous(Vous *v)
|
||||
{
|
||||
lock(&vouslock);
|
||||
v->link = vousfree;
|
||||
vousfree = v;
|
||||
unlock(&vouslock);
|
||||
}
|
||||
|
||||
static Vous*
|
||||
findvous(ulong tag, ulong val, int pid)
|
||||
{
|
||||
int h;
|
||||
Vous *v, **l;
|
||||
|
||||
lock(&vouslock);
|
||||
h = tag%VOUSHASH;
|
||||
for(l=&voushash[h], v=*l; v; l=&(*l)->link, v=*l){
|
||||
if(v->tag == tag){
|
||||
*l = v->link;
|
||||
unlock(&vouslock);
|
||||
return v;
|
||||
}
|
||||
}
|
||||
v = getvous();
|
||||
v->pid = pid;
|
||||
v->link = voushash[h];
|
||||
v->val = val;
|
||||
v->tag = tag;
|
||||
lock(&v->lk);
|
||||
voushash[h] = v;
|
||||
unlock(&vouslock);
|
||||
return v;
|
||||
}
|
||||
|
||||
#define DBG 0
|
||||
ulong
|
||||
rendezvous(ulong tag, ulong val)
|
||||
{
|
||||
int me, vpid;
|
||||
ulong rval;
|
||||
Vous *v;
|
||||
sigset_t mask;
|
||||
|
||||
me = getpid();
|
||||
v = findvous(tag, val, me);
|
||||
if(v->pid == me){
|
||||
if(DBG)fprint(2, "pid is %d tag %lux, sleeping\n", me, tag);
|
||||
/*
|
||||
* No rendezvous partner was found; the next guy
|
||||
* through will find v and wake us, so we must go
|
||||
* to sleep.
|
||||
*
|
||||
* To go to sleep:
|
||||
* 1. disable USR1 signals.
|
||||
* 2. unlock v->lk (tells waker okay to signal us).
|
||||
* 3. atomically suspend and enable USR1 signals.
|
||||
*
|
||||
* The call to ignusr1() could be done once at
|
||||
* process creation instead of every time through rendezvous.
|
||||
*/
|
||||
v->val = val;
|
||||
ignusr1();
|
||||
sigprocmask(SIG_SETMASK, NULL, &mask);
|
||||
sigaddset(&mask, SIGUSR1);
|
||||
sigprocmask(SIG_SETMASK, &mask, NULL);
|
||||
sigdelset(&mask, SIGUSR1);
|
||||
unlock(&v->lk);
|
||||
sigsuspend(&mask);
|
||||
rval = v->val;
|
||||
if(DBG)fprint(2, "pid is %d, awake\n", me);
|
||||
putvous(v);
|
||||
}else{
|
||||
/*
|
||||
* Found someone to meet. Wake him:
|
||||
*
|
||||
* A. lock v->lk (waits for him to get to his step 2)
|
||||
* B. send a USR1
|
||||
*
|
||||
* He won't get the USR1 until he suspends, which
|
||||
* means it must wake him up (it can't get delivered
|
||||
* before he sleeps).
|
||||
*/
|
||||
vpid = v->pid;
|
||||
lock(&v->lk);
|
||||
rval = v->val;
|
||||
v->val = val;
|
||||
unlock(&v->lk);
|
||||
if(kill(vpid, SIGUSR1) < 0){
|
||||
if(DBG)fprint(2, "pid is %d, kill %d failed: %r\n", me, vpid);
|
||||
abort();
|
||||
}
|
||||
}
|
||||
return rval;
|
||||
}
|
||||
|
||||
16
src/lib9/strecpy.c
Normal file
16
src/lib9/strecpy.c
Normal file
@@ -0,0 +1,16 @@
|
||||
#include <lib9.h>
|
||||
|
||||
char*
|
||||
strecpy(char *to, char *e, char *from)
|
||||
{
|
||||
if(to >= e)
|
||||
return to;
|
||||
to = memccpy(to, from, '\0', e - to);
|
||||
if(to == nil){
|
||||
to = e - 1;
|
||||
*to = '\0';
|
||||
}else{
|
||||
to--;
|
||||
}
|
||||
return to;
|
||||
}
|
||||
20
src/lib9/sysfatal.c
Normal file
20
src/lib9/sysfatal.c
Normal file
@@ -0,0 +1,20 @@
|
||||
#include <lib9.h>
|
||||
|
||||
void (*_sysfatal)(char*, ...);
|
||||
|
||||
void
|
||||
sysfatal(char *fmt, ...)
|
||||
{
|
||||
char buf[256];
|
||||
va_list arg;
|
||||
|
||||
va_start(arg, fmt);
|
||||
if(_sysfatal)
|
||||
(*_sysfatal)(fmt, arg);
|
||||
vseprint(buf, buf+sizeof buf, fmt, arg);
|
||||
va_end(arg);
|
||||
|
||||
fprint(2, "%s; %s\n", argv0 ? argv0 : "<prog>", buf);
|
||||
exits("fatal");
|
||||
}
|
||||
|
||||
6
src/lib9/tas-386.s
Normal file
6
src/lib9/tas-386.s
Normal file
@@ -0,0 +1,6 @@
|
||||
.globl _tas
|
||||
_tas:
|
||||
movl $0xCAFEBABE, %eax
|
||||
movl 4(%esp), %ecx
|
||||
xchgl %eax, 0(%ecx)
|
||||
ret
|
||||
8
src/lib9/test.c
Normal file
8
src/lib9/test.c
Normal file
@@ -0,0 +1,8 @@
|
||||
#include <lib9.h>
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
werrstr("hello world");
|
||||
print("%r\n");
|
||||
}
|
||||
21
src/lib9/testfork.c
Normal file
21
src/lib9/testfork.c
Normal file
@@ -0,0 +1,21 @@
|
||||
#include <lib9.h>
|
||||
|
||||
void
|
||||
sayhi(void *v)
|
||||
{
|
||||
USED(v);
|
||||
|
||||
print("hello from subproc\n");
|
||||
print("rendez got %lu from main\n", rendezvous(0x1234, 1234));
|
||||
exits(0);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
print("hello from main\n");
|
||||
ffork(RFMEM|RFPROC, sayhi, nil);
|
||||
|
||||
print("rendez got %lu from subproc\n", rendezvous(0x1234, 0));
|
||||
exits(0);
|
||||
}
|
||||
106
src/lib9/tokenize.c
Normal file
106
src/lib9/tokenize.c
Normal file
@@ -0,0 +1,106 @@
|
||||
#include <lib9.h>
|
||||
|
||||
static char qsep[] = " \t\r\n";
|
||||
|
||||
static char*
|
||||
qtoken(char *s, char *sep)
|
||||
{
|
||||
int quoting;
|
||||
char *t;
|
||||
|
||||
quoting = 0;
|
||||
t = s; /* s is output string, t is input string */
|
||||
while(*t!='\0' && (quoting || utfrune(sep, *t)==nil)){
|
||||
if(*t != '\''){
|
||||
*s++ = *t++;
|
||||
continue;
|
||||
}
|
||||
/* *t is a quote */
|
||||
if(!quoting){
|
||||
quoting = 1;
|
||||
t++;
|
||||
continue;
|
||||
}
|
||||
/* quoting and we're on a quote */
|
||||
if(t[1] != '\''){
|
||||
/* end of quoted section; absorb closing quote */
|
||||
t++;
|
||||
quoting = 0;
|
||||
continue;
|
||||
}
|
||||
/* doubled quote; fold one quote into two */
|
||||
t++;
|
||||
*s++ = *t++;
|
||||
}
|
||||
if(*s != '\0'){
|
||||
*s = '\0';
|
||||
if(t == s)
|
||||
t++;
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
static char*
|
||||
etoken(char *t, char *sep)
|
||||
{
|
||||
int quoting;
|
||||
|
||||
/* move to end of next token */
|
||||
quoting = 0;
|
||||
while(*t!='\0' && (quoting || utfrune(sep, *t)==nil)){
|
||||
if(*t != '\''){
|
||||
t++;
|
||||
continue;
|
||||
}
|
||||
/* *t is a quote */
|
||||
if(!quoting){
|
||||
quoting = 1;
|
||||
t++;
|
||||
continue;
|
||||
}
|
||||
/* quoting and we're on a quote */
|
||||
if(t[1] != '\''){
|
||||
/* end of quoted section; absorb closing quote */
|
||||
t++;
|
||||
quoting = 0;
|
||||
continue;
|
||||
}
|
||||
/* doubled quote; fold one quote into two */
|
||||
t += 2;
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
int
|
||||
gettokens(char *s, char **args, int maxargs, char *sep)
|
||||
{
|
||||
int nargs;
|
||||
|
||||
for(nargs=0; nargs<maxargs; nargs++){
|
||||
while(*s!='\0' && utfrune(sep, *s)!=nil)
|
||||
*s++ = '\0';
|
||||
if(*s == '\0')
|
||||
break;
|
||||
args[nargs] = s;
|
||||
s = etoken(s, sep);
|
||||
}
|
||||
|
||||
return nargs;
|
||||
}
|
||||
|
||||
int
|
||||
tokenize(char *s, char **args, int maxargs)
|
||||
{
|
||||
int nargs;
|
||||
|
||||
for(nargs=0; nargs<maxargs; nargs++){
|
||||
while(*s!='\0' && utfrune(qsep, *s)!=nil)
|
||||
s++;
|
||||
if(*s == '\0')
|
||||
break;
|
||||
args[nargs] = s;
|
||||
s = qtoken(s, qsep);
|
||||
}
|
||||
|
||||
return nargs;
|
||||
}
|
||||
52
src/lib9/u16.c
Normal file
52
src/lib9/u16.c
Normal file
@@ -0,0 +1,52 @@
|
||||
#include <lib9.h>
|
||||
static char t16e[] = "0123456789ABCDEF";
|
||||
|
||||
int
|
||||
dec16(uchar *out, int lim, char *in, int n)
|
||||
{
|
||||
int c, w = 0, i = 0;
|
||||
uchar *start = out;
|
||||
uchar *eout = out + lim;
|
||||
|
||||
while(n-- > 0){
|
||||
c = *in++;
|
||||
if('0' <= c && c <= '9')
|
||||
c = c - '0';
|
||||
else if('a' <= c && c <= 'z')
|
||||
c = c - 'a' + 10;
|
||||
else if('A' <= c && c <= 'Z')
|
||||
c = c - 'A' + 10;
|
||||
else
|
||||
continue;
|
||||
w = (w<<4) + c;
|
||||
i++;
|
||||
if(i == 2){
|
||||
if(out + 1 > eout)
|
||||
goto exhausted;
|
||||
*out++ = w;
|
||||
w = 0;
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
exhausted:
|
||||
return out - start;
|
||||
}
|
||||
|
||||
int
|
||||
enc16(char *out, int lim, uchar *in, int n)
|
||||
{
|
||||
uint c;
|
||||
char *eout = out + lim;
|
||||
char *start = out;
|
||||
|
||||
while(n-- > 0){
|
||||
c = *in++;
|
||||
if(out + 2 >= eout)
|
||||
goto exhausted;
|
||||
*out++ = t16e[c>>4];
|
||||
*out++ = t16e[c&0xf];
|
||||
}
|
||||
exhausted:
|
||||
*out = 0;
|
||||
return out - start;
|
||||
}
|
||||
109
src/lib9/u32.c
Normal file
109
src/lib9/u32.c
Normal file
@@ -0,0 +1,109 @@
|
||||
#include <lib9.h>
|
||||
|
||||
int
|
||||
dec32(uchar *dest, int ndest, char *src, int nsrc)
|
||||
{
|
||||
char *s, *tab;
|
||||
uchar *start;
|
||||
int i, u[8];
|
||||
|
||||
if(ndest+1 < (5*nsrc+7)/8)
|
||||
return -1;
|
||||
start = dest;
|
||||
tab = "23456789abcdefghijkmnpqrstuvwxyz";
|
||||
while(nsrc>=8){
|
||||
for(i=0; i<8; i++){
|
||||
s = strchr(tab,(int)src[i]);
|
||||
u[i] = s ? s-tab : 0;
|
||||
}
|
||||
*dest++ = (u[0]<<3) | (0x7 & (u[1]>>2));
|
||||
*dest++ = ((0x3 & u[1])<<6) | (u[2]<<1) | (0x1 & (u[3]>>4));
|
||||
*dest++ = ((0xf & u[3])<<4) | (0xf & (u[4]>>1));
|
||||
*dest++ = ((0x1 & u[4])<<7) | (u[5]<<2) | (0x3 & (u[6]>>3));
|
||||
*dest++ = ((0x7 & u[6])<<5) | u[7];
|
||||
src += 8;
|
||||
nsrc -= 8;
|
||||
}
|
||||
if(nsrc > 0){
|
||||
if(nsrc == 1 || nsrc == 3 || nsrc == 6)
|
||||
return -1;
|
||||
for(i=0; i<nsrc; i++){
|
||||
s = strchr(tab,(int)src[i]);
|
||||
u[i] = s ? s-tab : 0;
|
||||
}
|
||||
*dest++ = (u[0]<<3) | (0x7 & (u[1]>>2));
|
||||
if(nsrc == 2)
|
||||
goto out;
|
||||
*dest++ = ((0x3 & u[1])<<6) | (u[2]<<1) | (0x1 & (u[3]>>4));
|
||||
if(nsrc == 4)
|
||||
goto out;
|
||||
*dest++ = ((0xf & u[3])<<4) | (0xf & (u[4]>>1));
|
||||
if(nsrc == 5)
|
||||
goto out;
|
||||
*dest++ = ((0x1 & u[4])<<7) | (u[5]<<2) | (0x3 & (u[6]>>3));
|
||||
}
|
||||
out:
|
||||
return dest-start;
|
||||
}
|
||||
|
||||
int
|
||||
enc32(char *dest, int ndest, uchar *src, int nsrc)
|
||||
{
|
||||
char *tab, *start;
|
||||
int j;
|
||||
|
||||
if(ndest <= (8*nsrc+4)/5 )
|
||||
return -1;
|
||||
start = dest;
|
||||
tab = "23456789abcdefghijkmnpqrstuvwxyz";
|
||||
while(nsrc>=5){
|
||||
j = (0x1f & (src[0]>>3));
|
||||
*dest++ = tab[j];
|
||||
j = (0x1c & (src[0]<<2)) | (0x03 & (src[1]>>6));
|
||||
*dest++ = tab[j];
|
||||
j = (0x1f & (src[1]>>1));
|
||||
*dest++ = tab[j];
|
||||
j = (0x10 & (src[1]<<4)) | (0x0f & (src[2]>>4));
|
||||
*dest++ = tab[j];
|
||||
j = (0x1e & (src[2]<<1)) | (0x01 & (src[3]>>7));
|
||||
*dest++ = tab[j];
|
||||
j = (0x1f & (src[3]>>2));
|
||||
*dest++ = tab[j];
|
||||
j = (0x18 & (src[3]<<3)) | (0x07 & (src[4]>>5));
|
||||
*dest++ = tab[j];
|
||||
j = (0x1f & (src[4]));
|
||||
*dest++ = tab[j];
|
||||
src += 5;
|
||||
nsrc -= 5;
|
||||
}
|
||||
if(nsrc){
|
||||
j = (0x1f & (src[0]>>3));
|
||||
*dest++ = tab[j];
|
||||
j = (0x1c & (src[0]<<2));
|
||||
if(nsrc == 1)
|
||||
goto out;
|
||||
j |= (0x03 & (src[1]>>6));
|
||||
*dest++ = tab[j];
|
||||
j = (0x1f & (src[1]>>1));
|
||||
if(nsrc == 2)
|
||||
goto out;
|
||||
*dest++ = tab[j];
|
||||
j = (0x10 & (src[1]<<4));
|
||||
if(nsrc == 3)
|
||||
goto out;
|
||||
j |= (0x0f & (src[2]>>4));
|
||||
*dest++ = tab[j];
|
||||
j = (0x1e & (src[2]<<1));
|
||||
if(nsrc == 4)
|
||||
goto out;
|
||||
j |= (0x01 & (src[3]>>7));
|
||||
*dest++ = tab[j];
|
||||
j = (0x1f & (src[3]>>2));
|
||||
*dest++ = tab[j];
|
||||
j = (0x18 & (src[3]<<3));
|
||||
out:
|
||||
*dest++ = tab[j];
|
||||
}
|
||||
*dest = 0;
|
||||
return dest-start;
|
||||
}
|
||||
126
src/lib9/u64.c
Normal file
126
src/lib9/u64.c
Normal file
@@ -0,0 +1,126 @@
|
||||
#include <lib9.h>
|
||||
|
||||
enum {
|
||||
INVAL= 255
|
||||
};
|
||||
|
||||
static uchar t64d[256] = {
|
||||
INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,
|
||||
INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,
|
||||
INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL, 62,INVAL,INVAL,INVAL, 63,
|
||||
52, 53, 54, 55, 56, 57, 58, 59, 60, 61,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,
|
||||
INVAL, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
|
||||
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,INVAL,INVAL,INVAL,INVAL,INVAL,
|
||||
INVAL, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
|
||||
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,INVAL,INVAL,INVAL,INVAL,INVAL,
|
||||
INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,
|
||||
INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,
|
||||
INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,
|
||||
INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,
|
||||
INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,
|
||||
INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,
|
||||
INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,
|
||||
INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL
|
||||
};
|
||||
static char t64e[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
|
||||
int
|
||||
dec64(uchar *out, int lim, char *in, int n)
|
||||
{
|
||||
ulong b24;
|
||||
uchar *start = out;
|
||||
uchar *e = out + lim;
|
||||
int i, c;
|
||||
|
||||
b24 = 0;
|
||||
i = 0;
|
||||
while(n-- > 0){
|
||||
|
||||
c = t64d[*(uchar*)in++];
|
||||
if(c == INVAL)
|
||||
continue;
|
||||
switch(i){
|
||||
case 0:
|
||||
b24 = c<<18;
|
||||
break;
|
||||
case 1:
|
||||
b24 |= c<<12;
|
||||
break;
|
||||
case 2:
|
||||
b24 |= c<<6;
|
||||
break;
|
||||
case 3:
|
||||
if(out + 3 > e)
|
||||
goto exhausted;
|
||||
|
||||
b24 |= c;
|
||||
*out++ = b24>>16;
|
||||
*out++ = b24>>8;
|
||||
*out++ = b24;
|
||||
i = -1;
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
switch(i){
|
||||
case 2:
|
||||
if(out + 1 > e)
|
||||
goto exhausted;
|
||||
*out++ = b24>>16;
|
||||
break;
|
||||
case 3:
|
||||
if(out + 2 > e)
|
||||
goto exhausted;
|
||||
*out++ = b24>>16;
|
||||
*out++ = b24>>8;
|
||||
break;
|
||||
}
|
||||
exhausted:
|
||||
return out - start;
|
||||
}
|
||||
|
||||
int
|
||||
enc64(char *out, int lim, uchar *in, int n)
|
||||
{
|
||||
int i;
|
||||
ulong b24;
|
||||
char *start = out;
|
||||
char *e = out + lim;
|
||||
|
||||
for(i = n/3; i > 0; i--){
|
||||
b24 = (*in++)<<16;
|
||||
b24 |= (*in++)<<8;
|
||||
b24 |= *in++;
|
||||
if(out + 4 >= e)
|
||||
goto exhausted;
|
||||
*out++ = t64e[(b24>>18)];
|
||||
*out++ = t64e[(b24>>12)&0x3f];
|
||||
*out++ = t64e[(b24>>6)&0x3f];
|
||||
*out++ = t64e[(b24)&0x3f];
|
||||
}
|
||||
|
||||
switch(n%3){
|
||||
case 2:
|
||||
b24 = (*in++)<<16;
|
||||
b24 |= (*in)<<8;
|
||||
if(out + 4 >= e)
|
||||
goto exhausted;
|
||||
*out++ = t64e[(b24>>18)];
|
||||
*out++ = t64e[(b24>>12)&0x3f];
|
||||
*out++ = t64e[(b24>>6)&0x3f];
|
||||
*out++ = '=';
|
||||
break;
|
||||
case 1:
|
||||
b24 = (*in)<<16;
|
||||
if(out + 4 >= e)
|
||||
goto exhausted;
|
||||
*out++ = t64e[(b24>>18)];
|
||||
*out++ = t64e[(b24>>12)&0x3f];
|
||||
*out++ = '=';
|
||||
*out++ = '=';
|
||||
break;
|
||||
}
|
||||
exhausted:
|
||||
*out = 0;
|
||||
return out - start;
|
||||
}
|
||||
30
src/lib9/wait.c
Normal file
30
src/lib9/wait.c
Normal file
@@ -0,0 +1,30 @@
|
||||
#include <lib9.h>
|
||||
|
||||
Waitmsg*
|
||||
wait(void)
|
||||
{
|
||||
int n, l;
|
||||
char buf[512], *fld[5];
|
||||
Waitmsg *w;
|
||||
|
||||
n = await(buf, sizeof buf-1);
|
||||
if(n < 0)
|
||||
return nil;
|
||||
buf[n] = '\0';
|
||||
if(tokenize(buf, fld, nelem(fld)) != nelem(fld)){
|
||||
werrstr("couldn't parse wait message");
|
||||
return nil;
|
||||
}
|
||||
l = strlen(fld[4])+1;
|
||||
w = malloc(sizeof(Waitmsg)+l);
|
||||
if(w == nil)
|
||||
return nil;
|
||||
w->pid = atoi(fld[0]);
|
||||
w->time[0] = atoi(fld[1]);
|
||||
w->time[1] = atoi(fld[2]);
|
||||
w->time[2] = atoi(fld[3]);
|
||||
w->msg = (char*)&w[1];
|
||||
memmove(w->msg, fld[4], l);
|
||||
return w;
|
||||
}
|
||||
|
||||
13
src/lib9/werrstr.c
Normal file
13
src/lib9/werrstr.c
Normal file
@@ -0,0 +1,13 @@
|
||||
#include <lib9.h>
|
||||
|
||||
void
|
||||
werrstr(char *fmt, ...)
|
||||
{
|
||||
va_list arg;
|
||||
char buf[ERRMAX];
|
||||
|
||||
va_start(arg, fmt);
|
||||
vseprint(buf, buf+ERRMAX, fmt, arg);
|
||||
va_end(arg);
|
||||
errstr(buf, ERRMAX);
|
||||
}
|
||||
258
src/libbio/LICENSE
Normal file
258
src/libbio/LICENSE
Normal file
@@ -0,0 +1,258 @@
|
||||
The Plan 9 software is provided under the terms of the
|
||||
Lucent Public License, Version 1.02, reproduced below,
|
||||
with the following exceptions:
|
||||
|
||||
1. No right is granted to create derivative works of or
|
||||
to redistribute (other than with the Plan 9 Operating System)
|
||||
the screen imprinter fonts identified in subdirectory
|
||||
/lib/font/bit/lucida and printer fonts (Lucida Sans Unicode, Lucida
|
||||
Sans Italic, Lucida Sans Demibold, Lucida Typewriter, Lucida Sans
|
||||
Typewriter83), identified in subdirectory /sys/lib/postscript/font.
|
||||
These directories contain material copyrights by B&H Inc. and Y&Y Inc.
|
||||
|
||||
2. The printer fonts identified in subdirectory /sys/lib/ghostscript/font
|
||||
are subject to the GNU GPL, reproduced in the file /LICENSE.gpl.
|
||||
|
||||
3. The ghostscript program in the subdirectory /sys/src/cmd/gs is
|
||||
covered by the Aladdin Free Public License, reproduced in the file
|
||||
/LICENSE.afpl.
|
||||
|
||||
===================================================================
|
||||
|
||||
Lucent Public License Version 1.02
|
||||
|
||||
THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS PUBLIC
|
||||
LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE
|
||||
PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
|
||||
|
||||
1. DEFINITIONS
|
||||
|
||||
"Contribution" means:
|
||||
|
||||
a. in the case of Lucent Technologies Inc. ("LUCENT"), the Original
|
||||
Program, and
|
||||
b. in the case of each Contributor,
|
||||
|
||||
i. changes to the Program, and
|
||||
ii. additions to the Program;
|
||||
|
||||
where such changes and/or additions to the Program were added to the
|
||||
Program by such Contributor itself or anyone acting on such
|
||||
Contributor's behalf, and the Contributor explicitly consents, in
|
||||
accordance with Section 3C, to characterization of the changes and/or
|
||||
additions as Contributions.
|
||||
|
||||
"Contributor" means LUCENT and any other entity that has Contributed a
|
||||
Contribution to the Program.
|
||||
|
||||
"Distributor" means a Recipient that distributes the Program,
|
||||
modifications to the Program, or any part thereof.
|
||||
|
||||
"Licensed Patents" mean patent claims licensable by a Contributor
|
||||
which are necessarily infringed by the use or sale of its Contribution
|
||||
alone or when combined with the Program.
|
||||
|
||||
"Original Program" means the original version of the software
|
||||
accompanying this Agreement as released by LUCENT, including source
|
||||
code, object code and documentation, if any.
|
||||
|
||||
"Program" means the Original Program and Contributions or any part
|
||||
thereof
|
||||
|
||||
"Recipient" means anyone who receives the Program under this
|
||||
Agreement, including all Contributors.
|
||||
|
||||
2. GRANT OF RIGHTS
|
||||
|
||||
a. Subject to the terms of this Agreement, each Contributor hereby
|
||||
grants Recipient a non-exclusive, worldwide, royalty-free copyright
|
||||
license to reproduce, prepare derivative works of, publicly display,
|
||||
publicly perform, distribute and sublicense the Contribution of such
|
||||
Contributor, if any, and such derivative works, in source code and
|
||||
object code form.
|
||||
|
||||
b. Subject to the terms of this Agreement, each Contributor hereby
|
||||
grants Recipient a non-exclusive, worldwide, royalty-free patent
|
||||
license under Licensed Patents to make, use, sell, offer to sell,
|
||||
import and otherwise transfer the Contribution of such Contributor, if
|
||||
any, in source code and object code form. The patent license granted
|
||||
by a Contributor shall also apply to the combination of the
|
||||
Contribution of that Contributor and the Program if, at the time the
|
||||
Contribution is added by the Contributor, such addition of the
|
||||
Contribution causes such combination to be covered by the Licensed
|
||||
Patents. The patent license granted by a Contributor shall not apply
|
||||
to (i) any other combinations which include the Contribution, nor to
|
||||
(ii) Contributions of other Contributors. No hardware per se is
|
||||
licensed hereunder.
|
||||
|
||||
c. Recipient understands that although each Contributor grants the
|
||||
licenses to its Contributions set forth herein, no assurances are
|
||||
provided by any Contributor that the Program does not infringe the
|
||||
patent or other intellectual property rights of any other entity. Each
|
||||
Contributor disclaims any liability to Recipient for claims brought by
|
||||
any other entity based on infringement of intellectual property rights
|
||||
or otherwise. As a condition to exercising the rights and licenses
|
||||
granted hereunder, each Recipient hereby assumes sole responsibility
|
||||
to secure any other intellectual property rights needed, if any. For
|
||||
example, if a third party patent license is required to allow
|
||||
Recipient to distribute the Program, it is Recipient's responsibility
|
||||
to acquire that license before distributing the Program.
|
||||
|
||||
d. Each Contributor represents that to its knowledge it has sufficient
|
||||
copyright rights in its Contribution, if any, to grant the copyright
|
||||
license set forth in this Agreement.
|
||||
|
||||
3. REQUIREMENTS
|
||||
|
||||
A. Distributor may choose to distribute the Program in any form under
|
||||
this Agreement or under its own license agreement, provided that:
|
||||
|
||||
a. it complies with the terms and conditions of this Agreement;
|
||||
|
||||
b. if the Program is distributed in source code or other tangible
|
||||
form, a copy of this Agreement or Distributor's own license agreement
|
||||
is included with each copy of the Program; and
|
||||
|
||||
c. if distributed under Distributor's own license agreement, such
|
||||
license agreement:
|
||||
|
||||
i. effectively disclaims on behalf of all Contributors all warranties
|
||||
and conditions, express and implied, including warranties or
|
||||
conditions of title and non-infringement, and implied warranties or
|
||||
conditions of merchantability and fitness for a particular purpose;
|
||||
ii. effectively excludes on behalf of all Contributors all liability
|
||||
for damages, including direct, indirect, special, incidental and
|
||||
consequential damages, such as lost profits; and
|
||||
iii. states that any provisions which differ from this Agreement are
|
||||
offered by that Contributor alone and not by any other party.
|
||||
|
||||
B. Each Distributor must include the following in a conspicuous
|
||||
location in the Program:
|
||||
|
||||
Copyright (C) 2003, Lucent Technologies Inc. and others. All Rights
|
||||
Reserved.
|
||||
|
||||
C. In addition, each Contributor must identify itself as the
|
||||
originator of its Contribution in a manner that reasonably allows
|
||||
subsequent Recipients to identify the originator of the Contribution.
|
||||
Also, each Contributor must agree that the additions and/or changes
|
||||
are intended to be a Contribution. Once a Contribution is contributed,
|
||||
it may not thereafter be revoked.
|
||||
|
||||
4. COMMERCIAL DISTRIBUTION
|
||||
|
||||
Commercial distributors of software may accept certain
|
||||
responsibilities with respect to end users, business partners and the
|
||||
like. While this license is intended to facilitate the commercial use
|
||||
of the Program, the Distributor who includes the Program in a
|
||||
commercial product offering should do so in a manner which does not
|
||||
create potential liability for Contributors. Therefore, if a
|
||||
Distributor includes the Program in a commercial product offering,
|
||||
such Distributor ("Commercial Distributor") hereby agrees to defend
|
||||
and indemnify every Contributor ("Indemnified Contributor") against
|
||||
any losses, damages and costs (collectively"Losses") arising from
|
||||
claims, lawsuits and other legal actions brought by a third party
|
||||
against the Indemnified Contributor to the extent caused by the acts
|
||||
or omissions of such Commercial Distributor in connection with its
|
||||
distribution of the Program in a commercial product offering. The
|
||||
obligations in this section do not apply to any claims or Losses
|
||||
relating to any actual or alleged intellectual property infringement.
|
||||
In order to qualify, an Indemnified Contributor must: a) promptly
|
||||
notify the Commercial Distributor in writing of such claim, and b)
|
||||
allow the Commercial Distributor to control, and cooperate with the
|
||||
Commercial Distributor in, the defense and any related settlement
|
||||
negotiations. The Indemnified Contributor may participate in any such
|
||||
claim at its own expense.
|
||||
|
||||
For example, a Distributor might include the Program in a commercial
|
||||
product offering, Product X. That Distributor is then a Commercial
|
||||
Distributor. If that Commercial Distributor then makes performance
|
||||
claims, or offers warranties related to Product X, those performance
|
||||
claims and warranties are such Commercial Distributor's responsibility
|
||||
alone. Under this section, the Commercial Distributor would have to
|
||||
defend claims against the Contributors related to those performance
|
||||
claims and warranties, and if a court requires any Contributor to pay
|
||||
any damages as a result, the Commercial Distributor must pay those
|
||||
damages.
|
||||
|
||||
5. NO WARRANTY
|
||||
|
||||
EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS
|
||||
PROVIDED ON AN"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
|
||||
WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY
|
||||
OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely
|
||||
responsible for determining the appropriateness of using and
|
||||
distributing the Program and assumes all risks associated with its
|
||||
exercise of rights under this Agreement, including but not limited to
|
||||
the risks and costs of program errors, compliance with applicable
|
||||
laws, damage to or loss of data, programs or equipment, and
|
||||
unavailability or interruption of operations.
|
||||
|
||||
6. DISCLAIMER OF LIABILITY
|
||||
|
||||
EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR
|
||||
ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING
|
||||
WITHOUT LIMITATION LOST PROFITS), 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 OR
|
||||
DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
|
||||
HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
7. EXPORT CONTROL
|
||||
|
||||
Recipient agrees that Recipient alone is responsible for compliance
|
||||
with the United States export administration regulations (and the
|
||||
export control laws and regulation of any other countries).
|
||||
|
||||
8. GENERAL
|
||||
|
||||
If any provision of this Agreement is invalid or unenforceable under
|
||||
applicable law, it shall not affect the validity or enforceability of
|
||||
the remainder of the terms of this Agreement, and without further
|
||||
action by the parties hereto, such provision shall be reformed to the
|
||||
minimum extent necessary to make such provision valid and enforceable.
|
||||
|
||||
If Recipient institutes patent litigation against a Contributor with
|
||||
respect to a patent applicable to software (including a cross-claim or
|
||||
counterclaim in a lawsuit), then any patent licenses granted by that
|
||||
Contributor to such Recipient under this Agreement shall terminate as
|
||||
of the date such litigation is filed. In addition, if Recipient
|
||||
institutes patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Program
|
||||
itself (excluding combinations of the Program with other software or
|
||||
hardware) infringes such Recipient's patent(s), then such Recipient's
|
||||
rights granted under Section 2(b) shall terminate as of the date such
|
||||
litigation is filed.
|
||||
|
||||
All Recipient's rights under this Agreement shall terminate if it
|
||||
fails to comply with any of the material terms or conditions of this
|
||||
Agreement and does not cure such failure in a reasonable period of
|
||||
time after becoming aware of such noncompliance. If all Recipient's
|
||||
rights under this Agreement terminate, Recipient agrees to cease use
|
||||
and distribution of the Program as soon as reasonably practicable.
|
||||
However, Recipient's obligations under this Agreement and any licenses
|
||||
granted by Recipient relating to the Program shall continue and
|
||||
survive.
|
||||
|
||||
LUCENT may publish new versions (including revisions) of this
|
||||
Agreement from time to time. Each new version of the Agreement will be
|
||||
given a distinguishing version number. The Program (including
|
||||
Contributions) may always be distributed subject to the version of the
|
||||
Agreement under which it was received. In addition, after a new
|
||||
version of the Agreement is published, Contributor may elect to
|
||||
distribute the Program (including its Contributions) under the new
|
||||
version. No one other than LUCENT has the right to modify this
|
||||
Agreement. Except as expressly stated in Sections 2(a) and 2(b) above,
|
||||
Recipient receives no rights or licenses to the intellectual property
|
||||
of any Contributor under this Agreement, whether expressly, by
|
||||
implication, estoppel or otherwise. All rights in the Program not
|
||||
expressly granted under this Agreement are reserved.
|
||||
|
||||
This Agreement is governed by the laws of the State of New York and
|
||||
the intellectual property laws of the United States of America. No
|
||||
party to this Agreement will bring a legal action under this Agreement
|
||||
more than one year after the cause of action arose. Each party waives
|
||||
its rights to a jury trial in any resulting litigation.
|
||||
|
||||
7
src/libbio/Make.FreeBSD-386
Normal file
7
src/libbio/Make.FreeBSD-386
Normal file
@@ -0,0 +1,7 @@
|
||||
CC=gcc
|
||||
CFLAGS+=-Wall -Wno-missing-braces -Wno-parentheses -Wno-switch -O2 -g -c -I. -I$(PREFIX)/include
|
||||
O=o
|
||||
AR=ar
|
||||
ARFLAGS=rvc
|
||||
NAN=nan64.$O # default, can be overriden by Make.$(SYSNAME)
|
||||
NAN=nan64.$O
|
||||
6
src/libbio/Make.HP-UX-9000
Normal file
6
src/libbio/Make.HP-UX-9000
Normal file
@@ -0,0 +1,6 @@
|
||||
CC=cc
|
||||
CFLAGS=-O -c -Ae -I.
|
||||
O=o
|
||||
AR=ar
|
||||
ARFLAGS=rvc
|
||||
NAN=nan64.$O
|
||||
7
src/libbio/Make.Linux-386
Normal file
7
src/libbio/Make.Linux-386
Normal file
@@ -0,0 +1,7 @@
|
||||
CC=gcc
|
||||
CFLAGS+=-Wall -Wno-missing-braces -Wno-parentheses -Wno-switch -O2 -g -c -I.
|
||||
O=o
|
||||
AR=ar
|
||||
ARFLAGS=rvc
|
||||
NAN=nan64.$O # default, can be overriden by Make.$(SYSNAME)
|
||||
NAN=nan64.$O
|
||||
7
src/libbio/Make.NetBSD-386
Normal file
7
src/libbio/Make.NetBSD-386
Normal file
@@ -0,0 +1,7 @@
|
||||
CC=gcc
|
||||
CFLAGS+=-Wall -Wno-missing-braces -Wno-parentheses -Wno-switch -O2 -g -c -I. -I$(PREFIX)/include
|
||||
O=o
|
||||
AR=ar
|
||||
ARFLAGS=rvc
|
||||
NAN=nan64.$O # default, can be overriden by Make.$(SYSNAME)
|
||||
NAN=nan64.$O
|
||||
6
src/libbio/Make.OSF1-alpha
Normal file
6
src/libbio/Make.OSF1-alpha
Normal file
@@ -0,0 +1,6 @@
|
||||
CC=cc
|
||||
CFLAGS+=-g -c -I.
|
||||
O=o
|
||||
AR=ar
|
||||
ARFLAGS=rvc
|
||||
NAN=nan64.$O
|
||||
2
src/libbio/Make.SunOS-sun4u
Normal file
2
src/libbio/Make.SunOS-sun4u
Normal file
@@ -0,0 +1,2 @@
|
||||
include Make.SunOS-sun4u-$(CC)
|
||||
NAN=nan64.$O
|
||||
6
src/libbio/Make.SunOS-sun4u-cc
Normal file
6
src/libbio/Make.SunOS-sun4u-cc
Normal file
@@ -0,0 +1,6 @@
|
||||
CC=cc
|
||||
CFLAGS+=-g -c -I. -O
|
||||
O=o
|
||||
AR=ar
|
||||
ARFLAGS=rvc
|
||||
NAN=nan64.$O
|
||||
6
src/libbio/Make.SunOS-sun4u-gcc
Normal file
6
src/libbio/Make.SunOS-sun4u-gcc
Normal file
@@ -0,0 +1,6 @@
|
||||
CC=gcc
|
||||
CFLAGS+=-Wall -Wno-missing-braces -Wno-parentheses -Wno-switch -O2 -g -c
|
||||
O=o
|
||||
AR=ar
|
||||
ARFLAGS=rvc
|
||||
NAN=nan64.$O
|
||||
108
src/libbio/Makefile
Normal file
108
src/libbio/Makefile
Normal file
@@ -0,0 +1,108 @@
|
||||
|
||||
# this works in gnu make
|
||||
SYSNAME:=${shell uname}
|
||||
OBJTYPE:=${shell uname -m | sed 's;i.86;386;; s;/.*;;; s; ;;g'}
|
||||
|
||||
# this works in bsd make
|
||||
SYSNAME!=uname
|
||||
OBJTYPE!=uname -m | sed 's;i.86;386;; s;/.*;;; s; ;;g'
|
||||
|
||||
# the gnu rules will mess up bsd but not vice versa,
|
||||
# hence the gnu rules come first.
|
||||
|
||||
include Make.$(SYSNAME)-$(OBJTYPE)
|
||||
|
||||
PREFIX=/usr/local
|
||||
|
||||
NUKEFILES=
|
||||
|
||||
TGZFILES=
|
||||
|
||||
LIB=libbio.a
|
||||
VERSION=2.0
|
||||
PORTPLACE=devel/libbio
|
||||
NAME=libbio
|
||||
|
||||
OFILES=\
|
||||
bbuffered.$O\
|
||||
bfildes.$O\
|
||||
bflush.$O\
|
||||
bgetc.$O\
|
||||
bgetd.$O\
|
||||
binit.$O\
|
||||
boffset.$O\
|
||||
bprint.$O\
|
||||
bputc.$O\
|
||||
brdline.$O\
|
||||
brdstr.$O\
|
||||
bread.$O\
|
||||
bseek.$O\
|
||||
bwrite.$O\
|
||||
bgetrune.$O\
|
||||
bputrune.$O\
|
||||
|
||||
HFILES=\
|
||||
bio.h\
|
||||
|
||||
all: $(LIB)
|
||||
|
||||
install: $(LIB)
|
||||
test -d $(PREFIX)/man/man3 || mkdir $(PREFIX)/man/man3
|
||||
install -m 0644 bio.3 $(PREFIX)/man/man3/bio.3
|
||||
install -m 0644 bio.h $(PREFIX)/include
|
||||
install -m 0644 $(LIB) $(PREFIX)/lib/$(LIB)
|
||||
|
||||
bcat: bcat.$O $(LIB)
|
||||
$(CC) -o bcat bcat.$O $(LIB) -L/usr/local/lib -lfmt -lutf
|
||||
|
||||
$(LIB): $(OFILES)
|
||||
$(AR) $(ARFLAGS) $(LIB) $(OFILES)
|
||||
|
||||
NUKEFILES+=$(LIB)
|
||||
.c.$O:
|
||||
$(CC) $(CFLAGS) -I$(PREFIX)/include $*.c
|
||||
|
||||
%.$O: %.c
|
||||
$(CC) $(CFLAGS) -I$(PREFIX)/include $*.c
|
||||
|
||||
|
||||
$(OFILES): $(HFILES)
|
||||
|
||||
tgz:
|
||||
rm -rf $(NAME)-$(VERSION)
|
||||
mkdir $(NAME)-$(VERSION)
|
||||
cp Makefile Make.* README LICENSE NOTICE *.[ch137] rpm.spec bundle.ports $(TGZFILES) $(NAME)-$(VERSION)
|
||||
tar cf - $(NAME)-$(VERSION) | gzip >$(NAME)-$(VERSION).tgz
|
||||
rm -rf $(NAME)-$(VERSION)
|
||||
|
||||
clean:
|
||||
rm -f $(OFILES) $(LIB)
|
||||
|
||||
nuke:
|
||||
rm -f $(OFILES) *.tgz *.rpm $(NUKEFILES)
|
||||
|
||||
rpm:
|
||||
make tgz
|
||||
cp $(NAME)-$(VERSION).tgz /usr/src/RPM/SOURCES
|
||||
rpm -ba rpm.spec
|
||||
cp /usr/src/RPM/SRPMS/$(NAME)-$(VERSION)-1.src.rpm .
|
||||
cp /usr/src/RPM/RPMS/i586/$(NAME)-$(VERSION)-1.i586.rpm .
|
||||
scp *.rpm rsc@amsterdam.lcs.mit.edu:public_html/software
|
||||
|
||||
PORTDIR=/usr/ports/$(PORTPLACE)
|
||||
|
||||
ports:
|
||||
make tgz
|
||||
rm -rf $(PORTDIR)
|
||||
mkdir $(PORTDIR)
|
||||
cp $(NAME)-$(VERSION).tgz /usr/ports/distfiles
|
||||
cat bundle.ports | (cd $(PORTDIR) && awk '$$1=="---" && $$3=="---" { ofile=$$2; next} {if(ofile) print >ofile}')
|
||||
(cd $(PORTDIR); make makesum)
|
||||
(cd $(PORTDIR); make)
|
||||
(cd $(PORTDIR); /usr/local/bin/portlint)
|
||||
rm -rf $(PORTDIR)/work
|
||||
shar `find $(PORTDIR)` > ports.shar
|
||||
(cd $(PORTDIR); tar cf - *) | gzip >$(NAME)-$(VERSION)-ports.tgz
|
||||
scp *.tgz rsc@amsterdam.lcs.mit.edu:public_html/software
|
||||
|
||||
.phony: all clean nuke install tgz rpm ports
|
||||
37
src/libbio/Makefile.MID
Normal file
37
src/libbio/Makefile.MID
Normal file
@@ -0,0 +1,37 @@
|
||||
LIB=libbio.a
|
||||
VERSION=2.0
|
||||
PORTPLACE=devel/libbio
|
||||
NAME=libbio
|
||||
|
||||
OFILES=\
|
||||
bbuffered.$O\
|
||||
bfildes.$O\
|
||||
bflush.$O\
|
||||
bgetc.$O\
|
||||
bgetd.$O\
|
||||
binit.$O\
|
||||
boffset.$O\
|
||||
bprint.$O\
|
||||
bputc.$O\
|
||||
brdline.$O\
|
||||
brdstr.$O\
|
||||
bread.$O\
|
||||
bseek.$O\
|
||||
bwrite.$O\
|
||||
bgetrune.$O\
|
||||
bputrune.$O\
|
||||
|
||||
HFILES=\
|
||||
bio.h\
|
||||
|
||||
all: $(LIB)
|
||||
|
||||
install: $(LIB)
|
||||
test -d $(PREFIX)/man/man3 || mkdir $(PREFIX)/man/man3
|
||||
install -m 0644 bio.3 $(PREFIX)/man/man3/bio.3
|
||||
install -m 0644 bio.h $(PREFIX)/include
|
||||
install -m 0644 $(LIB) $(PREFIX)/lib/$(LIB)
|
||||
|
||||
bcat: bcat.$O $(LIB)
|
||||
$(CC) -o bcat bcat.$O $(LIB) -L/usr/local/lib -lfmt -lutf
|
||||
|
||||
27
src/libbio/NOTICE
Normal file
27
src/libbio/NOTICE
Normal file
@@ -0,0 +1,27 @@
|
||||
Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
|
||||
Portions Copyright © 1995-1997 C H Forsyth (forsyth@caldo.demon.co.uk). All rights reserved.
|
||||
Portions Copyright © 1997-1999 Vita Nuova Limited. All rights reserved.
|
||||
Portions Copyright © 2000-2002 Vita Nuova Holdings Limited (www.vitanuova.com). All rights reserved.
|
||||
|
||||
Under a licence agreement with Lucent Technologies Inc. effective 1st March 2000,
|
||||
Vita Nuova Holdings Limited has the right to determine (within a specified scope)
|
||||
the form and content of sublicences for this software.
|
||||
|
||||
Vita Nuova Holdings Limited now makes this software available as Free
|
||||
Software under the terms of the `GNU General Public LIcense, Version 2'
|
||||
(see the file LICENCE or http://www.fsf.org/copyleft/gpl.html for
|
||||
the full terms and conditions). One of the conditions of that licence
|
||||
is that you must keep intact all notices that refer to that licence and to the absence of
|
||||
of any warranty: for this software, note that includes this NOTICE file in particular.
|
||||
|
||||
This suite of programs is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
`GNU General Public License' for more details.
|
||||
|
||||
This copyright NOTICE applies to all files in this directory and
|
||||
subdirectories, unless another copyright notice appears in a given
|
||||
file or subdirectory. If you take code from this software to use in
|
||||
other programs, you must somehow include with it an appropriate
|
||||
copyright notice that includes the copyright notice and the other
|
||||
notices above.
|
||||
7
src/libbio/README
Normal file
7
src/libbio/README
Normal file
@@ -0,0 +1,7 @@
|
||||
This is a Unix port of the Plan 9 buffered I/O library,
|
||||
originally done for the Inferno operating system.
|
||||
|
||||
Russ Cox repackaged this to build as a standalone
|
||||
Unix library. Send comments about packaging to
|
||||
Russ Cox <rsc@post.harvard.edu>
|
||||
|
||||
20
src/libbio/bbuffered.c
Normal file
20
src/libbio/bbuffered.c
Normal file
@@ -0,0 +1,20 @@
|
||||
#include "lib9.h"
|
||||
#include <bio.h>
|
||||
|
||||
int
|
||||
Bbuffered(Biobuf *bp)
|
||||
{
|
||||
switch(bp->state) {
|
||||
case Bracteof:
|
||||
case Bractive:
|
||||
return -bp->icount;
|
||||
|
||||
case Bwactive:
|
||||
return bp->bsize + bp->ocount;
|
||||
|
||||
case Binactive:
|
||||
return 0;
|
||||
}
|
||||
fprint(2, "Bbuffered: unknown state %d\n", bp->state);
|
||||
return 0;
|
||||
}
|
||||
42
src/libbio/bcat.c
Normal file
42
src/libbio/bcat.c
Normal file
@@ -0,0 +1,42 @@
|
||||
#include <fmt.h>
|
||||
#include "bio.h"
|
||||
|
||||
Biobuf bout;
|
||||
|
||||
void
|
||||
bcat(Biobuf *b, char *name)
|
||||
{
|
||||
char buf[1000];
|
||||
int n;
|
||||
|
||||
while((n = Bread(b, buf, sizeof buf)) > 0){
|
||||
if(Bwrite(&bout, buf, n) < 0)
|
||||
fprint(2, "writing during %s: %r\n", name);
|
||||
}
|
||||
if(n < 0)
|
||||
fprint(2, "reading %s: %r\n", name);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
Biobuf b, *bp;
|
||||
|
||||
Binit(&bout, 1, O_WRONLY);
|
||||
|
||||
if(argc == 1){
|
||||
Binit(&b, 0, O_RDONLY);
|
||||
bcat(&b, "<stdin>");
|
||||
}else{
|
||||
for(i=1; i<argc; i++){
|
||||
if((bp = Bopen(argv[i], O_RDONLY)) == 0){
|
||||
fprint(2, "Bopen %s: %r\n", argv[i]);
|
||||
continue;
|
||||
}
|
||||
bcat(bp, argv[i]);
|
||||
Bterm(bp);
|
||||
}
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
9
src/libbio/bfildes.c
Normal file
9
src/libbio/bfildes.c
Normal file
@@ -0,0 +1,9 @@
|
||||
#include "lib9.h"
|
||||
#include <bio.h>
|
||||
|
||||
int
|
||||
Bfildes(Biobuf *bp)
|
||||
{
|
||||
|
||||
return bp->fid;
|
||||
}
|
||||
33
src/libbio/bflush.c
Normal file
33
src/libbio/bflush.c
Normal file
@@ -0,0 +1,33 @@
|
||||
#include "lib9.h"
|
||||
#include <bio.h>
|
||||
|
||||
int
|
||||
Bflush(Biobuf *bp)
|
||||
{
|
||||
int n, c;
|
||||
|
||||
switch(bp->state) {
|
||||
case Bwactive:
|
||||
n = bp->bsize+bp->ocount;
|
||||
if(n == 0)
|
||||
return 0;
|
||||
c = write(bp->fid, bp->bbuf, n);
|
||||
if(n == c) {
|
||||
bp->offset += n;
|
||||
bp->ocount = -bp->bsize;
|
||||
return 0;
|
||||
}
|
||||
bp->state = Binactive;
|
||||
bp->ocount = 0;
|
||||
break;
|
||||
|
||||
case Bracteof:
|
||||
bp->state = Bractive;
|
||||
|
||||
case Bractive:
|
||||
bp->icount = 0;
|
||||
bp->gbuf = bp->ebuf;
|
||||
return 0;
|
||||
}
|
||||
return Beof;
|
||||
}
|
||||
52
src/libbio/bgetc.c
Normal file
52
src/libbio/bgetc.c
Normal file
@@ -0,0 +1,52 @@
|
||||
#include "lib9.h"
|
||||
#include <bio.h>
|
||||
|
||||
int
|
||||
Bgetc(Biobuf *bp)
|
||||
{
|
||||
int i;
|
||||
|
||||
loop:
|
||||
i = bp->icount;
|
||||
if(i != 0) {
|
||||
bp->icount = i+1;
|
||||
return bp->ebuf[i];
|
||||
}
|
||||
if(bp->state != Bractive) {
|
||||
if(bp->state == Bracteof)
|
||||
bp->state = Bractive;
|
||||
return Beof;
|
||||
}
|
||||
/*
|
||||
* get next buffer, try to keep Bungetsize
|
||||
* characters pre-catenated from the previous
|
||||
* buffer to allow that many ungets.
|
||||
*/
|
||||
memmove(bp->bbuf-Bungetsize, bp->ebuf-Bungetsize, Bungetsize);
|
||||
i = read(bp->fid, bp->bbuf, bp->bsize);
|
||||
bp->gbuf = bp->bbuf;
|
||||
if(i <= 0) {
|
||||
if(i < 0)
|
||||
bp->state = Binactive;
|
||||
return Beof;
|
||||
}
|
||||
if(i < bp->bsize) {
|
||||
memmove(bp->ebuf-i-Bungetsize, bp->bbuf-Bungetsize, i+Bungetsize);
|
||||
bp->gbuf = bp->ebuf-i;
|
||||
}
|
||||
bp->icount = -i;
|
||||
bp->offset += i;
|
||||
goto loop;
|
||||
}
|
||||
|
||||
int
|
||||
Bungetc(Biobuf *bp)
|
||||
{
|
||||
|
||||
if(bp->state == Bracteof)
|
||||
bp->state = Bractive;
|
||||
if(bp->state != Bractive)
|
||||
return Beof;
|
||||
bp->icount--;
|
||||
return 1;
|
||||
}
|
||||
36
src/libbio/bgetd.c
Normal file
36
src/libbio/bgetd.c
Normal file
@@ -0,0 +1,36 @@
|
||||
#include "lib9.h"
|
||||
#include <bio.h>
|
||||
|
||||
struct bgetd
|
||||
{
|
||||
Biobuf* b;
|
||||
int eof;
|
||||
};
|
||||
|
||||
static int
|
||||
Bgetdf(void *vp)
|
||||
{
|
||||
int c;
|
||||
struct bgetd *bg = vp;
|
||||
|
||||
c = Bgetc(bg->b);
|
||||
if(c == Beof)
|
||||
bg->eof = 1;
|
||||
return c;
|
||||
}
|
||||
|
||||
int
|
||||
Bgetd(Biobuf *bp, double *dp)
|
||||
{
|
||||
double d;
|
||||
struct bgetd b;
|
||||
|
||||
b.b = bp;
|
||||
b.eof = 0;
|
||||
d = fmtcharstod(Bgetdf, &b);
|
||||
if(b.eof)
|
||||
return -1;
|
||||
Bungetc(bp);
|
||||
*dp = d;
|
||||
return 1;
|
||||
}
|
||||
47
src/libbio/bgetrune.c
Normal file
47
src/libbio/bgetrune.c
Normal file
@@ -0,0 +1,47 @@
|
||||
#include "lib9.h"
|
||||
#include <bio.h>
|
||||
#include <utf.h>
|
||||
|
||||
long
|
||||
Bgetrune(Biobuf *bp)
|
||||
{
|
||||
int c, i;
|
||||
Rune rune;
|
||||
char str[4];
|
||||
|
||||
c = Bgetc(bp);
|
||||
if(c < Runeself) { /* one char */
|
||||
bp->runesize = 1;
|
||||
return c;
|
||||
}
|
||||
str[0] = c;
|
||||
|
||||
for(i=1;;) {
|
||||
c = Bgetc(bp);
|
||||
if(c < 0)
|
||||
return c;
|
||||
str[i++] = c;
|
||||
|
||||
if(fullrune(str, i)) {
|
||||
bp->runesize = chartorune(&rune, str);
|
||||
while(i > bp->runesize) {
|
||||
Bungetc(bp);
|
||||
i--;
|
||||
}
|
||||
return rune;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
Bungetrune(Biobuf *bp)
|
||||
{
|
||||
|
||||
if(bp->state == Bracteof)
|
||||
bp->state = Bractive;
|
||||
if(bp->state != Bractive)
|
||||
return Beof;
|
||||
bp->icount -= bp->runesize;
|
||||
bp->runesize = 0;
|
||||
return 1;
|
||||
}
|
||||
142
src/libbio/binit.c
Normal file
142
src/libbio/binit.c
Normal file
@@ -0,0 +1,142 @@
|
||||
#include "lib9.h"
|
||||
#include <bio.h>
|
||||
|
||||
enum
|
||||
{
|
||||
MAXBUFS = 20
|
||||
};
|
||||
|
||||
static Biobuf* wbufs[MAXBUFS];
|
||||
static int atexitflag;
|
||||
|
||||
static
|
||||
void
|
||||
batexit(void)
|
||||
{
|
||||
Biobuf *bp;
|
||||
int i;
|
||||
|
||||
for(i=0; i<MAXBUFS; i++) {
|
||||
bp = wbufs[i];
|
||||
if(bp != 0) {
|
||||
wbufs[i] = 0;
|
||||
Bflush(bp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
deinstall(Biobuf *bp)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i=0; i<MAXBUFS; i++)
|
||||
if(wbufs[i] == bp)
|
||||
wbufs[i] = 0;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
install(Biobuf *bp)
|
||||
{
|
||||
int i;
|
||||
|
||||
deinstall(bp);
|
||||
for(i=0; i<MAXBUFS; i++)
|
||||
if(wbufs[i] == 0) {
|
||||
wbufs[i] = bp;
|
||||
break;
|
||||
}
|
||||
if(atexitflag == 0) {
|
||||
atexitflag = 1;
|
||||
atexit(batexit);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
Binits(Biobuf *bp, int f, int mode, unsigned char *p, int size)
|
||||
{
|
||||
|
||||
p += Bungetsize; /* make room for Bungets */
|
||||
size -= Bungetsize;
|
||||
|
||||
switch(mode) {
|
||||
default:
|
||||
fprint(2, "Bopen: unknown mode %d\n", mode);
|
||||
return Beof;
|
||||
|
||||
case OREAD:
|
||||
bp->state = Bractive;
|
||||
bp->ocount = 0;
|
||||
break;
|
||||
|
||||
case OWRITE:
|
||||
install(bp);
|
||||
bp->state = Bwactive;
|
||||
bp->ocount = -size;
|
||||
break;
|
||||
}
|
||||
bp->bbuf = p;
|
||||
bp->ebuf = p+size;
|
||||
bp->bsize = size;
|
||||
bp->icount = 0;
|
||||
bp->gbuf = bp->ebuf;
|
||||
bp->fid = f;
|
||||
bp->flag = 0;
|
||||
bp->rdline = 0;
|
||||
bp->offset = 0;
|
||||
/* bp->runesize = 0; */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
Binit(Biobuf *bp, int f, int mode)
|
||||
{
|
||||
return Binits(bp, f, mode, bp->b, sizeof(bp->b));
|
||||
}
|
||||
|
||||
Biobuf*
|
||||
Bopen(char *name, int mode)
|
||||
{
|
||||
Biobuf *bp;
|
||||
int f;
|
||||
|
||||
switch(mode) {
|
||||
default:
|
||||
fprint(2, "Bopen: unknown mode %d\n", mode);
|
||||
return 0;
|
||||
|
||||
case OREAD:
|
||||
f = open(name, OREAD);
|
||||
if(f < 0)
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case OWRITE:
|
||||
f = creat(name, 0666);
|
||||
if(f < 0)
|
||||
return 0;
|
||||
}
|
||||
bp = malloc(sizeof(Biobuf));
|
||||
if(bp == 0)
|
||||
return 0;
|
||||
Binits(bp, f, mode, bp->b, sizeof(bp->b));
|
||||
bp->flag = Bmagic;
|
||||
return bp;
|
||||
}
|
||||
|
||||
int
|
||||
Bterm(Biobuf *bp)
|
||||
{
|
||||
|
||||
deinstall(bp);
|
||||
Bflush(bp);
|
||||
if(bp->flag == Bmagic) {
|
||||
bp->flag = 0;
|
||||
close(bp->fid);
|
||||
free(bp);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
336
src/libbio/bio.3
Normal file
336
src/libbio/bio.3
Normal file
@@ -0,0 +1,336 @@
|
||||
.TH BIO 3
|
||||
.SH NAME
|
||||
Bopen, Binit, Binits, Brdline, Brdstr, Bgetc, Bgetd, Bungetc, Bread, Bseek, Boffset, Bfildes, Blinelen, Bputc, Bprint, Bvprint, Bwrite, Bflush, Bterm, Bbuffered \- buffered input/output
|
||||
.SH SYNOPSIS
|
||||
.ta \w'Biobuf* 'u
|
||||
.B #include <fmt.h>
|
||||
.B #include <bio.h>
|
||||
.PP
|
||||
.B
|
||||
Biobuf* Bopen(char *file, int mode)
|
||||
.PP
|
||||
.B
|
||||
int Binit(Biobuf *bp, int fd, int mode)
|
||||
.PP
|
||||
.B
|
||||
int Bterm(Biobuf *bp)
|
||||
.PP
|
||||
.B
|
||||
int Bprint(Biobuf *bp, char *format, ...)
|
||||
.PP
|
||||
.B
|
||||
int Bvprint(Biobuf *bp, char *format, va_list arglist);
|
||||
.PP
|
||||
.B
|
||||
void* Brdline(Biobuf *bp, int delim)
|
||||
.PP
|
||||
.B
|
||||
char* Brdstr(Biobuf *bp, int delim, int nulldelim)
|
||||
.PP
|
||||
.B
|
||||
int Blinelen(Biobuf *bp)
|
||||
.PP
|
||||
.B
|
||||
off_t Boffset(Biobuf *bp)
|
||||
.PP
|
||||
.B
|
||||
int Bfildes(Biobuf *bp)
|
||||
.PP
|
||||
.B
|
||||
int Bgetc(Biobuf *bp)
|
||||
.PP
|
||||
.B
|
||||
long Bgetrune(Biobufhdr *bp)
|
||||
.PP
|
||||
.B
|
||||
int Bgetd(Biobuf *bp, double *d)
|
||||
.PP
|
||||
.B
|
||||
int Bungetc(Biobuf *bp)
|
||||
.PP
|
||||
.B
|
||||
int Bungetrune(Biobufhdr *bp)
|
||||
.PP
|
||||
.B
|
||||
off_t Bseek(Biobuf *bp, off_t n, int type)
|
||||
.PP
|
||||
.B
|
||||
int Bputc(Biobuf *bp, int c)
|
||||
.PP
|
||||
.B
|
||||
int Bputrune(Biobufhdr *bp, long c)
|
||||
.PP
|
||||
.B
|
||||
long Bread(Biobuf *bp, void *addr, long nbytes)
|
||||
.PP
|
||||
.B
|
||||
long Bwrite(Biobuf *bp, void *addr, long nbytes)
|
||||
.PP
|
||||
.B
|
||||
int Bflush(Biobuf *bp)
|
||||
.PP
|
||||
.B
|
||||
int Bbuffered(Biobuf *bp)
|
||||
.PP
|
||||
.SH DESCRIPTION
|
||||
These routines implement fast buffered I/O.
|
||||
I/O on different file descriptors is independent.
|
||||
.PP
|
||||
.I Bopen
|
||||
opens
|
||||
.I file
|
||||
for mode
|
||||
.B O_RDONLY
|
||||
or creates for mode
|
||||
.BR O_WRONLY .
|
||||
It calls
|
||||
.IR malloc (3)
|
||||
to allocate a buffer.
|
||||
.PP
|
||||
.I Binit
|
||||
initializes a buffer
|
||||
with the open file descriptor passed in
|
||||
by the user.
|
||||
.PP
|
||||
Arguments
|
||||
of types pointer to Biobuf and pointer to Biobuf
|
||||
can be used interchangeably in the following routines.
|
||||
.PP
|
||||
.IR Bopen ,
|
||||
.IR Binit ,
|
||||
or
|
||||
.I Binits
|
||||
should be called before any of the
|
||||
other routines on that buffer.
|
||||
.I Bfildes
|
||||
returns the integer file descriptor of the associated open file.
|
||||
.PP
|
||||
.I Bterm
|
||||
flushes the buffer for
|
||||
.IR bp .
|
||||
If the buffer was allocated by
|
||||
.IR Bopen ,
|
||||
the buffer is
|
||||
.I freed
|
||||
and the file is closed.
|
||||
.PP
|
||||
.I Brdline
|
||||
reads a string from the file associated with
|
||||
.I bp
|
||||
up to and including the first
|
||||
.I delim
|
||||
character.
|
||||
The delimiter character at the end of the line is
|
||||
not altered.
|
||||
.I Brdline
|
||||
returns a pointer to the start of the line or
|
||||
.L 0
|
||||
on end-of-file or read error.
|
||||
.I Blinelen
|
||||
returns the length (including the delimiter)
|
||||
of the most recent string returned by
|
||||
.IR Brdline .
|
||||
.PP
|
||||
.I Brdstr
|
||||
returns a
|
||||
.IR malloc (3)-allocated
|
||||
buffer containing the next line of input delimited by
|
||||
.IR delim ,
|
||||
terminated by a NUL (0) byte.
|
||||
Unlike
|
||||
.IR Brdline ,
|
||||
which returns when its buffer is full even if no delimiter has been found,
|
||||
.I Brdstr
|
||||
will return an arbitrarily long line in a single call.
|
||||
If
|
||||
.I nulldelim
|
||||
is set, the terminal delimiter will be overwritten with a NUL.
|
||||
After a successful call to
|
||||
.IR Brdstr ,
|
||||
the return value of
|
||||
.I Blinelen
|
||||
will be the length of the returned buffer, excluding the NUL.
|
||||
.PP
|
||||
.I Bgetc
|
||||
returns the next byte from
|
||||
.IR bp ,
|
||||
or a negative value
|
||||
at end of file.
|
||||
.I Bungetc
|
||||
may be called immediately after
|
||||
.I Bgetc
|
||||
to allow the same byte to be reread.
|
||||
.PP
|
||||
.I Bgetrune
|
||||
calls
|
||||
.I Bgetc
|
||||
to read the bytes of the next
|
||||
.SM UTF
|
||||
sequence in the input stream and returns the value of the rune
|
||||
represented by the sequence.
|
||||
It returns a negative value
|
||||
at end of file.
|
||||
.I Bungetrune
|
||||
may be called immediately after
|
||||
.I Bgetrune
|
||||
to allow the same
|
||||
.SM UTF
|
||||
sequence to be reread as either bytes or a rune.
|
||||
.I Bungetc
|
||||
and
|
||||
.I Bungetrune
|
||||
may back up a maximum of five bytes.
|
||||
.PP
|
||||
.I Bgetd
|
||||
uses
|
||||
.I fmtcharstod
|
||||
(undocumented)
|
||||
and
|
||||
.I Bgetc
|
||||
to read the formatted
|
||||
floating-point number in the input stream,
|
||||
skipping initial blanks and tabs.
|
||||
The value is stored in
|
||||
.BR *d.
|
||||
.PP
|
||||
.I Bread
|
||||
reads
|
||||
.I nbytes
|
||||
of data from
|
||||
.I bp
|
||||
into memory starting at
|
||||
.IR addr .
|
||||
The number of bytes read is returned on success
|
||||
and a negative value is returned if a read error occurred.
|
||||
.PP
|
||||
.I Bseek
|
||||
applies
|
||||
.IR lseek (2)
|
||||
to
|
||||
.IR bp .
|
||||
It returns the new file offset.
|
||||
.I Boffset
|
||||
returns the file offset of the next character to be processed.
|
||||
.PP
|
||||
.I Bputc
|
||||
outputs the low order 8 bits of
|
||||
.I c
|
||||
on
|
||||
.IR bp .
|
||||
If this causes a
|
||||
.IR write
|
||||
to occur and there is an error,
|
||||
a negative value is returned.
|
||||
Otherwise, a zero is returned.
|
||||
.PP
|
||||
.I Bputrune
|
||||
calls
|
||||
.I Bputc
|
||||
to output the low order
|
||||
16 bits of
|
||||
.I c
|
||||
as a rune
|
||||
in
|
||||
.SM UTF
|
||||
format
|
||||
on the output stream.
|
||||
.PP
|
||||
.I Bprint
|
||||
is a buffered interface to
|
||||
.IR print (2).
|
||||
If this causes a
|
||||
.IR write
|
||||
to occur and there is an error,
|
||||
a negative value
|
||||
.RB ( Beof )
|
||||
is returned.
|
||||
Otherwise, the number of bytes output is returned.
|
||||
.I Bvprint
|
||||
does the same except it takes as argument a
|
||||
.B va_list
|
||||
parameter, so it can be called within a variadic function.
|
||||
.PP
|
||||
.I Bwrite
|
||||
outputs
|
||||
.I nbytes
|
||||
of data starting at
|
||||
.I addr
|
||||
to
|
||||
.IR bp .
|
||||
If this causes a
|
||||
.IR write
|
||||
to occur and there is an error,
|
||||
a negative value is returned.
|
||||
Otherwise, the number of bytes written is returned.
|
||||
.PP
|
||||
.I Bflush
|
||||
causes any buffered output associated with
|
||||
.I bp
|
||||
to be written.
|
||||
The return is as for
|
||||
.IR Bputc .
|
||||
.I Bflush
|
||||
is called on
|
||||
exit for every buffer still open
|
||||
for writing.
|
||||
.PP
|
||||
.I Bbuffered
|
||||
returns the number of bytes in the buffer.
|
||||
When reading, this is the number of bytes still available from the last
|
||||
read on the file; when writing, it is the number of bytes ready to be
|
||||
written.
|
||||
.PP
|
||||
This library uses
|
||||
.IR fmt (3)
|
||||
for diagnostic messages about internal errors,
|
||||
as well as for the implementation of
|
||||
.I Bprint
|
||||
and
|
||||
.IR Bvprint .
|
||||
It uses
|
||||
.IR utf (3)
|
||||
for the implementation of
|
||||
.I Bgetrune
|
||||
and
|
||||
.IR Bputrune .
|
||||
.SH SEE ALSO
|
||||
.IR atexit (3).
|
||||
.IR open (2),
|
||||
.IR print (3),
|
||||
.IR utf (7)
|
||||
.SH DIAGNOSTICS
|
||||
.I Bio
|
||||
routines that return integers yield
|
||||
.B Beof
|
||||
if
|
||||
.I bp
|
||||
is not the descriptor of an open file.
|
||||
.I Bopen
|
||||
returns zero if the file cannot be opened in the given mode.
|
||||
.SH HISTORY
|
||||
The
|
||||
.IR bio (3)
|
||||
library originally appeared in Plan 9.
|
||||
This is a port of the Plan 9 bio library.
|
||||
.SH BUGS
|
||||
.I Brdline
|
||||
returns an error on strings longer than the buffer associated
|
||||
with the file
|
||||
and also if the end-of-file is encountered
|
||||
before a delimiter.
|
||||
.I Blinelen
|
||||
will tell how many characters are available
|
||||
in these cases.
|
||||
In the case of a true end-of-file,
|
||||
.I Blinelen
|
||||
will return zero.
|
||||
At the cost of allocating a buffer,
|
||||
.I Brdstr
|
||||
sidesteps these issues.
|
||||
.PP
|
||||
The data returned by
|
||||
.I Brdline
|
||||
may be overwritten by calls to any other
|
||||
.I bio
|
||||
routine on the same
|
||||
.IR bp.
|
||||
79
src/libbio/bio.h
Normal file
79
src/libbio/bio.h
Normal file
@@ -0,0 +1,79 @@
|
||||
#ifndef _BIOH_
|
||||
#define _BIOH_ 1
|
||||
|
||||
#include <sys/types.h> /* for off_t */
|
||||
#include <fcntl.h> /* for O_RDONLY, O_WRONLY */
|
||||
|
||||
typedef struct Biobuf Biobuf;
|
||||
|
||||
enum
|
||||
{
|
||||
Bsize = 8*1024,
|
||||
Bungetsize = 4, /* space for ungetc */
|
||||
Bmagic = 0x314159,
|
||||
Beof = -1,
|
||||
Bbad = -2,
|
||||
|
||||
Binactive = 0, /* states */
|
||||
Bractive,
|
||||
Bwactive,
|
||||
Bracteof,
|
||||
|
||||
Bend
|
||||
};
|
||||
|
||||
struct Biobuf
|
||||
{
|
||||
int icount; /* neg num of bytes at eob */
|
||||
int ocount; /* num of bytes at bob */
|
||||
int rdline; /* num of bytes after rdline */
|
||||
int runesize; /* num of bytes of last getrune */
|
||||
int state; /* r/w/inactive */
|
||||
int fid; /* open file */
|
||||
int flag; /* magic if malloc'ed */
|
||||
off_t offset; /* offset of buffer in file */
|
||||
int bsize; /* size of buffer */
|
||||
unsigned char* bbuf; /* pointer to beginning of buffer */
|
||||
unsigned char* ebuf; /* pointer to end of buffer */
|
||||
unsigned char* gbuf; /* pointer to good data in buf */
|
||||
unsigned char b[Bungetsize+Bsize];
|
||||
};
|
||||
|
||||
#define BGETC(bp)\
|
||||
((bp)->icount?(bp)->bbuf[(bp)->bsize+(bp)->icount++]:Bgetc((bp)))
|
||||
#define BPUTC(bp,c)\
|
||||
((bp)->ocount?(bp)->bbuf[(bp)->bsize+(bp)->ocount++]=(c),0:Bputc((bp),(c)))
|
||||
#define BOFFSET(bp)\
|
||||
(((bp)->state==Bractive)?\
|
||||
(bp)->offset + (bp)->icount:\
|
||||
(((bp)->state==Bwactive)?\
|
||||
(bp)->offset + ((bp)->bsize + (bp)->ocount):\
|
||||
-1))
|
||||
#define BLINELEN(bp)\
|
||||
(bp)->rdline
|
||||
#define BFILDES(bp)\
|
||||
(bp)->fid
|
||||
|
||||
int Bbuffered(Biobuf*);
|
||||
int Bfildes(Biobuf*);
|
||||
int Bflush(Biobuf*);
|
||||
int Bgetc(Biobuf*);
|
||||
int Bgetd(Biobuf*, double*);
|
||||
int Binit(Biobuf*, int, int);
|
||||
int Binits(Biobuf*, int, int, unsigned char*, int);
|
||||
int Blinelen(Biobuf*);
|
||||
off_t Boffset(Biobuf*);
|
||||
Biobuf* Bopen(char*, int);
|
||||
int Bprint(Biobuf*, char*, ...);
|
||||
int Bputc(Biobuf*, int);
|
||||
void* Brdline(Biobuf*, int);
|
||||
long Bread(Biobuf*, void*, long);
|
||||
off_t Bseek(Biobuf*, off_t, int);
|
||||
int Bterm(Biobuf*);
|
||||
int Bungetc(Biobuf*);
|
||||
long Bwrite(Biobuf*, void*, long);
|
||||
char* Brdstr(Biobuf*, int, int);
|
||||
long Bgetrune(Biobuf*);
|
||||
int Bputrune(Biobuf*, long);
|
||||
|
||||
#endif
|
||||
25
src/libbio/boffset.c
Normal file
25
src/libbio/boffset.c
Normal file
@@ -0,0 +1,25 @@
|
||||
#include "lib9.h"
|
||||
#include <bio.h>
|
||||
|
||||
off_t
|
||||
Boffset(Biobuf *bp)
|
||||
{
|
||||
off_t n;
|
||||
|
||||
switch(bp->state) {
|
||||
default:
|
||||
fprint(2, "Boffset: unknown state %d\n", bp->state);
|
||||
n = Beof;
|
||||
break;
|
||||
|
||||
case Bracteof:
|
||||
case Bractive:
|
||||
n = bp->offset + bp->icount;
|
||||
break;
|
||||
|
||||
case Bwactive:
|
||||
n = bp->offset + (bp->bsize + bp->ocount);
|
||||
break;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
28
src/libbio/bprint.c
Normal file
28
src/libbio/bprint.c
Normal file
@@ -0,0 +1,28 @@
|
||||
#include "lib9.h"
|
||||
#include <bio.h>
|
||||
|
||||
int
|
||||
Bprint(Biobuf *bp, char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char *ip, *ep, *out;
|
||||
int n;
|
||||
|
||||
ep = (char*)bp->ebuf;
|
||||
ip = ep + bp->ocount;
|
||||
va_start(ap, fmt);
|
||||
out = vseprint(ip, ep, fmt, ap);
|
||||
va_end(ap);
|
||||
if(out == 0 || out >= ep-5) {
|
||||
Bflush(bp);
|
||||
ip = ep + bp->ocount;
|
||||
va_start(ap, fmt);
|
||||
out = vseprint(ip, ep, fmt, ap);
|
||||
va_end(ap);
|
||||
if(out >= ep-5)
|
||||
return Beof;
|
||||
}
|
||||
n = out-ip;
|
||||
bp->ocount += n;
|
||||
return n;
|
||||
}
|
||||
29
src/libbio/bputc.c
Normal file
29
src/libbio/bputc.c
Normal file
@@ -0,0 +1,29 @@
|
||||
#include "lib9.h"
|
||||
#include <bio.h>
|
||||
|
||||
int
|
||||
Bputc(Biobuf *bp, int c)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
loop:
|
||||
i = bp->ocount;
|
||||
j = i+1;
|
||||
if(i != 0) {
|
||||
bp->ocount = j;
|
||||
bp->ebuf[i] = c;
|
||||
return 0;
|
||||
}
|
||||
if(bp->state != Bwactive)
|
||||
return Beof;
|
||||
j = write(bp->fid, bp->bbuf, bp->bsize);
|
||||
if(j == bp->bsize) {
|
||||
bp->ocount = -bp->bsize;
|
||||
bp->offset += j;
|
||||
goto loop;
|
||||
}
|
||||
fprint(2, "Bputc: write error\n");
|
||||
bp->state = Binactive;
|
||||
bp->ocount = 0;
|
||||
return Beof;
|
||||
}
|
||||
23
src/libbio/bputrune.c
Normal file
23
src/libbio/bputrune.c
Normal file
@@ -0,0 +1,23 @@
|
||||
#include "lib9.h"
|
||||
#include <bio.h>
|
||||
#include <utf.h>
|
||||
|
||||
int
|
||||
Bputrune(Biobuf *bp, long c)
|
||||
{
|
||||
Rune rune;
|
||||
char str[4];
|
||||
int n;
|
||||
|
||||
rune = c;
|
||||
if(rune < Runeself) {
|
||||
Bputc(bp, rune);
|
||||
return 1;
|
||||
}
|
||||
n = runetochar(str, &rune);
|
||||
if(n == 0)
|
||||
return Bbad;
|
||||
if(Bwrite(bp, str, n) != n)
|
||||
return Beof;
|
||||
return n;
|
||||
}
|
||||
94
src/libbio/brdline.c
Normal file
94
src/libbio/brdline.c
Normal file
@@ -0,0 +1,94 @@
|
||||
#include "lib9.h"
|
||||
#include <bio.h>
|
||||
|
||||
void*
|
||||
Brdline(Biobuf *bp, int delim)
|
||||
{
|
||||
char *ip, *ep;
|
||||
int i, j;
|
||||
|
||||
i = -bp->icount;
|
||||
if(i == 0) {
|
||||
/*
|
||||
* eof or other error
|
||||
*/
|
||||
if(bp->state != Bractive) {
|
||||
if(bp->state == Bracteof)
|
||||
bp->state = Bractive;
|
||||
bp->rdline = 0;
|
||||
bp->gbuf = bp->ebuf;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* first try in remainder of buffer (gbuf doesn't change)
|
||||
*/
|
||||
ip = (char*)bp->ebuf - i;
|
||||
ep = memchr(ip, delim, i);
|
||||
if(ep) {
|
||||
j = (ep - ip) + 1;
|
||||
bp->rdline = j;
|
||||
bp->icount += j;
|
||||
return ip;
|
||||
}
|
||||
|
||||
/*
|
||||
* copy data to beginning of buffer
|
||||
*/
|
||||
if(i < bp->bsize)
|
||||
memmove(bp->bbuf, ip, i);
|
||||
bp->gbuf = bp->bbuf;
|
||||
|
||||
/*
|
||||
* append to buffer looking for the delim
|
||||
*/
|
||||
ip = (char*)bp->bbuf + i;
|
||||
while(i < bp->bsize) {
|
||||
j = read(bp->fid, ip, bp->bsize-i);
|
||||
if(j <= 0) {
|
||||
/*
|
||||
* end of file with no delim
|
||||
*/
|
||||
memmove(bp->ebuf-i, bp->bbuf, i);
|
||||
bp->rdline = i;
|
||||
bp->icount = -i;
|
||||
bp->gbuf = bp->ebuf-i;
|
||||
return 0;
|
||||
}
|
||||
bp->offset += j;
|
||||
i += j;
|
||||
ep = memchr(ip, delim, j);
|
||||
if(ep) {
|
||||
/*
|
||||
* found in new piece
|
||||
* copy back up and reset everything
|
||||
*/
|
||||
ip = (char*)bp->ebuf - i;
|
||||
if(i < bp->bsize){
|
||||
memmove(ip, bp->bbuf, i);
|
||||
bp->gbuf = (unsigned char*)ip;
|
||||
}
|
||||
j = (ep - (char*)bp->bbuf) + 1;
|
||||
bp->rdline = j;
|
||||
bp->icount = j - i;
|
||||
return ip;
|
||||
}
|
||||
ip += j;
|
||||
}
|
||||
|
||||
/*
|
||||
* full buffer without finding
|
||||
*/
|
||||
bp->rdline = bp->bsize;
|
||||
bp->icount = -bp->bsize;
|
||||
bp->gbuf = bp->bbuf;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
Blinelen(Biobuf *bp)
|
||||
{
|
||||
|
||||
return bp->rdline;
|
||||
}
|
||||
112
src/libbio/brdstr.c
Normal file
112
src/libbio/brdstr.c
Normal file
@@ -0,0 +1,112 @@
|
||||
#include "lib9.h"
|
||||
#include <bio.h>
|
||||
|
||||
static char*
|
||||
badd(char *p, int *np, char *data, int ndata, int delim, int nulldelim)
|
||||
{
|
||||
int n;
|
||||
|
||||
n = *np;
|
||||
p = realloc(p, n+ndata+1);
|
||||
if(p){
|
||||
memmove(p+n, data, ndata);
|
||||
n += ndata;
|
||||
if(n>0 && nulldelim && p[n-1]==delim)
|
||||
p[--n] = '\0';
|
||||
else
|
||||
p[n] = '\0';
|
||||
*np = n;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
char*
|
||||
Brdstr(Biobuf *bp, int delim, int nulldelim)
|
||||
{
|
||||
char *ip, *ep, *p;
|
||||
int i, j;
|
||||
|
||||
i = -bp->icount;
|
||||
bp->rdline = 0;
|
||||
if(i == 0) {
|
||||
/*
|
||||
* eof or other error
|
||||
*/
|
||||
if(bp->state != Bractive) {
|
||||
if(bp->state == Bracteof)
|
||||
bp->state = Bractive;
|
||||
bp->gbuf = bp->ebuf;
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* first try in remainder of buffer (gbuf doesn't change)
|
||||
*/
|
||||
ip = (char*)bp->ebuf - i;
|
||||
ep = memchr(ip, delim, i);
|
||||
if(ep) {
|
||||
j = (ep - ip) + 1;
|
||||
bp->icount += j;
|
||||
return badd(nil, &bp->rdline, ip, j, delim, nulldelim);
|
||||
}
|
||||
|
||||
/*
|
||||
* copy data to beginning of buffer
|
||||
*/
|
||||
if(i < bp->bsize)
|
||||
memmove(bp->bbuf, ip, i);
|
||||
bp->gbuf = bp->bbuf;
|
||||
|
||||
/*
|
||||
* append to buffer looking for the delim
|
||||
*/
|
||||
p = nil;
|
||||
for(;;){
|
||||
ip = (char*)bp->bbuf + i;
|
||||
while(i < bp->bsize) {
|
||||
j = read(bp->fid, ip, bp->bsize-i);
|
||||
if(j <= 0 && i == 0)
|
||||
return p;
|
||||
if(j <= 0 && i > 0){
|
||||
/*
|
||||
* end of file but no delim. pretend we got a delim
|
||||
* by making the delim \0 and smashing it with nulldelim.
|
||||
*/
|
||||
j = 1;
|
||||
ep = ip;
|
||||
delim = '\0';
|
||||
nulldelim = 1;
|
||||
*ep = delim; /* there will be room for this */
|
||||
}else{
|
||||
bp->offset += j;
|
||||
ep = memchr(ip, delim, j);
|
||||
}
|
||||
i += j;
|
||||
if(ep) {
|
||||
/*
|
||||
* found in new piece
|
||||
* copy back up and reset everything
|
||||
*/
|
||||
ip = (char*)bp->ebuf - i;
|
||||
if(i < bp->bsize){
|
||||
memmove(ip, bp->bbuf, i);
|
||||
bp->gbuf = (unsigned char*)ip;
|
||||
}
|
||||
j = (ep - (char*)bp->bbuf) + 1;
|
||||
bp->icount = j - i;
|
||||
return badd(p, &bp->rdline, ip, j, delim, nulldelim);
|
||||
}
|
||||
ip += j;
|
||||
}
|
||||
|
||||
/*
|
||||
* full buffer without finding; add to user string and continue
|
||||
*/
|
||||
p = badd(p, &bp->rdline, (char*)bp->bbuf, bp->bsize, 0, 0);
|
||||
i = 0;
|
||||
bp->icount = 0;
|
||||
bp->gbuf = bp->ebuf;
|
||||
}
|
||||
return 0; /* never happens */
|
||||
}
|
||||
45
src/libbio/bread.c
Normal file
45
src/libbio/bread.c
Normal file
@@ -0,0 +1,45 @@
|
||||
#include "lib9.h"
|
||||
#include <bio.h>
|
||||
|
||||
long
|
||||
Bread(Biobuf *bp, void *ap, long count)
|
||||
{
|
||||
long c;
|
||||
unsigned char *p;
|
||||
int i, n, ic;
|
||||
|
||||
p = ap;
|
||||
c = count;
|
||||
ic = bp->icount;
|
||||
|
||||
while(c > 0) {
|
||||
n = -ic;
|
||||
if(n > c)
|
||||
n = c;
|
||||
if(n == 0) {
|
||||
if(bp->state != Bractive)
|
||||
break;
|
||||
i = read(bp->fid, bp->bbuf, bp->bsize);
|
||||
if(i <= 0) {
|
||||
bp->state = Bracteof;
|
||||
if(i < 0)
|
||||
bp->state = Binactive;
|
||||
break;
|
||||
}
|
||||
bp->gbuf = bp->bbuf;
|
||||
bp->offset += i;
|
||||
if(i < bp->bsize) {
|
||||
memmove(bp->ebuf-i, bp->bbuf, i);
|
||||
bp->gbuf = bp->ebuf-i;
|
||||
}
|
||||
ic = -i;
|
||||
continue;
|
||||
}
|
||||
memmove(p, bp->ebuf+ic, n);
|
||||
c -= n;
|
||||
ic += n;
|
||||
p += n;
|
||||
}
|
||||
bp->icount = ic;
|
||||
return count-c;
|
||||
}
|
||||
56
src/libbio/bseek.c
Normal file
56
src/libbio/bseek.c
Normal file
@@ -0,0 +1,56 @@
|
||||
#include "lib9.h"
|
||||
#include <bio.h>
|
||||
|
||||
off_t
|
||||
Bseek(Biobuf *bp, off_t offset, int base)
|
||||
{
|
||||
off_t n, d;
|
||||
|
||||
switch(bp->state) {
|
||||
default:
|
||||
fprint(2, "Bseek: unknown state %d\n", bp->state);
|
||||
return Beof;
|
||||
|
||||
case Bracteof:
|
||||
bp->state = Bractive;
|
||||
bp->icount = 0;
|
||||
bp->gbuf = bp->ebuf;
|
||||
|
||||
case Bractive:
|
||||
n = offset;
|
||||
if(base == 1) {
|
||||
n += Boffset(bp);
|
||||
base = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* try to seek within buffer
|
||||
*/
|
||||
if(base == 0) {
|
||||
d = n - Boffset(bp);
|
||||
bp->icount += d;
|
||||
if(d >= 0) {
|
||||
if(bp->icount <= 0)
|
||||
return n;
|
||||
} else {
|
||||
if(bp->ebuf - bp->gbuf >= -bp->icount)
|
||||
return n;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* reset the buffer
|
||||
*/
|
||||
n = lseek(bp->fid, n, base);
|
||||
bp->icount = 0;
|
||||
bp->gbuf = bp->ebuf;
|
||||
break;
|
||||
|
||||
case Bwactive:
|
||||
Bflush(bp);
|
||||
n = lseek(bp->fid, offset, base);
|
||||
break;
|
||||
}
|
||||
bp->offset = n;
|
||||
return n;
|
||||
}
|
||||
45
src/libbio/bundle.ports
Normal file
45
src/libbio/bundle.ports
Normal file
@@ -0,0 +1,45 @@
|
||||
--- Makefile ---
|
||||
# New ports collection makefile for: libbio
|
||||
# Date Created: 11 Feb 2003
|
||||
# Whom: rsc
|
||||
#
|
||||
# THIS LINE NEEDS REPLACING. IT'S HERE TO GET BY PORTLINT
|
||||
# $FreeBSD: ports/devel/libbio/Makefile,v 1.1 2003/02/12 00:51:22 rsc Exp $
|
||||
|
||||
PORTNAME= libbio
|
||||
PORTVERSION= 2.0
|
||||
CATEGORIES= devel
|
||||
MASTER_SITES= http://pdos.lcs.mit.edu/~rsc/software/
|
||||
EXTRACT_SUFX= .tgz
|
||||
|
||||
MAINTAINER= rsc@post.harvard.edu
|
||||
|
||||
DEPENDS= ${PORTSDIR}/devel/libfmt ${PORTSDIR}/devel/libutf
|
||||
|
||||
MAN3= bio.3
|
||||
USE_REINPLACE= yes
|
||||
|
||||
.include <bsd.port.pre.mk>
|
||||
|
||||
post-patch:
|
||||
${REINPLACE_CMD} -e 's,$$(PREFIX),${PREFIX},g' ${WRKSRC}/Makefile
|
||||
|
||||
.include <bsd.port.post.mk>
|
||||
--- pkg-comment ---
|
||||
Simple buffered I/O library from Plan 9
|
||||
--- pkg-descr ---
|
||||
Libbio is a port of Plan 9's formatted I/O library.
|
||||
It provides most of the same functionality as stdio or sfio,
|
||||
but with a simpler interface and smaller footprint.
|
||||
|
||||
WWW: http://pdos.lcs.mit.edu/~rsc/software/#libbio
|
||||
http://plan9.bell-labs.com/magic/man2html/2/bio
|
||||
|
||||
Russ Cox
|
||||
rsc@post.harvard.edu
|
||||
--- pkg-plist ---
|
||||
lib/libbio.a
|
||||
include/bio.h
|
||||
--- /dev/null ---
|
||||
This is just a way to make sure blank lines don't
|
||||
creep into pkg-plist.
|
||||
38
src/libbio/bwrite.c
Normal file
38
src/libbio/bwrite.c
Normal file
@@ -0,0 +1,38 @@
|
||||
#include "lib9.h"
|
||||
#include <bio.h>
|
||||
|
||||
long
|
||||
Bwrite(Biobuf *bp, void *ap, long count)
|
||||
{
|
||||
long c;
|
||||
unsigned char *p;
|
||||
int i, n, oc;
|
||||
|
||||
p = ap;
|
||||
c = count;
|
||||
oc = bp->ocount;
|
||||
|
||||
while(c > 0) {
|
||||
n = -oc;
|
||||
if(n > c)
|
||||
n = c;
|
||||
if(n == 0) {
|
||||
if(bp->state != Bwactive)
|
||||
return Beof;
|
||||
i = write(bp->fid, bp->bbuf, bp->bsize);
|
||||
if(i != bp->bsize) {
|
||||
bp->state = Binactive;
|
||||
return Beof;
|
||||
}
|
||||
bp->offset += i;
|
||||
oc = -bp->bsize;
|
||||
continue;
|
||||
}
|
||||
memmove(bp->ebuf+oc, p, n);
|
||||
oc += n;
|
||||
c -= n;
|
||||
p += n;
|
||||
}
|
||||
bp->ocount = oc;
|
||||
return count-c;
|
||||
}
|
||||
12
src/libbio/lib9.h
Normal file
12
src/libbio/lib9.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#include <fmt.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define OREAD O_RDONLY
|
||||
#define OWRITE O_WRONLY
|
||||
|
||||
#include <utf.h>
|
||||
|
||||
#define nil ((void*)0)
|
||||
1
src/libbio/mkfile
Normal file
1
src/libbio/mkfile
Normal file
@@ -0,0 +1 @@
|
||||
<../libutf/mkfile
|
||||
30
src/libbio/rpm.spec
Normal file
30
src/libbio/rpm.spec
Normal file
@@ -0,0 +1,30 @@
|
||||
Summary: Simple buffered I/O library from Plan 9
|
||||
Name: libbio
|
||||
Version: 2.0
|
||||
Release: 1
|
||||
Group: Development/C
|
||||
Copyright: LGPL
|
||||
Packager: Russ Cox <rsc@post.harvard.edu>
|
||||
Source: http://pdos.lcs.mit.edu/~rsc/software/libbio-2.0.tgz
|
||||
URL: http://pdos.lcs.mit.edu/~rsc/software/#libbio
|
||||
Requires: libfmt libutf
|
||||
|
||||
%description
|
||||
Libbio is a port of Plan 9's formatted I/O library.
|
||||
It provides most of the same functionality as stdio or sfio,
|
||||
but with a simpler interface and smaller footprint.
|
||||
|
||||
http://plan9.bell-labs.com/magic/man2html/2/bio
|
||||
%prep
|
||||
%setup
|
||||
|
||||
%build
|
||||
make
|
||||
|
||||
%install
|
||||
make install
|
||||
|
||||
%files
|
||||
/usr/local/include/bio.h
|
||||
/usr/local/lib/libbio.a
|
||||
/usr/local/man/man3/bio.3
|
||||
19
src/libfmt/LICENSE
Normal file
19
src/libfmt/LICENSE
Normal file
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* The authors of this software are Rob Pike and Ken Thompson.
|
||||
* Copyright (c) 2002 by Lucent Technologies.
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose without fee is hereby granted, provided that this entire notice
|
||||
* is included in all copies of any software which is or includes a copy
|
||||
* or modification of this software and in all copies of the supporting
|
||||
* documentation for such software.
|
||||
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
|
||||
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
|
||||
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
This is a Unix port of the Plan 9 formatted I/O package.
|
||||
|
||||
Please send comments about the packaging
|
||||
to Russ Cox <rsc@post.harvard.edu>.
|
||||
|
||||
6
src/libfmt/Make.Darwin-PowerMacintosh
Normal file
6
src/libfmt/Make.Darwin-PowerMacintosh
Normal file
@@ -0,0 +1,6 @@
|
||||
CC=gcc
|
||||
CFLAGS+=-Wall -Wno-missing-braces -Wno-parentheses -Wno-switch -O2 -g -c -I. -I${PREFIX}/include
|
||||
O=o
|
||||
AR=ar
|
||||
ARFLAGS=rvc
|
||||
NAN=nan64.$O
|
||||
7
src/libfmt/Make.FreeBSD-386
Normal file
7
src/libfmt/Make.FreeBSD-386
Normal file
@@ -0,0 +1,7 @@
|
||||
CC=gcc
|
||||
CFLAGS+=-Wall -Wno-missing-braces -Wno-parentheses -Wno-switch -O2 -g -c -I. -I$(PREFIX)/include -pg
|
||||
O=o
|
||||
AR=ar
|
||||
ARFLAGS=rvc
|
||||
NAN=nan64.$O # default, can be overriden by Make.$(SYSNAME)
|
||||
NAN=nan64.$O
|
||||
6
src/libfmt/Make.HP-UX-9000
Normal file
6
src/libfmt/Make.HP-UX-9000
Normal file
@@ -0,0 +1,6 @@
|
||||
CC=cc
|
||||
CFLAGS=-O -c -Ae -I.
|
||||
O=o
|
||||
AR=ar
|
||||
ARFLAGS=rvc
|
||||
NAN=nan64.$O
|
||||
7
src/libfmt/Make.Linux-386
Normal file
7
src/libfmt/Make.Linux-386
Normal file
@@ -0,0 +1,7 @@
|
||||
CC=gcc
|
||||
CFLAGS+=-Wall -Wno-missing-braces -Wno-parentheses -Wno-switch -O2 -g -c -I. -DNEEDLL
|
||||
O=o
|
||||
AR=ar
|
||||
ARFLAGS=rvc
|
||||
NAN=nan64.$O # default, can be overriden by Make.$(SYSNAME)
|
||||
NAN=nan64.$O
|
||||
7
src/libfmt/Make.NetBSD-386
Normal file
7
src/libfmt/Make.NetBSD-386
Normal file
@@ -0,0 +1,7 @@
|
||||
CC=gcc
|
||||
CFLAGS+=-Wall -Wno-missing-braces -Wno-parentheses -Wno-switch -O2 -g -c -I. -I$(PREFIX)/include
|
||||
O=o
|
||||
AR=ar
|
||||
ARFLAGS=rvc
|
||||
NAN=nan64.$O # default, can be overriden by Make.$(SYSNAME)
|
||||
NAN=nan64.$O
|
||||
6
src/libfmt/Make.OSF1-alpha
Normal file
6
src/libfmt/Make.OSF1-alpha
Normal file
@@ -0,0 +1,6 @@
|
||||
CC=cc
|
||||
CFLAGS+=-g -c -I.
|
||||
O=o
|
||||
AR=ar
|
||||
ARFLAGS=rvc
|
||||
NAN=nan64.$O
|
||||
2
src/libfmt/Make.SunOS-sun4u
Normal file
2
src/libfmt/Make.SunOS-sun4u
Normal file
@@ -0,0 +1,2 @@
|
||||
include Make.SunOS-sun4u-$(CC)
|
||||
NAN=nan64.$O
|
||||
6
src/libfmt/Make.SunOS-sun4u-cc
Normal file
6
src/libfmt/Make.SunOS-sun4u-cc
Normal file
@@ -0,0 +1,6 @@
|
||||
CC=cc
|
||||
CFLAGS+=-g -c -I. -O
|
||||
O=o
|
||||
AR=ar
|
||||
ARFLAGS=rvc
|
||||
NAN=nan64.$O
|
||||
6
src/libfmt/Make.SunOS-sun4u-gcc
Normal file
6
src/libfmt/Make.SunOS-sun4u-gcc
Normal file
@@ -0,0 +1,6 @@
|
||||
CC=gcc
|
||||
CFLAGS+=-Wall -Wno-missing-braces -Wno-parentheses -Wno-switch -O2 -g -c
|
||||
O=o
|
||||
AR=ar
|
||||
ARFLAGS=rvc
|
||||
NAN=nan64.$O
|
||||
134
src/libfmt/Makefile
Normal file
134
src/libfmt/Makefile
Normal file
@@ -0,0 +1,134 @@
|
||||
|
||||
# this works in gnu make
|
||||
SYSNAME:=${shell uname}
|
||||
OBJTYPE:=${shell uname -m | sed 's;i.86;386;; s;/.*;;; s; ;;g'}
|
||||
|
||||
# this works in bsd make
|
||||
SYSNAME!=uname
|
||||
OBJTYPE!=uname -m | sed 's;i.86;386;; s;/.*;;; s; ;;g'
|
||||
|
||||
# the gnu rules will mess up bsd but not vice versa,
|
||||
# hence the gnu rules come first.
|
||||
|
||||
include Make.$(SYSNAME)-$(OBJTYPE)
|
||||
|
||||
PREFIX=/usr/local
|
||||
|
||||
NUKEFILES=
|
||||
|
||||
TGZFILES=
|
||||
|
||||
LIB=libfmt.a
|
||||
VERSION=2.0
|
||||
PORTPLACE=devel/libfmt
|
||||
NAME=libfmt
|
||||
|
||||
NUM=\
|
||||
charstod.$O\
|
||||
pow10.$O\
|
||||
|
||||
OFILES=\
|
||||
dofmt.$O\
|
||||
errfmt.$O\
|
||||
fltfmt.$O\
|
||||
fmt.$O\
|
||||
fmtfd.$O\
|
||||
fmtfdflush.$O\
|
||||
fmtlock.$O\
|
||||
fmtprint.$O\
|
||||
fmtquote.$O\
|
||||
fmtrune.$O\
|
||||
fmtstr.$O\
|
||||
fmtvprint.$O\
|
||||
fprint.$O\
|
||||
print.$O\
|
||||
runefmtstr.$O\
|
||||
runeseprint.$O\
|
||||
runesmprint.$O\
|
||||
runesnprint.$O\
|
||||
runesprint.$O\
|
||||
runevseprint.$O\
|
||||
runevsmprint.$O\
|
||||
runevsnprint.$O\
|
||||
seprint.$O\
|
||||
smprint.$O\
|
||||
snprint.$O\
|
||||
sprint.$O\
|
||||
strtod.$O\
|
||||
vfprint.$O\
|
||||
vseprint.$O\
|
||||
vsmprint.$O\
|
||||
vsnprint.$O\
|
||||
$(NUM)\
|
||||
$(NAN)\
|
||||
|
||||
HFILES=\
|
||||
fmtdef.h\
|
||||
fmt.h\
|
||||
|
||||
all: $(LIB)
|
||||
|
||||
install: $(LIB)
|
||||
test -d $(PREFIX)/man/man3 || mkdir $(PREFIX)/man/man3
|
||||
install -m 0644 print.3 $(PREFIX)/man/man3/print.3
|
||||
install -m 0644 fmtinstall.3 $(PREFIX)/man/man3/fmtinstall.3
|
||||
install -m 0644 fmt.h $(PREFIX)/include/fmt.h
|
||||
install -m 0644 $(LIB) $(PREFIX)/lib/$(LIB)
|
||||
|
||||
$(NAN).$O: nan.h
|
||||
strtod.$O: nan.h
|
||||
|
||||
test: $(LIB) test.$O
|
||||
$(CC) -o test test.$O $(LIB) -L$(PREFIX)/lib -lutf
|
||||
|
||||
$(LIB): $(OFILES)
|
||||
$(AR) $(ARFLAGS) $(LIB) $(OFILES)
|
||||
|
||||
NUKEFILES+=$(LIB)
|
||||
.c.$O:
|
||||
$(CC) $(CFLAGS) -I$(PREFIX)/include $*.c
|
||||
|
||||
%.$O: %.c
|
||||
$(CC) $(CFLAGS) -I$(PREFIX)/include $*.c
|
||||
|
||||
|
||||
$(OFILES): $(HFILES)
|
||||
|
||||
tgz:
|
||||
rm -rf $(NAME)-$(VERSION)
|
||||
mkdir $(NAME)-$(VERSION)
|
||||
cp Makefile Make.* README LICENSE NOTICE *.[ch137] rpm.spec bundle.ports $(TGZFILES) $(NAME)-$(VERSION)
|
||||
tar cf - $(NAME)-$(VERSION) | gzip >$(NAME)-$(VERSION).tgz
|
||||
rm -rf $(NAME)-$(VERSION)
|
||||
|
||||
clean:
|
||||
rm -f $(OFILES) $(LIB)
|
||||
|
||||
nuke:
|
||||
rm -f $(OFILES) *.tgz *.rpm $(NUKEFILES)
|
||||
|
||||
rpm:
|
||||
make tgz
|
||||
cp $(NAME)-$(VERSION).tgz /usr/src/RPM/SOURCES
|
||||
rpm -ba rpm.spec
|
||||
cp /usr/src/RPM/SRPMS/$(NAME)-$(VERSION)-1.src.rpm .
|
||||
cp /usr/src/RPM/RPMS/i586/$(NAME)-$(VERSION)-1.i586.rpm .
|
||||
scp *.rpm rsc@amsterdam.lcs.mit.edu:public_html/software
|
||||
|
||||
PORTDIR=/usr/ports/$(PORTPLACE)
|
||||
|
||||
ports:
|
||||
make tgz
|
||||
rm -rf $(PORTDIR)
|
||||
mkdir $(PORTDIR)
|
||||
cp $(NAME)-$(VERSION).tgz /usr/ports/distfiles
|
||||
cat bundle.ports | (cd $(PORTDIR) && awk '$$1=="---" && $$3=="---" { ofile=$$2; next} {if(ofile) print >ofile}')
|
||||
(cd $(PORTDIR); make makesum)
|
||||
(cd $(PORTDIR); make)
|
||||
(cd $(PORTDIR); /usr/local/bin/portlint)
|
||||
rm -rf $(PORTDIR)/work
|
||||
shar `find $(PORTDIR)` > ports.shar
|
||||
(cd $(PORTDIR); tar cf - *) | gzip >$(NAME)-$(VERSION)-ports.tgz
|
||||
scp *.tgz rsc@amsterdam.lcs.mit.edu:public_html/software
|
||||
|
||||
.phony: all clean nuke install tgz rpm ports
|
||||
63
src/libfmt/Makefile.MID
Normal file
63
src/libfmt/Makefile.MID
Normal file
@@ -0,0 +1,63 @@
|
||||
LIB=libfmt.a
|
||||
VERSION=2.0
|
||||
PORTPLACE=devel/libfmt
|
||||
NAME=libfmt
|
||||
|
||||
NUM=\
|
||||
charstod.$O\
|
||||
pow10.$O\
|
||||
|
||||
OFILES=\
|
||||
dofmt.$O\
|
||||
errfmt.$O\
|
||||
fltfmt.$O\
|
||||
fmt.$O\
|
||||
fmtfd.$O\
|
||||
fmtfdflush.$O\
|
||||
fmtlock.$O\
|
||||
fmtprint.$O\
|
||||
fmtquote.$O\
|
||||
fmtrune.$O\
|
||||
fmtstr.$O\
|
||||
fmtvprint.$O\
|
||||
fprint.$O\
|
||||
print.$O\
|
||||
runefmtstr.$O\
|
||||
runeseprint.$O\
|
||||
runesmprint.$O\
|
||||
runesnprint.$O\
|
||||
runesprint.$O\
|
||||
runevseprint.$O\
|
||||
runevsmprint.$O\
|
||||
runevsnprint.$O\
|
||||
seprint.$O\
|
||||
smprint.$O\
|
||||
snprint.$O\
|
||||
sprint.$O\
|
||||
strtod.$O\
|
||||
vfprint.$O\
|
||||
vseprint.$O\
|
||||
vsmprint.$O\
|
||||
vsnprint.$O\
|
||||
$(NUM)\
|
||||
$(NAN)\
|
||||
|
||||
HFILES=\
|
||||
fmtdef.h\
|
||||
fmt.h\
|
||||
|
||||
all: $(LIB)
|
||||
|
||||
install: $(LIB)
|
||||
test -d $(PREFIX)/man/man3 || mkdir $(PREFIX)/man/man3
|
||||
install -m 0644 print.3 $(PREFIX)/man/man3/print.3
|
||||
install -m 0644 fmtinstall.3 $(PREFIX)/man/man3/fmtinstall.3
|
||||
install -m 0644 fmt.h $(PREFIX)/include/fmt.h
|
||||
install -m 0644 $(LIB) $(PREFIX)/lib/$(LIB)
|
||||
|
||||
$(NAN).$O: nan.h
|
||||
strtod.$O: nan.h
|
||||
|
||||
test: $(LIB) test.$O
|
||||
$(CC) -o test test.$O $(LIB) -L$(PREFIX)/lib -lutf
|
||||
|
||||
19
src/libfmt/NOTICE
Normal file
19
src/libfmt/NOTICE
Normal file
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* The authors of this software are Rob Pike and Ken Thompson.
|
||||
* Copyright (c) 2002 by Lucent Technologies.
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose without fee is hereby granted, provided that this entire notice
|
||||
* is included in all copies of any software which is or includes a copy
|
||||
* or modification of this software and in all copies of the supporting
|
||||
* documentation for such software.
|
||||
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
|
||||
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
|
||||
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
This is a Unix port of the Plan 9 formatted I/O package.
|
||||
|
||||
Please send comments about the packaging
|
||||
to Russ Cox <rsc@post.harvard.edu>.
|
||||
|
||||
19
src/libfmt/README
Normal file
19
src/libfmt/README
Normal file
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* The authors of this software are Rob Pike and Ken Thompson.
|
||||
* Copyright (c) 2002 by Lucent Technologies.
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose without fee is hereby granted, provided that this entire notice
|
||||
* is included in all copies of any software which is or includes a copy
|
||||
* or modification of this software and in all copies of the supporting
|
||||
* documentation for such software.
|
||||
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
|
||||
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
|
||||
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
This is a Unix port of the Plan 9 formatted I/O package.
|
||||
|
||||
Please send comments about the packaging
|
||||
to Russ Cox <rsc@post.harvard.edu>.
|
||||
|
||||
51
src/libfmt/bundle.ports
Normal file
51
src/libfmt/bundle.ports
Normal file
@@ -0,0 +1,51 @@
|
||||
--- Makefile ---
|
||||
# New ports collection makefile for: libfmt
|
||||
# Date Created: 11 Feb 2003
|
||||
# Whom: rsc
|
||||
#
|
||||
# THIS LINE NEEDS REPLACING. IT'S HERE TO GET BY PORTLINT
|
||||
# $FreeBSD: ports/devel/libfmt/Makefile,v 1.1 2003/02/12 00:51:22 rsc Exp $
|
||||
|
||||
PORTNAME= libfmt
|
||||
PORTVERSION= 2.0
|
||||
CATEGORIES= devel
|
||||
MASTER_SITES= http://pdos.lcs.mit.edu/~rsc/software/
|
||||
EXTRACT_SUFX= .tgz
|
||||
|
||||
MAINTAINER= rsc@post.harvard.edu
|
||||
|
||||
DEPENDS= ${PORTSDIR}/devel/libutf
|
||||
|
||||
MAN3= print.3 fmtinstall.3
|
||||
|
||||
USE_REINPLACE=yes
|
||||
|
||||
.include <bsd.port.pre.mk>
|
||||
|
||||
post-patch:
|
||||
${REINPLACE_CMD} -e 's,$$(PREFIX),${PREFIX},g' ${WRKSRC}/Makefile
|
||||
|
||||
.include <bsd.port.post.mk>
|
||||
--- pkg-comment ---
|
||||
Extensible formatted print C library (printf with user-defined verbs)
|
||||
--- pkg-descr ---
|
||||
Libfmt is a port of Plan 9's formatted print library.
|
||||
As a base it provides all the syntax of ANSI printf
|
||||
but adds the ability for client programs to install
|
||||
new print verbs. One such print verb (installed by
|
||||
default) is %r, which prints the system error string.
|
||||
Instead of perror("foo"), you can write fprint(2, "foo: %r\n").
|
||||
This is especially nice when you write verbs to format
|
||||
the data structures used by your particular program.
|
||||
|
||||
WWW: http://pdos.lcs.mit.edu/~rsc/software/#libfmt
|
||||
http://plan9.bell-labs.com/magic/man2html/2/print
|
||||
|
||||
Russ Cox
|
||||
rsc@post.harvard.edu
|
||||
--- pkg-plist ---
|
||||
lib/libfmt.a
|
||||
include/fmt.h
|
||||
--- /dev/null ---
|
||||
This is just a way to make sure blank lines don't
|
||||
creep into pkg-plist.
|
||||
85
src/libfmt/charstod.c
Normal file
85
src/libfmt/charstod.c
Normal file
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* The authors of this software are Rob Pike and Ken Thompson.
|
||||
* Copyright (c) 2002 by Lucent Technologies.
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose without fee is hereby granted, provided that this entire notice
|
||||
* is included in all copies of any software which is or includes a copy
|
||||
* or modification of this software and in all copies of the supporting
|
||||
* documentation for such software.
|
||||
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
|
||||
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
|
||||
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
|
||||
*/
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include "utf.h"
|
||||
#include "fmt.h"
|
||||
#include "fmtdef.h"
|
||||
|
||||
/*
|
||||
* Reads a floating-point number by interpreting successive characters
|
||||
* returned by (*f)(vp). The last call it makes to f terminates the
|
||||
* scan, so is not a character in the number. It may therefore be
|
||||
* necessary to back up the input stream up one byte after calling charstod.
|
||||
*/
|
||||
|
||||
double
|
||||
fmtcharstod(int(*f)(void*), void *vp)
|
||||
{
|
||||
double num, dem;
|
||||
int neg, eneg, dig, exp, c;
|
||||
|
||||
num = 0;
|
||||
neg = 0;
|
||||
dig = 0;
|
||||
exp = 0;
|
||||
eneg = 0;
|
||||
|
||||
c = (*f)(vp);
|
||||
while(c == ' ' || c == '\t')
|
||||
c = (*f)(vp);
|
||||
if(c == '-' || c == '+'){
|
||||
if(c == '-')
|
||||
neg = 1;
|
||||
c = (*f)(vp);
|
||||
}
|
||||
while(c >= '0' && c <= '9'){
|
||||
num = num*10 + c-'0';
|
||||
c = (*f)(vp);
|
||||
}
|
||||
if(c == '.')
|
||||
c = (*f)(vp);
|
||||
while(c >= '0' && c <= '9'){
|
||||
num = num*10 + c-'0';
|
||||
dig++;
|
||||
c = (*f)(vp);
|
||||
}
|
||||
if(c == 'e' || c == 'E'){
|
||||
c = (*f)(vp);
|
||||
if(c == '-' || c == '+'){
|
||||
if(c == '-'){
|
||||
dig = -dig;
|
||||
eneg = 1;
|
||||
}
|
||||
c = (*f)(vp);
|
||||
}
|
||||
while(c >= '0' && c <= '9'){
|
||||
exp = exp*10 + c-'0';
|
||||
c = (*f)(vp);
|
||||
}
|
||||
}
|
||||
exp -= dig;
|
||||
if(exp < 0){
|
||||
exp = -exp;
|
||||
eneg = !eneg;
|
||||
}
|
||||
dem = __fmtpow10(exp);
|
||||
if(eneg)
|
||||
num /= dem;
|
||||
else
|
||||
num *= dem;
|
||||
if(neg)
|
||||
return -num;
|
||||
return num;
|
||||
}
|
||||
558
src/libfmt/dofmt.c
Normal file
558
src/libfmt/dofmt.c
Normal file
@@ -0,0 +1,558 @@
|
||||
/*
|
||||
* The authors of this software are Rob Pike and Ken Thompson.
|
||||
* Copyright (c) 2002 by Lucent Technologies.
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose without fee is hereby granted, provided that this entire notice
|
||||
* is included in all copies of any software which is or includes a copy
|
||||
* or modification of this software and in all copies of the supporting
|
||||
* documentation for such software.
|
||||
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
|
||||
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
|
||||
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
|
||||
*/
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include "utf.h"
|
||||
#include "fmt.h"
|
||||
#include "fmtdef.h"
|
||||
|
||||
/* format the output into f->to and return the number of characters fmted */
|
||||
int
|
||||
dofmt(Fmt *f, char *fmt)
|
||||
{
|
||||
Rune rune, *rt, *rs;
|
||||
int r;
|
||||
char *t, *s;
|
||||
int n, nfmt;
|
||||
|
||||
nfmt = f->nfmt;
|
||||
for(;;){
|
||||
if(f->runes){
|
||||
rt = (Rune*)f->to;
|
||||
rs = (Rune*)f->stop;
|
||||
while((r = *(uchar*)fmt) && r != '%'){
|
||||
if(r < Runeself)
|
||||
fmt++;
|
||||
else{
|
||||
fmt += chartorune(&rune, fmt);
|
||||
r = rune;
|
||||
}
|
||||
FMTRCHAR(f, rt, rs, r);
|
||||
}
|
||||
fmt++;
|
||||
f->nfmt += rt - (Rune *)f->to;
|
||||
f->to = rt;
|
||||
if(!r)
|
||||
return f->nfmt - nfmt;
|
||||
f->stop = rs;
|
||||
}else{
|
||||
t = (char*)f->to;
|
||||
s = (char*)f->stop;
|
||||
while((r = *(uchar*)fmt) && r != '%'){
|
||||
if(r < Runeself){
|
||||
FMTCHAR(f, t, s, r);
|
||||
fmt++;
|
||||
}else{
|
||||
n = chartorune(&rune, fmt);
|
||||
if(t + n > s){
|
||||
t = (char*)__fmtflush(f, t, n);
|
||||
if(t != nil)
|
||||
s = (char*)f->stop;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
while(n--)
|
||||
*t++ = *fmt++;
|
||||
}
|
||||
}
|
||||
fmt++;
|
||||
f->nfmt += t - (char *)f->to;
|
||||
f->to = t;
|
||||
if(!r)
|
||||
return f->nfmt - nfmt;
|
||||
f->stop = s;
|
||||
}
|
||||
|
||||
fmt = (char*)__fmtdispatch(f, fmt, 0);
|
||||
if(fmt == nil)
|
||||
return -1;
|
||||
}
|
||||
return 0; /* not reached */
|
||||
}
|
||||
|
||||
void *
|
||||
__fmtflush(Fmt *f, void *t, int len)
|
||||
{
|
||||
if(f->runes)
|
||||
f->nfmt += (Rune*)t - (Rune*)f->to;
|
||||
else
|
||||
f->nfmt += (char*)t - (char *)f->to;
|
||||
f->to = t;
|
||||
if(f->flush == 0 || (*f->flush)(f) == 0 || (char*)f->to + len > (char*)f->stop){
|
||||
f->stop = f->to;
|
||||
return nil;
|
||||
}
|
||||
return f->to;
|
||||
}
|
||||
|
||||
/*
|
||||
* put a formatted block of memory sz bytes long of n runes into the output buffer,
|
||||
* left/right justified in a field of at least f->width charactes
|
||||
*/
|
||||
int
|
||||
__fmtpad(Fmt *f, int n)
|
||||
{
|
||||
char *t, *s;
|
||||
int i;
|
||||
|
||||
t = (char*)f->to;
|
||||
s = (char*)f->stop;
|
||||
for(i = 0; i < n; i++)
|
||||
FMTCHAR(f, t, s, ' ');
|
||||
f->nfmt += t - (char *)f->to;
|
||||
f->to = t;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
__rfmtpad(Fmt *f, int n)
|
||||
{
|
||||
Rune *t, *s;
|
||||
int i;
|
||||
|
||||
t = (Rune*)f->to;
|
||||
s = (Rune*)f->stop;
|
||||
for(i = 0; i < n; i++)
|
||||
FMTRCHAR(f, t, s, ' ');
|
||||
f->nfmt += t - (Rune *)f->to;
|
||||
f->to = t;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
__fmtcpy(Fmt *f, const void *vm, int n, int sz)
|
||||
{
|
||||
Rune *rt, *rs, r;
|
||||
char *t, *s, *m, *me;
|
||||
ulong fl;
|
||||
int nc, w;
|
||||
|
||||
m = (char*)vm;
|
||||
me = m + sz;
|
||||
w = f->width;
|
||||
fl = f->flags;
|
||||
if((fl & FmtPrec) && n > f->prec)
|
||||
n = f->prec;
|
||||
if(f->runes){
|
||||
if(!(fl & FmtLeft) && __rfmtpad(f, w - n) < 0)
|
||||
return -1;
|
||||
rt = (Rune*)f->to;
|
||||
rs = (Rune*)f->stop;
|
||||
for(nc = n; nc > 0; nc--){
|
||||
r = *(uchar*)m;
|
||||
if(r < Runeself)
|
||||
m++;
|
||||
else if((me - m) >= UTFmax || fullrune(m, me-m))
|
||||
m += chartorune(&r, m);
|
||||
else
|
||||
break;
|
||||
FMTRCHAR(f, rt, rs, r);
|
||||
}
|
||||
f->nfmt += rt - (Rune *)f->to;
|
||||
f->to = rt;
|
||||
if(m < me)
|
||||
return -1;
|
||||
if(fl & FmtLeft && __rfmtpad(f, w - n) < 0)
|
||||
return -1;
|
||||
}else{
|
||||
if(!(fl & FmtLeft) && __fmtpad(f, w - n) < 0)
|
||||
return -1;
|
||||
t = (char*)f->to;
|
||||
s = (char*)f->stop;
|
||||
for(nc = n; nc > 0; nc--){
|
||||
r = *(uchar*)m;
|
||||
if(r < Runeself)
|
||||
m++;
|
||||
else if((me - m) >= UTFmax || fullrune(m, me-m))
|
||||
m += chartorune(&r, m);
|
||||
else
|
||||
break;
|
||||
FMTRUNE(f, t, s, r);
|
||||
}
|
||||
f->nfmt += t - (char *)f->to;
|
||||
f->to = t;
|
||||
if(fl & FmtLeft && __fmtpad(f, w - n) < 0)
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
__fmtrcpy(Fmt *f, const void *vm, int n)
|
||||
{
|
||||
Rune r, *m, *me, *rt, *rs;
|
||||
char *t, *s;
|
||||
ulong fl;
|
||||
int w;
|
||||
|
||||
m = (Rune*)vm;
|
||||
w = f->width;
|
||||
fl = f->flags;
|
||||
if((fl & FmtPrec) && n > f->prec)
|
||||
n = f->prec;
|
||||
if(f->runes){
|
||||
if(!(fl & FmtLeft) && __rfmtpad(f, w - n) < 0)
|
||||
return -1;
|
||||
rt = (Rune*)f->to;
|
||||
rs = (Rune*)f->stop;
|
||||
for(me = m + n; m < me; m++)
|
||||
FMTRCHAR(f, rt, rs, *m);
|
||||
f->nfmt += rt - (Rune *)f->to;
|
||||
f->to = rt;
|
||||
if(fl & FmtLeft && __rfmtpad(f, w - n) < 0)
|
||||
return -1;
|
||||
}else{
|
||||
if(!(fl & FmtLeft) && __fmtpad(f, w - n) < 0)
|
||||
return -1;
|
||||
t = (char*)f->to;
|
||||
s = (char*)f->stop;
|
||||
for(me = m + n; m < me; m++){
|
||||
r = *m;
|
||||
FMTRUNE(f, t, s, r);
|
||||
}
|
||||
f->nfmt += t - (char *)f->to;
|
||||
f->to = t;
|
||||
if(fl & FmtLeft && __fmtpad(f, w - n) < 0)
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* fmt out one character */
|
||||
int
|
||||
__charfmt(Fmt *f)
|
||||
{
|
||||
char x[1];
|
||||
|
||||
x[0] = va_arg(f->args, int);
|
||||
f->prec = 1;
|
||||
return __fmtcpy(f, (const char*)x, 1, 1);
|
||||
}
|
||||
|
||||
/* fmt out one rune */
|
||||
int
|
||||
__runefmt(Fmt *f)
|
||||
{
|
||||
Rune x[1];
|
||||
|
||||
x[0] = va_arg(f->args, int);
|
||||
return __fmtrcpy(f, (const void*)x, 1);
|
||||
}
|
||||
|
||||
/* public helper routine: fmt out a null terminated string already in hand */
|
||||
int
|
||||
fmtstrcpy(Fmt *f, char *s)
|
||||
{
|
||||
int p, i;
|
||||
if(!s)
|
||||
return __fmtcpy(f, "<nil>", 5, 5);
|
||||
/* if precision is specified, make sure we don't wander off the end */
|
||||
if(f->flags & FmtPrec){
|
||||
p = f->prec;
|
||||
for(i = 0; i < p; i++)
|
||||
if(s[i] == 0)
|
||||
break;
|
||||
return __fmtcpy(f, s, utfnlen(s, i), i); /* BUG?: won't print a partial rune at end */
|
||||
}
|
||||
|
||||
return __fmtcpy(f, s, utflen(s), strlen(s));
|
||||
}
|
||||
|
||||
/* fmt out a null terminated utf string */
|
||||
int
|
||||
__strfmt(Fmt *f)
|
||||
{
|
||||
char *s;
|
||||
|
||||
s = va_arg(f->args, char *);
|
||||
return fmtstrcpy(f, s);
|
||||
}
|
||||
|
||||
/* public helper routine: fmt out a null terminated rune string already in hand */
|
||||
int
|
||||
fmtrunestrcpy(Fmt *f, Rune *s)
|
||||
{
|
||||
Rune *e;
|
||||
int n, p;
|
||||
|
||||
if(!s)
|
||||
return __fmtcpy(f, "<nil>", 5, 5);
|
||||
/* if precision is specified, make sure we don't wander off the end */
|
||||
if(f->flags & FmtPrec){
|
||||
p = f->prec;
|
||||
for(n = 0; n < p; n++)
|
||||
if(s[n] == 0)
|
||||
break;
|
||||
}else{
|
||||
for(e = s; *e; e++)
|
||||
;
|
||||
n = e - s;
|
||||
}
|
||||
return __fmtrcpy(f, s, n);
|
||||
}
|
||||
|
||||
/* fmt out a null terminated rune string */
|
||||
int
|
||||
__runesfmt(Fmt *f)
|
||||
{
|
||||
Rune *s;
|
||||
|
||||
s = va_arg(f->args, Rune *);
|
||||
return fmtrunestrcpy(f, s);
|
||||
}
|
||||
|
||||
/* fmt a % */
|
||||
int
|
||||
__percentfmt(Fmt *f)
|
||||
{
|
||||
Rune x[1];
|
||||
|
||||
x[0] = f->r;
|
||||
f->prec = 1;
|
||||
return __fmtrcpy(f, (const void*)x, 1);
|
||||
}
|
||||
|
||||
/* fmt an integer */
|
||||
int
|
||||
__ifmt(Fmt *f)
|
||||
{
|
||||
char buf[70], *p, *conv;
|
||||
uvlong vu;
|
||||
ulong u;
|
||||
int neg, base, i, n, fl, w, isv;
|
||||
|
||||
neg = 0;
|
||||
fl = f->flags;
|
||||
isv = 0;
|
||||
vu = 0;
|
||||
u = 0;
|
||||
/*
|
||||
* Unsigned verbs
|
||||
*/
|
||||
switch(f->r){
|
||||
case 'o':
|
||||
case 'u':
|
||||
case 'x':
|
||||
case 'X':
|
||||
fl |= FmtUnsigned;
|
||||
break;
|
||||
}
|
||||
if(f->r == 'p'){
|
||||
u = (ulong)va_arg(f->args, void*);
|
||||
f->r = 'x';
|
||||
fl |= FmtUnsigned;
|
||||
}else if(fl & FmtVLong){
|
||||
isv = 1;
|
||||
if(fl & FmtUnsigned)
|
||||
vu = va_arg(f->args, uvlong);
|
||||
else
|
||||
vu = va_arg(f->args, vlong);
|
||||
}else if(fl & FmtLong){
|
||||
if(fl & FmtUnsigned)
|
||||
u = va_arg(f->args, ulong);
|
||||
else
|
||||
u = va_arg(f->args, long);
|
||||
}else if(fl & FmtByte){
|
||||
if(fl & FmtUnsigned)
|
||||
u = (uchar)va_arg(f->args, int);
|
||||
else
|
||||
u = (char)va_arg(f->args, int);
|
||||
}else if(fl & FmtShort){
|
||||
if(fl & FmtUnsigned)
|
||||
u = (ushort)va_arg(f->args, int);
|
||||
else
|
||||
u = (short)va_arg(f->args, int);
|
||||
}else{
|
||||
if(fl & FmtUnsigned)
|
||||
u = va_arg(f->args, uint);
|
||||
else
|
||||
u = va_arg(f->args, int);
|
||||
}
|
||||
conv = "0123456789abcdef";
|
||||
switch(f->r){
|
||||
case 'd':
|
||||
case 'i':
|
||||
base = 10;
|
||||
break;
|
||||
case 'u':
|
||||
base = 10;
|
||||
break;
|
||||
case 'x':
|
||||
base = 16;
|
||||
break;
|
||||
case 'X':
|
||||
base = 16;
|
||||
conv = "0123456789ABCDEF";
|
||||
break;
|
||||
case 'b':
|
||||
base = 2;
|
||||
break;
|
||||
case 'o':
|
||||
base = 8;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
if(!(fl & FmtUnsigned)){
|
||||
if(isv && (vlong)vu < 0){
|
||||
vu = -(vlong)vu;
|
||||
neg = 1;
|
||||
}else if(!isv && (long)u < 0){
|
||||
u = -(long)u;
|
||||
neg = 1;
|
||||
}
|
||||
}else{
|
||||
fl &= ~(FmtSign|FmtSpace); /* no + for unsigned conversions */
|
||||
}
|
||||
p = buf + sizeof buf - 1;
|
||||
n = 0;
|
||||
if(isv){
|
||||
while(vu){
|
||||
i = vu % base;
|
||||
vu /= base;
|
||||
if((fl & FmtComma) && n % 4 == 3){
|
||||
*p-- = ',';
|
||||
n++;
|
||||
}
|
||||
*p-- = conv[i];
|
||||
n++;
|
||||
}
|
||||
}else{
|
||||
while(u){
|
||||
i = u % base;
|
||||
u /= base;
|
||||
if((fl & FmtComma) && n % 4 == 3){
|
||||
*p-- = ',';
|
||||
n++;
|
||||
}
|
||||
*p-- = conv[i];
|
||||
n++;
|
||||
}
|
||||
}
|
||||
if(n == 0){
|
||||
if(!(fl & FmtPrec) || f->prec != 0){
|
||||
*p-- = '0';
|
||||
n = 1;
|
||||
}
|
||||
fl &= ~FmtSharp;
|
||||
}
|
||||
for(w = f->prec; n < w && p > buf+3; n++)
|
||||
*p-- = '0';
|
||||
if(neg || (fl & (FmtSign|FmtSpace)))
|
||||
n++;
|
||||
if(fl & FmtSharp){
|
||||
if(base == 16)
|
||||
n += 2;
|
||||
else if(base == 8){
|
||||
if(p[1] == '0')
|
||||
fl &= ~FmtSharp;
|
||||
else
|
||||
n++;
|
||||
}
|
||||
}
|
||||
if((fl & FmtZero) && !(fl & (FmtLeft|FmtPrec))){
|
||||
for(w = f->width; n < w && p > buf+3; n++)
|
||||
*p-- = '0';
|
||||
f->width = 0;
|
||||
}
|
||||
if(fl & FmtSharp){
|
||||
if(base == 16)
|
||||
*p-- = f->r;
|
||||
if(base == 16 || base == 8)
|
||||
*p-- = '0';
|
||||
}
|
||||
if(neg)
|
||||
*p-- = '-';
|
||||
else if(fl & FmtSign)
|
||||
*p-- = '+';
|
||||
else if(fl & FmtSpace)
|
||||
*p-- = ' ';
|
||||
f->flags &= ~FmtPrec;
|
||||
return __fmtcpy(f, p + 1, n, n);
|
||||
}
|
||||
|
||||
int
|
||||
__countfmt(Fmt *f)
|
||||
{
|
||||
void *p;
|
||||
ulong fl;
|
||||
|
||||
fl = f->flags;
|
||||
p = va_arg(f->args, void*);
|
||||
if(fl & FmtVLong){
|
||||
*(vlong*)p = f->nfmt;
|
||||
}else if(fl & FmtLong){
|
||||
*(long*)p = f->nfmt;
|
||||
}else if(fl & FmtByte){
|
||||
*(char*)p = f->nfmt;
|
||||
}else if(fl & FmtShort){
|
||||
*(short*)p = f->nfmt;
|
||||
}else{
|
||||
*(int*)p = f->nfmt;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
__flagfmt(Fmt *f)
|
||||
{
|
||||
switch(f->r){
|
||||
case ',':
|
||||
f->flags |= FmtComma;
|
||||
break;
|
||||
case '-':
|
||||
f->flags |= FmtLeft;
|
||||
break;
|
||||
case '+':
|
||||
f->flags |= FmtSign;
|
||||
break;
|
||||
case '#':
|
||||
f->flags |= FmtSharp;
|
||||
break;
|
||||
case ' ':
|
||||
f->flags |= FmtSpace;
|
||||
break;
|
||||
case 'u':
|
||||
f->flags |= FmtUnsigned;
|
||||
break;
|
||||
case 'h':
|
||||
if(f->flags & FmtShort)
|
||||
f->flags |= FmtByte;
|
||||
f->flags |= FmtShort;
|
||||
break;
|
||||
case 'L':
|
||||
f->flags |= FmtLDouble;
|
||||
break;
|
||||
case 'l':
|
||||
if(f->flags & FmtLong)
|
||||
f->flags |= FmtVLong;
|
||||
f->flags |= FmtLong;
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* default error format */
|
||||
int
|
||||
__badfmt(Fmt *f)
|
||||
{
|
||||
char x[3];
|
||||
|
||||
x[0] = '%';
|
||||
x[1] = f->r;
|
||||
x[2] = '%';
|
||||
f->prec = 3;
|
||||
__fmtcpy(f, (const void*)x, 3, 3);
|
||||
return 0;
|
||||
}
|
||||
61
src/libfmt/dorfmt.c
Normal file
61
src/libfmt/dorfmt.c
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* The authors of this software are Rob Pike and Ken Thompson.
|
||||
* Copyright (c) 2002 by Lucent Technologies.
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose without fee is hereby granted, provided that this entire notice
|
||||
* is included in all copies of any software which is or includes a copy
|
||||
* or modification of this software and in all copies of the supporting
|
||||
* documentation for such software.
|
||||
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
|
||||
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
|
||||
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
|
||||
*/
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include "utf.h"
|
||||
#include "fmt.h"
|
||||
#include "fmtdef.h"
|
||||
|
||||
/* format the output into f->to and return the number of characters fmted */
|
||||
|
||||
int
|
||||
dorfmt(Fmt *f, const Rune *fmt)
|
||||
{
|
||||
Rune *rt, *rs;
|
||||
int r;
|
||||
char *t, *s;
|
||||
int nfmt;
|
||||
|
||||
nfmt = f->nfmt;
|
||||
for(;;){
|
||||
if(f->runes){
|
||||
rt = f->to;
|
||||
rs = f->stop;
|
||||
while((r = *fmt++) && r != '%'){
|
||||
FMTRCHAR(f, rt, rs, r);
|
||||
}
|
||||
f->nfmt += rt - (Rune *)f->to;
|
||||
f->to = rt;
|
||||
if(!r)
|
||||
return f->nfmt - nfmt;
|
||||
f->stop = rs;
|
||||
}else{
|
||||
t = f->to;
|
||||
s = f->stop;
|
||||
while((r = *fmt++) && r != '%'){
|
||||
FMTRUNE(f, t, f->stop, r);
|
||||
}
|
||||
f->nfmt += t - (char *)f->to;
|
||||
f->to = t;
|
||||
if(!r)
|
||||
return f->nfmt - nfmt;
|
||||
f->stop = s;
|
||||
}
|
||||
|
||||
fmt = __fmtdispatch(f, fmt, 1);
|
||||
if(fmt == nil)
|
||||
return -1;
|
||||
}
|
||||
return 0; /* not reached */
|
||||
}
|
||||
28
src/libfmt/errfmt.c
Normal file
28
src/libfmt/errfmt.c
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* The authors of this software are Rob Pike and Ken Thompson.
|
||||
* Copyright (c) 2002 by Lucent Technologies.
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose without fee is hereby granted, provided that this entire notice
|
||||
* is included in all copies of any software which is or includes a copy
|
||||
* or modification of this software and in all copies of the supporting
|
||||
* documentation for such software.
|
||||
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
|
||||
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
|
||||
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
|
||||
*/
|
||||
#include <stdarg.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include "utf.h"
|
||||
#include "fmt.h"
|
||||
#include "fmtdef.h"
|
||||
|
||||
int
|
||||
__errfmt(Fmt *f)
|
||||
{
|
||||
char *s;
|
||||
|
||||
s = strerror(errno);
|
||||
return fmtstrcpy(f, s);
|
||||
}
|
||||
610
src/libfmt/fltfmt.c
Normal file
610
src/libfmt/fltfmt.c
Normal file
@@ -0,0 +1,610 @@
|
||||
/*
|
||||
* The authors of this software are Rob Pike and Ken Thompson.
|
||||
* Copyright (c) 2002 by Lucent Technologies.
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose without fee is hereby granted, provided that this entire notice
|
||||
* is included in all copies of any software which is or includes a copy
|
||||
* or modification of this software and in all copies of the supporting
|
||||
* documentation for such software.
|
||||
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
|
||||
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
|
||||
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <float.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <stdarg.h>
|
||||
#include "fmt.h"
|
||||
#include "fmtdef.h"
|
||||
#include "nan.h"
|
||||
|
||||
enum
|
||||
{
|
||||
FDEFLT = 6,
|
||||
NSIGNIF = 17
|
||||
};
|
||||
|
||||
/*
|
||||
* first few powers of 10, enough for about 1/2 of the
|
||||
* total space for doubles.
|
||||
*/
|
||||
static double pows10[] =
|
||||
{
|
||||
1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
|
||||
1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
|
||||
1e20, 1e21, 1e22, 1e23, 1e24, 1e25, 1e26, 1e27, 1e28, 1e29,
|
||||
1e30, 1e31, 1e32, 1e33, 1e34, 1e35, 1e36, 1e37, 1e38, 1e39,
|
||||
1e40, 1e41, 1e42, 1e43, 1e44, 1e45, 1e46, 1e47, 1e48, 1e49,
|
||||
1e50, 1e51, 1e52, 1e53, 1e54, 1e55, 1e56, 1e57, 1e58, 1e59,
|
||||
1e60, 1e61, 1e62, 1e63, 1e64, 1e65, 1e66, 1e67, 1e68, 1e69,
|
||||
1e70, 1e71, 1e72, 1e73, 1e74, 1e75, 1e76, 1e77, 1e78, 1e79,
|
||||
1e80, 1e81, 1e82, 1e83, 1e84, 1e85, 1e86, 1e87, 1e88, 1e89,
|
||||
1e90, 1e91, 1e92, 1e93, 1e94, 1e95, 1e96, 1e97, 1e98, 1e99,
|
||||
1e100, 1e101, 1e102, 1e103, 1e104, 1e105, 1e106, 1e107, 1e108, 1e109,
|
||||
1e110, 1e111, 1e112, 1e113, 1e114, 1e115, 1e116, 1e117, 1e118, 1e119,
|
||||
1e120, 1e121, 1e122, 1e123, 1e124, 1e125, 1e126, 1e127, 1e128, 1e129,
|
||||
1e130, 1e131, 1e132, 1e133, 1e134, 1e135, 1e136, 1e137, 1e138, 1e139,
|
||||
1e140, 1e141, 1e142, 1e143, 1e144, 1e145, 1e146, 1e147, 1e148, 1e149,
|
||||
1e150, 1e151, 1e152, 1e153, 1e154, 1e155, 1e156, 1e157, 1e158, 1e159,
|
||||
};
|
||||
|
||||
static double
|
||||
pow10(int n)
|
||||
{
|
||||
double d;
|
||||
int neg;
|
||||
|
||||
neg = 0;
|
||||
if(n < 0){
|
||||
if(n < DBL_MIN_10_EXP){
|
||||
return 0.;
|
||||
}
|
||||
neg = 1;
|
||||
n = -n;
|
||||
}else if(n > DBL_MAX_10_EXP){
|
||||
return HUGE_VAL;
|
||||
}
|
||||
if(n < (int)(sizeof(pows10)/sizeof(pows10[0])))
|
||||
d = pows10[n];
|
||||
else{
|
||||
d = pows10[sizeof(pows10)/sizeof(pows10[0]) - 1];
|
||||
for(;;){
|
||||
n -= sizeof(pows10)/sizeof(pows10[0]) - 1;
|
||||
if(n < (int)(sizeof(pows10)/sizeof(pows10[0]))){
|
||||
d *= pows10[n];
|
||||
break;
|
||||
}
|
||||
d *= pows10[sizeof(pows10)/sizeof(pows10[0]) - 1];
|
||||
}
|
||||
}
|
||||
if(neg){
|
||||
return 1./d;
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
static int
|
||||
xadd(char *a, int n, int v)
|
||||
{
|
||||
char *b;
|
||||
int c;
|
||||
|
||||
if(n < 0 || n >= NSIGNIF)
|
||||
return 0;
|
||||
for(b = a+n; b >= a; b--) {
|
||||
c = *b + v;
|
||||
if(c <= '9') {
|
||||
*b = c;
|
||||
return 0;
|
||||
}
|
||||
*b = '0';
|
||||
v = 1;
|
||||
}
|
||||
*a = '1'; /* overflow adding */
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
xsub(char *a, int n, int v)
|
||||
{
|
||||
char *b;
|
||||
int c;
|
||||
|
||||
for(b = a+n; b >= a; b--) {
|
||||
c = *b - v;
|
||||
if(c >= '0') {
|
||||
*b = c;
|
||||
return 0;
|
||||
}
|
||||
*b = '9';
|
||||
v = 1;
|
||||
}
|
||||
*a = '9'; /* underflow subtracting */
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
xaddexp(char *p, int e)
|
||||
{
|
||||
char se[9];
|
||||
int i;
|
||||
|
||||
*p++ = 'e';
|
||||
if(e < 0) {
|
||||
*p++ = '-';
|
||||
e = -e;
|
||||
}
|
||||
i = 0;
|
||||
while(e) {
|
||||
se[i++] = e % 10 + '0';
|
||||
e /= 10;
|
||||
}
|
||||
if(i == 0) {
|
||||
*p++ = '0';
|
||||
} else {
|
||||
while(i > 0)
|
||||
*p++ = se[--i];
|
||||
}
|
||||
*p++ = '\0';
|
||||
}
|
||||
|
||||
static char*
|
||||
xdodtoa(char *s1, double f, int chr, int prec, int *decpt, int *rsign)
|
||||
{
|
||||
char s2[NSIGNIF+10];
|
||||
double g, h;
|
||||
int e, d, i;
|
||||
int c2, sign, oerr;
|
||||
|
||||
if(chr == 'F')
|
||||
chr = 'f';
|
||||
if(prec > NSIGNIF)
|
||||
prec = NSIGNIF;
|
||||
if(prec < 0)
|
||||
prec = 0;
|
||||
if(__isNaN(f)) {
|
||||
*decpt = 9999;
|
||||
*rsign = 0;
|
||||
strcpy(s1, "nan");
|
||||
return &s1[3];
|
||||
}
|
||||
sign = 0;
|
||||
if(f < 0) {
|
||||
f = -f;
|
||||
sign++;
|
||||
}
|
||||
*rsign = sign;
|
||||
if(__isInf(f, 1) || __isInf(f, -1)) {
|
||||
*decpt = 9999;
|
||||
strcpy(s1, "inf");
|
||||
return &s1[3];
|
||||
}
|
||||
|
||||
e = 0;
|
||||
g = f;
|
||||
if(g != 0) {
|
||||
frexp(f, &e);
|
||||
e = (int)(e * .301029995664);
|
||||
if(e >= -150 && e <= +150) {
|
||||
d = 0;
|
||||
h = f;
|
||||
} else {
|
||||
d = e/2;
|
||||
h = f * pow10(-d);
|
||||
}
|
||||
g = h * pow10(d-e);
|
||||
while(g < 1) {
|
||||
e--;
|
||||
g = h * pow10(d-e);
|
||||
}
|
||||
while(g >= 10) {
|
||||
e++;
|
||||
g = h * pow10(d-e);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* convert NSIGNIF digits and convert
|
||||
* back to get accuracy.
|
||||
*/
|
||||
for(i=0; i<NSIGNIF; i++) {
|
||||
d = (int)g;
|
||||
s1[i] = d + '0';
|
||||
g = (g - d) * 10;
|
||||
}
|
||||
s1[i] = 0;
|
||||
|
||||
/*
|
||||
* try decimal rounding to eliminate 9s
|
||||
*/
|
||||
c2 = prec + 1;
|
||||
if(chr == 'f')
|
||||
c2 += e;
|
||||
oerr = errno;
|
||||
if(c2 >= NSIGNIF-2) {
|
||||
strcpy(s2, s1);
|
||||
d = e;
|
||||
s1[NSIGNIF-2] = '0';
|
||||
s1[NSIGNIF-1] = '0';
|
||||
xaddexp(s1+NSIGNIF, e-NSIGNIF+1);
|
||||
g = fmtstrtod(s1, nil);
|
||||
if(g == f)
|
||||
goto found;
|
||||
if(xadd(s1, NSIGNIF-3, 1)) {
|
||||
e++;
|
||||
xaddexp(s1+NSIGNIF, e-NSIGNIF+1);
|
||||
}
|
||||
g = fmtstrtod(s1, nil);
|
||||
if(g == f)
|
||||
goto found;
|
||||
strcpy(s1, s2);
|
||||
e = d;
|
||||
}
|
||||
|
||||
/*
|
||||
* convert back so s1 gets exact answer
|
||||
*/
|
||||
for(d = 0; d < 10; d++) {
|
||||
xaddexp(s1+NSIGNIF, e-NSIGNIF+1);
|
||||
g = fmtstrtod(s1, nil);
|
||||
if(f > g) {
|
||||
if(xadd(s1, NSIGNIF-1, 1))
|
||||
e--;
|
||||
continue;
|
||||
}
|
||||
if(f < g) {
|
||||
if(xsub(s1, NSIGNIF-1, 1))
|
||||
e++;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
found:
|
||||
errno = oerr;
|
||||
|
||||
/*
|
||||
* sign
|
||||
*/
|
||||
d = 0;
|
||||
i = 0;
|
||||
|
||||
/*
|
||||
* round & adjust 'f' digits
|
||||
*/
|
||||
c2 = prec + 1;
|
||||
if(chr == 'f'){
|
||||
if(xadd(s1, c2+e, 5))
|
||||
e++;
|
||||
c2 += e;
|
||||
if(c2 < 0){
|
||||
c2 = 0;
|
||||
e = -prec - 1;
|
||||
}
|
||||
}else{
|
||||
if(xadd(s1, c2, 5))
|
||||
e++;
|
||||
}
|
||||
if(c2 > NSIGNIF){
|
||||
c2 = NSIGNIF;
|
||||
}
|
||||
|
||||
*decpt = e + 1;
|
||||
|
||||
/*
|
||||
* terminate the converted digits
|
||||
*/
|
||||
s1[c2] = '\0';
|
||||
return &s1[c2];
|
||||
}
|
||||
|
||||
/*
|
||||
* this function works like the standard dtoa, if you want it.
|
||||
*/
|
||||
#if 0
|
||||
static char*
|
||||
__dtoa(double f, int mode, int ndigits, int *decpt, int *rsign, char **rve)
|
||||
{
|
||||
static char s2[NSIGNIF + 10];
|
||||
char *es;
|
||||
int chr, prec;
|
||||
|
||||
switch(mode) {
|
||||
/* like 'e' */
|
||||
case 2:
|
||||
case 4:
|
||||
case 6:
|
||||
case 8:
|
||||
chr = 'e';
|
||||
break;
|
||||
/* like 'g' */
|
||||
case 0:
|
||||
case 1:
|
||||
default:
|
||||
chr = 'g';
|
||||
break;
|
||||
/* like 'f' */
|
||||
case 3:
|
||||
case 5:
|
||||
case 7:
|
||||
case 9:
|
||||
chr = 'f';
|
||||
break;
|
||||
}
|
||||
|
||||
if(chr != 'f' && ndigits){
|
||||
ndigits--;
|
||||
}
|
||||
prec = ndigits;
|
||||
if(prec > NSIGNIF)
|
||||
prec = NSIGNIF;
|
||||
if(ndigits == 0)
|
||||
prec = NSIGNIF;
|
||||
es = xdodtoa(s2, f, chr, prec, decpt, rsign);
|
||||
|
||||
/*
|
||||
* strip trailing 0
|
||||
*/
|
||||
for(; es > s2 + 1; es--){
|
||||
if(es[-1] != '0'){
|
||||
break;
|
||||
}
|
||||
}
|
||||
*es = '\0';
|
||||
if(rve != NULL)
|
||||
*rve = es;
|
||||
return s2;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
fmtzdotpad(Fmt *f, int n, int pt)
|
||||
{
|
||||
char *t, *s;
|
||||
int i;
|
||||
Rune *rt, *rs;
|
||||
|
||||
if(f->runes){
|
||||
rt = (Rune*)f->to;
|
||||
rs = (Rune*)f->stop;
|
||||
for(i = 0; i < n; i++){
|
||||
if(i == pt){
|
||||
FMTRCHAR(f, rt, rs, '.');
|
||||
}
|
||||
FMTRCHAR(f, rt, rs, '0');
|
||||
}
|
||||
f->nfmt += rt - (Rune*)f->to;
|
||||
f->to = rt;
|
||||
}else{
|
||||
t = (char*)f->to;
|
||||
s = (char*)f->stop;
|
||||
for(i = 0; i < n; i++){
|
||||
if(i == pt){
|
||||
FMTCHAR(f, t, s, '.');
|
||||
}
|
||||
FMTCHAR(f, t, s, '0');
|
||||
}
|
||||
f->nfmt += t - (char *)f->to;
|
||||
f->to = t;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
__efgfmt(Fmt *fmt)
|
||||
{
|
||||
double f;
|
||||
char s1[NSIGNIF+10];
|
||||
int e, d, n;
|
||||
int c1, c2, c3, c4, ucase, sign, chr, prec, fl;
|
||||
|
||||
f = va_arg(fmt->args, double);
|
||||
prec = FDEFLT;
|
||||
fl = fmt->flags;
|
||||
fmt->flags = 0;
|
||||
if(fl & FmtPrec)
|
||||
prec = fmt->prec;
|
||||
chr = fmt->r;
|
||||
ucase = 0;
|
||||
if(chr == 'E'){
|
||||
chr = 'e';
|
||||
ucase = 1;
|
||||
}else if(chr == 'F'){
|
||||
chr = 'f';
|
||||
ucase = 1;
|
||||
}else if(chr == 'G'){
|
||||
chr = 'g';
|
||||
ucase = 1;
|
||||
}
|
||||
if(prec > 0 && chr == 'g')
|
||||
prec--;
|
||||
if(prec < 0)
|
||||
prec = 0;
|
||||
|
||||
xdodtoa(s1, f, chr, prec, &e, &sign);
|
||||
e--;
|
||||
if(*s1 == 'i' || *s1 == 'n'){
|
||||
if(ucase){
|
||||
if(*s1 == 'i'){
|
||||
strcpy(s1, "INF");
|
||||
}else{
|
||||
strcpy(s1, "NAN");
|
||||
}
|
||||
}
|
||||
fmt->flags = fl & (FmtWidth|FmtLeft);
|
||||
return __fmtcpy(fmt, (const void*)s1, 3, 3);
|
||||
}
|
||||
|
||||
/*
|
||||
* copy into final place
|
||||
* c1 digits of leading '0'
|
||||
* c2 digits from conversion
|
||||
* c3 digits of trailing '0'
|
||||
* c4 digits after '.'
|
||||
*/
|
||||
c1 = 0;
|
||||
c2 = prec + 1;
|
||||
c3 = 0;
|
||||
c4 = prec;
|
||||
switch(chr) {
|
||||
default:
|
||||
chr = 'e';
|
||||
break;
|
||||
case 'g':
|
||||
/*
|
||||
* decide on 'e' of 'f' style convers
|
||||
*/
|
||||
if(e >= -4 && e <= prec) {
|
||||
c1 = -e;
|
||||
c4 = prec - e;
|
||||
chr = 'h'; /* flag for 'f' style */
|
||||
}
|
||||
break;
|
||||
case 'f':
|
||||
c1 = -e;
|
||||
if(c1 > prec)
|
||||
c1 = prec + 1;
|
||||
c2 += e;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* clean up c1 c2 and c3
|
||||
*/
|
||||
if(c1 < 0)
|
||||
c1 = 0;
|
||||
if(c2 < 0)
|
||||
c2 = 0;
|
||||
if(c2 > NSIGNIF) {
|
||||
c3 = c2-NSIGNIF;
|
||||
c2 = NSIGNIF;
|
||||
}
|
||||
|
||||
/*
|
||||
* trim trailing zeros for %g
|
||||
*/
|
||||
if(!(fl & FmtSharp)
|
||||
&& (chr == 'g' || chr == 'h')){
|
||||
if(c4 >= c3){
|
||||
c4 -= c3;
|
||||
c3 = 0;
|
||||
}else{
|
||||
c3 -= c4;
|
||||
c4 = 0;
|
||||
}
|
||||
while(c4 && c2 > 1 && s1[c2 - 1] == '0'){
|
||||
c4--;
|
||||
c2--;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* calculate the total length
|
||||
*/
|
||||
n = c1 + c2 + c3;
|
||||
if(sign || (fl & (FmtSign|FmtSpace)))
|
||||
n++;
|
||||
if(c4 || (fl & FmtSharp)){
|
||||
n++;
|
||||
}
|
||||
if(chr == 'e' || chr == 'g'){
|
||||
n += 4;
|
||||
if(e >= 100)
|
||||
n++;
|
||||
}
|
||||
|
||||
/*
|
||||
* pad to width if right justified
|
||||
*/
|
||||
if((fl & (FmtWidth|FmtLeft)) == FmtWidth && n < fmt->width){
|
||||
if(fl & FmtZero){
|
||||
c1 += fmt->width - n;
|
||||
}else{
|
||||
if(__fmtpad(fmt, fmt->width - n) < 0){
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* sign
|
||||
*/
|
||||
d = 0;
|
||||
if(sign)
|
||||
d = '-';
|
||||
else if(fl & FmtSign)
|
||||
d = '+';
|
||||
else if(fl & FmtSpace)
|
||||
d = ' ';
|
||||
if(d && fmtrune(fmt, d) < 0){
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* copy digits
|
||||
*/
|
||||
c4 = c1 + c2 + c3 - c4;
|
||||
if(c1 > 0){
|
||||
if(fmtzdotpad(fmt, c1, c4) < 0){
|
||||
return -1;
|
||||
}
|
||||
c4 -= c1;
|
||||
}
|
||||
d = 0;
|
||||
if(c4 >= 0 && c4 < c2){
|
||||
if(__fmtcpy(fmt, s1, c4, c4) < 0 || fmtrune(fmt, '.') < 0)
|
||||
return -1;
|
||||
d = c4;
|
||||
c2 -= c4;
|
||||
c4 = -1;
|
||||
}
|
||||
if(__fmtcpy(fmt, (const void*)(s1 + d), c2, c2) < 0){
|
||||
return -1;
|
||||
}
|
||||
c4 -= c2;
|
||||
if(c3 > 0){
|
||||
if(fmtzdotpad(fmt, c3, c4) < 0){
|
||||
return -1;
|
||||
}
|
||||
c4 -= c3;
|
||||
}
|
||||
|
||||
/*
|
||||
* strip trailing '0' on g conv
|
||||
*/
|
||||
if((fl & FmtSharp) && c4 == 0 && fmtrune(fmt, '.') < 0){
|
||||
return -1;
|
||||
}
|
||||
if(chr == 'e' || chr == 'g') {
|
||||
d = 0;
|
||||
if(ucase)
|
||||
s1[d++] = 'E';
|
||||
else
|
||||
s1[d++] = 'e';
|
||||
c1 = e;
|
||||
if(c1 < 0) {
|
||||
s1[d++] = '-';
|
||||
c1 = -c1;
|
||||
} else
|
||||
s1[d++] = '+';
|
||||
if(c1 >= 100) {
|
||||
s1[d++] = c1/100 + '0';
|
||||
c1 = c1%100;
|
||||
}
|
||||
s1[d++] = c1/10 + '0';
|
||||
s1[d++] = c1%10 + '0';
|
||||
if(__fmtcpy(fmt, s1, d, d) < 0){
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if((fl & (FmtWidth|FmtLeft)) == (FmtWidth|FmtLeft) && n < fmt->width){
|
||||
if(__fmtpad(fmt, fmt->width - n) < 0){
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
221
src/libfmt/fmt.c
Normal file
221
src/libfmt/fmt.c
Normal file
@@ -0,0 +1,221 @@
|
||||
/*
|
||||
* The authors of this software are Rob Pike and Ken Thompson.
|
||||
* Copyright (c) 2002 by Lucent Technologies.
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose without fee is hereby granted, provided that this entire notice
|
||||
* is included in all copies of any software which is or includes a copy
|
||||
* or modification of this software and in all copies of the supporting
|
||||
* documentation for such software.
|
||||
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
|
||||
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
|
||||
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
|
||||
*/
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include "utf.h"
|
||||
#include "fmt.h"
|
||||
#include "fmtdef.h"
|
||||
|
||||
enum
|
||||
{
|
||||
Maxfmt = 64
|
||||
};
|
||||
|
||||
typedef struct Convfmt Convfmt;
|
||||
struct Convfmt
|
||||
{
|
||||
int c;
|
||||
volatile Fmts fmt; /* for spin lock in fmtfmt; avoids race due to write order */
|
||||
};
|
||||
|
||||
struct
|
||||
{
|
||||
/* lock by calling __fmtlock, __fmtunlock */
|
||||
int nfmt;
|
||||
Convfmt fmt[Maxfmt];
|
||||
} fmtalloc;
|
||||
|
||||
static Convfmt knownfmt[] = {
|
||||
' ', __flagfmt,
|
||||
'#', __flagfmt,
|
||||
'%', __percentfmt,
|
||||
'+', __flagfmt,
|
||||
',', __flagfmt,
|
||||
'-', __flagfmt,
|
||||
'C', __runefmt, /* Plan 9 addition */
|
||||
'E', __efgfmt,
|
||||
'F', __efgfmt, /* ANSI only */
|
||||
'G', __efgfmt,
|
||||
'L', __flagfmt, /* ANSI only */
|
||||
'S', __runesfmt, /* Plan 9 addition */
|
||||
'X', __ifmt,
|
||||
'b', __ifmt, /* Plan 9 addition */
|
||||
'c', __charfmt,
|
||||
'd', __ifmt,
|
||||
'e', __efgfmt,
|
||||
'f', __efgfmt,
|
||||
'g', __efgfmt,
|
||||
'h', __flagfmt,
|
||||
'i', __ifmt, /* ANSI only */
|
||||
'l', __flagfmt,
|
||||
'n', __countfmt,
|
||||
'o', __ifmt,
|
||||
'p', __ifmt,
|
||||
'r', __errfmt,
|
||||
's', __strfmt,
|
||||
'u', __ifmt, /* in Plan 9, __flagfmt */
|
||||
'x', __ifmt,
|
||||
0, nil,
|
||||
};
|
||||
|
||||
|
||||
int (*fmtdoquote)(int);
|
||||
|
||||
/*
|
||||
* __fmtlock() must be set
|
||||
*/
|
||||
static int
|
||||
__fmtinstall(int c, Fmts f)
|
||||
{
|
||||
Convfmt *p, *ep;
|
||||
|
||||
if(c<=0 || c>=65536)
|
||||
return -1;
|
||||
if(!f)
|
||||
f = __badfmt;
|
||||
|
||||
ep = &fmtalloc.fmt[fmtalloc.nfmt];
|
||||
for(p=fmtalloc.fmt; p<ep; p++)
|
||||
if(p->c == c)
|
||||
break;
|
||||
|
||||
if(p == &fmtalloc.fmt[Maxfmt])
|
||||
return -1;
|
||||
|
||||
p->fmt = f;
|
||||
if(p == ep){ /* installing a new format character */
|
||||
fmtalloc.nfmt++;
|
||||
p->c = c;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
fmtinstall(int c, Fmts f)
|
||||
{
|
||||
int ret;
|
||||
|
||||
__fmtlock();
|
||||
ret = __fmtinstall(c, f);
|
||||
__fmtunlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
static Fmts
|
||||
fmtfmt(int c)
|
||||
{
|
||||
Convfmt *p, *ep;
|
||||
|
||||
ep = &fmtalloc.fmt[fmtalloc.nfmt];
|
||||
for(p=fmtalloc.fmt; p<ep; p++)
|
||||
if(p->c == c){
|
||||
while(p->fmt == nil) /* loop until value is updated */
|
||||
;
|
||||
return p->fmt;
|
||||
}
|
||||
|
||||
/* is this a predefined format char? */
|
||||
__fmtlock();
|
||||
for(p=knownfmt; p->c; p++)
|
||||
if(p->c == c){
|
||||
__fmtinstall(p->c, p->fmt);
|
||||
__fmtunlock();
|
||||
return p->fmt;
|
||||
}
|
||||
__fmtunlock();
|
||||
|
||||
return __badfmt;
|
||||
}
|
||||
|
||||
void*
|
||||
__fmtdispatch(Fmt *f, void *fmt, int isrunes)
|
||||
{
|
||||
Rune rune, r;
|
||||
int i, n;
|
||||
|
||||
f->flags = 0;
|
||||
f->width = f->prec = 0;
|
||||
|
||||
for(;;){
|
||||
if(isrunes){
|
||||
r = *(Rune*)fmt;
|
||||
fmt = (Rune*)fmt + 1;
|
||||
}else{
|
||||
fmt = (char*)fmt + chartorune(&rune, (char*)fmt);
|
||||
r = rune;
|
||||
}
|
||||
f->r = r;
|
||||
switch(r){
|
||||
case '\0':
|
||||
return nil;
|
||||
case '.':
|
||||
f->flags |= FmtWidth|FmtPrec;
|
||||
continue;
|
||||
case '0':
|
||||
if(!(f->flags & FmtWidth)){
|
||||
f->flags |= FmtZero;
|
||||
continue;
|
||||
}
|
||||
/* fall through */
|
||||
case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
i = 0;
|
||||
while(r >= '0' && r <= '9'){
|
||||
i = i * 10 + r - '0';
|
||||
if(isrunes){
|
||||
r = *(Rune*)fmt;
|
||||
fmt = (Rune*)fmt + 1;
|
||||
}else{
|
||||
r = *(char*)fmt;
|
||||
fmt = (char*)fmt + 1;
|
||||
}
|
||||
}
|
||||
if(isrunes)
|
||||
fmt = (Rune*)fmt - 1;
|
||||
else
|
||||
fmt = (char*)fmt - 1;
|
||||
numflag:
|
||||
if(f->flags & FmtWidth){
|
||||
f->flags |= FmtPrec;
|
||||
f->prec = i;
|
||||
}else{
|
||||
f->flags |= FmtWidth;
|
||||
f->width = i;
|
||||
}
|
||||
continue;
|
||||
case '*':
|
||||
i = va_arg(f->args, int);
|
||||
if(i < 0){
|
||||
/*
|
||||
* negative precision =>
|
||||
* ignore the precision.
|
||||
*/
|
||||
if(f->flags & FmtPrec){
|
||||
f->flags &= ~FmtPrec;
|
||||
f->prec = 0;
|
||||
continue;
|
||||
}
|
||||
i = -i;
|
||||
f->flags |= FmtLeft;
|
||||
}
|
||||
goto numflag;
|
||||
}
|
||||
n = (*fmtfmt(r))(f);
|
||||
if(n < 0)
|
||||
return nil;
|
||||
if(n == 0)
|
||||
return fmt;
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user