mirror of
https://github.com/9fans/plan9port.git
synced 2025-01-12 11:10:07 +00:00
tweaks
This commit is contained in:
parent
ba19f6b5b4
commit
c8af1ab17b
3 changed files with 30101 additions and 0 deletions
|
@ -23,6 +23,7 @@ extern "C" {
|
||||||
#include <utf.h>
|
#include <utf.h>
|
||||||
#include <fmt.h>
|
#include <fmt.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
#include <ctype.h> /* for tolower */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* OS-specific crap
|
* OS-specific crap
|
||||||
|
|
342
src/cmd/look.c
Normal file
342
src/cmd/look.c
Normal file
|
@ -0,0 +1,342 @@
|
||||||
|
#include <u.h>
|
||||||
|
#include <libc.h>
|
||||||
|
#include <bio.h>
|
||||||
|
/* Macros for Rune support of ctype.h-like functions */
|
||||||
|
|
||||||
|
#define isupper(r) (L'A' <= (r) && (r) <= L'Z')
|
||||||
|
#define islower(r) (L'a' <= (r) && (r) <= L'z')
|
||||||
|
#define isalpha(r) (isupper(r) || islower(r))
|
||||||
|
#define islatin1(r) (0xC0 <= (r) && (r) <= 0xFF)
|
||||||
|
|
||||||
|
#define isdigit(r) (L'0' <= (r) && (r) <= L'9')
|
||||||
|
|
||||||
|
#define isalnum(r) (isalpha(r) || isdigit(r))
|
||||||
|
|
||||||
|
#define isspace(r) ((r) == L' ' || (r) == L'\t' \
|
||||||
|
|| (0x0A <= (r) && (r) <= 0x0D))
|
||||||
|
|
||||||
|
#define tolower(r) ((r)-'A'+'a')
|
||||||
|
|
||||||
|
#define sgn(v) ((v) < 0 ? -1 : ((v) > 0 ? 1 : 0))
|
||||||
|
|
||||||
|
#define WORDSIZ 4000
|
||||||
|
char *filename = "#9/lib/words";
|
||||||
|
Biobuf *dfile;
|
||||||
|
Biobuf bout;
|
||||||
|
Biobuf bin;
|
||||||
|
|
||||||
|
int fold;
|
||||||
|
int direc;
|
||||||
|
int exact;
|
||||||
|
int iflag;
|
||||||
|
int rev = 1; /*-1 for reverse-ordered file, not implemented*/
|
||||||
|
int (*compare)(Rune*, Rune*);
|
||||||
|
Rune tab = '\t';
|
||||||
|
Rune entry[WORDSIZ];
|
||||||
|
Rune word[WORDSIZ];
|
||||||
|
Rune key[50], orig[50];
|
||||||
|
Rune latin_fold_tab[] =
|
||||||
|
{
|
||||||
|
/* Table to fold latin 1 characters to ASCII equivalents
|
||||||
|
based at Rune value 0xc0
|
||||||
|
|
||||||
|
À Á Â Ã Ä Å Æ Ç
|
||||||
|
È É Ê Ë Ì Í Î Ï
|
||||||
|
Ð Ñ Ò Ó Ô Õ Ö ×
|
||||||
|
Ø Ù Ú Û Ü Ý Þ ß
|
||||||
|
à á â ã ä å æ ç
|
||||||
|
è é ê ë ì í î ï
|
||||||
|
ð ñ ò ó ô õ ö ÷
|
||||||
|
ø ù ú û ü ý þ ÿ
|
||||||
|
*/
|
||||||
|
'a', 'a', 'a', 'a', 'a', 'a', 'a', 'c',
|
||||||
|
'e', 'e', 'e', 'e', 'i', 'i', 'i', 'i',
|
||||||
|
'd', 'n', 'o', 'o', 'o', 'o', 'o', 0 ,
|
||||||
|
'o', 'u', 'u', 'u', 'u', 'y', 0 , 0 ,
|
||||||
|
'a', 'a', 'a', 'a', 'a', 'a', 'a', 'c',
|
||||||
|
'e', 'e', 'e', 'e', 'i', 'i', 'i', 'i',
|
||||||
|
'd', 'n', 'o', 'o', 'o', 'o', 'o', 0 ,
|
||||||
|
'o', 'u', 'u', 'u', 'u', 'y', 0 , 'y',
|
||||||
|
};
|
||||||
|
|
||||||
|
int locate(void);
|
||||||
|
int acomp(Rune*, Rune*);
|
||||||
|
int getword(Biobuf*, Rune *rp, int n);
|
||||||
|
void torune(char*, Rune*);
|
||||||
|
void rcanon(Rune*, Rune*);
|
||||||
|
int ncomp(Rune*, Rune*);
|
||||||
|
|
||||||
|
void
|
||||||
|
main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
|
||||||
|
filename = unsharp(filename);
|
||||||
|
|
||||||
|
Binit(&bin, 0, OREAD);
|
||||||
|
Binit(&bout, 1, OWRITE);
|
||||||
|
compare = acomp;
|
||||||
|
ARGBEGIN{
|
||||||
|
case 'd':
|
||||||
|
direc++;
|
||||||
|
break;
|
||||||
|
case 'f':
|
||||||
|
fold++;
|
||||||
|
break;
|
||||||
|
case 'i':
|
||||||
|
iflag++;
|
||||||
|
break;
|
||||||
|
case 'n':
|
||||||
|
compare = ncomp;
|
||||||
|
break;
|
||||||
|
case 't':
|
||||||
|
chartorune(&tab,ARGF());
|
||||||
|
break;
|
||||||
|
case 'x':
|
||||||
|
exact++;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fprint(2, "%s: bad option %c\n", argv0, ARGC());
|
||||||
|
fprint(2, "usage: %s -[dfinx] [-t c] [string] [file]\n", argv0);
|
||||||
|
exits("usage");
|
||||||
|
} ARGEND
|
||||||
|
if(!iflag){
|
||||||
|
if(argc >= 1) {
|
||||||
|
torune(argv[0], orig);
|
||||||
|
argv++;
|
||||||
|
argc--;
|
||||||
|
} else
|
||||||
|
iflag++;
|
||||||
|
}
|
||||||
|
if(argc < 1) {
|
||||||
|
direc++;
|
||||||
|
fold++;
|
||||||
|
} else
|
||||||
|
filename = argv[0];
|
||||||
|
if (!iflag)
|
||||||
|
rcanon(orig, key);
|
||||||
|
dfile = Bopen(filename, OREAD);
|
||||||
|
if(dfile == 0) {
|
||||||
|
fprint(2, "look: can't open %s\n", filename);
|
||||||
|
exits("no dictionary");
|
||||||
|
}
|
||||||
|
if(!iflag)
|
||||||
|
if(!locate())
|
||||||
|
exits("not found");
|
||||||
|
do {
|
||||||
|
if(iflag) {
|
||||||
|
Bflush(&bout);
|
||||||
|
if(!getword(&bin, orig, sizeof(orig)/sizeof(orig[0])))
|
||||||
|
exits(0);
|
||||||
|
rcanon(orig, key);
|
||||||
|
if(!locate())
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!exact || !acomp(word, key))
|
||||||
|
Bprint(&bout, "%S\n", entry);
|
||||||
|
while(getword(dfile, entry, sizeof(entry)/sizeof(entry[0]))) {
|
||||||
|
rcanon(entry, word);
|
||||||
|
n = compare(key, word);
|
||||||
|
switch(n) {
|
||||||
|
case -1:
|
||||||
|
if(exact)
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
if (!exact || !acomp(word, orig))
|
||||||
|
Bprint(&bout, "%S\n", entry);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while(iflag);
|
||||||
|
exits(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
locate(void)
|
||||||
|
{
|
||||||
|
long top, bot, mid;
|
||||||
|
long c;
|
||||||
|
int n;
|
||||||
|
|
||||||
|
bot = 0;
|
||||||
|
top = Bseek(dfile, 0L, 2);
|
||||||
|
for(;;) {
|
||||||
|
mid = (top+bot) / 2;
|
||||||
|
Bseek(dfile, mid, 0);
|
||||||
|
do
|
||||||
|
c = Bgetrune(dfile);
|
||||||
|
while(c>=0 && c!='\n');
|
||||||
|
mid = Boffset(dfile);
|
||||||
|
if(!getword(dfile, entry, sizeof(entry)/sizeof(entry[0])))
|
||||||
|
break;
|
||||||
|
rcanon(entry, word);
|
||||||
|
n = compare(key, word);
|
||||||
|
switch(n) {
|
||||||
|
case -2:
|
||||||
|
case -1:
|
||||||
|
case 0:
|
||||||
|
if(top <= mid)
|
||||||
|
break;
|
||||||
|
top = mid;
|
||||||
|
continue;
|
||||||
|
case 1:
|
||||||
|
case 2:
|
||||||
|
bot = mid;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Bseek(dfile, bot, 0);
|
||||||
|
while(getword(dfile, entry, sizeof(entry)/sizeof(entry[0]))) {
|
||||||
|
rcanon(entry, word);
|
||||||
|
n = compare(key, word);
|
||||||
|
switch(n) {
|
||||||
|
case -2:
|
||||||
|
return 0;
|
||||||
|
case -1:
|
||||||
|
if(exact)
|
||||||
|
return 0;
|
||||||
|
case 0:
|
||||||
|
return 1;
|
||||||
|
case 1:
|
||||||
|
case 2:
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* acomp(s, t) returns:
|
||||||
|
* -2 if s strictly precedes t
|
||||||
|
* -1 if s is a prefix of t
|
||||||
|
* 0 if s is the same as t
|
||||||
|
* 1 if t is a prefix of s
|
||||||
|
* 2 if t strictly precedes s
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
acomp(Rune *s, Rune *t)
|
||||||
|
{
|
||||||
|
int cs, ct;
|
||||||
|
|
||||||
|
for(;;) {
|
||||||
|
cs = *s;
|
||||||
|
ct = *t;
|
||||||
|
if(cs != ct)
|
||||||
|
break;
|
||||||
|
if(cs == 0)
|
||||||
|
return 0;
|
||||||
|
s++;
|
||||||
|
t++;
|
||||||
|
}
|
||||||
|
if(cs == 0)
|
||||||
|
return -1;
|
||||||
|
if(ct == 0)
|
||||||
|
return 1;
|
||||||
|
if(cs < ct)
|
||||||
|
return -2;
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
torune(char *old, Rune *new)
|
||||||
|
{
|
||||||
|
do old += chartorune(new, old);
|
||||||
|
while(*new++);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
rcanon(Rune *old, Rune *new)
|
||||||
|
{
|
||||||
|
Rune r;
|
||||||
|
|
||||||
|
while((r = *old++) && r != tab) {
|
||||||
|
if (islatin1(r) && latin_fold_tab[r-0xc0])
|
||||||
|
r = latin_fold_tab[r-0xc0];
|
||||||
|
if(direc)
|
||||||
|
if(!(isalnum(r) || r == L' ' || r == L'\t'))
|
||||||
|
continue;
|
||||||
|
if(fold)
|
||||||
|
if(isupper(r))
|
||||||
|
r = tolower(r);
|
||||||
|
*new++ = r;
|
||||||
|
}
|
||||||
|
*new = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ncomp(Rune *s, Rune *t)
|
||||||
|
{
|
||||||
|
Rune *is, *it, *js, *jt;
|
||||||
|
int a, b;
|
||||||
|
int ssgn, tsgn;
|
||||||
|
|
||||||
|
while(isspace(*s))
|
||||||
|
s++;
|
||||||
|
while(isspace(*t))
|
||||||
|
t++;
|
||||||
|
ssgn = tsgn = -2*rev;
|
||||||
|
if(*s == '-') {
|
||||||
|
s++;
|
||||||
|
ssgn = -ssgn;
|
||||||
|
}
|
||||||
|
if(*t == '-') {
|
||||||
|
t++;
|
||||||
|
tsgn = -tsgn;
|
||||||
|
}
|
||||||
|
for(is = s; isdigit(*is); is++)
|
||||||
|
;
|
||||||
|
for(it = t; isdigit(*it); it++)
|
||||||
|
;
|
||||||
|
js = is;
|
||||||
|
jt = it;
|
||||||
|
a = 0;
|
||||||
|
if(ssgn == tsgn)
|
||||||
|
while(it>t && is>s)
|
||||||
|
if(b = *--it - *--is)
|
||||||
|
a = b;
|
||||||
|
while(is > s)
|
||||||
|
if(*--is != '0')
|
||||||
|
return -ssgn;
|
||||||
|
while(it > t)
|
||||||
|
if(*--it != '0')
|
||||||
|
return tsgn;
|
||||||
|
if(a)
|
||||||
|
return sgn(a)*ssgn;
|
||||||
|
if(*(s=js) == '.')
|
||||||
|
s++;
|
||||||
|
if(*(t=jt) == '.')
|
||||||
|
t++;
|
||||||
|
if(ssgn == tsgn)
|
||||||
|
while(isdigit(*s) && isdigit(*t))
|
||||||
|
if(a = *t++ - *s++)
|
||||||
|
return sgn(a)*ssgn;
|
||||||
|
while(isdigit(*s))
|
||||||
|
if(*s++ != '0')
|
||||||
|
return -ssgn;
|
||||||
|
while(isdigit(*t))
|
||||||
|
if(*t++ != '0')
|
||||||
|
return tsgn;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
getword(Biobuf *f, Rune *rp, int n)
|
||||||
|
{
|
||||||
|
long c;
|
||||||
|
|
||||||
|
while(n-- > 0) {
|
||||||
|
c = Bgetrune(f);
|
||||||
|
if(c < 0)
|
||||||
|
return 0;
|
||||||
|
if(c == '\n') {
|
||||||
|
*rp = L'\0';
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
*rp++ = c;
|
||||||
|
}
|
||||||
|
fprint(2, "Look: word too long. Bailing out.\n");
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in a new issue