#include #include #include #include "charfilter.h" #include "alt_unistd.h" #include "configuration.h" #ifdef OS_UNIX_ALIKE #include #endif char *verstring="sap V0.2 beta"; /* Poniższe procedury uwzględniają specyfikę kolejności liter w alfabecie polskim oraz ograniczenie dostępnych znaków */ unsigned char _convtable[256],_avtable[256]; #ifndef OS_AMIGAOS unsigned char *txt1="aąbcćdeęfghijklłmnńoópqrsśtuvwxyzźż*<>'/.,"; unsigned char *txt2="AĄBCĆDEĘFGHIJKLŁMNŃOÓPQRSŚTUVWXYZŹŻ*<>'/.,"; #else unsigned char *txt1="aąbcćdeęfghijklłmnńoópqrsśtuvwxyzźż*<>'/.,âëîďôűú"; unsigned char *txt2="AĄBCĆDEĘFGHIJKLŁMNŃOÓPQRSŚTUVWXYZŹŻ*<>'/.,ÂËÎĎÔŰÚ"; #endif int asciionly_mode; /* if true use only base ASCII (<128) chars */ mk_convt(void) { int i;unsigned char *c1,*c2; memset(_convtable,0,256); // a tak, na wszelki wypadek for (i=0;i<256;i++) _avtable[i]=i; for (i=0,c1=txt1,c2=txt2;*c1;c1++,c2++,i++) { _convtable[(*c1)&255]=_convtable[(*c2)&255]=i+1; _avtable[(*c2)&255]=*c1; } } is_prt(int c) { return _convtable[c&255]; } l_tolower(int c) { if (!_convtable[c=(c&255)]) return 0; return _avtable[c]; } l_compare(char *c1,char *c2) { for (;*c1;c1++,c2++) { if (!*c2) return 1; // c1>c2; if (_convtable[(*c1)&255]>_convtable[(*c2)&255]) return 1; if (_convtable[(*c1)&255]<_convtable[(*c2)&255]) return -1; } if (*c2) return -1; return 0; } l_match(char *c1,char *c2) { for (;*c1;c1++,c2++) { if (!*c2 || *c2=='*') return 0; // c1 match c2; if (_convtable[(*c1)&255]>_convtable[(*c2)&255]) return 1; if (_convtable[(*c1)&255]<_convtable[(*c2)&255]) return -1; } if (*c2 && *c2!='*') return -1; return 0; } l_pmatch(char *c1,char *c2) { for (;;) { if (*c2=='*') { while (*c2=='*') c2++; if (!*c2) return 0; while (*c1) if (!l_pmatch(c1++,c2)) return 0; return 1; } if (*c1!=*c2) return 1; if (!*c1) return 0; c1++;c2++; } } struct vobel { long npages; long nwords; long *page_offsets; long actual_page; long lastpage,lastindex; FILE *f; char *pairbuffer; char **pairs; // strona short wordspp; short dsize; short dvoffset; short *sizes; char *first; char body[16384]; } vobel[2]; ReadVobel(char *name,int nr) { char avname[256]; long v_long,ls,i;char *c; if (!(vobel[nr].f=fopen(name,"rb"))) { c=getenv("HOME"); c=NULL; if (c) { strcpy(avname,c); strcat(avname,DIRECTORY_SEPARATOR); strcat(avname,name); if (!(vobel[nr].f=fopen(avname,"rb"))) { strcpy(avname,DICTIONARIES_DIRECTORY); strcat(avname,name); if (!(vobel[nr].f=fopen(avname,"rb"))) exit(100); } } else { strcpy(avname,DICTIONARIES_DIRECTORY); strcat(avname,name); if (!(vobel[nr].f=fopen(avname,"rb"))) exit(100); } } if (!fread(&v_long,sizeof(long),1,vobel[nr].f)) goto zle; #ifdef MSB_FIRST_PROCESSOR lsb2msb(&v_long); #endif if (v_long!=0xFADEABBA) { alt_fprintf(asciionly_mode,stderr,"Plik %s nie jest plikiem słownika!\n",avname); exit(100); } if (!fread(&vobel[nr].nwords,sizeof(long),1,vobel[nr].f)) goto zle; #ifdef MSB_FIRST_PROCESSOR lsb2msb(&(vobel[nr].nwords)); #endif if (!fread(&vobel[nr].npages,sizeof(long),1,vobel[nr].f)) goto zle; #ifdef MSB_FIRST_PROCESSOR lsb2msb(&(vobel[nr].npages)); #endif /* teraz alokujemy tablicę offsetów opisów */ if (!(vobel[nr].page_offsets=malloc(sizeof(long)*vobel[nr].npages))) goto zle; if (!fread(vobel[nr].page_offsets,sizeof(long)*vobel[nr].npages,1,vobel[nr].f)) goto zle; #ifdef MSB_FIRST_PROCESSOR { int remaining_longs=vobel[nr].npages; long *current_point=vobel[nr].page_offsets; while(remaining_longs--) lsb2msb(current_point++); } #endif ls=vobel[nr].page_offsets[0]-sizeof(long)*(vobel[nr].npages+3); if(!(vobel[nr].pairbuffer=malloc(ls))) goto zle; if (!fread(vobel[nr].pairbuffer,1,ls,vobel[nr].f)) goto zle; /* tak jakby wszystko wczytane... */ if (!(vobel[nr].pairs=malloc(sizeof(char *)*2*vobel[nr].npages))) goto zle; for (i=0,c=vobel[nr].pairbuffer;i<2*vobel[nr].npages;i++) { vobel[nr].pairs[i]=c; while(*c++); } vobel[nr].actual_page=-1; vobel[nr].lastpage=0; vobel[nr].lastindex=-1; return; zle: alt_fprintf(asciionly_mode,stderr,"Błąd odczytu słownika %s\n",avname); exit(21); } read_page(nr,np) int nr,np; { if (vobel[nr].actual_page==np) return; fseek(vobel[nr].f,vobel[nr].page_offsets[np],SEEK_SET); if (!fread(&vobel[nr].wordspp,sizeof(short),1,vobel[nr].f)) goto zle; if (!fread(&vobel[nr].dsize,sizeof(short),1,vobel[nr].f)) goto zle; if (!fread(&vobel[nr].dvoffset,sizeof(short),1,vobel[nr].f)) goto zle; #ifdef MSB_FIRST_PROCESSOR short_lsb2msb(&vobel[nr].wordspp); short_lsb2msb(&vobel[nr].dsize); short_lsb2msb(&vobel[nr].dvoffset); #endif if (!fread(vobel[nr].body,1,(long)vobel[nr].dsize,vobel[nr].f)) goto zle; #ifdef MSB_FIRST_PROCESSOR { int remaining_shorts=vobel[nr].wordspp; short *current_point=(short *)vobel[nr].body; while(remaining_shorts--) short_lsb2msb(current_point++); } #endif vobel[nr].actual_page=np; vobel[nr].sizes=(short *)vobel[nr].body; vobel[nr].first=vobel[nr].body+sizeof(short)*vobel[nr].wordspp; return; zle: alt_fprintf(asciionly_mode,stderr,"Błąd odczytu\n"); exit(100); } char buf1[8192],buf2[8192]; struct markpol {char *pm;int flag;int mask;} markpol[]={ {"przymiotnik",1,15}, {"przysłówek",2,15}, {"spójnik",3,15}, {"liczebnik",4,15}, {"partykuła",5,15}, {"przedrostek",6,15}, {"przyimek",7,15}, {"zaimek",8,15}, {"rzeczownik",9,15}, {"czasownik posiłkowy",10,15}, {"czasownik nieprzechodni",11,15}, {"czasownik nieosobowy",12,15}, {"czasownik zwrotny",13,15}, {"czasownik przechodni",14,15}, /* 16 - 4 bajty */ {"czasownik",15,15}, {"rodzaj żeński",16,0x30}, /* 4 bajty */ {"rodzaj męski",32,0x30}, {"rodzaj nijaki",16+32,0x30}, {"liczba pojedyncza",64,0xc0}, {"liczba mnoga",128,0xc0}, {"tylko liczba mnoga",128+64,0xc0}, {"czas przeszły",2048,2048|4096|8192|16384}, {"czas teraźniejszy",4096,2048|4096|8192|16384}, {"czas przyszły",2048+4096,2048|4096|8192|16384}, {"bezokolicznik",8192,2048|4096|8192|16384}, {"stopień najwyższy",16384,2048|4096|8192|16384}, {"regularny",256,256}, /* 3 bajty */ {"wyraz potoczny",1024,1024}, {"skrót",512,512}, {"stopień wyższy",16384|8192,2048|4096|8192|16384}, {0,0}}; /* ciągi unikowe */ char haslo[2][32]={"\x1b[1;33m","\x1b[0m"}; char grama[2][32]={"\x1b[32m","\x1b[0m"}; char vide[2][32]={"\x1b[33m","\x1b[0m"}; char count[2][32]={"\x1b[33m","\x1b[0m"}; char header[2][32]={"\x1b[31m","\x1b[0m"}; parsestr(c) char *c; { char *d;int i,v; for (d=c;*c;) if (*c!='\\') *d++=*c++; else { c++;v=0; for (i=0;i<3;i++) if (*c>='0' && *c<'8') v=(v<<3) | ((*c++)-'0'); else break; *d++=v; } *d=0; } linetoparam(line) char *line; { char cv1[32],cv2[32],*c,*d;int cx,i; if (!strchr("hgpwc",*line)) return; cx=*line++; while(*line && isspace(*line)) line++; if (*line++!='\"') return; for (i=0;*line && *line!='\"';i++,line++) if (i<31) cv1[i]=*line; cv1[i]=0; parsestr(cv1); if (!*line) return; line++; while (*line) if (*line++=='\"') break; if (!line) return; for (i=0;*line && *line!='\"';i++,line++) if (i<31) cv2[i]=*line; cv2[i]=0; parsestr(cv2); if (!*line) return; switch(tolower(cx)) { case 'h': strcpy(haslo[0],cv1);strcpy(haslo[1],cv2);break; case 'g': strcpy(grama[0],cv1);strcpy(grama[1],cv2);break; case 'p': strcpy(vide[0],cv1);strcpy(vide[1],cv2);break; case 'w': strcpy(count[0],cv1);strcpy(count[1],cv2);break; case 'c': strcpy(header[0],cv1);strcpy(header[1],cv2);break; } } getsaprc() { char terminal[256],*c,*d;int got; char fline[256]; FILE *f; if (c=getenv("HOME")) { strcpy(fline,c); strcat(fline,DIRECTORY_SEPARATOR); strcat(fline,LOCAL_SAPRC_FILENAME); if (f=fopen(fline,"rb")) goto sapok; } if (!(f=fopen(GLOBAL_SAPRC_FULLPATH,"rb"))) return; sapok: if (!(c=getenv("TERM"))) strcpy(terminal,"dummy");else strcpy(terminal,c); // printf("Current terminal:%s\n",terminal); for (c=terminal;*c;c++) *c=tolower(*c); got=0; for (;;) { if (!got) { if (!fgets(fline,256,f)) break; } c=fline;got=0; while(*c && isspace(*c)) c++; if (*c=='#') continue; if (!*c) continue; if (!strncmp(c,"term",4)) { c+=4; while (*c && *c!='=') c++; if (!*c) continue; c++; d=c; while(*d && !isspace(*d)) d++; *d=0; for (d=c;*d;d++) *d=tolower(*d); //printf("Terminal desc:%s\n",c); // if (strcmp(c,terminal)) continue; if (!strcmp(c,terminal)) break; for (;;) { if (!fgets(fline,256,f)) break; c=fline; while(*c && isspace(*c)) c++; if (!*c || *c=='#') continue; if (*c!='.') { got=1; break; } linetoparam(c+1); } continue; } } } mksecbuf(hass) char *hass; { char *c,*d;int v,i,mc,cdoll; c=buf1; d=buf2; cdoll=0; strcpy(d,haslo[0]);strcat(d,hass);strcat(d,haslo[1]);strcat(d," - ");d+=strlen(d); while (*c) { switch(*c) { case ',': case '.': case ')': *d++=*c++; if (!strchr(".,",*c)) *d++=' '; continue; case '$': if (cdoll) {*d++=';';*d++=' ';} d+=sprintf(d,"%s%c)%s ",count[0],'a'+cdoll,count[1]); cdoll++;c++; continue; case '-': strcpy(d," - ");d+=3;c++;continue; case '{': strcpy(d,haslo[0]);d+=strlen(d);c++;continue; case '}': cdoll=0; strcpy(d,haslo[1]);strcat(d," - ");d+=strlen(d);c++;continue; case '*': strcpy(d,hass); d+=strlen(d);c++; continue; case '=': strcpy(d,vide[0]); strcat(d,"patrz:"); strcat(d,vide[1]); strcat(d," "); d+=strlen(d);c++;continue; case '#': strcpy(d,grama[0]);d+=strlen(d); c++; v=((*c++)<<8) & 0xff00; v|=(*c++)&255; for (i=mc=0;markpol[i].pm;i++) if ((v& markpol[i].mask)==markpol[i].flag) { if (mc) *d++=','; strcpy(d,markpol[i].pm); d+=strlen(d); *d++=' '; mc=1; } strcpy(d,grama[1]); d+=strlen(d); continue; } *d++=*c++; } *d=0; } findslowo(slowo,nr,f) char *slowo;int nr;FILE *f; { int i,j,n,off,ixi;char *c; if (slowo[0]=='<') { if (vobel[nr].lastindex<=0) { if (vobel[nr].lastpage<=0) { outofvob: sprintf(buf2,"poza zakresem słownika\n"); return; } read_page(nr,--vobel[nr].lastpage); vobel[nr].lastindex=vobel[nr].wordspp-1; } else { read_page(nr,vobel[nr].lastpage); vobel[nr].lastindex--; } fslowo: off=vobel[nr].dvoffset; c=vobel[nr].first; for (i=0;i') { read_page(nr,vobel[nr].lastpage); if (vobel[nr].lastindex>=vobel[nr].wordspp-1) { if (vobel[nr].lastpage>=vobel[nr].npages-1) goto outofvob; read_page(nr,++vobel[nr].lastpage); vobel[nr].lastindex=0; } else vobel[nr].lastindex++; goto fslowo; } if (c=strchr(slowo,'*')) { if (c[1]) goto xmatch; for (i=0;i0) goto noslowo; n=l_match(vobel[nr].pairs[2*i+1],slowo); if (n>=0) goto okfpage; } goto noslowo; okfpage: read_page(nr,i); c=vobel[nr].first; for (i=0,off=vobel[nr].dvoffset;i0) break; while(*c++); off+=vobel[nr].sizes[i]; } goto noslowo; } for (i=0;i0) goto noslowo; n=l_compare(vobel[nr].pairs[2*i+1],slowo); if (n>=0) goto okpage; } noslowo: sprintf(buf2,"Nie znalazłem słowa %s%s%s\n",haslo[0],slowo,haslo[1]); return; okpage: read_page(nr,i); c=vobel[nr].first; for (i=0,off=vobel[nr].dvoffset;i0) break; while(*c++); off+=vobel[nr].sizes[i]; } goto noslowo; rslowo: vobel[nr].lastpage=vobel[nr].actual_page; vobel[nr].lastindex=i; fxslowo: memcpy(buf1,vobel[nr].body+off,vobel[nr].sizes[i]); buf1[vobel[nr].sizes[i]]=0; mksecbuf(slowo); return; xmatch: ixi=0; for (i=0;i0) { if (!ixi) goto noslowo; return; } n=l_match(vobel[nr].pairs[2*i+1],slowo); if (n<0) continue; read_page(nr,i); for (c=vobel[nr].first,off=vobel[nr].dvoffset,j=0;j0) { if (!ixi) goto noslowo; return; } if (!n && !l_pmatch(c,slowo)) { if (ixi)alt_fprintf(asciionly_mode,f,"%s--\n",buf2); ixi++; vobel[nr].lastpage=vobel[nr].actual_page; vobel[nr].lastindex=j; memcpy(buf1,vobel[nr].body+off,vobel[nr].sizes[j]); buf1[vobel[nr].sizes[j]]=0; mksecbuf(c); if (ixi>=100) return; /* no, to nie miejsce na drukowanie słownika! */ } while(*c++); off+=vobel[nr].sizes[j]; } } if (!ixi) goto noslowo; } char slowo[32]; trim(char *c) { char *d;int n; for(d=c;*c;) if (n=l_tolower(*c++)) *d++=n; *d=0; } char tmpoutname[256]; char *helpstring="" "Jeśli słowa pobierane są z pliku lub standartowego wejścia, w każdej\n" "linii może być tylko jedno słowo lub polecenie. Oprócz pełnych słów\ndopuszczalne są:\n" " -p (przełączenie w tryb polsko-angielski)\n" " -a (przełączenie w tryb angielsko-polski)\n" " < (poprzednie słowo)\n" " > (następne słowo)\n" " tekst* powoduje odnalezienie pierwszego słowa\n rozpoczynającego się od \"tekst\"\n" " . (koniec przetwarzania)\n" "Program akceptuje również coś w rodzaju wyrażeń - jeśli gwiazdka\n" "nie jest ostatnim znakiem wprowadzanego słowa, będą wypisane wszystkie\n" "słowa pasujące do wzorca w którym gwiazdka zastępuje dowolny (również pusty)\n" "ciąg znaków. Ilość wypisanych haseł jest ograniczona do 100.\n" ""; main(int argc,char *argv[]) { int opcja,voc,lmode,vsl; char *tmp,*infname; char systin[256]; FILE *f,*fi; mk_convt(); lmode=0; asciionly_mode=0; while((opcja=alt_getopt(argc,argv,"ivhpalf:"))!=EOF) { switch(opcja) { case 'v': alt_fprintf(asciionly_mode,stderr,"%s",verstring);exit(0); case 'h': lmode|=2;break; // case 'x': lmode|=4;break; case 'l': lmode|=1;break; case 'p': lmode|=8;break; case 'a': lmode|=16;break; case 'f': infname=alt_optarg;lmode|=32;break; case 'i': asciionly_mode=1;break; } } if (lmode & 2) { //help alt_fprintf(asciionly_mode,stderr,"%s\n",verstring); alt_fprintf(asciionly_mode,stderr,"Copyright (c)1998 Bohdan R. Rau\n"); alt_fprintf(asciionly_mode,stderr,"Copyright (c)2001 Daniel Mealha Cabrita\n"); alt_fprintf(asciionly_mode,stderr,"Sposób użycia:\n",argv[0]); alt_fprintf(asciionly_mode,stderr," %s -v wyświetla wersję programu\n",argv[0]); alt_fprintf(asciionly_mode,stderr," %s -h pomoc (to, co czytasz)\n",argv[0]); alt_fprintf(asciionly_mode,stderr," %s [-apli] [słowo] ...\n",argv[0]); alt_fprintf(asciionly_mode,stderr," %s [-apli] -f \n",argv[0]); alt_fprintf(asciionly_mode,stderr,"Opcje:\n"); alt_fprintf(asciionly_mode,stderr," -f - pobieranie słów z pliku\n"); alt_fprintf(asciionly_mode,stderr," -l - filtrowanie wyjścia przez less -r\n"); alt_fprintf(asciionly_mode,stderr," -i - tekst tylko na ASCII\n"); alt_fprintf(asciionly_mode,stderr," -a - słownik angielsko-polski\n"); alt_fprintf(asciionly_mode,stderr," -p - słownik polsko-angielski (domyślnie)\n"); alt_fprintf(asciionly_mode,stderr,"%s",helpstring); exit(0); } if (lmode & 4) { alt_fprintf(asciionly_mode,stderr,"Jeszcze nie działa :-(\n"); exit(0); } voc='p'; if (lmode & 16) voc='a'; if (!(lmode & 32)) { // dane z linii czy stdin if (argc>alt_optind) lmode|=64; // dane z linii; } // sprawdzenie dla less if (lmode & 1) { if (lmode & (32 | 64)) lmode|=128; /* less wywoływany na końcu gdy dane z linii lub pliku */ } if (lmode & 32) { if (strcmp(infname,"-")) fi=fopen(infname,"rb"); else fi=stdin; if (!fi) exit(100); } else if (!(lmode & 64)) fi=stdin; else fi=0; getsaprc(); // jeśli less ma być otwarty na początku: if (lmode & 128) { tmp=tmpnam(tmpoutname); if (!tmp) exit(100); if (!(f=fopen(tmp,"w"))) exit(100); } else f=stdout; ReadVobel(FILENAME_DATABASE_1,0); ReadVobel(FILENAME_DATABASE_2,1); for (;;) { if (fi) { if (!fgets(slowo,32,fi)) break; } else { if (alt_optind>=argc) break; memcpy(slowo,argv[alt_optind++],31); slowo[31]=0; } if (slowo[0]=='.') break; if (slowo[0]=='-') { if (tolower(slowo[1])=='p') voc='p';else if (tolower(slowo[1])=='a') voc='a'; continue; } trim(slowo); if (asciionly_mode){ transform_from_ascii(asciionly_mode,slowo); #ifdef OS_AMIGAOS } else { transform_fromto_amigapl_iso(slowo); #endif } if (!slowo[0]) continue; if ((lmode & 1) && !(lmode & 128)) { // less wywoływany za każdym razem tmp=tmpnam(tmpoutname); if (!(f=fopen(tmp,"w"))) exit(100); } alt_fprintf(asciionly_mode,f,"%s%s%s\n",header[0], (voc=='p') ? "Słownik polsko-angielski":"Słownik angielsko-polski",header[1]); findslowo(slowo,(voc=='p')?1:0,f); alt_fprintf(asciionly_mode,f,"%s",buf2); if ((lmode & 1) && !(lmode & 128)) { // less wywoływany za każdym razem fclose(f); sprintf(systin,"less -r %s\nrm -f %s",tmp,tmp); system(systin); } } if (lmode & 128) { // less wywoływany na końcu fclose(f); sprintf(systin,"less -r %s\nrm -f %s",tmp,tmp); system(systin); } exit(0); }