Merge remote-tracking branch 'origin/front' into front

This commit is contained in:
xfnw 2022-07-18 22:31:02 -04:00
commit 917ae0345f
29 changed files with 86682 additions and 3270 deletions

83100
lib/hanzi.zidian Normal file

File diff suppressed because it is too large Load Diff

12
lib/ktrans/README Normal file
View File

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

2
lib/ktrans/grabskkdicts Executable file
View File

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

2
lib/ktrans/skk2ktrans Executable file
View File

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

View File

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

View File

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

View File

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

View File

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

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -13,6 +13,7 @@ dev
cap
fs
ether netif
bridge log
ip arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium inferno
draw screen swcursor
mouse screen swcursor
@ -26,8 +27,10 @@ link
etherimx ethermii
ethermedium
loopbackmedium
netdevmedium
i2cimx devi2c
pciimx pci
ip
tcp
udp

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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

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

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

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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