plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

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 }