| #include <u.h> |
| #include <libc.h> |
| #include <bio.h> |
| #include "dict.h" |
| |
| /* Possible tags */ |
| enum { |
| DF, /* definition */ |
| DX, /* definition/example */ |
| ET, /* etymology */ |
| EX, /* example */ |
| LA, /* label */ |
| ME, /* main entry */ |
| NU, /* sense number */ |
| PR, /* pronunciation */ |
| PS, /* grammar part */ |
| XR, /* cross reference */ |
| XX /* cross reference (whole entry) */ |
| }; |
| |
| /* Assoc tables must be sorted on first field */ |
| |
| static Assoc tagtab[] = { |
| {"df", DF}, |
| {"dx", DX}, |
| {"et", ET}, |
| {"ex", EX}, |
| {"la", LA}, |
| {"me", ME}, |
| {"nu", NU}, |
| {"pr", PR}, |
| {"ps", PS}, |
| {"xr", XR}, |
| {"xx", XX} |
| }; |
| static long sget(char *, char *, char **, char **); |
| static void soutpiece(char *, char *); |
| |
| void |
| slangprintentry(Entry e, int cmd) |
| { |
| char *p, *pe, *vs, *ve; |
| long t; |
| |
| p = e.start; |
| pe = e.end; |
| if(cmd == 'h') { |
| t = sget(p, pe, &vs, &ve); |
| if(t == ME) |
| soutpiece(vs, ve); |
| outnl(0); |
| return; |
| } |
| while(p < pe) { |
| switch(sget(p, pe, &vs, &ve)) { |
| case DF: |
| soutpiece(vs, ve); |
| outchars(". "); |
| break; |
| case DX: |
| soutpiece(vs, ve); |
| outchars(". "); |
| break; |
| case ET: |
| outchars("["); |
| soutpiece(vs, ve); |
| outchars("] "); |
| break; |
| case EX: |
| outchars("E.g., "); |
| soutpiece(vs, ve); |
| outchars(". "); |
| break; |
| case LA: |
| outchars("("); |
| soutpiece(vs, ve); |
| outchars(") "); |
| break; |
| case ME: |
| outnl(0); |
| soutpiece(vs, ve); |
| outnl(0); |
| break; |
| case NU: |
| outnl(2); |
| soutpiece(vs, ve); |
| outchars(". "); |
| break; |
| case PR: |
| outchars("["); |
| soutpiece(vs, ve); |
| outchars("] "); |
| break; |
| case PS: |
| outnl(1); |
| soutpiece(vs, ve); |
| outchars(". "); |
| break; |
| case XR: |
| outchars("See "); |
| soutpiece(vs, ve); |
| outchars(". "); |
| break; |
| case XX: |
| outchars("See "); |
| soutpiece(vs, ve); |
| outchars(". "); |
| break; |
| default: |
| ve = pe; /* will end loop */ |
| break; |
| } |
| p = ve; |
| } |
| outnl(0); |
| } |
| |
| long |
| slangnextoff(long fromoff) |
| { |
| long a; |
| char *p; |
| |
| a = Bseek(bdict, fromoff, 0); |
| if(a < 0) |
| return -1; |
| for(;;) { |
| p = Brdline(bdict, '\n'); |
| if(!p) |
| break; |
| if(p[0] == 'm' && p[1] == 'e' && p[2] == ' ') |
| return (Boffset(bdict)-Blinelen(bdict)); |
| } |
| return -1; |
| } |
| |
| void |
| slangprintkey(void) |
| { |
| Bprint(bout, "No key\n"); |
| } |
| |
| /* |
| * Starting from b, find next line beginning with a tag. |
| * Don't go past e, but assume *e==0. |
| * Return tag value, or -1 if no more tags before e. |
| * Set pvb to beginning of value (after tag). |
| * Set pve to point at newline that ends the value. |
| */ |
| static long |
| sget(char *b, char *e, char **pvb, char **pve) |
| { |
| char *p; |
| char buf[3]; |
| long t, tans; |
| |
| buf[2] = 0; |
| tans = -1; |
| for(p = b;;) { |
| if(p[2] == ' ') { |
| buf[0] = p[0]; |
| buf[1] = p[1]; |
| t = lookassoc(tagtab, asize(tagtab), buf); |
| if(t < 0) { |
| if(debug) |
| err("tag %s\n", buf); |
| p += 3; |
| } else { |
| if(tans < 0) { |
| p += 3; |
| tans = t; |
| *pvb = p; |
| } else { |
| *pve = p; |
| break; |
| } |
| } |
| } |
| p = strchr(p, '\n'); |
| if(!p || ++p >= e) { |
| if(tans >= 0) |
| *pve = e-1; |
| break; |
| } |
| } |
| return tans; |
| } |
| |
| static void |
| soutpiece(char *b, char *e) |
| { |
| int c, lastc; |
| |
| lastc = 0; |
| while(b < e) { |
| c = *b++; |
| if(c == '\n') |
| c = ' '; |
| if(!(c == ' ' && lastc == ' ') && c != '@') |
| outchar(c); |
| lastc = c; |
| } |
| } |