prose.c (2899B)
1 #include <u.h> 2 #include <libc.h> 3 #include <bio.h> 4 #include "sky.h" 5 6 extern Biobuf bout; 7 8 char* 9 append(char *p, char *s) 10 { 11 while(*s) 12 *p++ = *s++; 13 return p; 14 } 15 16 int 17 matchlen(char *a, char *b) 18 { 19 int n; 20 21 for(n=0; *a==*b; a++, b++, n++) 22 if(*a == 0) 23 return n; 24 if(*a == 0) 25 return n; 26 return 0; 27 } 28 29 char* 30 prose(char *s, char *desc[][2], short index[]) 31 { 32 static char buf[512]; 33 char *p=buf; 34 int i, j, k, max; 35 36 j = 0; 37 while(*s){ 38 if(p >= buf+sizeof buf) 39 abort(); 40 if(*s == ' '){ 41 if(p>buf && p[-1]!=' ') 42 *p++ = ' '; 43 s++; 44 continue; 45 } 46 if(*s == ','){ 47 *p++ = ';', s++; 48 continue; 49 } 50 if(s[0]=='M' && '0'<=s[1] && s[1]<='9'){ /* Messier tag */ 51 *p++ = *s++; 52 continue; /* below will copy the number */ 53 } 54 if((i=index[(uchar)*s]) == -1){ 55 Dup: 56 switch(*s){ 57 default: 58 while(*s && *s!=',' && *s!=' ') 59 *p++=*s++; 60 break; 61 62 case '0': case '1': case '2': case '3': case '4': 63 case '5': case '6': case '7': case '8': case '9': 64 while('0'<=*s && *s<='9') 65 *p++ = *s++; 66 if(*s=='\'' || *s=='s') 67 *p++ = *s++; 68 break; 69 70 case '(': case ')': 71 case '\'': case '"': 72 case '&': case '-': case '+': 73 *p++ = *s++; 74 break; 75 76 case '*': 77 if('0'<=s[1] && s[1]<='9'){ 78 int flag=0; 79 s++; 80 Pnumber: 81 while('0'<=*s && *s<='9') 82 *p++=*s++; 83 if(s[0] == '-'){ 84 *p++ = *s++; 85 flag++; 86 goto Pnumber; 87 } 88 if(s[0]==',' && s[1]==' ' && '0'<=s[2] && s[2]<='9'){ 89 *p++ = *s++; 90 s++; /* skip blank */ 91 flag++; 92 goto Pnumber; 93 } 94 if(s[0] == '.'){ 95 if(s[1]=='.' && s[2]=='.'){ 96 *p++ = '-'; 97 s += 3; 98 flag++; 99 goto Pnumber; 100 } 101 *p++ = *s++; 102 goto Pnumber; 103 } 104 p = append(p, "m star"); 105 if(flag) 106 *p++ = 's'; 107 *p++ = ' '; 108 break; 109 } 110 if(s[1] == '*'){ 111 if(s[2] == '*'){ 112 p = append(p, "triple star "); 113 s += 3; 114 }else{ 115 p = append(p, "double star "); 116 s += 2; 117 } 118 break; 119 } 120 p = append(p, "star "); 121 s++; 122 break; 123 } 124 continue; 125 } 126 for(max=-1; desc[i][0] && desc[i][0][0]==*s; i++){ 127 k = matchlen(desc[i][0], s); 128 if(k > max) 129 max = k, j = i; 130 } 131 if(max == 0) 132 goto Dup; 133 s += max; 134 for(k=0; desc[j][1][k]; k++) 135 *p++=desc[j][1][k]; 136 if(*s == ' ') 137 *p++ = *s++; 138 else if(*s == ',') 139 *p++ = ';', s++; 140 else 141 *p++ = ' '; 142 } 143 *p = 0; 144 return buf; 145 } 146 147 void 148 prdesc(char *s, char *desc[][2], short index[]) 149 { 150 int c, j; 151 152 if(index[0] == 0){ 153 index[0] = 1; 154 for(c=1, j=0; c<128; c++) 155 if(desc[j][0]==0 || desc[j][0][0]>c) 156 index[c] = -1; 157 else if(desc[j][0][0] == c){ 158 index[c] = j; 159 while(desc[j][0] && desc[j][0][0] == c) 160 j++; 161 if(j >= NINDEX){ 162 fprint(2, "scat: internal error: too many prose entries\n"); 163 exits("NINDEX"); 164 } 165 } 166 } 167 Bprint(&bout, "\t%s [%s]\n", prose(s, desc, index), s); 168 }