]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/scat/prose.c
cc: use 7 octal digits for 21 bit runes
[plan9front.git] / sys / src / cmd / scat / prose.c
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[*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 }