xref: /plan9/sys/src/cmd/scat/prose.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 #include "sky.h"
5 
6 extern	Biobuf	bout;
7 
8 char*
append(char * p,char * s)9 append(char *p, char *s)
10 {
11 	while(*s)
12 		*p++ = *s++;
13 	return p;
14 }
15 
16 int
matchlen(char * a,char * b)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*
prose(char * s,char * desc[][2],short index[])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[*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
prdesc(char * s,char * desc[][2],short index[])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 }
169