Rev 8161 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
10 | reyssat | 1 | /* Copyright (C) 2002-2003 XIAO, Gang of Universite de Nice - Sophia Antipolis |
2 | * |
||
3 | * This program is free software; you can redistribute it and/or modify |
||
4 | * it under the terms of the GNU General Public License as published by |
||
5 | * the Free Software Foundation; either version 2 of the License, or |
||
6 | * (at your option) any later version. |
||
7 | * |
||
8 | * This program is distributed in the hope that it will be useful, |
||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
11 | * GNU General Public License for more details. |
||
12 | * |
||
13 | * You should have received a copy of the GNU General Public License |
||
14 | * along with this program; if not, write to the Free Software |
||
15 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
||
16 | */ |
||
8161 | bpr | 17 | #include "symtext.h" |
10 | reyssat | 18 | |
19 | char cpbuf[MAX_LINELEN+1]; |
||
20 | char *cpnext; |
||
21 | int noaddw=0; |
||
22 | |||
23 | char Mbuf[MAX_LINELEN+1]; |
||
24 | char *Mnext; |
||
25 | struct { |
||
26 | char *Mptr; |
||
27 | int blkptr; |
||
28 | } Mind[MAX_BLOCKS]; |
||
29 | int Mcnt; |
||
30 | |||
31 | struct liststruct { |
||
32 | listtype lcnt; |
||
33 | listtype *listlen; |
||
34 | listtype *list; |
||
35 | } clist; |
||
36 | |||
37 | void cp_oneblock(char *p, struct block *blk, int next); |
||
38 | |||
8161 | bpr | 39 | /* debugger: show the detail of blocks */ |
10 | reyssat | 40 | void showblocks(void) |
41 | { |
||
42 | int i, j, k; |
||
43 | struct block *blk; |
||
44 | if(!debug) return; |
||
45 | for(i=0;i<nextblock;i++) { |
||
8161 | bpr | 46 | blk=blockbuf+i; |
47 | fprintf(stderr,"Block %2d: next=%2d. ",i,blk->nextblock); |
||
48 | if(blk->fn==mt_string) { |
||
49 | fprintf(stderr,"String %s.\n",blk->string); |
||
50 | continue; |
||
51 | } |
||
52 | if(blk->fn==mt_permpick) { |
||
53 | fprintf(stderr,"Permpick %d items %d lists starting %d\n", |
||
54 | blk->len, blk->lcnt, blk->sublock); |
||
55 | for(j=0;j<blk->lcnt;j++) { |
||
56 | fprintf(stderr," list %d: ", j); |
||
57 | for(k=0;k<blk->listlen[j];k++) |
||
58 | fprintf(stderr,"%d ",blk->lists[j][k]); |
||
59 | fprintf(stderr,"\n"); |
||
60 | } |
||
61 | continue; |
||
62 | } |
||
63 | if(blk->fn==mt_m) { |
||
64 | fprintf(stderr,"Macro starting %d ending %d\n", blk->sublock, |
||
65 | blockbuf[blk->sublock].mend); |
||
66 | continue; |
||
67 | } |
||
68 | if(blk->fn==mt_neg) { |
||
69 | fprintf(stderr,"Neg starting %d\n", blk->sublock); |
||
70 | continue; |
||
71 | } |
||
72 | if(blk->fn==mt_dic) { |
||
73 | fprintf(stderr,"Dic %s.\n", blk->string); |
||
74 | continue; |
||
75 | } |
||
76 | if(blk->fn==mt_w) { |
||
77 | fprintf(stderr,"Word list.\n"); |
||
78 | continue; |
||
79 | } |
||
80 | if(blk->fn==mt_wild) { |
||
81 | fprintf(stderr,"Wild min=%d, max=%d.\n", blk->lstart, blk->len+blk->lstart); |
||
82 | continue; |
||
83 | } |
||
84 | if(blk->fn==mt_out) { |
||
85 | fprintf(stderr,"Output for \"%s\", sub=%d.\n", blk->string,blk->sublock); |
||
86 | continue; |
||
87 | } |
||
88 | fprintf(stderr,"Unknown type!\n"); |
||
10 | reyssat | 89 | } |
8161 | bpr | 90 | |
10 | reyssat | 91 | } |
92 | |||
8161 | bpr | 93 | /* remove punctuations */ |
10 | reyssat | 94 | void depunct(char *p,char *str) |
95 | { |
||
96 | char *pp; |
||
97 | for(pp=p; *pp; pp++) { |
||
8161 | bpr | 98 | if(strchr(str,*pp)==NULL) continue; |
99 | if(*pp=='.' && pp>p && isdigit(pp[-1]) && isdigit(pp[1])) continue; |
||
100 | *pp=' '; |
||
10 | reyssat | 101 | } |
102 | } |
||
103 | |||
8161 | bpr | 104 | /* p must have MAX_LINELEN */ |
10 | reyssat | 105 | void isolate_punct(char *p) |
106 | { |
||
107 | char buf[MAX_LINELEN+1]; |
||
108 | char *p1, *p2; |
||
109 | for(p1=p, p2=buf; *p1 && p2<buf+MAX_LINELEN; p1++) { |
||
8161 | bpr | 110 | if(myisalnum(*p1) || (*p1&128) || *p1==' ' || *p1=='_') { |
111 | *p2++=*p1; continue; |
||
112 | } |
||
113 | if((*p1=='.' || *p1==',') && p1>p && isdigit(p1[-1]) && isdigit(p1[1])) { |
||
114 | *p2++=*p1; continue; |
||
115 | } |
||
116 | if(p2>buf && !myisspace(p2[-1])) *p2++=' '; |
||
117 | *p2++=*p1; |
||
118 | if(p1[1] && !myisspace(p1[1])) *p2++=' '; |
||
10 | reyssat | 119 | } |
8195 | bpr | 120 | if(p2>=buf+MAX_LINELEN) sym_error("string_too_long"); |
10 | reyssat | 121 | *p2=0; |
122 | snprintf(p,MAX_LINELEN,"%s",buf); |
||
123 | } |
||
124 | |||
125 | void alphaonly(char *p) |
||
126 | { |
||
127 | char *pp; |
||
128 | for(pp=p; *pp; pp++) if(!myisalpha(*pp)) *pp=' '; |
||
129 | } |
||
130 | |||
131 | void alnumonly(char *p) |
||
132 | { |
||
133 | char *pp; |
||
134 | for(pp=p; *pp; pp++) if(!myisalnum(*pp)) *pp=' '; |
||
135 | } |
||
136 | |||
8161 | bpr | 137 | /* buffer must have MAX_LINELEN */ |
10 | reyssat | 138 | void strfold(char *p) |
139 | { |
||
140 | char *pp; |
||
141 | singlespace(p); |
||
142 | if(noaddw&2) goto fend; |
||
143 | if(options&op_nocase) for(pp=p; *pp; pp++) *pp=tolower(*pp); |
||
144 | if(options&op_reaccent) reaccent(p); |
||
145 | if(options&op_deaccent) deaccent(p); |
||
146 | if(options&op_alphaonly) alphaonly(p); |
||
147 | if(options&op_alnumonly) alnumonly(p); |
||
148 | isolate_punct(p); |
||
149 | if(options&op_nopunct) depunct(p,char_punct); |
||
150 | if(options&op_nomath) depunct(p,char_math); |
||
151 | if(options&op_noparenth) depunct(p,char_parenth); |
||
152 | if(options&op_nocs) depunct(p,char_cs); |
||
153 | if(options&op_noquote) depunct(p,char_quote); |
||
154 | if(suffixcnt>0) suffix_translate(p); |
||
155 | _translate(p,transdic); |
||
8161 | bpr | 156 | |
10 | reyssat | 157 | fend: |
158 | singlespace(p);strip_trailing_spaces(p); |
||
3718 | reyssat | 159 | if(myisspace(*p)) ovlstrcpy(p,find_word_start(p)); |
10 | reyssat | 160 | } |
161 | |||
8161 | bpr | 162 | /* at entry p must point to an atom start! */ |
10 | reyssat | 163 | char *find_atom_end(char *p) |
164 | { |
||
165 | char *pp; |
||
166 | if(*p=='[') { |
||
8161 | bpr | 167 | pp=find_matching(p+1,']'); |
168 | if(pp!=NULL) return pp+1; |
||
8195 | bpr | 169 | else sym_error("unmatched_parentheses %.20s",p); |
10 | reyssat | 170 | } |
171 | return find_word_end(p); |
||
172 | } |
||
173 | |||
174 | #define find_atom_start(x) find_word_start(x) |
||
175 | #define next_atom(x) find_atom_start(find_atom_end(x)) |
||
176 | |||
8161 | bpr | 177 | /* p must have MAX_LINELEN */ |
10 | reyssat | 178 | void macro_trans(char *p) |
179 | { |
||
180 | char *atoms[MAX_BLOCKS], *atom2[MAX_BLOCKS]; |
||
181 | char tbuf[MAX_LINELEN+1], ttbuf[MAX_LINELEN+1], vbuf[8]; |
||
182 | char *pt, *pp, *pe, *p1, *p2, *p3; |
||
183 | char *pt1, *pt2; |
||
184 | int i,k,m,n,repcnt,start,min; |
||
8161 | bpr | 185 | |
10 | reyssat | 186 | if(dic[macrodic].len<=0) return; |
187 | repcnt=start=0; pt=p; |
||
188 | recalc: |
||
189 | repcnt++; |
||
8195 | bpr | 190 | if(repcnt>=MAX_BLOCKS) sym_error("macro_level_overflow %.20s",p); |
10 | reyssat | 191 | for(i=start, pp=find_atom_start(pt); i<MAX_BLOCKS && *pp; pp=next_atom(pp), i++) |
192 | atoms[i]=pp; |
||
8195 | bpr | 193 | if(i>=MAX_BLOCKS-1) sym_error("block_overflow %.20s",p); |
10 | reyssat | 194 | atoms[i]=pp+strlen(pp); |
195 | for(k=0;k<i;k++) { |
||
8161 | bpr | 196 | pp=atoms[k]; switch(*pp) { |
197 | case '[': { |
||
198 | pe=find_atom_end(pp); pp++; |
||
199 | if(pe[-1]!=']') break; |
||
200 | if(myislower(*pp)) { |
||
201 | for(p1=pp;myisalnum(*p1) || *p1=='_'; p1++); |
||
202 | if(*p1!=':') break; |
||
203 | *p1++=0; pe[-1]=0; |
||
204 | for(m=0,p2=p1;*p2;m++,p2=p3) { |
||
205 | p3=find_item_end(p2); if(*p3) *p3++=0; |
||
206 | atom2[m]=p2; |
||
207 | } |
||
208 | if(m==0) m=1; |
||
209 | snprintf(tbuf,sizeof(tbuf),"%s",pp); |
||
210 | _translate(tbuf,macrodic); |
||
8195 | bpr | 211 | if(tbuf[0]==0) sym_error("bad_macro %.50s",pp); |
8161 | bpr | 212 | for(p1=strchr(tbuf,'@'); p1; p1=strchr(p1,'@')) { |
213 | for(p2=p1+1;isdigit(*p2) || *p2=='-';p2++); |
||
8195 | bpr | 214 | if(p2==p1+1 || p2>p1+6) sym_error("syntax_error %.20s",p1); |
8161 | bpr | 215 | memmove(vbuf,p1,p2-p1); vbuf[p2-p1]=0; |
216 | n=atoi(vbuf+1); |
||
8195 | bpr | 217 | if(n<=0 || n>m) sym_error("wrong_parmcnt macro %.50s",pp); |
8161 | bpr | 218 | string_modify(tbuf,p1,p2,atom2[n-1]); |
219 | } |
||
220 | n=strlen(tbuf); if(n<MAX_LINELEN) { |
||
221 | tbuf[n++]=' '; tbuf[n]=0; |
||
222 | } |
||
223 | string_modify(p,pp-1,pe,tbuf); pt=pp-1; start=k; |
||
224 | goto recalc; |
||
225 | } |
||
226 | break; |
||
227 | } |
||
228 | case '_': { |
||
229 | pe=find_word_end(pp); |
||
8195 | bpr | 230 | if(pe-pp>MAX_NAMELEN) sym_error("name_too_long %.20s",pp); |
8161 | bpr | 231 | memmove(tbuf,pp,pe-pp); tbuf[pe-pp]=0; |
232 | _translate(tbuf,macrodic); |
||
233 | if(tbuf[0]==0) break; |
||
234 | pt1=pp; pt2=find_atom_end(pt1); min=k; |
||
235 | for(p1=strchr(tbuf,'@'); p1; p1=strchr(p1,'@')) { |
||
236 | for(p2=p1+1;isdigit(*p2) || *p2=='-';p2++); |
||
8195 | bpr | 237 | if(p2==p1+1 || p2>p1+6) sym_error("syntax_error %.20s",p1); |
8161 | bpr | 238 | memmove(vbuf,p1,p2-p1); vbuf[p2-p1]=0; |
239 | n=atoi(vbuf+1); |
||
8195 | bpr | 240 | if(n<-4 || n==0 || n>4) sym_error("bad_macro %.20s",atoms[k]); |
8161 | bpr | 241 | n+=k; |
8195 | bpr | 242 | if(n<0 || n>=i) sym_error("bad_macro_position %.20s",atoms[k]); |
8161 | bpr | 243 | p3=find_atom_end(atoms[n]); |
244 | if(p3>pt2) pt2=p3; |
||
245 | if(atoms[n]<pt1) {min=n;pt1=atoms[n];} |
||
246 | memmove(ttbuf,atoms[n],p3-atoms[n]); ttbuf[p3-atoms[n]]=' '; |
||
247 | ttbuf[p3-atoms[n]+1]=0; |
||
248 | string_modify(tbuf,p1,p2,ttbuf); |
||
249 | } |
||
250 | string_modify(p,pt1,pt2,tbuf); pt=pt1; start=min; |
||
251 | goto recalc; |
||
252 | } |
||
253 | default: break; |
||
254 | } |
||
10 | reyssat | 255 | } |
256 | } |
||
257 | |||
258 | char *add2cp(char *p) |
||
259 | { |
||
260 | char *pp, *p1, *p2, buf[MAX_LINELEN+1]; |
||
261 | int l; |
||
262 | snprintf(buf,sizeof(buf),"%s",p); strfold(buf); l=strlen(buf); |
||
8195 | bpr | 263 | if((cpnext-cpbuf)+l>=MAX_LINELEN) sym_error("string_too_long"); |
10 | reyssat | 264 | pp=cpnext; memmove(pp,buf,l+1); cpnext+=l+1; |
265 | if(!noaddw) for(p1=find_word_start(buf); *p1; p1=find_word_start(p2)) { |
||
8161 | bpr | 266 | p2=find_word_end(p1); l=p2-p1; |
267 | if(*p2) *p2++=0; |
||
268 | if(wordchr(wbuf,p1)!=NULL) continue; |
||
269 | if(wptr-wbuf>=sizeof(wbuf)-l-2) continue; |
||
270 | if(wptr>wbuf) *wptr++=' '; |
||
271 | memmove(wptr,p1,l); wptr+=l; *wptr=0; |
||
10 | reyssat | 272 | } |
273 | return pp; |
||
274 | } |
||
275 | |||
276 | void cp_string(char *p, struct block *blk, int next) |
||
277 | { |
||
278 | blk->fn=mt_string; |
||
279 | blk->string=add2cp(p); |
||
280 | blk->len=strlen(blk->string); |
||
281 | blk->nextblock=next; |
||
282 | if(blk==blockbuf+nextblock) nextblock++; |
||
283 | } |
||
284 | |||
8161 | bpr | 285 | /* p must have MAX_LINELEN */ |
10 | reyssat | 286 | void cp_cutline(char *p, struct block *blk, int next) |
287 | { |
||
288 | char *p1, *p2, *p3; |
||
289 | char buf[MAX_LINELEN+1]; |
||
290 | int l, ll, n, idx, start, end; |
||
291 | struct block *b; |
||
292 | |||
3813 | kbelabas | 293 | if(debug>=3) fprintf(stderr,"Cutline %d/%d for %.15s.\n", |
8161 | bpr | 294 | (int)(blk-blockbuf), nextblock, p); |
10 | reyssat | 295 | for(p1=strstr(p,"[|]"); p1; p1=strstr(p1,"[|]")) memmove(p1," | ",3); |
296 | macro_trans(p); |
||
297 | singlespace(p); |
||
298 | p=find_word_start(p); strip_trailing_spaces(p); |
||
299 | l=0; p3=p; do { |
||
8161 | bpr | 300 | p1=find_word_start(p3); |
301 | if(*p1) l++; |
||
302 | p2=strparchr(p1,'['); |
||
303 | if(p2!=NULL) p3=find_matching(p2+1,']'); |
||
8195 | bpr | 304 | if(p3==NULL) sym_error("unmatched_parentheses %.20s",p); |
8161 | bpr | 305 | if(p2!=NULL && p2>p1) l++; |
306 | p3++; |
||
10 | reyssat | 307 | } while(p2!=NULL); |
308 | if(l==0) { |
||
8161 | bpr | 309 | buf[0]=0; cp_string(buf,blk,next); |
310 | return; |
||
10 | reyssat | 311 | } |
312 | idx=start=nextblock; nextblock+=l-1; end=nextblock; |
||
8195 | bpr | 313 | if(nextblock > MAX_BLOCKS) sym_error("block_overflow %.20s",p); |
10 | reyssat | 314 | for(p1=find_word_start(p); *p1; p1=find_word_start(p3)) { |
8161 | bpr | 315 | p2=strparchr(p1,'['); |
316 | if(p2==NULL) p2=p1+strlen(p1); |
||
317 | ll=p2-p1; |
||
318 | if(ll>0) { |
||
319 | memmove(buf,p1,ll); buf[ll]=0; |
||
320 | if(idx==start) b=blk; else b=blockbuf+idx-1; |
||
321 | if(idx<end) n=idx; else n=next; |
||
322 | if(debug>=3) fprintf(stderr,"String block %d/%d for %.15s.\n", |
||
323 | (int)(b-blockbuf), nextblock, buf); |
||
324 | cp_string(buf,b,n); |
||
325 | idx++; |
||
326 | } |
||
327 | if(*p2=='[') { |
||
328 | p2++; p3=find_matching(p2,']'); |
||
329 | memmove(buf,p2,p3-p2); buf[p3-p2]=0; p3++; |
||
330 | if(idx==start) b=blk; else b=blockbuf+idx-1; |
||
331 | if(idx<end) n=idx; else n=next; |
||
332 | cp_oneblock(buf,b,n); |
||
333 | idx++; |
||
334 | } |
||
335 | else p3=p2; |
||
10 | reyssat | 336 | } |
337 | } |
||
338 | |||
339 | unsigned int objnum(char *p, char delim) |
||
340 | { |
||
341 | int i; char *p1, *p2; |
||
342 | |||
343 | if(*p==0) return 1; |
||
344 | i=0; |
||
345 | for(p1=p; p1; p1=p2, i++) { |
||
8161 | bpr | 346 | p2=strparchr(p1,delim); if(p2) p2++; |
10 | reyssat | 347 | } |
348 | return i; |
||
349 | } |
||
350 | |||
351 | void _permpick(char *p, int n, struct block *blk, int next, char delim) |
||
352 | { |
||
353 | int i, t, idx; |
||
354 | char buf[MAX_LINELEN+1]; |
||
355 | char *pp, *pe; |
||
8161 | bpr | 356 | |
10 | reyssat | 357 | idx=nextblock; nextblock+=n; |
8195 | bpr | 358 | if(nextblock > MAX_BLOCKS) sym_error("block_overflow %.20s",p); |
10 | reyssat | 359 | blk->len=n; |
360 | blk->sublock=idx; |
||
361 | blk->fn=mt_permpick; |
||
362 | blk->lcnt=clist.lcnt; |
||
363 | blk->nextblock=next; |
||
8195 | bpr | 364 | if(nextlist+n > MAX_LISTS) sym_error("list_overflow %.20s",p); |
10 | reyssat | 365 | blk->listlen=listbuf+nextlist; nextlist+=n; |
366 | for(i=t=0; i<clist.lcnt; i++) { |
||
8161 | bpr | 367 | blk->listlen[i]=clist.listlen[i]; |
368 | blk->lists[i]=listbuf+nextlist+t; |
||
369 | t+=clist.listlen[i]; |
||
10 | reyssat | 370 | } |
8195 | bpr | 371 | if(nextlist+t > MAX_LISTS) sym_error("list_overflow %.20s",p); |
10 | reyssat | 372 | memmove(listbuf+nextlist,clist.list,t*sizeof(listtype)); |
373 | nextlist+=t; |
||
374 | for(i=0, pp=find_word_start(p);i<n;i++,idx++,pp=find_word_start(pe)) { |
||
8161 | bpr | 375 | pe=strparchr(pp,delim); |
376 | if(pe==NULL) pe=pp+strlen(pp); else *pe++=0; |
||
377 | snprintf(buf,sizeof(buf),"%s",pp); |
||
378 | cp_cutline(buf,blockbuf+idx,next); |
||
10 | reyssat | 379 | } |
380 | } |
||
381 | |||
8161 | bpr | 382 | /* alt for two flavours */ |
10 | reyssat | 383 | void _alt(char *p, struct block *blk, int next, char delim) |
384 | { |
||
385 | int n; |
||
386 | listtype ltab[]={-1}; |
||
387 | listtype len[]={1}; |
||
8161 | bpr | 388 | |
10 | reyssat | 389 | clist.lcnt=1; clist.listlen=len; clist.list=ltab; |
390 | n=objnum(p,delim); if(n==0) n=1; |
||
391 | _permpick(p,n,blk,next,delim); |
||
392 | } |
||
393 | |||
394 | void cp_alt(char *p, struct block *blk, int next) |
||
395 | { |
||
396 | _alt(p,blk,next,','); |
||
397 | } |
||
398 | |||
399 | void cp_alt2(char *p, struct block *blk, int next) |
||
400 | { |
||
401 | _alt(p,blk,next,'|'); |
||
402 | } |
||
403 | |||
404 | void cp_aperm(char *p, struct block *blk, int next) |
||
405 | { |
||
406 | int i, n; |
||
407 | listtype ltab[MAX_BLOCKS]; |
||
408 | listtype len; |
||
409 | |||
8195 | bpr | 410 | n=objnum(p,','); if(n<4) sym_error("wrong_parmcnt ins %.20s",p); |
411 | if(n>=MAX_BLOCKS/2) sym_error("block_overflow %.20s",p); |
||
10 | reyssat | 412 | clist.lcnt=1; len=2*n-5; clist.listlen=&len; |
413 | for(i=0;i<n-2;i++) ltab[2*i]=-2; |
||
414 | for(i=0;i<n-4;i++) ltab[2*i+1]=0; |
||
415 | ltab[len-2]=1; |
||
416 | clist.list=ltab; |
||
417 | _permpick(p,n,blk,blk-blockbuf,','); |
||
418 | blk->lstart=2; |
||
419 | } |
||
420 | |||
421 | void cp_apick(char *p, struct block *blk, int next) |
||
422 | { |
||
423 | int i, n, t; |
||
424 | char *p1; |
||
425 | listtype ltab[MAX_BLOCKS]; |
||
426 | listtype len; |
||
427 | |||
8195 | bpr | 428 | n=objnum(p,','); if(n<4) sym_error("wrong_parmcnt ins %.20s",p); |
429 | if(n>=MAX_BLOCKS/2) sym_error("block_overflow %.20s",p); |
||
10 | reyssat | 430 | p1=find_item_end(p); if(*p1) *p1++=0; |
8195 | bpr | 431 | t=atoi(p); if(t<=0 || t>n-3) sym_error("syntax_error ins %.20s",p); |
10 | reyssat | 432 | clist.lcnt=1; len=2*t-1; clist.listlen=&len; |
433 | for(i=0;i<t;i++) ltab[2*i]=-2; |
||
434 | for(i=0;i<t-1;i++) ltab[2*i+1]=0; |
||
435 | ltab[len-2]=1; |
||
436 | clist.list=ltab; |
||
437 | _permpick(p1,n,blk,blk-blockbuf,','); |
||
438 | blk->lstart=2; |
||
439 | } |
||
440 | |||
441 | void cp_dic(char *p, struct block *blk, int next) |
||
442 | { |
||
443 | int i, n; |
||
444 | char *p1, *p2; |
||
445 | n=objnum(p,','); |
||
8195 | bpr | 446 | if(n!=1) sym_error("wrong_parmcnt dic %.20s",p); |
10 | reyssat | 447 | p1=find_word_start(p); p2=find_word_end(p1); |
448 | if(*p2) *p2++=0; |
||
449 | p2=find_word_start(p2); |
||
450 | i=getdic(p1); |
||
8195 | bpr | 451 | if(i<0) sym_error("bad_dictionary %.20s",p1); |
10 | reyssat | 452 | noaddw=3; |
453 | blk->string=add2cp(p2); |
||
454 | noaddw=0; |
||
455 | blk->len=strlen(blk->string); |
||
456 | blk->lind1=i; |
||
457 | blk->fn=mt_dic; |
||
458 | blk->nextblock=next; |
||
459 | } |
||
460 | |||
461 | void cp_dperm(char *p, struct block *blk, int next) |
||
462 | { |
||
463 | int n; |
||
464 | listtype ltab[]={0,1,2,2,3,0}; |
||
465 | listtype len[]={3,3}; |
||
8161 | bpr | 466 | |
10 | reyssat | 467 | clist.lcnt=2; clist.listlen=len; clist.list=ltab; |
468 | n=objnum(p,','); |
||
8195 | bpr | 469 | if(n!=4) sym_error("wrong_parmcnt dperm %.20s",p); |
10 | reyssat | 470 | _permpick(p,n,blk,blk-blockbuf,','); |
471 | } |
||
472 | |||
473 | void cp_ins(char *p, struct block *blk, int next) |
||
474 | { |
||
475 | int i, n; |
||
476 | listtype ltab[MAX_BLOCKS]; |
||
477 | listtype len; |
||
478 | |||
8195 | bpr | 479 | n=objnum(p,','); if(n<3) sym_error("wrong_parmcnt ins %.20s",p); |
480 | if(n>=MAX_BLOCKS/2) sym_error("block_overflow %.20s",p); |
||
10 | reyssat | 481 | clist.lcnt=1; len=2*n-2; clist.listlen=&len; |
482 | for(i=1;i<n;i++) ltab[2*i-2]=i; |
||
483 | for(i=1;i<len;i+=2) ltab[i]=-12; |
||
484 | ltab[len-1]=-13; |
||
485 | clist.list=ltab; |
||
486 | _permpick(p,n,blk,blk-blockbuf,','); |
||
487 | blk->lstart=1; |
||
488 | } |
||
489 | |||
490 | void cp_iperm(char *p, struct block *blk, int next) |
||
491 | { |
||
492 | int n; |
||
493 | listtype ltab[]={0,1,2,2,1,0}; |
||
494 | listtype len[]={3,3}; |
||
495 | |||
496 | clist.lcnt=2; clist.listlen=len; clist.list=ltab; |
||
497 | n=objnum(p,','); |
||
8195 | bpr | 498 | if(n!=3) sym_error("wrong_parmcnt iperm %.20s",p); |
10 | reyssat | 499 | _permpick(p,n,blk,blk-blockbuf,','); |
500 | } |
||
501 | |||
502 | void cp_m(char *p, struct block *blk, int next) |
||
503 | { |
||
504 | int i, idx; |
||
505 | char buf[MAX_LINELEN+1]; |
||
8161 | bpr | 506 | |
8195 | bpr | 507 | i=objnum(p,','); if(i!=1) sym_error("wrong_parmcnt m %.20s",p); |
10 | reyssat | 508 | blk->fn=mt_m; |
509 | blk->string=NULL; |
||
510 | blk->len=1; |
||
511 | blk->nextblock=next; |
||
512 | p=find_word_start(p);singlespace(p);strip_trailing_spaces(p); |
||
513 | for(i=0;i<Mcnt && strcmp(p,Mind[i].Mptr)!=0;i++); |
||
8195 | bpr | 514 | if(nextblock >= MAX_BLOCKS-2) sym_error("block_overflow %.20s",p); |
10 | reyssat | 515 | if(i<Mcnt) blk->sublock=Mind[i].blkptr; |
516 | else { |
||
8161 | bpr | 517 | i=strlen(p); |
8195 | bpr | 518 | if(Mnext-Mbuf+i >= MAX_LINELEN-1) sym_error("Mbuf_overflow %.20s",p); |
519 | if(Mcnt >= MAX_BLOCKS) sym_error("Mind_overflow %.20s",p); |
||
8161 | bpr | 520 | Mind[Mcnt].Mptr=Mnext; Mind[Mcnt].blkptr=nextblock; |
521 | Mcnt++; |
||
522 | memcpy(Mnext,p,i+1); Mnext+=i+1; |
||
523 | idx=nextblock; blk->sublock=idx; nextblock++; |
||
524 | snprintf(buf,sizeof(buf),"%s",p); |
||
525 | cp_cutline(buf,blockbuf+idx,-2); |
||
526 | blockbuf[idx].mend=nextblock; |
||
10 | reyssat | 527 | } |
528 | } |
||
529 | |||
530 | void cp_neg(char *p, struct block *blk, int next) |
||
531 | { |
||
532 | int n, idx; |
||
533 | char buf[MAX_LINELEN+1]; |
||
534 | n=objnum(p,','); if(n==0) n=1; |
||
8195 | bpr | 535 | if(n>1) sym_error("wrong_parmcnt neg %.20s",p); |
10 | reyssat | 536 | blk->fn=mt_neg; |
537 | blk->len=1; |
||
538 | blk->nextblock=next; |
||
8195 | bpr | 539 | if(nextblock >= MAX_BLOCKS) sym_error("block_overflow %.20s",p); |
10 | reyssat | 540 | idx=nextblock; blk->sublock=idx; nextblock++; |
541 | snprintf(buf,sizeof(buf),"%s",p); |
||
542 | cp_cutline(buf,blockbuf+idx,blk-blockbuf); |
||
543 | } |
||
544 | |||
545 | void cp_none(char *p, struct block *blk, int next) |
||
546 | { |
||
547 | blk->fn=mt_nomatch; |
||
548 | blk->string=""; |
||
549 | blk->nextblock=next; |
||
550 | } |
||
551 | |||
552 | void _pick(char *p, struct block *blk, int next, int type) |
||
553 | { |
||
554 | int i, n, t, v; |
||
555 | listtype ltab[MAX_BLOCKS]; |
||
556 | listtype len; |
||
557 | char *p1; |
||
558 | |||
559 | n=objnum(p,','); n--; |
||
8195 | bpr | 560 | if(n<2) sym_error("wrong_parmcnt pick %.20s",p); |
561 | if(n>=MAX_BLOCKS) sym_error("block_overflow %.20s",p); |
||
10 | reyssat | 562 | p1=strparchr(p,','); *p1++=0; |
563 | p=find_word_start(p); v=0; |
||
564 | if(*p=='-') {p++; type-=5;} |
||
565 | else if(*p=='+') {v=2; p++;} |
||
8195 | bpr | 566 | t=atoi(p); if(t<1 || t>MAX_PICKS || t>n) sym_error("bad_pickcnt %.20s",p); |
10 | reyssat | 567 | clist.lcnt=1; len=t+v; clist.listlen=&len; |
568 | for(i=0;i<t;i++) ltab[i]=type; |
||
569 | if(v) {ltab[i++]=-6; ltab[i]=-5;} |
||
570 | clist.list=ltab; |
||
571 | _permpick(p1,n,blk,blk-blockbuf,','); |
||
572 | } |
||
573 | |||
574 | void cp_out(char *p, struct block *blk, int next) |
||
575 | { |
||
576 | char buf[MAX_LINELEN+1]; |
||
577 | char *p1; |
||
578 | int n, idx; |
||
8195 | bpr | 579 | n=objnum(p,','); if(n!=2) sym_error("wrong_parmcnt out %.20s",p); |
10 | reyssat | 580 | p1=strparchr(p,','); if(p1) *p1++=0; else p1=p+strlen(p); |
581 | p=find_word_start(p); *find_word_end(p)=0; |
||
582 | noaddw=3; |
||
583 | blk->string=add2cp(p); |
||
584 | noaddw=0; |
||
585 | blk->len=strlen(blk->string); |
||
586 | blk->fn=mt_out; |
||
587 | blk->nextblock=next; |
||
8195 | bpr | 588 | if(nextblock >= MAX_BLOCKS) sym_error("block_overflow %.20s",p); |
10 | reyssat | 589 | idx=nextblock; blk->sublock=idx; nextblock++; |
590 | snprintf(buf,sizeof(buf),"%s",p1); |
||
591 | cp_cutline(buf,blockbuf+idx,blk-blockbuf); |
||
592 | } |
||
593 | |||
594 | void cp_opick(char *p, struct block *blk, int next) |
||
595 | { |
||
596 | _pick(p,blk,next,-3); |
||
597 | } |
||
598 | |||
599 | void cp_perm(char *p, struct block *blk, int next) |
||
600 | { |
||
601 | int i, n; |
||
602 | listtype ltab[MAX_BLOCKS]; |
||
603 | listtype len; |
||
604 | |||
605 | n=objnum(p,','); if(n==0) n=1; |
||
8195 | bpr | 606 | if(n>=MAX_BLOCKS) sym_error("block_overflow %.20s",p); |
10 | reyssat | 607 | clist.lcnt=1; len=n; clist.listlen=&len; |
608 | for(i=0;i<n;i++) ltab[i]=-2; |
||
609 | clist.list=ltab; |
||
610 | _permpick(p,n,blk,blk-blockbuf,','); |
||
611 | } |
||
612 | |||
613 | void cp_pick(char *p, struct block *blk, int next) |
||
614 | { |
||
615 | _pick(p,blk,next,-2); |
||
616 | } |
||
617 | |||
618 | void cp_rep(char *p, struct block *blk, int next) |
||
619 | { |
||
620 | int n; |
||
621 | listtype ltab[]={-1,-5}; |
||
622 | listtype len[]={2}; |
||
623 | |||
624 | clist.lcnt=1; clist.listlen=len; clist.list=ltab; |
||
625 | n=objnum(p,','); if(n==0) n=1; |
||
626 | _permpick(p,n,blk,blk-blockbuf,','); |
||
627 | } |
||
628 | |||
629 | void cp_w(char *p, struct block *blk, int next) |
||
630 | { |
||
631 | items2words(p); |
||
632 | blk->string=add2cp(p); |
||
633 | blk->fn=mt_w; |
||
634 | blk->nextblock=next; |
||
635 | } |
||
636 | |||
637 | void cp_wild(char *p, struct block *blk, int next) |
||
638 | { |
||
639 | int n, min, max; |
||
640 | char *pp, *pe; |
||
8195 | bpr | 641 | n=objnum(p,','); if(n!=1) sym_error("wrong_parmcnt wild %.20s\n",p); |
10 | reyssat | 642 | blk->string=""; |
643 | max=min=0; |
||
644 | for(pp=find_word_start(p); *pp; pp=find_word_start(pe)) { |
||
8161 | bpr | 645 | pe=find_word_end(pp); |
8195 | bpr | 646 | if(pp[0]!='*') sym_error("syntax_error wild %.20s\n",p); |
8161 | bpr | 647 | if(pp[1]!='*') { |
648 | min++; continue; |
||
649 | } |
||
650 | if(isdigit(pp[2])) max+=atoi(pp+2); |
||
651 | else max=MAX_BLOCKS; |
||
10 | reyssat | 652 | } |
653 | blk->len=max; |
||
654 | blk->lstart=min; |
||
655 | blk->fn=mt_wild; |
||
656 | blk->nextblock=next; |
||
657 | } |
||
658 | |||
8161 | bpr | 659 | struct builtin builtin[]={ |
660 | {"Alt", cp_alt}, |
||
10 | reyssat | 661 | {"Aperm", cp_aperm}, |
662 | {"Apick", cp_apick}, |
||
663 | {"Dic", cp_dic}, |
||
664 | {"Dperm", cp_dperm}, |
||
665 | {"Ins", cp_ins}, |
||
666 | {"Iperm", cp_iperm}, |
||
667 | {"M", cp_m}, |
||
668 | {"Neg", cp_neg}, |
||
669 | {"Nomatch", cp_none}, |
||
670 | {"None", cp_none}, |
||
671 | {"Not", cp_neg}, |
||
672 | {"Opick", cp_opick}, |
||
673 | {"Out", cp_out}, |
||
674 | {"Perm", cp_perm}, |
||
675 | {"Pick", cp_pick}, |
||
676 | {"Rep", cp_rep}, |
||
677 | {"W", cp_w}, |
||
678 | {"Wild", cp_wild}, |
||
679 | }; |
||
680 | |||
8161 | bpr | 681 | int builtincnt=(sizeof(builtin)/sizeof(builtin[0])); |
10 | reyssat | 682 | |
8161 | bpr | 683 | /* p must have MAX_LINELEN */ |
10 | reyssat | 684 | void cp_oneblock(char *p, struct block *blk, int next) |
685 | { |
||
686 | char *pp, *pe; |
||
687 | int i; |
||
3813 | kbelabas | 688 | if(debug>=3) fprintf(stderr,"Oneblock %d/%d for %.15s.\n", |
8161 | bpr | 689 | (int)(blk-blockbuf), nextblock, p); |
10 | reyssat | 690 | if(myisupper(*p)) { |
8161 | bpr | 691 | for(pe=p; pe-p < MAX_BINAME && myisalpha(*pe); pe++); |
692 | if(*pe==':') { |
||
693 | *pe++=0; |
||
694 | i=search_list(builtin,builtincnt,sizeof(builtin[0]),p); |
||
8195 | bpr | 695 | if(i<0) sym_error("unknown_cmd %.20s",p); |
8161 | bpr | 696 | builtin[i].fn(pe,blk,next); |
697 | blk->nextblock=next; |
||
698 | return; |
||
699 | } |
||
10 | reyssat | 700 | } |
701 | if(*p=='*') { |
||
8161 | bpr | 702 | cp_wild(p,blk,next); |
703 | return; |
||
10 | reyssat | 704 | } |
705 | pp=strparchr(p,'|'); if(pp==NULL) { |
||
8161 | bpr | 706 | cp_cutline(p,blk,next); |
10 | reyssat | 707 | } |
708 | else cp_alt2(p,blk,next); |
||
709 | } |
||
710 | |||
8161 | bpr | 711 | /* p must have MAX_LINELEN */ |
10 | reyssat | 712 | void compile(char *p) |
713 | { |
||
714 | nextblock=1; nextlist=0; |
||
715 | cpnext=cpbuf; |
||
716 | memset(blockbuf,0,sizeof(blockbuf)); |
||
717 | cp_oneblock(p,blockbuf,-1); |
||
718 | showblocks(); |
||
719 | } |
||
720 |