|  | #include <u.h> | 
|  | #include <libc.h> | 
|  | #include <bio.h> | 
|  | #include "sky.h" | 
|  |  | 
|  | extern	Biobuf	bout; | 
|  |  | 
|  | char* | 
|  | append(char *p, char *s) | 
|  | { | 
|  | while(*s) | 
|  | *p++ = *s++; | 
|  | return p; | 
|  | } | 
|  |  | 
|  | int | 
|  | matchlen(char *a, char *b) | 
|  | { | 
|  | int n; | 
|  |  | 
|  | for(n=0; *a==*b; a++, b++, n++) | 
|  | if(*a == 0) | 
|  | return n; | 
|  | if(*a == 0) | 
|  | return n; | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | char* | 
|  | prose(char *s, char *desc[][2], short index[]) | 
|  | { | 
|  | static char buf[512]; | 
|  | char *p=buf; | 
|  | int i, j, k, max; | 
|  |  | 
|  | j = 0; | 
|  | while(*s){ | 
|  | if(p >= buf+sizeof buf) | 
|  | abort(); | 
|  | if(*s == ' '){ | 
|  | if(p>buf && p[-1]!=' ') | 
|  | *p++ = ' '; | 
|  | s++; | 
|  | continue; | 
|  | } | 
|  | if(*s == ','){ | 
|  | *p++ = ';', s++; | 
|  | continue; | 
|  | } | 
|  | if(s[0]=='M' && '0'<=s[1] && s[1]<='9'){	/* Messier tag */ | 
|  | *p++ = *s++; | 
|  | continue;	/* below will copy the number */ | 
|  | } | 
|  | if((i=index[(uchar)*s]) == -1){ | 
|  | Dup: | 
|  | switch(*s){ | 
|  | default: | 
|  | while(*s && *s!=',' && *s!=' ') | 
|  | *p++=*s++; | 
|  | break; | 
|  |  | 
|  | case '0': case '1': case '2': case '3': case '4': | 
|  | case '5': case '6': case '7': case '8': case '9': | 
|  | while('0'<=*s && *s<='9') | 
|  | *p++ = *s++; | 
|  | if(*s=='\'' || *s=='s') | 
|  | *p++ = *s++; | 
|  | break; | 
|  |  | 
|  | case '(': case ')': | 
|  | case '\'': case '"': | 
|  | case '&': case '-': case '+': | 
|  | *p++ = *s++; | 
|  | break; | 
|  |  | 
|  | case '*': | 
|  | if('0'<=s[1] && s[1]<='9'){ | 
|  | int flag=0; | 
|  | s++; | 
|  | Pnumber: | 
|  | while('0'<=*s && *s<='9') | 
|  | *p++=*s++; | 
|  | if(s[0] == '-'){ | 
|  | *p++ = *s++; | 
|  | flag++; | 
|  | goto Pnumber; | 
|  | } | 
|  | if(s[0]==',' && s[1]==' ' && '0'<=s[2] && s[2]<='9'){ | 
|  | *p++ = *s++; | 
|  | s++;	/* skip blank */ | 
|  | flag++; | 
|  | goto Pnumber; | 
|  | } | 
|  | if(s[0] == '.'){ | 
|  | if(s[1]=='.' && s[2]=='.'){ | 
|  | *p++ = '-'; | 
|  | s += 3; | 
|  | flag++; | 
|  | goto Pnumber; | 
|  | } | 
|  | *p++ = *s++; | 
|  | goto Pnumber; | 
|  | } | 
|  | p = append(p, "m star"); | 
|  | if(flag) | 
|  | *p++ = 's'; | 
|  | *p++ = ' '; | 
|  | break; | 
|  | } | 
|  | if(s[1] == '*'){ | 
|  | if(s[2] == '*'){ | 
|  | p = append(p, "triple star "); | 
|  | s += 3; | 
|  | }else{ | 
|  | p = append(p, "double star "); | 
|  | s += 2; | 
|  | } | 
|  | break; | 
|  | } | 
|  | p = append(p, "star "); | 
|  | s++; | 
|  | break; | 
|  | } | 
|  | continue; | 
|  | } | 
|  | for(max=-1; desc[i][0] && desc[i][0][0]==*s; i++){ | 
|  | k = matchlen(desc[i][0], s); | 
|  | if(k > max) | 
|  | max = k, j = i; | 
|  | } | 
|  | if(max == 0) | 
|  | goto Dup; | 
|  | s += max; | 
|  | for(k=0; desc[j][1][k]; k++) | 
|  | *p++=desc[j][1][k]; | 
|  | if(*s == ' ') | 
|  | *p++ = *s++; | 
|  | else if(*s == ',') | 
|  | *p++ = ';', s++; | 
|  | else | 
|  | *p++ = ' '; | 
|  | } | 
|  | *p = 0; | 
|  | return buf; | 
|  | } | 
|  |  | 
|  | void | 
|  | prdesc(char *s, char *desc[][2], short index[]) | 
|  | { | 
|  | int c, j; | 
|  |  | 
|  | if(index[0] == 0){ | 
|  | index[0] = 1; | 
|  | for(c=1, j=0; c<128; c++) | 
|  | if(desc[j][0]==0 || desc[j][0][0]>c) | 
|  | index[c] = -1; | 
|  | else if(desc[j][0][0] == c){ | 
|  | index[c] = j; | 
|  | while(desc[j][0] && desc[j][0][0] == c) | 
|  | j++; | 
|  | if(j >= NINDEX){ | 
|  | fprint(2, "scat: internal error: too many prose entries\n"); | 
|  | exits("NINDEX"); | 
|  | } | 
|  | } | 
|  | } | 
|  | Bprint(&bout, "\t%s [%s]\n", prose(s, desc, index), s); | 
|  | } |