Compare commits
32 commits
290fc21b2c
...
a0ac839193
Author | SHA1 | Date | |
---|---|---|---|
a0ac839193 | |||
|
bc64cc50ac | ||
|
520a39efcd | ||
a62a6d09b1 | |||
|
3cc07dddfb | ||
|
4063334e6f | ||
|
951ab17262 | ||
35a6dacb3d | |||
9d6ef2d008 | |||
|
dd8a2d3964 | ||
917ae0345f | |||
|
d1acc58316 | ||
|
d4eb08a860 | ||
de8181a85c | |||
939d1fd742 | |||
|
1c585c2cc2 | ||
|
ce2ad9701d | ||
|
8f1954c0dd | ||
|
b3dc2af6d6 | ||
|
e402fd8340 | ||
|
e01e80c5e7 | ||
|
2ca5abbc2b | ||
|
25a0d57478 | ||
|
d618223086 | ||
|
9fc38d43d4 | ||
|
0ec0154bc9 | ||
|
23620b2e70 | ||
|
c147614656 | ||
|
ccbabf1c16 | ||
|
06d7118e94 | ||
|
467c95b4a8 | ||
|
498e9e7d83 |
41 changed files with 87129 additions and 3370 deletions
83100
lib/hanzi.zidian
Normal file
83100
lib/hanzi.zidian
Normal file
File diff suppressed because it is too large
Load diff
12
lib/ktrans/README
Normal file
12
lib/ktrans/README
Normal 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
2
lib/ktrans/grabskkdicts
Executable file
|
@ -0,0 +1,2 @@
|
||||||
|
#!/bin/rc
|
||||||
|
git/clone https://github.com/skk-dev/dict skkdicts
|
2
lib/ktrans/skk2ktrans
Executable file
2
lib/ktrans/skk2ktrans
Executable file
|
@ -0,0 +1,2 @@
|
||||||
|
#!/bin/rc
|
||||||
|
tcs -sf jis | awk '$1 !~ /;;/ {gsub("(^\/|\/$)", "", $2); gsub(" ", " "); gsub("\/", " ", $2);} {print}'
|
4
lib/theo
4
lib/theo
|
@ -956,3 +956,7 @@ I really don't understand the approach being taken here.
|
||||||
I want to understand what the goal here is.
|
I want to understand what the goal here is.
|
||||||
It won't happen.
|
It won't happen.
|
||||||
That is either a funny joke, or it shows you don't understand Unix.
|
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.
|
||||||
|
|
|
@ -22,16 +22,18 @@ if(~ $#p9part 0){
|
||||||
exit ''
|
exit ''
|
||||||
}
|
}
|
||||||
|
|
||||||
echo
|
if(test -f /386/mbr){
|
||||||
echo 'If you use the Windows NT/2000/XP master boot record'
|
echo
|
||||||
echo 'or a master boot record from a Unix clone (e.g., LILO or'
|
echo 'If you use the Windows NT/2000/XP master boot record'
|
||||||
echo 'FreeBSD bootmgr), it is probably safe to continue using'
|
echo 'or a master boot record from a Unix clone (e.g., LILO or'
|
||||||
echo 'that boot record rather than install the Plan 9 boot record.'
|
echo 'FreeBSD bootmgr), it is probably safe to continue using'
|
||||||
echo
|
echo 'that boot record rather than install the Plan 9 boot record.'
|
||||||
prompt 'Install the Plan 9 master boot record' yes no
|
echo
|
||||||
switch($rd) {
|
prompt 'Install the Plan 9 master boot record' yes no
|
||||||
case yes
|
switch($rd) {
|
||||||
|
case yes
|
||||||
disk/mbr -m /386/mbr /dev/$disk/data
|
disk/mbr -m /386/mbr /dev/$disk/data
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
prompt 'Mark the Plan 9 partition active' yes no
|
prompt 'Mark the Plan 9 partition active' yes no
|
||||||
|
|
|
@ -30,16 +30,26 @@ case go
|
||||||
9fat=$rd
|
9fat=$rd
|
||||||
export 9fat
|
export 9fat
|
||||||
|
|
||||||
|
if(~ $#bootfile 1){
|
||||||
bootfile=`{basename $bootfile}
|
bootfile=`{basename $bootfile}
|
||||||
|
}
|
||||||
|
if(! ~ $#bootfile 1 || ! test -f /$cputype/$bootfile) {
|
||||||
|
bootfile=()
|
||||||
|
}
|
||||||
|
|
||||||
if(! test -f /tmp/plan9.ini) {
|
if(! test -f /tmp/plan9.ini) {
|
||||||
@{
|
@{
|
||||||
|
if(~ $#bootfile 1)
|
||||||
echo 'bootfile='^$bootfile
|
echo 'bootfile='^$bootfile
|
||||||
|
if(~ $#fs 1)
|
||||||
echo 'bootargs=local!'^$fs' '$"fsflags
|
echo 'bootargs=local!'^$fs' '$"fsflags
|
||||||
if(~ $#nvram 1)
|
if(~ $#nvram 1)
|
||||||
echo 'nvram='^$nvram
|
echo 'nvram='^$nvram
|
||||||
|
if(~ $#mouseport 1)
|
||||||
echo 'mouseport='^$mouseport
|
echo 'mouseport='^$mouseport
|
||||||
|
if(~ $#monitor 1)
|
||||||
echo 'monitor='^$monitor
|
echo 'monitor='^$monitor
|
||||||
|
if(~ $#vgasize 1)
|
||||||
echo 'vgasize='^$vgasize
|
echo 'vgasize='^$vgasize
|
||||||
cd '#ec'
|
cd '#ec'
|
||||||
for(i in *){
|
for(i in *){
|
||||||
|
@ -72,32 +82,50 @@ case go
|
||||||
# always make backup of old bootsector
|
# always make backup of old bootsector
|
||||||
logprog dd -bs 512 -count 1 -if $9fat -of /tmp/pbs.bak
|
logprog dd -bs 512 -count 1 -if $9fat -of /tmp/pbs.bak
|
||||||
|
|
||||||
|
if (! test -f /386/pbs) {
|
||||||
if(~ $need9fatformat yes){
|
if(~ $need9fatformat yes){
|
||||||
log Initializing Plan 9 FAT partition.
|
log Initializing Plan 9 FAT partition.
|
||||||
logprog disk/format -r 2 -d -b /n/newfs/386/pbs -l PLAN9 $9fat
|
logprog disk/format -r 2 -d -l PLAN9 $9fat
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if not {
|
||||||
|
if(~ $need9fatformat yes){
|
||||||
|
log Initializing Plan 9 FAT partition.
|
||||||
|
logprog disk/format -r 2 -d -b /386/pbs -l PLAN9 $9fat
|
||||||
}
|
}
|
||||||
if not {
|
if not {
|
||||||
log Updating bootsector.
|
log Updating bootsector.
|
||||||
logprog disk/format -b /n/newfs/386/pbs $9fat
|
logprog disk/format -b /386/pbs $9fat
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
logprog mount -c /srv/dos /n/9fat $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
|
# make file continous on disk
|
||||||
logprog chmod +al /n/9fat/9bootfat
|
logprog chmod +al /n/9fat/9bootfat
|
||||||
|
}
|
||||||
|
|
||||||
# copy config
|
# copy config
|
||||||
|
logprog rm -f /n/9fat/plan9.ini
|
||||||
logprog cp /tmp/plan9.ini /n/9fat/plan9.ini
|
logprog cp /tmp/plan9.ini /n/9fat/plan9.ini
|
||||||
|
|
||||||
# copy kernel
|
# 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
|
# copy efi bootloader
|
||||||
|
for(i in /386/*.efi){
|
||||||
|
if(test -f $i) {
|
||||||
logprog mkdir -p /n/9fat/efi/boot
|
logprog mkdir -p /n/9fat/efi/boot
|
||||||
logprog cp /386/^(bootia32.efi bootx64.efi) /n/9fat/efi/boot
|
logprog cp $i /n/9fat/efi/boot/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
# copy in backups
|
# copy in backups
|
||||||
if(test -f /tmp/oldplan9.ini)
|
if(test -f /tmp/oldplan9.ini)
|
||||||
|
|
|
@ -5260,3 +5260,5 @@ MY NAME IS BEING USED IN A PHISHING ATTACK. DO NOT RESPOND TO MAIL OFFERING MON
|
||||||
Xterm.js
|
Xterm.js
|
||||||
GPU.js
|
GPU.js
|
||||||
Joys of Porting a Kernel to WebAssembly
|
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
|
||||||
|
|
|
@ -835,8 +835,10 @@ used.
|
||||||
The snarf buffer is unaffected.
|
The snarf buffer is unaffected.
|
||||||
.TP
|
.TP
|
||||||
.B <rio>
|
.B <rio>
|
||||||
Exchange snarf buffers with
|
Exchange dot with snarf buffer of
|
||||||
.IR rio .
|
.IR rio .
|
||||||
|
If dot is the null string, the text in the snarf buffer is
|
||||||
|
used.
|
||||||
.TP
|
.TP
|
||||||
.BI / regexp
|
.BI / regexp
|
||||||
Search forward for the next match of the last regular expression
|
Search forward for the next match of the last regular expression
|
||||||
|
|
|
@ -67,6 +67,11 @@ and any initial arguments to that program, for example
|
||||||
ls | mc
|
ls | mc
|
||||||
.EE
|
.EE
|
||||||
.PP
|
.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,
|
When a C program is executed,
|
||||||
it is called as follows:
|
it is called as follows:
|
||||||
.IP
|
.IP
|
||||||
|
|
98
sys/man/3/i2c
Normal file
98
sys/man/3/i2c
Normal 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.
|
58
sys/man/3/ip
58
sys/man/3/ip
|
@ -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
|
The connect fails if the combination of local and remote address/port pairs
|
||||||
are already assigned to another port.
|
are already assigned to another port.
|
||||||
.TP
|
.TP
|
||||||
.BI announce\ X
|
.BI announce\ [ip-address ! ]port
|
||||||
.I X
|
Set the local IP address and port number and accept calls there. If
|
||||||
is a decimal port number or
|
ip-address is left out, accept calls on any address. If port is 0, a
|
||||||
.LR * .
|
port is automatically choosen that is not yet announced.
|
||||||
Set the local port
|
If the address is
|
||||||
number to
|
|
||||||
.I X
|
|
||||||
and accept calls to
|
|
||||||
.IR X .
|
|
||||||
If
|
|
||||||
.I X
|
|
||||||
is
|
|
||||||
.LR * ,
|
.LR * ,
|
||||||
accept
|
accept calls on any address.
|
||||||
calls for any port that no process has explicitly announced.
|
If port is
|
||||||
The local IP address cannot be set.
|
.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
|
.B Announce
|
||||||
fails if the connection is already announced or connected.
|
fails if the connection is already announced.
|
||||||
.TP
|
.TP
|
||||||
.BI bind\ X
|
.BI bind\ [ip-address ! ]port
|
||||||
.I X
|
Set the local IP address and port number like for a server connection
|
||||||
is a decimal port number or
|
similar to the
|
||||||
.LR * .
|
.B announce
|
||||||
Set the local port number to
|
command.
|
||||||
.IR X .
|
If ip-address is left out, an address is automatically selected. If
|
||||||
This exists to support emulation
|
port is 0, a port is automatically choosen that is not yet announced.
|
||||||
of BSD sockets by the APE libraries (see
|
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))
|
.IR pcc (1))
|
||||||
and is not otherwise used.
|
and is not otherwise used.
|
||||||
.\" this is gone
|
.\" this is gone
|
||||||
|
|
|
@ -62,7 +62,7 @@ changeuser, convkeys, printnetkey, status, enable, disable, authsrv, guard.srv,
|
||||||
.PP
|
.PP
|
||||||
.B auth/box
|
.B auth/box
|
||||||
[
|
[
|
||||||
.B -d
|
.B -s
|
||||||
] [
|
] [
|
||||||
.B -rc
|
.B -rc
|
||||||
.I file
|
.I file
|
||||||
|
@ -298,9 +298,8 @@ the child namespace; the
|
||||||
flag specifies a string of driver
|
flag specifies a string of driver
|
||||||
characters to keep. The
|
characters to keep. The
|
||||||
.B -s
|
.B -s
|
||||||
flag gives a base set of namespace
|
flag initializes the namespace to what rc expects,
|
||||||
components, ones expected by rc, then passes
|
and passes its arguments unmodified to /bin/rc.
|
||||||
the first argument as a script file to rc.
|
|
||||||
.PP
|
.PP
|
||||||
.I As
|
.I As
|
||||||
executes
|
executes
|
||||||
|
|
|
@ -13,6 +13,7 @@ dev
|
||||||
tls
|
tls
|
||||||
cap
|
cap
|
||||||
fs
|
fs
|
||||||
|
bridge log
|
||||||
ip arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium inferno
|
ip arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium inferno
|
||||||
draw screen swcursor
|
draw screen swcursor
|
||||||
mouse mouse
|
mouse mouse
|
||||||
|
@ -22,10 +23,11 @@ dev
|
||||||
usb
|
usb
|
||||||
|
|
||||||
link
|
link
|
||||||
loopbackmedium
|
|
||||||
ethermedium
|
|
||||||
archbcm
|
archbcm
|
||||||
usbdwc
|
usbdwc
|
||||||
|
ethermedium
|
||||||
|
loopbackmedium
|
||||||
|
netdevmedium
|
||||||
|
|
||||||
ip
|
ip
|
||||||
tcp
|
tcp
|
||||||
|
|
|
@ -13,6 +13,7 @@ dev
|
||||||
tls
|
tls
|
||||||
cap
|
cap
|
||||||
fs
|
fs
|
||||||
|
bridge log
|
||||||
ip arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium inferno
|
ip arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium inferno
|
||||||
draw screen swcursor
|
draw screen swcursor
|
||||||
mouse mouse
|
mouse mouse
|
||||||
|
@ -22,10 +23,11 @@ dev
|
||||||
usb
|
usb
|
||||||
|
|
||||||
link
|
link
|
||||||
loopbackmedium
|
|
||||||
ethermedium
|
|
||||||
archbcm2
|
archbcm2
|
||||||
usbdwc
|
usbdwc
|
||||||
|
ethermedium
|
||||||
|
loopbackmedium
|
||||||
|
netdevmedium
|
||||||
|
|
||||||
ip
|
ip
|
||||||
tcp
|
tcp
|
||||||
|
|
|
@ -13,6 +13,7 @@ dev
|
||||||
tls
|
tls
|
||||||
cap
|
cap
|
||||||
fs
|
fs
|
||||||
|
bridge log
|
||||||
ip arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium inferno
|
ip arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium inferno
|
||||||
draw screen swcursor
|
draw screen swcursor
|
||||||
mouse mouse
|
mouse mouse
|
||||||
|
@ -23,10 +24,11 @@ dev
|
||||||
dtracy
|
dtracy
|
||||||
|
|
||||||
link
|
link
|
||||||
loopbackmedium
|
|
||||||
ethermedium
|
|
||||||
archbcm3
|
archbcm3
|
||||||
usbdwc
|
usbdwc
|
||||||
|
ethermedium
|
||||||
|
loopbackmedium
|
||||||
|
netdevmedium
|
||||||
|
|
||||||
ip
|
ip
|
||||||
tcp
|
tcp
|
||||||
|
|
|
@ -14,6 +14,7 @@ dev
|
||||||
cap
|
cap
|
||||||
fs
|
fs
|
||||||
ether netif
|
ether netif
|
||||||
|
bridge log
|
||||||
ip arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium inferno
|
ip arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium inferno
|
||||||
draw screen swcursor
|
draw screen swcursor
|
||||||
mouse mouse
|
mouse mouse
|
||||||
|
@ -31,6 +32,7 @@ link
|
||||||
ethergenet ethermii
|
ethergenet ethermii
|
||||||
ethermedium
|
ethermedium
|
||||||
loopbackmedium
|
loopbackmedium
|
||||||
|
netdevmedium
|
||||||
|
|
||||||
ip
|
ip
|
||||||
tcp
|
tcp
|
||||||
|
|
349
sys/src/9/imx8/devrtc.c
Normal file
349
sys/src/9/imx8/devrtc.c
Normal 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;
|
||||||
|
}
|
|
@ -265,7 +265,7 @@ intrenable(int irq, void (*f)(Ureg*, void*), void *a, int tbdf, char *)
|
||||||
prio = 0x80;
|
prio = 0x80;
|
||||||
intid = irq;
|
intid = irq;
|
||||||
if((v = xalloc(sizeof(Vctl))) == nil)
|
if((v = xalloc(sizeof(Vctl))) == nil)
|
||||||
panic("irqenable: no mem");
|
panic("intrenable: no mem");
|
||||||
v->irq = irq;
|
v->irq = irq;
|
||||||
v->intid = intid;
|
v->intid = intid;
|
||||||
v->f = f;
|
v->f = f;
|
||||||
|
|
|
@ -13,12 +13,14 @@ dev
|
||||||
cap
|
cap
|
||||||
fs
|
fs
|
||||||
ether netif
|
ether netif
|
||||||
|
bridge log
|
||||||
ip arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium inferno
|
ip arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium inferno
|
||||||
draw screen swcursor
|
draw screen swcursor
|
||||||
mouse screen swcursor
|
mouse screen swcursor
|
||||||
uart
|
uart
|
||||||
usb
|
usb
|
||||||
i2c
|
i2c
|
||||||
|
rtc devi2c
|
||||||
sd
|
sd
|
||||||
|
|
||||||
link
|
link
|
||||||
|
@ -26,8 +28,10 @@ link
|
||||||
etherimx ethermii
|
etherimx ethermii
|
||||||
ethermedium
|
ethermedium
|
||||||
loopbackmedium
|
loopbackmedium
|
||||||
|
netdevmedium
|
||||||
i2cimx devi2c
|
i2cimx devi2c
|
||||||
pciimx pci
|
pciimx pci
|
||||||
|
|
||||||
ip
|
ip
|
||||||
tcp
|
tcp
|
||||||
udp
|
udp
|
||||||
|
|
|
@ -227,26 +227,25 @@ rtcwrite(Chan* c, void* buf, long n, vlong off)
|
||||||
char *a, *start;
|
char *a, *start;
|
||||||
Rtc rtc;
|
Rtc rtc;
|
||||||
ulong secs;
|
ulong secs;
|
||||||
|
char *cp, sbuf[32];
|
||||||
uchar bcdclock[Nbcd];
|
uchar bcdclock[Nbcd];
|
||||||
char *cp, *ep;
|
|
||||||
ulong offset = off;
|
ulong offset = off;
|
||||||
|
|
||||||
if(offset!=0)
|
if(offset!=0)
|
||||||
error(Ebadarg);
|
error(Ebadarg);
|
||||||
|
|
||||||
|
|
||||||
switch((ulong)c->qid.path){
|
switch((ulong)c->qid.path){
|
||||||
case Qrtc:
|
case Qrtc:
|
||||||
/*
|
/*
|
||||||
* read the time
|
* read the time
|
||||||
*/
|
*/
|
||||||
cp = ep = buf;
|
if(n >= sizeof(sbuf))
|
||||||
ep += n;
|
error(Ebadarg);
|
||||||
while(cp < ep){
|
strncpy(sbuf, buf, n);
|
||||||
if(*cp>='0' && *cp<='9')
|
sbuf[n] = '\0';
|
||||||
|
for(cp = sbuf; *cp != '\0'; cp++)
|
||||||
|
if(*cp >= '0' && *cp <= '9')
|
||||||
break;
|
break;
|
||||||
cp++;
|
|
||||||
}
|
|
||||||
secs = strtoul(cp, 0, 0);
|
secs = strtoul(cp, 0, 0);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -20,7 +20,7 @@ dev
|
||||||
dtracy
|
dtracy
|
||||||
|
|
||||||
ether netif
|
ether netif
|
||||||
bridge netif log
|
bridge log
|
||||||
ip arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium inferno
|
ip arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium inferno
|
||||||
|
|
||||||
draw screen vga vgax vgasoft
|
draw screen vga vgax vgasoft
|
||||||
|
@ -81,9 +81,9 @@ link
|
||||||
ethervirtio pci
|
ethervirtio pci
|
||||||
ethervirtio10 pci
|
ethervirtio10 pci
|
||||||
ethermedium
|
ethermedium
|
||||||
pcmciamodem
|
|
||||||
netdevmedium
|
|
||||||
loopbackmedium
|
loopbackmedium
|
||||||
|
netdevmedium
|
||||||
|
pcmciamodem
|
||||||
usbuhci pci
|
usbuhci pci
|
||||||
usbohci pci
|
usbohci pci
|
||||||
usbehci usbehcipc
|
usbehci usbehcipc
|
||||||
|
|
|
@ -19,8 +19,8 @@ dev
|
||||||
fs
|
fs
|
||||||
|
|
||||||
ether netif
|
ether netif
|
||||||
bridge netif log
|
bridge log
|
||||||
ip arp chandial ip ipv6 ipaux iproute netlog ethermedium nullmedium pktmedium inferno
|
ip arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium inferno
|
||||||
|
|
||||||
draw screen vga vgax vgasoft
|
draw screen vga vgax vgasoft
|
||||||
mouse mouse
|
mouse mouse
|
||||||
|
@ -79,9 +79,9 @@ link
|
||||||
ethervirtio pci
|
ethervirtio pci
|
||||||
ethervirtio10 pci
|
ethervirtio10 pci
|
||||||
ethermedium
|
ethermedium
|
||||||
# pcmciamodem
|
|
||||||
netdevmedium
|
|
||||||
loopbackmedium
|
loopbackmedium
|
||||||
|
netdevmedium
|
||||||
|
# pcmciamodem
|
||||||
usbuhci pci
|
usbuhci pci
|
||||||
usbohci pci
|
usbohci pci
|
||||||
usbehci pci usbehcipc
|
usbehci pci usbehcipc
|
||||||
|
|
|
@ -243,35 +243,19 @@ sysrfork(va_list list)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
shargs(char *s, int n, char **ap)
|
shargs(char *s, int n, char **ap, int nap)
|
||||||
{
|
{
|
||||||
|
char *p;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if(n <= 2 || s[0] != '#' || s[1] != '!')
|
if(n <= 2 || s[0] != '#' || s[1] != '!')
|
||||||
return -1;
|
return -1;
|
||||||
s += 2;
|
s += 2;
|
||||||
n -= 2; /* skip #! */
|
n -= 2; /* skip #! */
|
||||||
for(i=0;; i++){
|
if((p = memchr(s, '\n', n)) == nil)
|
||||||
if(i >= n)
|
|
||||||
return 0;
|
return 0;
|
||||||
if(s[i]=='\n')
|
*p = 0;
|
||||||
break;
|
i = tokenize(s, ap, nap-1);
|
||||||
}
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
ap[i] = nil;
|
ap[i] = nil;
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
@ -300,12 +284,15 @@ beswav(uvlong v)
|
||||||
uintptr
|
uintptr
|
||||||
sysexec(va_list list)
|
sysexec(va_list list)
|
||||||
{
|
{
|
||||||
|
union {
|
||||||
struct {
|
struct {
|
||||||
Exec;
|
Exec;
|
||||||
uvlong hdr[1];
|
uvlong hdr[1];
|
||||||
} ehdr;
|
} ehdr;
|
||||||
char line[sizeof(ehdr)];
|
char buf[256];
|
||||||
char *progarg[sizeof(line)/2+1];
|
} u;
|
||||||
|
char line[256];
|
||||||
|
char *progarg[32+1];
|
||||||
volatile char *args, *elem, *file0;
|
volatile char *args, *elem, *file0;
|
||||||
char **argv, **argp, **argp0;
|
char **argv, **argp, **argp0;
|
||||||
char *a, *e, *charp, *file;
|
char *a, *e, *charp, *file;
|
||||||
|
@ -353,22 +340,22 @@ sysexec(va_list list)
|
||||||
if(!indir)
|
if(!indir)
|
||||||
kstrdup(&elem, up->genbuf);
|
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)) {
|
if(n >= sizeof(Exec)) {
|
||||||
magic = beswal(ehdr.magic);
|
magic = beswal(u.ehdr.magic);
|
||||||
if(magic == AOUT_MAGIC) {
|
if(magic == AOUT_MAGIC) {
|
||||||
if(magic & HDR_MAGIC) {
|
if(magic & HDR_MAGIC) {
|
||||||
if(n < sizeof(ehdr))
|
if(n < sizeof(u.ehdr))
|
||||||
error(Ebadexec);
|
error(Ebadexec);
|
||||||
entry = beswav(ehdr.hdr[0]);
|
entry = beswav(u.ehdr.hdr[0]);
|
||||||
text = UTZERO+sizeof(ehdr);
|
text = UTZERO+sizeof(u.ehdr);
|
||||||
} else {
|
} else {
|
||||||
entry = beswal(ehdr.entry);
|
entry = beswal(u.ehdr.entry);
|
||||||
text = UTZERO+sizeof(Exec);
|
text = UTZERO+sizeof(Exec);
|
||||||
}
|
}
|
||||||
if(entry < text)
|
if(entry < text)
|
||||||
error(Ebadexec);
|
error(Ebadexec);
|
||||||
text += beswal(ehdr.text);
|
text += beswal(u.ehdr.text);
|
||||||
if(text <= entry || text >= (USTKTOP-USTKSIZE))
|
if(text <= entry || text >= (USTKTOP-USTKSIZE))
|
||||||
error(Ebadexec);
|
error(Ebadexec);
|
||||||
|
|
||||||
|
@ -393,8 +380,8 @@ sysexec(va_list list)
|
||||||
/*
|
/*
|
||||||
* Process #! /bin/sh args ...
|
* Process #! /bin/sh args ...
|
||||||
*/
|
*/
|
||||||
memmove(line, &ehdr, n);
|
memmove(line, u.buf, n);
|
||||||
n = shargs(line, n, progarg);
|
n = shargs(line, n, progarg, nelem(progarg));
|
||||||
if(n < 1)
|
if(n < 1)
|
||||||
error(Ebadexec);
|
error(Ebadexec);
|
||||||
/*
|
/*
|
||||||
|
@ -411,8 +398,8 @@ sysexec(va_list list)
|
||||||
|
|
||||||
t = (text+align) & ~align;
|
t = (text+align) & ~align;
|
||||||
text -= UTZERO;
|
text -= UTZERO;
|
||||||
data = beswal(ehdr.data);
|
data = beswal(u.ehdr.data);
|
||||||
bss = beswal(ehdr.bss);
|
bss = beswal(u.ehdr.bss);
|
||||||
align = BY2PG-1;
|
align = BY2PG-1;
|
||||||
d = (t + data + align) & ~align;
|
d = (t + data + align) & ~align;
|
||||||
bssend = t + data + bss;
|
bssend = t + data + bss;
|
||||||
|
|
|
@ -12,6 +12,7 @@ dev
|
||||||
pipe
|
pipe
|
||||||
dup
|
dup
|
||||||
ether netif
|
ether netif
|
||||||
|
bridge log
|
||||||
ip arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium inferno
|
ip arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium inferno
|
||||||
tls
|
tls
|
||||||
cap
|
cap
|
||||||
|
|
|
@ -39,6 +39,30 @@ _sock_inport(struct sockaddr *a)
|
||||||
return 0;
|
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
|
int
|
||||||
_sock_inaddr(int af, char *ip, char *port, void *a, int *alen)
|
_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);
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
int
|
int
|
||||||
bind(int fd, void *a, int alen)
|
bind(int fd, void *a, int alen)
|
||||||
{
|
{
|
||||||
int n, len, cfd, port;
|
int n, len, cfd;
|
||||||
struct sockaddr *sa;
|
struct sockaddr *sa;
|
||||||
Rock *r;
|
Rock *r;
|
||||||
char msg[128];
|
char msg[128];
|
||||||
|
@ -55,20 +55,25 @@ bind(int fd, void *a, int alen)
|
||||||
errno = EBADF;
|
errno = EBADF;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
port = _sock_inport(&r->addr);
|
|
||||||
if(port > 0)
|
strcpy(msg, "bind ");
|
||||||
snprintf(msg, sizeof msg, "bind %d", port);
|
_sock_inaddr2string(r, msg + 5, sizeof msg - 5);
|
||||||
else
|
|
||||||
strcpy(msg, "bind *");
|
|
||||||
n = write(cfd, msg, strlen(msg));
|
n = write(cfd, msg, strlen(msg));
|
||||||
if(n < 0){
|
if(n < 0){
|
||||||
errno = EOPNOTSUPP; /* Improve error reporting!!! */
|
_syserrno();
|
||||||
|
if(errno == EPLAN9)
|
||||||
|
errno = EOPNOTSUPP;
|
||||||
close(cfd);
|
close(cfd);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
close(cfd);
|
close(cfd);
|
||||||
if(port <= 0)
|
|
||||||
|
if(_sock_inport(&r->addr) == 0)
|
||||||
_sock_ingetaddr(r, &r->addr, 0, "local");
|
_sock_ingetaddr(r, &r->addr, 0, "local");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -121,7 +121,7 @@ listen(fd, backlog)
|
||||||
int backlog;
|
int backlog;
|
||||||
{
|
{
|
||||||
Rock *r;
|
Rock *r;
|
||||||
int n, cfd, port;
|
int n, cfd;
|
||||||
char msg[128];
|
char msg[128];
|
||||||
struct sockaddr_un *lunix;
|
struct sockaddr_un *lunix;
|
||||||
|
|
||||||
|
@ -139,20 +139,13 @@ listen(fd, backlog)
|
||||||
errno = EBADF;
|
errno = EBADF;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
port = _sock_inport(&r->addr);
|
strcpy(msg, "announce ");
|
||||||
if(port >= 0) {
|
_sock_inaddr2string(r, msg + 9, sizeof msg - 9);
|
||||||
if(write(cfd, "bind 0", 6) < 0) {
|
|
||||||
errno = EGREG;
|
|
||||||
close(cfd);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
snprintf(msg, sizeof msg, "announce %d", port);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
strcpy(msg, "announce *");
|
|
||||||
n = write(cfd, msg, strlen(msg));
|
n = write(cfd, msg, strlen(msg));
|
||||||
if(n < 0){
|
if(n < 0){
|
||||||
errno = EOPNOTSUPP; /* Improve error reporting!!! */
|
_syserrno();
|
||||||
|
if(errno == EPLAN9)
|
||||||
|
errno = EOPNOTSUPP;
|
||||||
close(cfd);
|
close(cfd);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,5 +43,7 @@ extern int _sock_data(int, char*, int, int, int, Rock**);
|
||||||
extern int _sock_ipattr(char*);
|
extern int _sock_ipattr(char*);
|
||||||
extern void* _sock_inip(struct sockaddr*);
|
extern void* _sock_inip(struct sockaddr*);
|
||||||
extern int _sock_inport(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 int _sock_inaddr(int, char*, char*, void*, int*);
|
||||||
extern void _sock_ingetaddr(Rock*, void*, int*, char*);
|
extern void _sock_ingetaddr(Rock*, void*, int*, char*);
|
||||||
|
extern char* _sock_inaddr2string(Rock *r, char *dest, int dlen);
|
||||||
|
|
|
@ -3,6 +3,10 @@
|
||||||
#include <auth.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
|
static void
|
||||||
binderr(char *new, char *old, int flag)
|
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);
|
fprint(2, "bind %s %s %s\n", dash, new, old);
|
||||||
}
|
}
|
||||||
if(bind(new, old, flag) < 0)
|
if(bind(new, old, flag) < 0)
|
||||||
sysfatal("bind: %r");
|
sysfatal("bind %s: %r", new);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
resolvenames(char **names, int nname)
|
resolvenames(char **names, int nname)
|
||||||
{
|
{
|
||||||
int i;
|
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++){
|
for(i = 0; i < nname; i++){
|
||||||
if(names[i] == nil)
|
if(names[i] == nil)
|
||||||
continue;
|
continue;
|
||||||
|
@ -55,10 +53,9 @@ resolvenames(char **names, int nname)
|
||||||
case '/':
|
case '/':
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
names[i] = cleanname(smprint("%s/%s", buf, names[i]));
|
names[i] = cleanname(smprint("%s/%s", cwd, names[i]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
close(fd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -103,6 +100,7 @@ sandbox(char **names, int *flags, int nname)
|
||||||
free(d);
|
free(d);
|
||||||
binderr(skel, dir, MBEFORE);
|
binderr(skel, dir, MBEFORE);
|
||||||
}
|
}
|
||||||
|
if(flags[j] != -1)
|
||||||
binderr(names[j], targ, flags[j]);
|
binderr(names[j], targ, flags[j]);
|
||||||
}
|
}
|
||||||
binderr(newroot, "/", MREPL);
|
binderr(newroot, "/", MREPL);
|
||||||
|
@ -133,16 +131,11 @@ skelfs(void)
|
||||||
sysfatal("/mnt/d mount setup: %r");
|
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
|
static void
|
||||||
push(char *path, int flag)
|
push(char *path, int flag)
|
||||||
{
|
{
|
||||||
if(nparts == nelem(parts))
|
if(nparts == nelem(parts))
|
||||||
sysfatal("component overflow");
|
sysfatal("too many bound paths");
|
||||||
parts[nparts] = path;
|
parts[nparts] = path;
|
||||||
mflags[nparts++] = flag;
|
mflags[nparts++] = flag;
|
||||||
}
|
}
|
||||||
|
@ -150,23 +143,23 @@ push(char *path, int flag)
|
||||||
void
|
void
|
||||||
usage(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");
|
exits("usage");
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
main(int argc, char **argv)
|
main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
char devs[1024];
|
char **argp, devs[128];
|
||||||
int dfd;
|
int i, narg, dfd;
|
||||||
char *path;
|
|
||||||
char *a;
|
char *a;
|
||||||
int sflag;
|
int sflag;
|
||||||
|
|
||||||
nparts = 0;
|
nparts = 0;
|
||||||
path = "/";
|
narg = 0;
|
||||||
memset(devs, 0, sizeof devs);
|
memset(devs, 0, sizeof devs);
|
||||||
sflag = 0;
|
sflag = 0;
|
||||||
|
argp = argv;
|
||||||
ARGBEGIN{
|
ARGBEGIN{
|
||||||
case 'D':
|
case 'D':
|
||||||
debug++;
|
debug++;
|
||||||
|
@ -184,9 +177,6 @@ main(int argc, char **argv)
|
||||||
case 'e':
|
case 'e':
|
||||||
snprint(devs, sizeof devs, "%s%s", devs, EARGF(usage()));
|
snprint(devs, sizeof devs, "%s%s", devs, EARGF(usage()));
|
||||||
break;
|
break;
|
||||||
case '.':
|
|
||||||
path = EARGF(usage());
|
|
||||||
break;
|
|
||||||
case 's':
|
case 's':
|
||||||
sflag = 1;
|
sflag = 1;
|
||||||
break;
|
break;
|
||||||
|
@ -195,18 +185,19 @@ main(int argc, char **argv)
|
||||||
break;
|
break;
|
||||||
}ARGEND
|
}ARGEND
|
||||||
|
|
||||||
if(argc == 0)
|
if(argc == 0 && !sflag)
|
||||||
usage();
|
usage();
|
||||||
|
|
||||||
|
if(getwd(cwd, sizeof(cwd)) == nil)
|
||||||
|
sysfatal("getwd: %r");
|
||||||
|
push(cwd, -1);
|
||||||
if(sflag){
|
if(sflag){
|
||||||
snprint(devs, sizeof devs, "%s%s", devs, "|d");
|
snprint(devs, sizeof devs, "%s%s", devs, "|d");
|
||||||
push("/srv", MREPL|MCREATE);
|
push("/srv", MREPL|MCREATE);
|
||||||
push("/env", MREPL|MCREATE);
|
push("/env", MREPL|MCREATE);
|
||||||
push("/rc", MREPL);
|
push("/rc", MREPL);
|
||||||
push("/bin", MREPL);
|
push("/bin", MREPL);
|
||||||
push(argv[0], MREPL);
|
argp[narg++] = "/bin/rc";
|
||||||
rc[1] = argv[0];
|
|
||||||
argv = rc;
|
|
||||||
} else {
|
} else {
|
||||||
if(access(argv[0], AEXIST) == -1){
|
if(access(argv[0], AEXIST) == -1){
|
||||||
if((argv[0] = smprint("/bin/%s", argv[0])) == nil)
|
if((argv[0] = smprint("/bin/%s", argv[0])) == nil)
|
||||||
|
@ -216,6 +207,9 @@ main(int argc, char **argv)
|
||||||
}
|
}
|
||||||
push(argv[0], MREPL);
|
push(argv[0], MREPL);
|
||||||
}
|
}
|
||||||
|
for(i = 0; i < argc; i++)
|
||||||
|
argp[narg++] = argv[i];
|
||||||
|
argp[narg] = nil;
|
||||||
|
|
||||||
rfork(RFNAMEG|RFFDG);
|
rfork(RFNAMEG|RFFDG);
|
||||||
skelfs();
|
skelfs();
|
||||||
|
@ -238,8 +232,8 @@ main(int argc, char **argv)
|
||||||
}
|
}
|
||||||
close(dfd);
|
close(dfd);
|
||||||
|
|
||||||
if(chdir(path) < 0)
|
if(chdir(cwd) < 0)
|
||||||
sysfatal("can not cd to %s", path);
|
sysfatal("chdir %s: %r", cwd);
|
||||||
exec(argv[0], argv);
|
exec(argp[0], argp);
|
||||||
sysfatal("exec: %r");
|
sysfatal("exec: %r");
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,7 +64,7 @@ lookup(Pfilt *pf, Object *o)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
filtermatch1(Pfilt *pf, Object *t, Object *pt)
|
matchesfilter1(Pfilt *pf, Object *t, Object *pt)
|
||||||
{
|
{
|
||||||
Object *a, *b;
|
Object *a, *b;
|
||||||
Hash ha, hb;
|
Hash ha, hb;
|
||||||
|
@ -88,7 +88,7 @@ filtermatch1(Pfilt *pf, Object *t, Object *pt)
|
||||||
sysfatal("read %H: %r", ha);
|
sysfatal("read %H: %r", ha);
|
||||||
if((b = readobject(hb)) == nil)
|
if((b = readobject(hb)) == nil)
|
||||||
sysfatal("read %H: %r", hb);
|
sysfatal("read %H: %r", hb);
|
||||||
r = filtermatch1(&pf->sub[i], a, b);
|
r = matchesfilter1(&pf->sub[i], a, b);
|
||||||
unref(a);
|
unref(a);
|
||||||
unref(b);
|
unref(b);
|
||||||
if(r)
|
if(r)
|
||||||
|
@ -98,11 +98,12 @@ filtermatch1(Pfilt *pf, Object *t, Object *pt)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
filtermatch(Object *o)
|
matchesfilter(Object *o)
|
||||||
{
|
{
|
||||||
Object *t, *p, *pt;
|
Object *t, *p, *pt;
|
||||||
int i, r;
|
int i, r;
|
||||||
|
|
||||||
|
assert(o->type == GCommit);
|
||||||
if(pathfilt == nil)
|
if(pathfilt == nil)
|
||||||
return 1;
|
return 1;
|
||||||
if((t = readobject(o->commit->tree)) == nil)
|
if((t = readobject(o->commit->tree)) == nil)
|
||||||
|
@ -112,7 +113,7 @@ filtermatch(Object *o)
|
||||||
sysfatal("read %H: %r", o->commit->parent[i]);
|
sysfatal("read %H: %r", o->commit->parent[i]);
|
||||||
if((pt = readobject(p->commit->tree)) == nil)
|
if((pt = readobject(p->commit->tree)) == nil)
|
||||||
sysfatal("read %H: %r", o->commit->tree);
|
sysfatal("read %H: %r", o->commit->tree);
|
||||||
r = filtermatch1(pathfilt, t, pt);
|
r = matchesfilter1(pathfilt, t, pt);
|
||||||
unref(p);
|
unref(p);
|
||||||
unref(pt);
|
unref(pt);
|
||||||
if(r)
|
if(r)
|
||||||
|
@ -131,16 +132,13 @@ nextline(char *p, char *e)
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static int
|
||||||
show(Object *o)
|
show(Object *o)
|
||||||
{
|
{
|
||||||
Tm tm;
|
Tm tm;
|
||||||
char *p, *q, *e;
|
char *p, *q, *e;
|
||||||
|
|
||||||
assert(o->type == GCommit);
|
assert(o->type == GCommit);
|
||||||
if(!filtermatch(o))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if(shortlog){
|
if(shortlog){
|
||||||
p = o->commit->msg;
|
p = o->commit->msg;
|
||||||
e = p + o->commit->nmsg;
|
e = p + o->commit->nmsg;
|
||||||
|
@ -170,6 +168,7 @@ show(Object *o)
|
||||||
Bprint(out, "\n");
|
Bprint(out, "\n");
|
||||||
}
|
}
|
||||||
Bflush(out);
|
Bflush(out);
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -181,10 +180,14 @@ showquery(char *q)
|
||||||
|
|
||||||
if((n = resolverefs(&h, q)) == -1)
|
if((n = resolverefs(&h, q)) == -1)
|
||||||
sysfatal("resolve: %r");
|
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)
|
if((o = readobject(h[i])) == nil)
|
||||||
sysfatal("read %H: %r", h[i]);
|
sysfatal("read %H: %r", h[i]);
|
||||||
|
if(matchesfilter(o)){
|
||||||
show(o);
|
show(o);
|
||||||
|
if(msgcount != -1)
|
||||||
|
msgcount--;
|
||||||
|
}
|
||||||
unref(o);
|
unref(o);
|
||||||
}
|
}
|
||||||
exits(nil);
|
exits(nil);
|
||||||
|
@ -207,8 +210,12 @@ showcommits(char *c)
|
||||||
qinit(&objq);
|
qinit(&objq);
|
||||||
osinit(&done);
|
osinit(&done);
|
||||||
qput(&objq, o, 0);
|
qput(&objq, o, 0);
|
||||||
while(qpop(&objq, &e) && (msgcount == -1 || msgcount-- > 0)){
|
while(qpop(&objq, &e) && (msgcount == -1 || msgcount > 0)){
|
||||||
|
if(matchesfilter(e.o)){
|
||||||
show(e.o);
|
show(e.o);
|
||||||
|
if(msgcount != -1)
|
||||||
|
msgcount--;
|
||||||
|
}
|
||||||
for(i = 0; i < e.o->commit->nparent; i++){
|
for(i = 0; i < e.o->commit->nparent; i++){
|
||||||
if(oshas(&done, e.o->commit->parent[i]))
|
if(oshas(&done, e.o->commit->parent[i]))
|
||||||
continue;
|
continue;
|
||||||
|
|
224
sys/src/cmd/ktrans/hash.c
Normal file
224
sys/src/cmd/ktrans/hash.c
Normal 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
23
sys/src/cmd/ktrans/hash.h
Normal 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);
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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
|
@ -6,16 +6,26 @@
|
||||||
* okamoto@granite.cias.osakafu-u.ac.jp
|
* 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 <u.h>
|
||||||
#include <libc.h>
|
#include <libc.h>
|
||||||
#include <bio.h>
|
#include <bio.h>
|
||||||
|
#include "hash.h"
|
||||||
#include "ktrans.h"
|
#include "ktrans.h"
|
||||||
#include "jisho.h"
|
|
||||||
|
|
||||||
#define LSIZE 256
|
#define LSIZE 256
|
||||||
|
|
||||||
Rune lbuf[LSIZE]; /* hiragana buffer for key input written by send() */
|
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 */
|
uchar okurigana[LSIZE]; /* buffer for okurigana */
|
||||||
char okuri = 0; /* buffer/flag for capital input char */
|
char okuri = 0; /* buffer/flag for capital input char */
|
||||||
int in, out;
|
int in, out;
|
||||||
|
@ -23,16 +33,10 @@ int llen, olen, joshi = 0;
|
||||||
int natural = 1; /* not Japanese but English mode */
|
int natural = 1; /* not Japanese but English mode */
|
||||||
|
|
||||||
int changelang(int);
|
int changelang(int);
|
||||||
int dotrans(Dictionary*);
|
int dotrans(Hmap*);
|
||||||
int nrune(char *);
|
int nrune(char *);
|
||||||
void send(uchar *, int);
|
void send(uchar *, int);
|
||||||
Map *match(uchar *p, int *nc, Map *table);
|
Hmap* opendict(Hmap *, char *);
|
||||||
|
|
||||||
extern Dictionary *openQDIC(char *);
|
|
||||||
extern KouhoList *getKouhoHash(Dictionary*, char *);
|
|
||||||
extern KouhoList *getKouhoFile(DicList*, char *);
|
|
||||||
extern void freeQDIC(Dictionary*);
|
|
||||||
extern void selectKouho(KouhoList **, KouhoList*);
|
|
||||||
|
|
||||||
void
|
void
|
||||||
kbdopen(void)
|
kbdopen(void)
|
||||||
|
@ -89,6 +93,49 @@ kbdopen(void)
|
||||||
exits(nil);
|
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
|
void
|
||||||
usage(void)
|
usage(void)
|
||||||
{
|
{
|
||||||
|
@ -101,11 +148,11 @@ main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
|
|
||||||
uchar *bp, *ep, buf[128];
|
uchar *bp, *ep, buf[128];
|
||||||
Map *mp;
|
Map lkup, last;
|
||||||
int nchar, wantmore;
|
int wantmore;
|
||||||
int n, c;
|
int n, c;
|
||||||
char *dictname;
|
char *jishoname, *zidianname;
|
||||||
Dictionary *jisho;
|
Hmap *jisho, *zidian;
|
||||||
|
|
||||||
ARGBEGIN{
|
ARGBEGIN{
|
||||||
default: usage();
|
default: usage();
|
||||||
|
@ -113,9 +160,20 @@ main(int argc, char *argv[])
|
||||||
if(argc != 0)
|
if(argc != 0)
|
||||||
usage();
|
usage();
|
||||||
|
|
||||||
if((dictname = getenv("jisho")) == nil)
|
if((jishoname = getenv("jisho")) == nil)
|
||||||
dictname = "/lib/kanji.jisho";
|
jishoname = "/lib/kanji.jisho";
|
||||||
jisho = openQDIC(dictname);
|
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();
|
kbdopen();
|
||||||
if(fork())
|
if(fork())
|
||||||
|
@ -147,8 +205,8 @@ main(int argc, char *argv[])
|
||||||
wantmore = 0;
|
wantmore = 0;
|
||||||
|
|
||||||
if (*bp=='') { /* ^x read ktrans-jisho once more */
|
if (*bp=='') { /* ^x read ktrans-jisho once more */
|
||||||
freeQDIC(jisho);
|
jisho = opendict(jisho, jishoname);
|
||||||
jisho = openQDIC(dictname);
|
zidian = opendict(zidian, zidianname);
|
||||||
llen = 0;
|
llen = 0;
|
||||||
olen = okuri = joshi = 0;
|
olen = okuri = joshi = 0;
|
||||||
wantmore=0;
|
wantmore=0;
|
||||||
|
@ -156,6 +214,9 @@ main(int argc, char *argv[])
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (*bp=='') { /* ^\ (start translation command) */
|
if (*bp=='') { /* ^\ (start translation command) */
|
||||||
|
if (table == hanzi)
|
||||||
|
c = dotrans(zidian);
|
||||||
|
else
|
||||||
c = dotrans(jisho);
|
c = dotrans(jisho);
|
||||||
if (c)
|
if (c)
|
||||||
*bp = c; /* pointer to translated rune */
|
*bp = c; /* pointer to translated rune */
|
||||||
|
@ -167,11 +228,13 @@ main(int argc, char *argv[])
|
||||||
bp++;
|
bp++;
|
||||||
llen = 0;
|
llen = 0;
|
||||||
olen = okuri = joshi = 0;
|
olen = okuri = joshi = 0;
|
||||||
|
last.kana = nil;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (changelang(*bp)) { /* change language mode OK */
|
if (changelang(*bp)) { /* change language mode OK */
|
||||||
bp++;
|
bp++;
|
||||||
olen = okuri = joshi = 0;
|
olen = okuri = joshi = 0;
|
||||||
|
last.kana = nil;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (natural || *bp<=' ' || *bp>='{') { /* English mode but not ascii */
|
if (natural || *bp<=' ' || *bp>='{') { /* English mode but not ascii */
|
||||||
|
@ -179,6 +242,7 @@ main(int argc, char *argv[])
|
||||||
int rlen = chartorune(&r, (char *)bp);
|
int rlen = chartorune(&r, (char *)bp);
|
||||||
send(bp, rlen); /* write bp to /dev/cons */
|
send(bp, rlen); /* write bp to /dev/cons */
|
||||||
bp += rlen;
|
bp += rlen;
|
||||||
|
last.kana = nil;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (table == hira && (*bp >= 'A' && *bp <= 'Z') && (*(bp+1) < 'A'
|
if (table == hira && (*bp >= 'A' && *bp <= 'Z') && (*(bp+1) < 'A'
|
||||||
|
@ -192,25 +256,31 @@ main(int argc, char *argv[])
|
||||||
joshi = 1;
|
joshi = 1;
|
||||||
olen = 0;
|
olen = 0;
|
||||||
}
|
}
|
||||||
mp = match(bp, &nchar, table);
|
if(hmapget(table, (char*)bp, &lkup) < 0){
|
||||||
if (mp == 0) {
|
if(last.kana != nil){
|
||||||
if (nchar>0) { /* match, longer possible */
|
send((uchar*)last.kana, strlen(last.kana));
|
||||||
wantmore++;
|
bp += strlen(last.roma);
|
||||||
|
} else
|
||||||
|
send(bp++, 1);
|
||||||
|
last.kana = nil;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
send(bp++, 1); /* alphabet in kana mode */
|
/* concatinations; only advance a single character */
|
||||||
} else {
|
if(lkup.kana != nil && strstr("ッっ", lkup.kana))
|
||||||
send((uchar*)mp->kana, strlen(mp->kana));
|
lkup.roma = "_";
|
||||||
bp += nchar;
|
/* partial match */
|
||||||
}
|
if(lkup.kana == nil || lkup.leadstomore == 1){
|
||||||
}
|
if(lkup.kana != nil)
|
||||||
}
|
last = lkup;
|
||||||
}
|
|
||||||
|
|
||||||
int
|
wantmore = 1;
|
||||||
min(int a, int b)
|
break;
|
||||||
{
|
}
|
||||||
return a<b? a: b;
|
last.kana = nil;
|
||||||
|
send((uchar*)lkup.kana, strlen(lkup.kana));
|
||||||
|
bp += strlen(lkup.roma);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -232,7 +302,9 @@ send(uchar *p, int n)
|
||||||
llen -= 64;
|
llen -= 64;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (table!=hira || natural)
|
if(table != hira && table != hanzi)
|
||||||
|
return;
|
||||||
|
if(natural && table != hanzi)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ep = p+n;
|
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
|
int
|
||||||
changelang(int c)
|
changelang(int c)
|
||||||
{
|
{
|
||||||
switch(c){
|
switch(c){
|
||||||
case '': /* ^t (English mode) */
|
case '': /* ^t (English mode) */
|
||||||
natural = 1;
|
natural = 1;
|
||||||
|
table = hira;
|
||||||
llen = 0;
|
llen = 0;
|
||||||
return 1;
|
return 1;
|
||||||
break;
|
break;
|
||||||
|
@ -334,23 +370,80 @@ changelang(int c)
|
||||||
llen = 0;
|
llen = 0;
|
||||||
return 1;
|
return 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case '': /* ^c (Chinese mode) */
|
||||||
|
natural = 1;
|
||||||
|
table = hanzi;
|
||||||
|
llen = 0;
|
||||||
|
return 1;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return 0;
|
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
|
* write translated kanji runes to stdout and return last character
|
||||||
* if it's not ctl-\. if the last is ctl-\, proceed with
|
* if it's not ctl-\. if the last is ctl-\, proceed with
|
||||||
* translation of the next kouho
|
* translation of the next kouho
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
dotrans(Dictionary *dic)
|
dotrans(Hmap *dic)
|
||||||
{
|
{
|
||||||
Rune *res, r[1];
|
Rune *res, r[1];
|
||||||
char v[1024], *p, tbuf[64], hirabuf[64];
|
char v[1024], *p, tbuf[64], hirabuf[64];
|
||||||
int j, lastlen, nokouho = 0;
|
int j, lastlen, nokouho = 0;
|
||||||
char ch;
|
char ch;
|
||||||
KouhoList *fstkouho, *currentkouho;
|
int i;
|
||||||
|
char *kouho[16];
|
||||||
|
|
||||||
if (llen==0)
|
if (llen==0)
|
||||||
return 0; /* don't use kanji transform function */
|
return 0; /* don't use kanji transform function */
|
||||||
|
@ -375,15 +468,13 @@ dotrans(Dictionary *dic)
|
||||||
if (okuri && joshi != 1) /* verb mode */
|
if (okuri && joshi != 1) /* verb mode */
|
||||||
hirabuf[strlen(hirabuf) - 1] = '\0';
|
hirabuf[strlen(hirabuf) - 1] = '\0';
|
||||||
|
|
||||||
if(!(fstkouho = getKouhoHash(dic, v))) { /* not found */
|
if(hmapget(dic, v, kouho) < 0){
|
||||||
llen = olen = okuri = joshi = 0;
|
llen = olen = okuri = joshi = 0;
|
||||||
okurigana[0] = 0;
|
okurigana[0] = 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
for(i = 0; i < nelem(kouho) && kouho[i] != nil; i++) {
|
||||||
currentkouho = fstkouho;
|
p = kouho[i];
|
||||||
for(;;) {
|
|
||||||
p = currentkouho->kouhotop; /* p to the head of kanji kouho array */
|
|
||||||
lastlen = nrune(tbuf); /* number of rune chars */
|
lastlen = nrune(tbuf); /* number of rune chars */
|
||||||
|
|
||||||
if (okuri && joshi != 1) /* verb mode */
|
if (okuri && joshi != 1) /* verb mode */
|
||||||
|
@ -407,10 +498,9 @@ dotrans(Dictionary *dic)
|
||||||
exits(nil);
|
exits(nil);
|
||||||
|
|
||||||
if (ch == '') { /* if next input is ^\, once again */
|
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;
|
nokouho = 0;
|
||||||
strcpy(tbuf, p);
|
strcpy(tbuf, p);
|
||||||
currentkouho = currentkouho->nextkouho;
|
|
||||||
|
|
||||||
if (okuri && joshi != 1) /* verb mode */
|
if (okuri && joshi != 1) /* verb mode */
|
||||||
for (j=0; j<nrune(tbuf); j++)
|
for (j=0; j<nrune(tbuf); j++)
|
||||||
|
@ -442,8 +532,12 @@ dotrans(Dictionary *dic)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if(!nokouho) /* learn the previous use of the kouho */
|
if(!nokouho && i != 0){ /* learn the previous use of the kouho */
|
||||||
selectKouho(&(fstkouho->dicitem->kouho), currentkouho);
|
p = kouho[0];
|
||||||
|
kouho[0] = kouho[i];
|
||||||
|
kouho[i] = p;
|
||||||
|
hmapupd(&dic, v, kouho);
|
||||||
|
}
|
||||||
|
|
||||||
olen = okuri = joshi = 0;
|
olen = okuri = joshi = 0;
|
||||||
okurigana[0] = 0;
|
okurigana[0] = 0;
|
||||||
|
|
|
@ -2,9 +2,9 @@
|
||||||
|
|
||||||
BIN=/$objtype/bin
|
BIN=/$objtype/bin
|
||||||
TARG=ktrans
|
TARG=ktrans
|
||||||
HFILES=jisho.h ktrans.h
|
HFILES=ktrans.h
|
||||||
OFILES=\
|
OFILES=\
|
||||||
|
hash.$O\
|
||||||
main.$O\
|
main.$O\
|
||||||
jisho.$O
|
|
||||||
|
|
||||||
</sys/src/cmd/mkone
|
</sys/src/cmd/mkone
|
||||||
|
|
|
@ -608,6 +608,8 @@ redraw(void)
|
||||||
for(j=0; j<nhidden; j++)
|
for(j=0; j<nhidden; j++)
|
||||||
if(w == hidden[j])
|
if(w == hidden[j])
|
||||||
break;
|
break;
|
||||||
|
memmove(w->cols, &cols[BACK], sizeof(w->cols));
|
||||||
|
|
||||||
frinittick(w);
|
frinittick(w);
|
||||||
incref(w);
|
incref(w);
|
||||||
if(j < nhidden){
|
if(j < nhidden){
|
||||||
|
|
|
@ -802,6 +802,8 @@ changemesg(Plumbmsg *pm)
|
||||||
|
|
||||||
digest = plumblookup(pm->attr, "digest");
|
digest = plumblookup(pm->attr, "digest");
|
||||||
action = plumblookup(pm->attr, "mailtype");
|
action = plumblookup(pm->attr, "mailtype");
|
||||||
|
if(digest == nil || action == nil)
|
||||||
|
return;
|
||||||
if(strcmp(action, "new") == 0){
|
if(strcmp(action, "new") == 0){
|
||||||
if((m = load(pm->data, digest, 1)) == nil)
|
if((m = load(pm->data, digest, 1)) == nil)
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<div class="left>
|
<div class="left">
|
||||||
<a href="https://owen.bellz.org">escape</a> |
|
<a href="https://owen.bellz.org">escape</a> |
|
||||||
<a href="//withdrawal.owen.bellz.org">withdrawal</a>
|
<a href="//withdrawal.owen.bellz.org">withdrawal</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Reference in a new issue