Compare commits

..

32 commits

Author SHA1 Message Date
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
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
35a6dacb3d fix quotations in werc top bar 2022-07-19 10:42:15 -04:00
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
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
de8181a85c oops, fix rioback some more 2022-07-15 13:07:39 -04:00
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. 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.

View file

@ -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

View file

@ -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)

View file

@ -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

View file

@ -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

View file

@ -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
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 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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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
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; 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;

View file

@ -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

View file

@ -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);
/* /*

View file

@ -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

View file

@ -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

View file

@ -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;

View file

@ -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

View file

@ -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;
}

View file

@ -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;
} }

View file

@ -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;
} }

View file

@ -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);

View file

@ -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");
} }

View file

@ -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
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 * 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;

View file

@ -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

View file

@ -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){

View file

@ -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;

View file

@ -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>