Compare commits

...

32 commits

Author SHA1 Message Date
xfnw a0ac839193 Merge remote-tracking branch 'origin/front' into front 2022-07-27 16:29:22 -04:00
Ori Bernstein bc64cc50ac auth/box: preserve cwd name, but clear it out
Auth/box previously switched to /, rather than
preserving the cwd. This would break relative
paths to items that would get pulled into the
namespace.

This change removes the '-.' flag, and causes
auth/box to keep the current working directory,
making it more usable for scripting.
2022-07-26 04:57:40 +00:00
Ori Bernstein 520a39efcd sysproc: raise limit on #! lines, and allow quoted args
Our #! line length is very short, and the naïve quoting
makes it difficult to pass more complicated arguments to
the programs being run. This is fine for simple interpreters,
but it's often useful to pass arguments to more complicated
interpreters like auth/box or awk.

This change raises the limit, but also switches to tokenizing
via tokenize(2), rather than hand rolled whitespace splitting.

The limits chosen are arbitrary, but they leave approximately
3 KiB of stack space on 386, and 13k on amd64. This is a lot
of stack used, but it should leave enough for fairly deep
devtab chan stacks.
2022-07-25 04:48:44 +00:00
xfnw a62a6d09b1 Merge remote-tracking branch 'origin/front' into front 2022-07-21 17:46:09 -04:00
cinap_lenrek 3cc07dddfb devrtc: fix mistake. 2022-07-21 00:44:34 +00:00
cinap_lenrek 4063334e6f pc/rtc: make sure string is NUL terminates for rtc write 2022-07-20 18:52:02 +00:00
cinap_lenrek 951ab17262 imx8: add simple i2c rtc driver for NXP PCF8523
datasheet:

http://nxp.com/docs/en/data-sheet/PCF8523.pdf
2022-07-20 18:49:28 +00:00
xfnw 35a6dacb3d fix quotations in werc top bar 2022-07-19 10:42:15 -04:00
xfnw 9d6ef2d008 Merge remote-tracking branch 'origin/front' into front 2022-07-19 10:42:05 -04:00
Ori Bernstein dd8a2d3964 git/log: only count the messages we show when limiting counts
when logging with `git/log -c count', we would count all messages
that we inspected, rather than just the ones that got printed.
This isn't what we should have done.

While we're in here, refactor show() to only show the message,
rather than filtering and then showing.
2022-07-19 03:56:00 +00:00
xfnw 917ae0345f Merge remote-tracking branch 'origin/front' into front 2022-07-18 22:31:02 -04:00
cinap_lenrek d1acc58316 kernel: consistently add devbridge and netdevmedium to kernel configs 2022-07-18 17:19:57 +00:00
glenda d4eb08a860 /sys/games/lib/fortunes: Use a client written in Go? -- Skip Tavakkolian 2022-07-17 22:28:44 +00:00
xfnw de8181a85c oops, fix rioback some more 2022-07-15 13:07:39 -04:00
xfnw 939d1fd742 Merge remote-tracking branch 'origin/front' into front 2022-07-15 09:57:33 -04:00
Sigrid Solveig Haflínudóttir 1c585c2cc2 sam(1): clarify "<rio>" works on dot just like "look" 2022-07-14 21:12:37 +00:00
Sigrid Solveig Haflínudóttir ce2ad9701d imx8: gic: irqenable → intrenable 2022-07-14 01:06:52 +00:00
Ori Bernstein 8f1954c0dd upas/Mail: check if plumb attrs are nil 2022-07-13 21:01:11 +00:00
Benjamin Riefenstahl b3dc2af6d6 man/3/ip (ip): Discuss local IP addresses for "announce" and "bind". 2022-06-11 13:00:05 +00:00
Benjamin Riefenstahl e402fd8340 ape/bsd/bind.c, ape/bsd/listen.c: Use _syserrno. 2022-07-06 03:46:07 +00:00
Benjamin Riefenstahl e01e80c5e7 ape/bsd/listen.c: Drop "bind 0".
There does not seem to be a good reason for this.  The "bind" command
has no practical consequence.
2022-07-06 03:38:17 +00:00
Benjamin Riefenstahl 2ca5abbc2b ape/bsd/bind.c: Do not pretend that the port could be negative.
Ports are filtered through "htons" which returns an "unsigned short".
2022-06-11 12:34:31 +00:00
Benjamin Riefenstahl 25a0d57478 ape/bsd/bind.c, ape/bsd/listen.c: Set local IP.
Despite what the man pages say, local addresses can actually be set so
do that.
2022-06-10 20:39:28 +00:00
Benjamin Riefenstahl d618223086 ape/bsd/listen.c: Do not try to issue "announce *".
"port >= 0" is always true, because the port always gets filtered
through "htons" which returns "unsigned short", so we can just drop
the "else" branch here.

Anyway "announce 0" works fine with the Plan9 API, there is not need
for "announce *" here.
2022-06-10 20:22:39 +00:00
Benjamin Riefenstahl 9fc38d43d4 ape/bsd/bind.c: Do not issue "bind *".
Despite the documentation, "bind *" is invalid and gives the error
"bad numeric port" in devip.c:setladdrport.

"bind 0" OTOH is actually supported fine in the Plan9 API and has the
right sematics.
2022-06-10 16:02:13 +00:00
Jacob Moody 0ec0154bc9 ktrans: don't leak on conflicting jisho lines
Tidy up the hash interface to make cleanup
a bit more explicit vs non cleanup.
2022-07-17 17:51:11 +00:00
cinap_lenrek 23620b2e70 inst: make bootsetup work for on pc architectures 2022-07-17 16:27:15 +00:00
Jacob Moody c147614656 ktrans: 你好
This consolidates jisho and map lookups
to use the same structure and removes
the old jisho code.
2022-07-17 14:52:11 +00:00
cinap_lenrek ccbabf1c16 i2c(3): fix typos, thanks quinq 2022-07-17 14:43:46 +00:00
cinap_lenrek 06d7118e94 i2c(3): Add documentation for kernels devi2c 2022-07-17 14:22:47 +00:00
rodri 467c95b4a8 /lib/ktrans: added tools to fetch skk dicts and convert them to ktrans jishos 2022-07-17 14:10:31 +00:00
glenda 498e9e7d83 /lib/theo: The man page says "don't do that". 2022-07-16 23:56:02 +00:00
41 changed files with 87129 additions and 3370 deletions

83100
lib/hanzi.zidian Normal file

File diff suppressed because it is too large Load diff

12
lib/ktrans/README Normal file
View file

@ -0,0 +1,12 @@
#
# The following are a set of tools to obtain and process dictionaries from the SKK project in order to use them with ktrans(1).
#
# grabskkdicts pulls the skk kana-kanji conversion dictionaries from the skk-dev/dict repo.
# skk2ktrans takes an skk dictionary and converts it into a kanji jisho suitable to be used with ktrans(1).
#
# You can fetch and convert all the dictionaries by running this file.
#
grabskkdicts
for(d in skkdicts/SKK-JISYO.*)
<$d skk2ktrans >$d.jisho

2
lib/ktrans/grabskkdicts Executable file
View file

@ -0,0 +1,2 @@
#!/bin/rc
git/clone https://github.com/skk-dev/dict skkdicts

2
lib/ktrans/skk2ktrans Executable file
View file

@ -0,0 +1,2 @@
#!/bin/rc
tcs -sf jis | awk '$1 !~ /;;/ {gsub("(^\/|\/$)", "", $2); gsub(" ", " "); gsub("\/", " ", $2);} {print}'

View file

@ -956,3 +956,7 @@ I really don't understand the approach being taken here.
I want to understand what the goal here is.
It won't happen.
That is either a funny joke, or it shows you don't understand Unix.
The smallest diffs are the best.
I don't understand what the proposal is.
The man page says "don't do that".
That seems disgustingly verbose to me.

View file

@ -22,16 +22,18 @@ if(~ $#p9part 0){
exit ''
}
echo
echo 'If you use the Windows NT/2000/XP master boot record'
echo 'or a master boot record from a Unix clone (e.g., LILO or'
echo 'FreeBSD bootmgr), it is probably safe to continue using'
echo 'that boot record rather than install the Plan 9 boot record.'
echo
prompt 'Install the Plan 9 master boot record' yes no
switch($rd) {
case yes
disk/mbr -m /386/mbr /dev/$disk/data
if(test -f /386/mbr){
echo
echo 'If you use the Windows NT/2000/XP master boot record'
echo 'or a master boot record from a Unix clone (e.g., LILO or'
echo 'FreeBSD bootmgr), it is probably safe to continue using'
echo 'that boot record rather than install the Plan 9 boot record.'
echo
prompt 'Install the Plan 9 master boot record' yes no
switch($rd) {
case yes
disk/mbr -m /386/mbr /dev/$disk/data
}
}
prompt 'Mark the Plan 9 partition active' yes no

View file

@ -30,17 +30,27 @@ case go
9fat=$rd
export 9fat
bootfile=`{basename $bootfile}
if(~ $#bootfile 1){
bootfile=`{basename $bootfile}
}
if(! ~ $#bootfile 1 || ! test -f /$cputype/$bootfile) {
bootfile=()
}
if(! test -f /tmp/plan9.ini) {
@{
echo 'bootfile='^$bootfile
echo 'bootargs=local!'^$fs' '$"fsflags
if(~ $#bootfile 1)
echo 'bootfile='^$bootfile
if(~ $#fs 1)
echo 'bootargs=local!'^$fs' '$"fsflags
if(~ $#nvram 1)
echo 'nvram='^$nvram
echo 'mouseport='^$mouseport
echo 'monitor='^$monitor
echo 'vgasize='^$vgasize
if(~ $#mouseport 1)
echo 'mouseport='^$mouseport
if(~ $#monitor 1)
echo 'monitor='^$monitor
if(~ $#vgasize 1)
echo 'vgasize='^$vgasize
cd '#ec'
for(i in *){
echo -n $"i'='
@ -72,32 +82,50 @@ case go
# always make backup of old bootsector
logprog dd -bs 512 -count 1 -if $9fat -of /tmp/pbs.bak
if(~ $need9fatformat yes){
log Initializing Plan 9 FAT partition.
logprog disk/format -r 2 -d -b /n/newfs/386/pbs -l PLAN9 $9fat
if (! test -f /386/pbs) {
if(~ $need9fatformat yes){
log Initializing Plan 9 FAT partition.
logprog disk/format -r 2 -d -l PLAN9 $9fat
}
}
if not {
log Updating bootsector.
logprog disk/format -b /n/newfs/386/pbs $9fat
if(~ $need9fatformat yes){
log Initializing Plan 9 FAT partition.
logprog disk/format -r 2 -d -b /386/pbs -l PLAN9 $9fat
}
if not {
log Updating bootsector.
logprog disk/format -b /386/pbs $9fat
}
}
logprog mount -c /srv/dos /n/9fat $9fat
logprog rm -f /n/9fat/^(9bootfat plan9.ini $bootfile)
if(test -f /386/9bootfat) {
logprog rm -f /n/9fat/9bootfat
logprog cp /386/9bootfat /n/9fat/9bootfat
logprog cp /n/newfs/386/9bootfat /n/9fat/9bootfat
# make file continous on disk
logprog chmod +al /n/9fat/9bootfat
# make file continous on disk
logprog chmod +al /n/9fat/9bootfat
}
# copy config
logprog rm -f /n/9fat/plan9.ini
logprog cp /tmp/plan9.ini /n/9fat/plan9.ini
# copy kernel
logprog cp /n/newfs/$cputype/$bootfile /n/9fat/
if(~ $#bootfile 1){
logprog rm -f /n/9fat/$bootfile
logprog cp /$cputype/$bootfile /n/9fat/$bootfile
}
# copy efi bootloader
logprog mkdir -p /n/9fat/efi/boot
logprog cp /386/^(bootia32.efi bootx64.efi) /n/9fat/efi/boot
for(i in /386/*.efi){
if(test -f $i) {
logprog mkdir -p /n/9fat/efi/boot
logprog cp $i /n/9fat/efi/boot/
}
}
# copy in backups
if(test -f /tmp/oldplan9.ini)

View file

@ -5260,3 +5260,5 @@ MY NAME IS BEING USED IN A PHISHING ATTACK. DO NOT RESPOND TO MAIL OFFERING MON
Xterm.js
GPU.js
Joys of Porting a Kernel to WebAssembly
Never change anything. You can only make it worse. -- Ted Unangst
Use a client written in Go? -- Skip Tavakkolian

View file

@ -835,8 +835,10 @@ used.
The snarf buffer is unaffected.
.TP
.B <rio>
Exchange snarf buffers with
Exchange dot with snarf buffer of
.IR rio .
If dot is the null string, the text in the snarf buffer is
used.
.TP
.BI / regexp
Search forward for the next match of the last regular expression

View file

@ -67,6 +67,11 @@ and any initial arguments to that program, for example
ls | mc
.EE
.PP
There may be up to 256 bytes of arguments passed to the interpreter.
These are tokenized into up to 32 arguments by
.IR tokenize (2)
before being passed as the interpreters argument vector.
.PP
When a C program is executed,
it is called as follows:
.IP

98
sys/man/3/i2c Normal file
View file

@ -0,0 +1,98 @@
.TH I2C 3
.SH NAME
i2c \- I²C Bus Interface
.SH SYNOPSIS
.nf
.B bind -a #J /dev
.PP
.nf
.BI /dev/ bus /i2c. n .ctl
.BI /dev/ bus /i2c. n .data
.SH DESCRIPTION
The I²C (Inter-Integrated Circuit) bus is a serial bus standard
invented by Philips.
It is used to connect chips over short-distances like on a motherboard
or between boards.
The bus requires only a single data signal
.IR SDA ,
a clock signal
.I SDC
and ground.
Devices on the bus have 7-bit or 10-bit addresses, which is
determined by the device (see the datasheet).
Every device monitors the bus and waits for the master to initiate
a transaction.
Each transaction starts with the master sending the target device address
with a direction bit and the device acknowledges each byte
received if its address matched.
Depending on the device, more bytes must be transmitted after the
.IR device-address .
For example, encoding a register number at a memory offset.
We refer to these bytes as the
.IR sub-address .
After the address phase, the data phase begins where
zero or more data bytes are either transmitted or received
depending on the transaction direction.
.PP
This driver supports multiple buses (controllers) to be registered
by platform specific code in the kernel.
Each bus is represented as a directory with a platform specific name.
.PP
Because all received bytes are acknowledged by target devices,
it is possible for the master to enumerate all existing addresses
on a bus, which is done when accessing the
.I bus
directory.
.PP
Platform specific code can also register individual devices,
supplying a meaningful device configuration.
It can also be necessary to manually register devices if
the device has been disabled by an enable signal or
otherwise inhibited during enumeration.
.PP
Each device appears as a control (
.BI i2c. n .ctl
)
and a data file (
.BI i2c. n .data
) in the
.I bus
directory
where
.I n
is the device-address in hexadecimal.
.PP
The data file is used to initiate transactions to the device.
The initial
.I sub-address
bytes sent are derived from the file position according to the device
configuration, and the length of the data phase is controlled by
the requested read or write size.
The requested size might be truncated by the driver if
the request exceeds the logical file-size.
.PP
The control-file provides access to the device configuration.
When read,
it reproduces this configuration in text form.
The following text lines are accepted when written to the control-file:
.TF "subaddress n"
.TP
.BI "subaddress " n
Sets the length
.IR n ,
in bytes, of the sub-address for the device
that is derived from the file-position of the data-file.
This can be set to zero if no sub-address bytes should
be generated by the driver.
By default, the sub-address length is 1.
.TP
.BI "size " n
Changes the logical size of the data-file to
.IR n .
Making sure the file-position is not exceeding this size.
.SH SOURCE
.B /sys/src/9/port/devi2c.c
.SH HISTORY
The file-interface has been inspired by infernos devi2c,
but with the addition of supporting multiple buses
and device enumeration.

View file

@ -682,33 +682,43 @@ Otherwise a free port number starting at 5000 is chosen.
The connect fails if the combination of local and remote address/port pairs
are already assigned to another port.
.TP
.BI announce\ X
.I X
is a decimal port number or
.LR * .
Set the local port
number to
.I X
and accept calls to
.IR X .
If
.I X
is
.BI announce\ [ip-address ! ]port
Set the local IP address and port number and accept calls there. If
ip-address is left out, accept calls on any address. If port is 0, a
port is automatically choosen that is not yet announced.
If the address is
.LR * ,
accept
calls for any port that no process has explicitly announced.
The local IP address cannot be set.
accept calls on any address.
If port is
.LR * ,
accept calls on any port.
If port is
.LR * ,
and the address is left out, accept calls on any address and port.
.B Announce
fails if the connection is already announced or connected.
fails if the connection is already announced.
.TP
.BI bind\ X
.I X
is a decimal port number or
.LR * .
Set the local port number to
.IR X .
This exists to support emulation
of BSD sockets by the APE libraries (see
.BI bind\ [ip-address ! ]port
Set the local IP address and port number like for a server connection
similar to the
.B announce
command.
If ip-address is left out, an address is automatically selected. If
port is 0, a port is automatically choosen that is not yet announced.
This command has no actual effect, beyond remembering the parameters
and possibly selecting an unused port.
The commands
.B announce
and
.B connect
reset both the local address and the port according to their own
parameters.
This command also does
.B not
reserve the IP address and port, another connection can use them, even
while they are registered in a connection by this command.
This exists to support emulation of BSD sockets by the APE libraries
(see
.IR pcc (1))
and is not otherwise used.
.\" this is gone

View file

@ -62,7 +62,7 @@ changeuser, convkeys, printnetkey, status, enable, disable, authsrv, guard.srv,
.PP
.B auth/box
[
.B -d
.B -s
] [
.B -rc
.I file
@ -298,9 +298,8 @@ the child namespace; the
flag specifies a string of driver
characters to keep. The
.B -s
flag gives a base set of namespace
components, ones expected by rc, then passes
the first argument as a script file to rc.
flag initializes the namespace to what rc expects,
and passes its arguments unmodified to /bin/rc.
.PP
.I As
executes

View file

@ -13,7 +13,8 @@ dev
tls
cap
fs
ip arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium inferno
bridge log
ip arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium inferno
draw screen swcursor
mouse mouse
uart gpio
@ -22,10 +23,11 @@ dev
usb
link
loopbackmedium
ethermedium
archbcm
usbdwc
ethermedium
loopbackmedium
netdevmedium
ip
tcp

View file

@ -13,7 +13,8 @@ dev
tls
cap
fs
ip arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium inferno
bridge log
ip arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium inferno
draw screen swcursor
mouse mouse
uart gpio
@ -22,10 +23,11 @@ dev
usb
link
loopbackmedium
ethermedium
archbcm2
usbdwc
ethermedium
loopbackmedium
netdevmedium
ip
tcp

View file

@ -13,7 +13,8 @@ dev
tls
cap
fs
ip arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium inferno
bridge log
ip arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium inferno
draw screen swcursor
mouse mouse
uart gpio
@ -23,10 +24,11 @@ dev
dtracy
link
loopbackmedium
ethermedium
archbcm3
usbdwc
ethermedium
loopbackmedium
netdevmedium
ip
tcp

View file

@ -14,7 +14,8 @@ dev
cap
fs
ether netif
ip arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium inferno
bridge log
ip arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium inferno
draw screen swcursor
mouse mouse
uart gpio
@ -31,6 +32,7 @@ link
ethergenet ethermii
ethermedium
loopbackmedium
netdevmedium
ip
tcp

349
sys/src/9/imx8/devrtc.c Normal file
View file

@ -0,0 +1,349 @@
/*
* NXP PCF8523 real time clock
*/
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "../port/error.h"
#include "../port/i2c.h"
enum {
Seconds= 0x03,
Minutes= 0x04,
Hours= 0x05,
Mday= 0x06,
Wday= 0x07,
Month= 0x08,
Year= 0x09,
Nbcd= 1+Year-Seconds,
};
typedef struct Rtc Rtc;
struct Rtc
{
int sec;
int min;
int hour;
int mday;
int wday;
int mon;
int year;
};
enum{
Qdir = 0,
Qrtc,
};
Dirtab rtcdir[]={
".", {Qdir, 0, QTDIR}, 0, 0555,
"rtc", {Qrtc, 0}, 0, 0664,
};
static ulong rtc2sec(Rtc*);
static void sec2rtc(ulong, Rtc*);
static I2Cdev *i2c;
static Chan*
rtcattach(char* spec)
{
i2c = i2cdev(i2cbus("i2c3"), 0x68);
if(i2c == nil)
error(Enonexist);
i2c->subaddr = 1;
i2c->size = 0x14;
return devattach('r', spec);
}
static Walkqid*
rtcwalk(Chan* c, Chan *nc, char** name, int nname)
{
return devwalk(c, nc, name, nname, rtcdir, nelem(rtcdir), devgen);
}
static int
rtcstat(Chan* c, uchar* dp, int n)
{
return devstat(c, dp, n, rtcdir, nelem(rtcdir), devgen);
}
static Chan*
rtcopen(Chan* c, int omode)
{
omode = openmode(omode);
switch((ulong)c->qid.path){
case Qrtc:
if(strcmp(up->user, eve)!=0 && omode!=OREAD)
error(Eperm);
break;
}
return devopen(c, omode, rtcdir, nelem(rtcdir), devgen);
}
static void
rtcclose(Chan*)
{
}
#define GETBCD(o) (((bcdclock[o]&0xf)%10) + 10*((bcdclock[o]>>4)%10))
static long
_rtctime(void)
{
uchar bcdclock[Nbcd];
Rtc rtc;
/* read clock values */
i2crecv(i2c, bcdclock, Nbcd, Seconds);
/*
* convert from BCD
*/
rtc.sec = GETBCD(Seconds-Seconds) % 60;
rtc.min = GETBCD(Minutes-Seconds) % 60;
rtc.hour = GETBCD(Hours-Seconds) % 24;
rtc.mday = GETBCD(Mday-Seconds);
rtc.wday = GETBCD(Wday-Seconds) % 7;
rtc.mon = GETBCD(Month-Seconds);
rtc.year = GETBCD(Year-Seconds) % 100;
/*
* the world starts jan 1 1970
*/
if(rtc.year < 70)
rtc.year += 2000;
else
rtc.year += 1900;
return rtc2sec(&rtc);
}
long
rtctime(void)
{
int i;
long t, ot;
/* loop till we get two reads in a row the same */
t = _rtctime();
for(i = 0; i < 100; i++){
ot = t;
t = _rtctime();
if(ot == t)
break;
}
if(i == 100) print("we are boofheads\n");
return t;
}
static long
rtcread(Chan* c, void* buf, long n, vlong off)
{
ulong offset = off;
if(c->qid.type & QTDIR)
return devdirread(c, buf, n, rtcdir, nelem(rtcdir), devgen);
switch((ulong)c->qid.path){
case Qrtc:
return readnum(offset, buf, n, rtctime(), 12);
}
error(Ebadarg);
return 0;
}
#define PUTBCD(n,o) bcdclock[o] = (n % 10) | (((n / 10) % 10)<<4)
static long
rtcwrite(Chan* c, void* buf, long n, vlong off)
{
Rtc rtc;
ulong secs;
char *cp, sbuf[32];
uchar bcdclock[Nbcd];
ulong offset = off;
if(offset!=0)
error(Ebadarg);
switch((ulong)c->qid.path){
case Qrtc:
if(n >= sizeof(sbuf))
error(Ebadarg);
strncpy(sbuf, buf, n);
sbuf[n] = '\0';
for(cp = sbuf; *cp != '\0'; cp++)
if(*cp >= '0' && *cp <= '9')
break;
secs = strtoul(cp, 0, 0);
/*
* convert to bcd
*/
sec2rtc(secs, &rtc);
PUTBCD(rtc.sec, Seconds-Seconds);
PUTBCD(rtc.min, Minutes-Seconds);
PUTBCD(rtc.hour, Hours-Seconds);
PUTBCD(rtc.mday, Mday-Seconds);
PUTBCD(rtc.wday, Wday-Seconds);
PUTBCD(rtc.mon, Month-Seconds);
PUTBCD(rtc.year, Year-Seconds);
/*
* write the clock
*/
i2csend(i2c, bcdclock, Nbcd, Seconds);
return n;
}
error(Ebadarg);
return 0;
}
Dev rtcdevtab = {
'r',
"rtc",
devreset,
devinit,
devshutdown,
rtcattach,
rtcwalk,
rtcstat,
rtcopen,
devcreate,
rtcclose,
rtcread,
devbread,
rtcwrite,
devbwrite,
devremove,
devwstat,
};
#define SEC2MIN 60L
#define SEC2HOUR (60L*SEC2MIN)
#define SEC2DAY (24L*SEC2HOUR)
/*
* days per month plus days/year
*/
static int dmsize[] =
{
365, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
};
static int ldmsize[] =
{
366, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
};
/*
* return the days/month for the given year
*/
static int*
yrsize(int y)
{
if((y%4) == 0 && ((y%100) != 0 || (y%400) == 0))
return ldmsize;
else
return dmsize;
}
/*
* compute seconds since Jan 1 1970
*/
static ulong
rtc2sec(Rtc *rtc)
{
ulong secs;
int i;
int *d2m;
secs = 0;
/*
* seconds per year
*/
for(i = 1970; i < rtc->year; i++){
d2m = yrsize(i);
secs += d2m[0] * SEC2DAY;
}
/*
* seconds per month
*/
d2m = yrsize(rtc->year);
for(i = 1; i < rtc->mon; i++)
secs += d2m[i] * SEC2DAY;
secs += (rtc->mday-1) * SEC2DAY;
secs += rtc->hour * SEC2HOUR;
secs += rtc->min * SEC2MIN;
secs += rtc->sec;
return secs;
}
/*
* compute rtc from seconds since Jan 1 1970
*/
static void
sec2rtc(ulong secs, Rtc *rtc)
{
int d;
long hms, day;
int *d2m;
/*
* break initial number into days
*/
hms = secs % SEC2DAY;
day = secs / SEC2DAY;
if(hms < 0) {
hms += SEC2DAY;
day -= 1;
}
/*
* 19700101 was thursday
*/
rtc->wday = (day + 7340036L) % 7;
/*
* generate hours:minutes:seconds
*/
rtc->sec = hms % 60;
d = hms / 60;
rtc->min = d % 60;
d /= 60;
rtc->hour = d;
/*
* year number
*/
if(day >= 0)
for(d = 1970; day >= *yrsize(d); d++)
day -= *yrsize(d);
else
for (d = 1970; day < 0; d--)
day += *yrsize(d-1);
rtc->year = d;
/*
* generate month
*/
d2m = yrsize(rtc->year);
for(d = 1; day >= d2m[d]; d++)
day -= d2m[d];
rtc->mday = day + 1;
rtc->mon = d;
return;
}

View file

@ -265,7 +265,7 @@ intrenable(int irq, void (*f)(Ureg*, void*), void *a, int tbdf, char *)
prio = 0x80;
intid = irq;
if((v = xalloc(sizeof(Vctl))) == nil)
panic("irqenable: no mem");
panic("intrenable: no mem");
v->irq = irq;
v->intid = intid;
v->f = f;

View file

@ -13,12 +13,14 @@ dev
cap
fs
ether netif
bridge log
ip arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium inferno
draw screen swcursor
mouse screen swcursor
uart
usb
i2c
rtc devi2c
sd
link
@ -26,8 +28,10 @@ link
etherimx ethermii
ethermedium
loopbackmedium
netdevmedium
i2cimx devi2c
pciimx pci
ip
tcp
udp

View file

@ -227,26 +227,25 @@ rtcwrite(Chan* c, void* buf, long n, vlong off)
char *a, *start;
Rtc rtc;
ulong secs;
char *cp, sbuf[32];
uchar bcdclock[Nbcd];
char *cp, *ep;
ulong offset = off;
if(offset!=0)
error(Ebadarg);
switch((ulong)c->qid.path){
case Qrtc:
/*
* read the time
*/
cp = ep = buf;
ep += n;
while(cp < ep){
if(*cp>='0' && *cp<='9')
if(n >= sizeof(sbuf))
error(Ebadarg);
strncpy(sbuf, buf, n);
sbuf[n] = '\0';
for(cp = sbuf; *cp != '\0'; cp++)
if(*cp >= '0' && *cp <= '9')
break;
cp++;
}
secs = strtoul(cp, 0, 0);
/*

View file

@ -20,7 +20,7 @@ dev
dtracy
ether netif
bridge netif log
bridge log
ip arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium inferno
draw screen vga vgax vgasoft
@ -81,9 +81,9 @@ link
ethervirtio pci
ethervirtio10 pci
ethermedium
pcmciamodem
netdevmedium
loopbackmedium
netdevmedium
pcmciamodem
usbuhci pci
usbohci pci
usbehci usbehcipc

View file

@ -19,8 +19,8 @@ dev
fs
ether netif
bridge netif log
ip arp chandial ip ipv6 ipaux iproute netlog ethermedium nullmedium pktmedium inferno
bridge log
ip arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium inferno
draw screen vga vgax vgasoft
mouse mouse
@ -79,9 +79,9 @@ link
ethervirtio pci
ethervirtio10 pci
ethermedium
# pcmciamodem
netdevmedium
loopbackmedium
netdevmedium
# pcmciamodem
usbuhci pci
usbohci pci
usbehci pci usbehcipc

View file

@ -243,35 +243,19 @@ sysrfork(va_list list)
}
static int
shargs(char *s, int n, char **ap)
shargs(char *s, int n, char **ap, int nap)
{
char *p;
int i;
if(n <= 2 || s[0] != '#' || s[1] != '!')
return -1;
s += 2;
n -= 2; /* skip #! */
for(i=0;; i++){
if(i >= n)
return 0;
if(s[i]=='\n')
break;
}
s[i] = 0;
i = 0;
for(;;) {
while(*s==' ' || *s=='\t')
s++;
if(*s == 0)
break;
ap[i++] = s++;
while(*s && *s!=' ' && *s!='\t')
s++;
if(*s == 0)
break;
*s++ = 0;
}
if((p = memchr(s, '\n', n)) == nil)
return 0;
*p = 0;
i = tokenize(s, ap, nap-1);
ap[i] = nil;
return i;
}
@ -300,12 +284,15 @@ beswav(uvlong v)
uintptr
sysexec(va_list list)
{
struct {
Exec;
uvlong hdr[1];
} ehdr;
char line[sizeof(ehdr)];
char *progarg[sizeof(line)/2+1];
union {
struct {
Exec;
uvlong hdr[1];
} ehdr;
char buf[256];
} u;
char line[256];
char *progarg[32+1];
volatile char *args, *elem, *file0;
char **argv, **argp, **argp0;
char *a, *e, *charp, *file;
@ -353,22 +340,22 @@ sysexec(va_list list)
if(!indir)
kstrdup(&elem, up->genbuf);
n = devtab[tc->type]->read(tc, &ehdr, sizeof(ehdr), 0);
n = devtab[tc->type]->read(tc, u.buf, sizeof(u.buf), 0);
if(n >= sizeof(Exec)) {
magic = beswal(ehdr.magic);
magic = beswal(u.ehdr.magic);
if(magic == AOUT_MAGIC) {
if(magic & HDR_MAGIC) {
if(n < sizeof(ehdr))
if(n < sizeof(u.ehdr))
error(Ebadexec);
entry = beswav(ehdr.hdr[0]);
text = UTZERO+sizeof(ehdr);
entry = beswav(u.ehdr.hdr[0]);
text = UTZERO+sizeof(u.ehdr);
} else {
entry = beswal(ehdr.entry);
entry = beswal(u.ehdr.entry);
text = UTZERO+sizeof(Exec);
}
if(entry < text)
error(Ebadexec);
text += beswal(ehdr.text);
text += beswal(u.ehdr.text);
if(text <= entry || text >= (USTKTOP-USTKSIZE))
error(Ebadexec);
@ -393,8 +380,8 @@ sysexec(va_list list)
/*
* Process #! /bin/sh args ...
*/
memmove(line, &ehdr, n);
n = shargs(line, n, progarg);
memmove(line, u.buf, n);
n = shargs(line, n, progarg, nelem(progarg));
if(n < 1)
error(Ebadexec);
/*
@ -411,8 +398,8 @@ sysexec(va_list list)
t = (text+align) & ~align;
text -= UTZERO;
data = beswal(ehdr.data);
bss = beswal(ehdr.bss);
data = beswal(u.ehdr.data);
bss = beswal(u.ehdr.bss);
align = BY2PG-1;
d = (t + data + align) & ~align;
bssend = t + data + bss;

View file

@ -11,8 +11,9 @@ dev
env
pipe
dup
ether netif
ip arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium inferno
ether netif
bridge log
ip arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium inferno
tls
cap
kprof

View file

@ -39,6 +39,30 @@ _sock_inport(struct sockaddr *a)
return 0;
}
int
_sock_inisany(int af, void *addr)
{
int alen;
void *any;
/* an IPv4 address that is auto-initialized to all zeros */
static struct in_addr inaddr_any;
switch(af){
case AF_INET:
alen = sizeof inaddr_any.s_addr;
any = &inaddr_any;
break;
case AF_INET6:
alen = sizeof in6addr_any;
any = &in6addr_any;
break;
default:
return 0;
}
return 0 == memcmp(addr, any, alen);
}
int
_sock_inaddr(int af, char *ip, char *port, void *a, int *alen)
{
@ -97,3 +121,23 @@ _sock_ingetaddr(Rock *r, void *a, int *alen, char *file)
close(fd);
}
}
char *
_sock_inaddr2string(Rock *r, char *dest, int dlen)
{
int af = r->domain;
void *addr = _sock_inip(&r->addr);
int port = _sock_inport(&r->addr);
char *d = dest;
char *dend = dest+dlen;
if(!_sock_inisany(af, addr)){
inet_ntop(af, addr, d, dlen-1);
d = memchr(d, 0, dlen-1);
*(d++) = '!';
}
snprintf(d, dend-d, "%d", port);
return dest;
}

View file

@ -24,7 +24,7 @@
int
bind(int fd, void *a, int alen)
{
int n, len, cfd, port;
int n, len, cfd;
struct sockaddr *sa;
Rock *r;
char msg[128];
@ -55,20 +55,25 @@ bind(int fd, void *a, int alen)
errno = EBADF;
return -1;
}
port = _sock_inport(&r->addr);
if(port > 0)
snprintf(msg, sizeof msg, "bind %d", port);
else
strcpy(msg, "bind *");
strcpy(msg, "bind ");
_sock_inaddr2string(r, msg + 5, sizeof msg - 5);
n = write(cfd, msg, strlen(msg));
if(n < 0){
errno = EOPNOTSUPP; /* Improve error reporting!!! */
_syserrno();
if(errno == EPLAN9)
errno = EOPNOTSUPP;
close(cfd);
return -1;
}
close(cfd);
if(port <= 0)
if(_sock_inport(&r->addr) == 0)
_sock_ingetaddr(r, &r->addr, 0, "local");
return 0;
}

View file

@ -121,7 +121,7 @@ listen(fd, backlog)
int backlog;
{
Rock *r;
int n, cfd, port;
int n, cfd;
char msg[128];
struct sockaddr_un *lunix;
@ -139,20 +139,13 @@ listen(fd, backlog)
errno = EBADF;
return -1;
}
port = _sock_inport(&r->addr);
if(port >= 0) {
if(write(cfd, "bind 0", 6) < 0) {
errno = EGREG;
close(cfd);
return -1;
}
snprintf(msg, sizeof msg, "announce %d", port);
}
else
strcpy(msg, "announce *");
strcpy(msg, "announce ");
_sock_inaddr2string(r, msg + 9, sizeof msg - 9);
n = write(cfd, msg, strlen(msg));
if(n < 0){
errno = EOPNOTSUPP; /* Improve error reporting!!! */
_syserrno();
if(errno == EPLAN9)
errno = EOPNOTSUPP;
close(cfd);
return -1;
}

View file

@ -43,5 +43,7 @@ extern int _sock_data(int, char*, int, int, int, Rock**);
extern int _sock_ipattr(char*);
extern void* _sock_inip(struct sockaddr*);
extern int _sock_inport(struct sockaddr*);
extern int _sock_inisany(int af, void *addr);
extern int _sock_inaddr(int, char*, char*, void*, int*);
extern void _sock_ingetaddr(Rock*, void*, int*, char*);
extern char* _sock_inaddr2string(Rock *r, char *dest, int dlen);

View file

@ -2,7 +2,11 @@
#include <libc.h>
#include <auth.h>
static int debug;
static int debug;
static char cwd[8192];
static char *parts[256];
static int mflags[nelem(parts)];
static int nparts;
static void
binderr(char *new, char *old, int flag)
@ -32,20 +36,14 @@ binderr(char *new, char *old, int flag)
fprint(2, "bind %s %s %s\n", dash, new, old);
}
if(bind(new, old, flag) < 0)
sysfatal("bind: %r");
sysfatal("bind %s: %r", new);
}
static void
resolvenames(char **names, int nname)
{
int i;
char buf[8192];
int fd;
fd = open(".", OREAD|OCEXEC);
if(fd < 0)
sysfatal("could not open .: %r");
fd2path(fd, buf, sizeof buf);
for(i = 0; i < nname; i++){
if(names[i] == nil)
continue;
@ -55,10 +53,9 @@ resolvenames(char **names, int nname)
case '/':
break;
default:
names[i] = cleanname(smprint("%s/%s", buf, names[i]));
}
names[i] = cleanname(smprint("%s/%s", cwd, names[i]));
}
}
close(fd);
}
static void
@ -103,7 +100,8 @@ sandbox(char **names, int *flags, int nname)
free(d);
binderr(skel, dir, MBEFORE);
}
binderr(names[j], targ, flags[j]);
if(flags[j] != -1)
binderr(names[j], targ, flags[j]);
}
binderr(newroot, "/", MREPL);
}
@ -133,16 +131,11 @@ skelfs(void)
sysfatal("/mnt/d mount setup: %r");
}
static char *parts[256];
static int mflags[nelem(parts)];
static int nparts;
static char *rc[] = { "/bin/rc", nil , nil};
static void
push(char *path, int flag)
{
if(nparts == nelem(parts))
sysfatal("component overflow");
sysfatal("too many bound paths");
parts[nparts] = path;
mflags[nparts++] = flag;
}
@ -150,23 +143,23 @@ push(char *path, int flag)
void
usage(void)
{
fprint(2, "usage %s: [ -d ] [ -r file ] [ -c dir ] [ -e devs ] [ -. path ] cmd args...\n", argv0);
fprint(2, "usage %s: [ -r file ] [ -c dir ] [ -e devs ] cmd args...\n", argv0);
exits("usage");
}
void
main(int argc, char **argv)
{
char devs[1024];
int dfd;
char *path;
char **argp, devs[128];
int i, narg, dfd;
char *a;
int sflag;
nparts = 0;
path = "/";
narg = 0;
memset(devs, 0, sizeof devs);
sflag = 0;
argp = argv;
ARGBEGIN{
case 'D':
debug++;
@ -184,9 +177,6 @@ main(int argc, char **argv)
case 'e':
snprint(devs, sizeof devs, "%s%s", devs, EARGF(usage()));
break;
case '.':
path = EARGF(usage());
break;
case 's':
sflag = 1;
break;
@ -195,18 +185,19 @@ main(int argc, char **argv)
break;
}ARGEND
if(argc == 0)
if(argc == 0 && !sflag)
usage();
if(getwd(cwd, sizeof(cwd)) == nil)
sysfatal("getwd: %r");
push(cwd, -1);
if(sflag){
snprint(devs, sizeof devs, "%s%s", devs, "|d");
push("/srv", MREPL|MCREATE);
push("/env", MREPL|MCREATE);
push("/rc", MREPL);
push("/bin", MREPL);
push(argv[0], MREPL);
rc[1] = argv[0];
argv = rc;
argp[narg++] = "/bin/rc";
} else {
if(access(argv[0], AEXIST) == -1){
if((argv[0] = smprint("/bin/%s", argv[0])) == nil)
@ -216,6 +207,9 @@ main(int argc, char **argv)
}
push(argv[0], MREPL);
}
for(i = 0; i < argc; i++)
argp[narg++] = argv[i];
argp[narg] = nil;
rfork(RFNAMEG|RFFDG);
skelfs();
@ -225,7 +219,7 @@ main(int argc, char **argv)
resolvenames(parts, nparts);
sandbox(parts, mflags, nparts);
if(debug)
fprint(2, "chdev %s\n", devs);
@ -238,8 +232,8 @@ main(int argc, char **argv)
}
close(dfd);
if(chdir(path) < 0)
sysfatal("can not cd to %s", path);
exec(argv[0], argv);
if(chdir(cwd) < 0)
sysfatal("chdir %s: %r", cwd);
exec(argp[0], argp);
sysfatal("exec: %r");
}

View file

@ -64,7 +64,7 @@ lookup(Pfilt *pf, Object *o)
}
int
filtermatch1(Pfilt *pf, Object *t, Object *pt)
matchesfilter1(Pfilt *pf, Object *t, Object *pt)
{
Object *a, *b;
Hash ha, hb;
@ -88,7 +88,7 @@ filtermatch1(Pfilt *pf, Object *t, Object *pt)
sysfatal("read %H: %r", ha);
if((b = readobject(hb)) == nil)
sysfatal("read %H: %r", hb);
r = filtermatch1(&pf->sub[i], a, b);
r = matchesfilter1(&pf->sub[i], a, b);
unref(a);
unref(b);
if(r)
@ -98,11 +98,12 @@ filtermatch1(Pfilt *pf, Object *t, Object *pt)
}
int
filtermatch(Object *o)
matchesfilter(Object *o)
{
Object *t, *p, *pt;
int i, r;
assert(o->type == GCommit);
if(pathfilt == nil)
return 1;
if((t = readobject(o->commit->tree)) == nil)
@ -112,7 +113,7 @@ filtermatch(Object *o)
sysfatal("read %H: %r", o->commit->parent[i]);
if((pt = readobject(p->commit->tree)) == nil)
sysfatal("read %H: %r", o->commit->tree);
r = filtermatch1(pathfilt, t, pt);
r = matchesfilter1(pathfilt, t, pt);
unref(p);
unref(pt);
if(r)
@ -131,16 +132,13 @@ nextline(char *p, char *e)
return p;
}
static void
static int
show(Object *o)
{
Tm tm;
char *p, *q, *e;
assert(o->type == GCommit);
if(!filtermatch(o))
return;
if(shortlog){
p = o->commit->msg;
e = p + o->commit->nmsg;
@ -170,6 +168,7 @@ show(Object *o)
Bprint(out, "\n");
}
Bflush(out);
return 1;
}
static void
@ -181,10 +180,14 @@ showquery(char *q)
if((n = resolverefs(&h, q)) == -1)
sysfatal("resolve: %r");
for(i = 0; i < n && (msgcount == -1 || msgcount-- > 0); i++){
for(i = 0; i < n && (msgcount == -1 || msgcount > 0); i++){
if((o = readobject(h[i])) == nil)
sysfatal("read %H: %r", h[i]);
show(o);
if(matchesfilter(o)){
show(o);
if(msgcount != -1)
msgcount--;
}
unref(o);
}
exits(nil);
@ -207,8 +210,12 @@ showcommits(char *c)
qinit(&objq);
osinit(&done);
qput(&objq, o, 0);
while(qpop(&objq, &e) && (msgcount == -1 || msgcount-- > 0)){
show(e.o);
while(qpop(&objq, &e) && (msgcount == -1 || msgcount > 0)){
if(matchesfilter(e.o)){
show(e.o);
if(msgcount != -1)
msgcount--;
}
for(i = 0; i < e.o->commit->nparent; i++){
if(oshas(&done, e.o->commit->parent[i]))
continue;

224
sys/src/cmd/ktrans/hash.c Normal file
View file

@ -0,0 +1,224 @@
#include <u.h>
#include <libc.h>
#include "hash.h"
typedef struct Hnode Hnode;
struct Hnode {
int filled;
int next;
void *key;
};
enum{
Tagsize = sizeof(Hnode),
};
uvlong
shash(char *s)
{
uvlong hash;
hash = 7;
for(; *s; s++)
hash = hash*31 + *s;
return hash;
}
Hmap*
hmapalloc(int nbuckets, int size)
{
void *store;
Hmap *h;
int nsz;
nsz = Tagsize + size;
store = mallocz(sizeof(*h) + (nbuckets * nsz), 1);
if(store == nil)
return nil;
h = store;
h->nbs = nbuckets;
h->nsz = nsz;
h->len = h->cap = nbuckets;
h->nodes = store;
h->nodes += sizeof(*h);
return store;
}
int
hmaprepl(Hmap **store, char *key, void *new, void *old, int freekeys)
{
Hnode *n;
uchar *v;
uchar *oldv;
Hmap *h;
int next;
vlong diff;
h = *store;
oldv = nil;
v = h->nodes + (shash(key)%h->nbs) * h->nsz;
for(;;){
n = (Hnode*)v;
next = n->next;
if(n->filled == 0)
goto replace;
if(strcmp(n->key, key) == 0){
if(freekeys)
free(n->key);
oldv = v + Tagsize;
goto replace;
}
if(next == 0)
break;
v = h->nodes + next*h->nsz;
}
if(h->cap == h->len){
/* figure out way back from a relocation */
diff = v - h->nodes;
h->cap *= 2;
*store = realloc(*store, sizeof(*h) + h->cap*h->nsz);
h = *store;
h->nodes = (uchar*)*store + sizeof(*h);
memset(h->nodes + h->len*h->nsz, 0, h->nsz);
v = h->nodes + diff;
n = (Hnode*)v;
}
n->next = h->len;
h->len++;
assert(h->len <= h->cap);
v = h->nodes + n->next*h->nsz;
n = (Hnode*)v;
replace:
memmove(v + Tagsize, new, h->nsz - Tagsize);
n->filled++;
n->key = key;
n->next = next;
if(old != nil && oldv != nil){
memmove(old, oldv, h->nsz - Tagsize);
return 1;
}
return 0;
}
int
hmapupd(Hmap **h, char *key, void *new)
{
char *prev;
prev = hmapkey(*h, key);
if(prev == nil)
prev = key;
return hmaprepl(h, prev, new, nil, 0);
}
void*
_hmapget(Hmap *h, char *key)
{
Hnode *n;
uchar *v;
v = h->nodes + (shash(key)%h->nbs)*h->nsz;
for(;;){
n = (Hnode*)v;
if(n->filled != 0 && strcmp(n->key, key) == 0)
return v;
if(n->next == 0)
break;
v = h->nodes + n->next*h->nsz;
}
return nil;
}
int
hmapget(Hmap *h, char *key, void *dst)
{
uchar *v;
v = _hmapget(h, key);
if(v == nil)
return -1;
if(dst != nil)
memmove(dst, v + Tagsize, h->nsz - Tagsize);
return 0;
}
int
hmapdel(Hmap *h, char *key, void *dst, int freekey)
{
uchar *v;
Hnode *n;
v = _hmapget(h, key);
if(v == nil)
return -1;
n = (Hnode*)v;
n->filled = 0;
if(freekey)
free(n->key);
if(dst != nil)
memmove(dst, v + Tagsize, h->nsz - Tagsize);
return 0;
}
char*
hmapkey(Hmap *h, char *key)
{
uchar *v;
Hnode *n;
v = _hmapget(h, key);
if(v == nil)
return nil;
n = (Hnode*)v;
return n->key;
}
Hmap*
hmaprehash(Hmap *old, int buckets)
{
int i;
uchar *v;
Hnode *n;
Hmap *new;
if(buckets == 0)
buckets = old->len;
new = hmapalloc(buckets, old->nsz - Tagsize);
for(i=0 ; i < old->len; i++){
v = old->nodes + i*old->nsz;
n = (Hnode*)v;
hmaprepl(&new, n->key, v + Tagsize, nil, 0);
}
free(old);
return new;
}
void
hmapreset(Hmap *h, int freekeys)
{
Hnode *n;
uchar *v;
int i;
for(i=0; i < h->len; i++){
v = h->nodes + i*h->nsz;
n = (Hnode*)v;
if(n->filled == 0)
continue;
if(freekeys)
free(n->key);
n->filled = 0;
}
h->len = 0;
}

23
sys/src/cmd/ktrans/hash.h Normal file
View file

@ -0,0 +1,23 @@
typedef union Hkey Hkey;
union Hkey {
void *p;
int v;
};
typedef struct Hmap Hmap;
struct Hmap {
int nbs;
int nsz;
int len;
int cap;
uchar *nodes;
};
Hmap* hmapalloc(int nbuckets, int size);
int hmapget(Hmap *h, char *key, void *dst);
int hmaprepl(Hmap **h, char *key, void *new, void *old, int freekeys);
int hmapupd(Hmap **h, char *key, void *new);
int hmapdel(Hmap *h, char *key, void *dst, int freekey);
char* hmapkey(Hmap *h, char *key);
void hmapreset(Hmap *h, int freekeys);

View file

@ -1,211 +0,0 @@
/*
* open jisho file, and set the size of this jisho etc
*
* Kenji Okamoto August 4, 2000
* Osaka Prefecture Univ.
* okamoto@granite.cias.osakafu-u.ac.jp
*/
#include <u.h>
#include <libc.h>
#include <bio.h>
#include "jisho.h"
Dictionary *openQDIC(char *);
void freeQDIC(Dictionary*);
KouhoList *getKouhoHash(Dictionary*, char *);
KouhoList *getKouhoFile(DicList*, char *);
void selectKouho(KouhoList **, KouhoList*);
int hashVal(char *);
void addHash(Hash **, DicList*);
/*
* Open QuickDIC (hashed personal dictionary)
* open skk styled ktrans dictionary file, and make its hash table
* based on individual header kana strings
*
* KouhoList
* |---------|
* Hash |---->kouho---->kouhotop
* |-------| |
* dic---->dhash---->dicindex---->kanahead
* |--------| |--------|
* Dictionary DicList
*
*/
Dictionary *
openQDIC(char *dicname)
{
Biobuf *f;
void *Bbuf;
Dictionary *dic;
DicList *dicitem; /* for a future extension */
char buf[1024], *startstr, *endstr;
int i;
SET(dicitem); /* yes, I know I'm wrong, but... */
dic = (Dictionary*)malloc(sizeof(Dictionary));
/* make room for pointer array (size=HASHSIZE) of hash table */
for(i=0; i< HASHSIZE; i++) dic->dhash[i] = 0;
dic->dlist = 0; /* for a future extension (more than one dics ^_^ */
if ((f = Bopen(dicname, OREAD)) == 0)
return dic;
/* make hash table by the dic's header word */
while(Bbuf = Brdline(f, '\n')) {
strncpy(buf, (char *)Bbuf, Blinelen(f));
if (buf[0] == ';') /* comment line */
continue;
else {
/* get header word from jisho */
startstr = buf;
if(!(endstr = utfutf(startstr, "\t"))) break;
*endstr = '\0';
/* dicitem includes each header word from the jisho */
dicitem = (DicList*)malloc(sizeof(DicList)+(endstr-startstr+1));
dicitem->nextitem = 0; /* for a future extension */
strcpy(dicitem->kanahead, startstr);
dicitem->kouho = getKouhoFile(dicitem, endstr); /* read kouho from jisho */
addHash(dic->dhash, dicitem);
}
continue;
}
dic->dlist = dicitem;
Bterm(f);
return dic;
}
/*
* free dynamically allocated memory
*/
void
freeQDIC(Dictionary *dic)
{
Hash *hash1, *hash2;
DicList *dlist, *dlist2;
int l;
for (dlist = dic->dlist;
dlist != 0;
dlist2 = dlist, dlist = dlist->nextitem, free((void *)dlist2));
for (l = 0; l < HASHSIZE; l++) {
for (hash1 = dic->dhash[l]; hash1; hash1 = hash2) {
if (hash1->next !=0) {
hash2 = hash1->next;
free((void *)hash1);
}else
break;
}
}
free((void *)dic);
}
int
hashVal(char *s)
{
uint h;
h = 0x811c9dc5;
while(*s != 0)
h = (h^(uchar)*s++) * 0x1000193;
return h % HASHSIZE;
}
void
addHash(Hash **hash, DicList *ditem)
{
Hash *h;
int v;
v = hashVal(ditem->kanahead);
h = (Hash*)malloc(sizeof(Hash));
h->dicindex = ditem;
h->length = strlen(ditem->kanahead);
h->next = hash[v];
hash[v] = h;
}
/*
* read Kouho list from the jisho file defined by Biobuf descriptor f
*
* revised for Plan 9 by K.Okamoto
*/
KouhoList *
getKouhoFile(DicList *dicitem, char * endstr)
{
char *kouhostart, *kouhoend;
KouhoList *kouhoitem, *currntkouhoitem=0, *prevkouhoitem;
prevkouhoitem = 0;
kouhostart = endstr + 1;
while((kouhoend = utfutf(kouhostart, " ")) ||
(kouhoend = utfutf(kouhostart, "\n"))) {
*kouhoend = '\0';
kouhoitem = (KouhoList*)malloc(sizeof(KouhoList)+(kouhoend-kouhostart+1));
kouhoitem->nextkouho = 0;
kouhoitem->prevkouho = prevkouhoitem;
kouhoitem->dicitem = dicitem;
strcpy(kouhoitem->kouhotop, kouhostart);
if (prevkouhoitem)
prevkouhoitem->nextkouho = kouhoitem;
else
currntkouhoitem = kouhoitem;
prevkouhoitem = kouhoitem;
kouhostart = kouhoend + 1;
}
return currntkouhoitem;
}
/*
* get matched kouho from the hash table of header word of the dict
* if found, returns pointer to the first candidate in the hash table.
* if not found, returns 0.
*
* from getCand() in skklib.c by Akinori Ito et al.,(aito@ei5sun.yz.yamagata-u.ac.jp)
*/
KouhoList *
getKouhoHash(Dictionary *dic, char *s)
{
int l, v;
Hash *h;
l = strlen(s);
v = hashVal(s);
for (h = dic->dhash[v]; h != 0; h = h->next) {
if (h->length != l ||
strcmp(h->dicindex->kanahead, s)) continue;
return h->dicindex->kouho; /* return matched kouho */
}
return 0;
}
/*
* from skklib.c by Akinori Ito et al.,(aito@ei5sun.yz.yamagata-u.ac.jp)
* just modified to read easier for current purpose
*/
void
selectKouho(KouhoList **first, KouhoList *current)
{
/* take off currentkouho from the kouholist table */
if (current->prevkouho) {
current->prevkouho->nextkouho = current->nextkouho;
if (current->nextkouho)
current->nextkouho->prevkouho = current->prevkouho;
current->prevkouho = 0;
}
/* take place of firstkouho by currentkouho */
if (*first != current) {
(*first)->prevkouho = current;
current->nextkouho = *first;
*first = current;
}
}

View file

@ -1,41 +0,0 @@
/*
* Kenji Okamoto August 4, 2000
* Osaka Prefecture Univ.
* okamoto@granite.cias.osakafu-u.ac.jp
*/
#define HASHSIZE 257
/*
* Structure for Dictionary's header word (in Hiragana)
*/
typedef struct DicList DicList;
struct DicList {
struct KouhoList *kouho;
struct DicList *nextitem; /* for a future extension */
char kanahead[1];
};
/*
* Structure for Kouho of each index word in the dictionary
*/
typedef struct KouhoList KouhoList;
struct KouhoList {
struct KouhoList *nextkouho;
struct KouhoList *prevkouho;
struct DicList *dicitem;
char kouhotop[1]; /* top of the kouhos */
} ;
typedef struct Hash Hash;
struct Hash {
DicList *dicindex; /* pointer to a KouhoList and kanahead etc */
short length;
struct Hash *next;
};
typedef struct Dictionary Dictionary;
struct Dictionary {
DicList *dlist; /* for a future extension, having more than one dictionaries */
Hash *dhash[HASHSIZE];
};

File diff suppressed because it is too large Load diff

View file

@ -6,16 +6,26 @@
* okamoto@granite.cias.osakafu-u.ac.jp
*/
/*
* A glossary on some of the Japanese vocabulary used:
* kana: syllabic letting, either hiragana() or katakana()
* kanji(): borrowed characters, in
* Okurigana(): kana tail to kanji, in
* Joshi(): particle, in
* Jisho(): dictionary
* kouho(): candidate
*/
#include <u.h>
#include <libc.h>
#include <bio.h>
#include "hash.h"
#include "ktrans.h"
#include "jisho.h"
#define LSIZE 256
Rune lbuf[LSIZE]; /* hiragana buffer for key input written by send() */
Map *table = hira; /* default language conversion table */
Hmap *table;
uchar okurigana[LSIZE]; /* buffer for okurigana */
char okuri = 0; /* buffer/flag for capital input char */
int in, out;
@ -23,16 +33,10 @@ int llen, olen, joshi = 0;
int natural = 1; /* not Japanese but English mode */
int changelang(int);
int dotrans(Dictionary*);
int dotrans(Hmap*);
int nrune(char *);
void send(uchar *, int);
Map *match(uchar *p, int *nc, Map *table);
extern Dictionary *openQDIC(char *);
extern KouhoList *getKouhoHash(Dictionary*, char *);
extern KouhoList *getKouhoFile(DicList*, char *);
extern void freeQDIC(Dictionary*);
extern void selectKouho(KouhoList **, KouhoList*);
Hmap* opendict(Hmap *, char *);
void
kbdopen(void)
@ -89,6 +93,49 @@ kbdopen(void)
exits(nil);
}
Map signalmore = {
"_", nil, 1,
};
Hmap*
initmap(Map *m, int n)
{
int i, j;
char buf[16];
char *s;
Map prev;
Hmap *h;
h = hmapalloc(n, sizeof(Map));
for(i = 0; i < n; i++){
if(m[i].roma == nil || m[i].roma[0] == '\0')
continue;
//We mark all partial strings so we know when
//we have partial match when ingesting.
j = 2;
for(s = m[i].roma; *s && j <= sizeof buf; s++){
snprint(buf, j, "%s", m[i].roma);
prev = m[i];
if(hmapget(h, buf, &prev) == 0){
if(prev.leadstomore == 1 && s[1] == '\0'){
//confict; partial & valid input
prev = m[i];
prev.leadstomore = 1;
}
}
if(s[1] == '\0'){
hmaprepl(&h, strdup(buf), &prev, nil, 1);
} else {
hmaprepl(&h, strdup(buf), &signalmore, nil, 1);
}
j++;
}
}
return h;
}
void
usage(void)
{
@ -101,11 +148,11 @@ main(int argc, char *argv[])
{
uchar *bp, *ep, buf[128];
Map *mp;
int nchar, wantmore;
Map lkup, last;
int wantmore;
int n, c;
char *dictname;
Dictionary *jisho;
char *jishoname, *zidianname;
Hmap *jisho, *zidian;
ARGBEGIN{
default: usage();
@ -113,9 +160,20 @@ main(int argc, char *argv[])
if(argc != 0)
usage();
if((dictname = getenv("jisho")) == nil)
dictname = "/lib/kanji.jisho";
jisho = openQDIC(dictname);
if((jishoname = getenv("jisho")) == nil)
jishoname = "/lib/kanji.jisho";
jisho = opendict(nil, jishoname);
if((zidianname = getenv("zidian")) == nil)
zidianname = "/lib/hanzi.zidian";
zidian = opendict(nil, zidianname);
hira = table = initmap(mhira, nelem(mhira));
kata = initmap(mkata, nelem(mkata));
greek = initmap(mgreek, nelem(mgreek));
cyril = initmap(mcyril, nelem(mcyril));
hangul = initmap(mhangul, nelem(mhangul));
last = (Map){nil, nil, -1};
kbdopen();
if(fork())
@ -147,8 +205,8 @@ main(int argc, char *argv[])
wantmore = 0;
if (*bp=='') { /* ^x read ktrans-jisho once more */
freeQDIC(jisho);
jisho = openQDIC(dictname);
jisho = opendict(jisho, jishoname);
zidian = opendict(zidian, zidianname);
llen = 0;
olen = okuri = joshi = 0;
wantmore=0;
@ -156,7 +214,10 @@ main(int argc, char *argv[])
continue;
}
if (*bp=='') { /* ^\ (start translation command) */
c = dotrans(jisho);
if (table == hanzi)
c = dotrans(zidian);
else
c = dotrans(jisho);
if (c)
*bp = c; /* pointer to translated rune */
else
@ -167,11 +228,13 @@ main(int argc, char *argv[])
bp++;
llen = 0;
olen = okuri = joshi = 0;
last.kana = nil;
continue;
}
if (changelang(*bp)) { /* change language mode OK */
bp++;
olen = okuri = joshi = 0;
last.kana = nil;
continue;
}
if (natural || *bp<=' ' || *bp>='{') { /* English mode but not ascii */
@ -179,6 +242,7 @@ main(int argc, char *argv[])
int rlen = chartorune(&r, (char *)bp);
send(bp, rlen); /* write bp to /dev/cons */
bp += rlen;
last.kana = nil;
continue;
}
if (table == hira && (*bp >= 'A' && *bp <= 'Z') && (*(bp+1) < 'A'
@ -192,27 +256,33 @@ main(int argc, char *argv[])
joshi = 1;
olen = 0;
}
mp = match(bp, &nchar, table);
if (mp == 0) {
if (nchar>0) { /* match, longer possible */
wantmore++;
break;
}
send(bp++, 1); /* alphabet in kana mode */
} else {
send((uchar*)mp->kana, strlen(mp->kana));
bp += nchar;
if(hmapget(table, (char*)bp, &lkup) < 0){
if(last.kana != nil){
send((uchar*)last.kana, strlen(last.kana));
bp += strlen(last.roma);
} else
send(bp++, 1);
last.kana = nil;
break;
}
/* concatinations; only advance a single character */
if(lkup.kana != nil && strstr("ッっ", lkup.kana))
lkup.roma = "_";
/* partial match */
if(lkup.kana == nil || lkup.leadstomore == 1){
if(lkup.kana != nil)
last = lkup;
wantmore = 1;
break;
}
last.kana = nil;
send((uchar*)lkup.kana, strlen(lkup.kana));
bp += strlen(lkup.roma);
}
}
}
int
min(int a, int b)
{
return a<b? a: b;
}
/*
* send UTF string (p) with length (n) to stdout
* and write rune (r) in global lbuf[] buffer
@ -232,7 +302,9 @@ send(uchar *p, int n)
llen -= 64;
}
if (table!=hira || natural)
if(table != hira && table != hanzi)
return;
if(natural && table != hanzi)
return;
ep = p+n;
@ -253,49 +325,13 @@ send(uchar *p, int n)
}
}
/*
* Romaji to Hiragana/Katakana conversion
* romaji shoud be input as small letter
* returns the matched address in table, hira, kata, etc.
* nc: number of character (return value)
*/
Map *
match(uchar *p, int *nc, Map *table)
{
register Map *longp = 0, *kp;
static char last;
int longest = 0;
*nc = -1;
for (kp=table; kp->roma; kp++) {
if (*p == *kp->roma) {
int lr = strlen(kp->roma);
int len = min(lr, strlen((char *)p));
if (strncmp(kp->roma, (char *)p, len)==0) {
if (len<lr) {
*nc = 1;
return 0;
}
if (len>longest) {
longest = len;
longp = kp;
}
}
}
}
if (longp) {
last = longp->roma[longest-1];
*nc = longp->advance;
}
return longp;
}
int
changelang(int c)
{
switch(c){
case '': /* ^t (English mode) */
natural = 1;
table = hira;
llen = 0;
return 1;
break;
@ -334,23 +370,80 @@ changelang(int c)
llen = 0;
return 1;
break;
case '': /* ^c (Chinese mode) */
natural = 1;
table = hanzi;
llen = 0;
return 1;
break;
}
return 0;
}
Hmap*
opendict(Hmap *h, char *name)
{
Biobuf *b;
char *p;
char *dot, *rest;
char *kouho[16];
int i;
b = Bopen(name, OREAD);
if(b == nil)
return nil;
if(h == nil)
h = hmapalloc(8192, sizeof(kouho));
else
hmapreset(h, 1);
while(p = Brdstr(b, '\n', 1)){
if(p[0] == '\0' || p[0] == ';'){
Err:
free(p);
continue;
}
dot = utfrune(p, '\t');
if(dot == nil)
goto Err;
*dot = '\0';
rest = dot+1;
if(*rest == '\0')
goto Err;
memset(kouho, 0, sizeof kouho);
i = 0;
while(i < nelem(kouho)-1 && (dot = utfrune(rest, ' '))){
*dot = '\0';
kouho[i++] = rest;
rest = dot+1;
}
if(i < nelem(kouho)-1)
kouho[i] = rest;
/* key is the base pointer; overwrites clean up for us */
hmaprepl(&h, p, kouho, nil, 1);
}
Bterm(b);
return h;
}
/*
* write translated kanji runes to stdout and return last character
* if it's not ctl-\. if the last is ctl-\, proceed with
* translation of the next kouho
*/
int
dotrans(Dictionary *dic)
dotrans(Hmap *dic)
{
Rune *res, r[1];
char v[1024], *p, tbuf[64], hirabuf[64];
int j, lastlen, nokouho = 0;
char ch;
KouhoList *fstkouho, *currentkouho;
int i;
char *kouho[16];
if (llen==0)
return 0; /* don't use kanji transform function */
@ -375,15 +468,13 @@ dotrans(Dictionary *dic)
if (okuri && joshi != 1) /* verb mode */
hirabuf[strlen(hirabuf) - 1] = '\0';
if(!(fstkouho = getKouhoHash(dic, v))) { /* not found */
if(hmapget(dic, v, kouho) < 0){
llen = olen = okuri = joshi = 0;
okurigana[0] = 0;
return 0;
}
currentkouho = fstkouho;
for(;;) {
p = currentkouho->kouhotop; /* p to the head of kanji kouho array */
for(i = 0; i < nelem(kouho) && kouho[i] != nil; i++) {
p = kouho[i];
lastlen = nrune(tbuf); /* number of rune chars */
if (okuri && joshi != 1) /* verb mode */
@ -407,10 +498,9 @@ dotrans(Dictionary *dic)
exits(nil);
if (ch == '') { /* if next input is ^\, once again */
if(currentkouho->nextkouho != 0) { /* have next kouho */
if(i+1 < nelem(kouho) && kouho[i+1] != nil) { /* have next kouho */
nokouho = 0;
strcpy(tbuf, p);
currentkouho = currentkouho->nextkouho;
if (okuri && joshi != 1) /* verb mode */
for (j=0; j<nrune(tbuf); j++)
@ -442,8 +532,12 @@ dotrans(Dictionary *dic)
break;
}
} else {
if(!nokouho) /* learn the previous use of the kouho */
selectKouho(&(fstkouho->dicitem->kouho), currentkouho);
if(!nokouho && i != 0){ /* learn the previous use of the kouho */
p = kouho[0];
kouho[0] = kouho[i];
kouho[i] = p;
hmapupd(&dic, v, kouho);
}
olen = okuri = joshi = 0;
okurigana[0] = 0;

View file

@ -2,9 +2,9 @@
BIN=/$objtype/bin
TARG=ktrans
HFILES=jisho.h ktrans.h
HFILES=ktrans.h
OFILES=\
hash.$O\
main.$O\
jisho.$O
</sys/src/cmd/mkone

View file

@ -608,6 +608,8 @@ redraw(void)
for(j=0; j<nhidden; j++)
if(w == hidden[j])
break;
memmove(w->cols, &cols[BACK], sizeof(w->cols));
frinittick(w);
incref(w);
if(j < nhidden){

View file

@ -802,6 +802,8 @@ changemesg(Plumbmsg *pm)
digest = plumblookup(pm->attr, "digest");
action = plumblookup(pm->attr, "mailtype");
if(digest == nil || action == nil)
return;
if(strcmp(action, "new") == 0){
if((m = load(pm->data, digest, 1)) == nil)
return;

View file

@ -1,4 +1,4 @@
<div class="left>
<div class="left">
<a href="https://owen.bellz.org">escape</a> |
<a href="//withdrawal.owen.bellz.org">withdrawal</a>
</div>