]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/bc.y
realemu: implement IDIV, mark 0xE0000 writeable, fix DIV overfow trap
[plan9front.git] / sys / src / cmd / bc.y
1 %{
2         #include        <u.h>
3         #include        <libc.h>
4         #include        <bio.h>
5
6         #define bsp_max 5000
7
8         Biobuf  *in;
9         Biobuf  bstdin;
10         Biobuf  bstdout;
11         char    cary[1000];
12         char*   cp = { cary };
13         char    string[1000];
14         char*   str = { string };
15         int     crs = 128;
16         int     rcrs = 128;     /* reset crs */
17         int     bindx = 0;
18         int     lev = 0;
19         int     ln;
20         char*   ttp;
21         char*   ss = "";
22         int     bstack[10] = { 0 };
23         char*   numb[15] =
24         {
25                 " 0", " 1", " 2", " 3", " 4", " 5",
26                 " 6", " 7", " 8", " 9", " 10", " 11",
27                 " 12", " 13", " 14"
28         };
29         char*   pre;
30         char*   post;
31
32         long    peekc = -1;
33         int     sargc;
34         int     ifile;
35         char**  sargv;
36
37         char    *funtab[] =
38         {
39                 "<1>","<2>","<3>","<4>","<5>",
40                 "<6>","<7>","<8>","<9>","<10>",
41                 "<11>","<12>","<13>","<14>","<15>",
42                 "<16>","<17>","<18>","<19>","<20>",
43                 "<21>","<22>","<23>","<24>","<25>",
44                 "<26>"
45         };
46         char    *atab[] =
47         {
48                 "<221>","<222>","<223>","<224>","<225>",
49                 "<226>","<227>","<228>","<229>","<230>",
50                 "<231>","<232>","<233>","<234>","<235>",
51                 "<236>","<237>","<238>","<239>","<240>",
52                 "<241>","<242>","<243>","<244>","<245>",
53                 "<246>"
54         };
55         char*   letr[26] =
56         {
57                 "a","b","c","d","e","f","g","h","i","j",
58                 "k","l","m","n","o","p","q","r","s","t",
59                 "u","v","w","x","y","z"
60         };
61         char*   dot = { "." };
62         char*   bspace[bsp_max];
63         char**  bsp_nxt = bspace;
64         int     bdebug = 0;
65         int     lflag;
66         int     cflag;
67         int     sflag;
68
69         char*   bundle(int, ...);
70         void    conout(char*, char*);
71         int     cpeek(int, int, int);
72         int     getch(void);
73         char*   geta(char*);
74         char*   getf(char*);
75         void    getout(void);
76         void    output(char*);
77         void    pp(char*);
78         void    routput(char*);
79         void    tp(char*);
80         void    yyerror(char*, ...);
81         int     yyparse(void);
82
83         typedef void*   pointer;
84         #pragma varargck        type    "lx"    pointer
85
86 %}
87 %union
88 {
89         char*   cptr;
90         int     cc;
91 }
92
93 %type   <cptr>  pstat stat stat1 def slist dlets e ase nase
94 %type   <cptr>  slist re fprefix cargs eora cons constant lora
95 %type   <cptr>  crs
96
97 %token  <cptr>  LETTER EQOP _AUTO DOT
98 %token  <cc>    DIGIT SQRT LENGTH _IF FFF EQ
99 %token  <cc>    _PRINT _WHILE _FOR NE LE GE INCR DECR
100 %token  <cc>    _RETURN _BREAK _DEFINE BASE OBASE SCALE
101 %token  <cc>    QSTR ERROR
102
103 %right  '=' EQOP
104 %left   '+' '-'
105 %left   '*' '/' '%'
106 %right  '^'
107 %left   UMINUS
108
109 %%
110 start:
111         start stuff
112 |       stuff
113
114 stuff:
115         pstat tail
116         {
117                 output($1);
118         }
119 |       def dargs ')' '{' dlist slist '}'
120         {
121                 ttp = bundle(6, pre, $6, post , "0", numb[lev], "Q");
122                 conout(ttp, (char*)$1);
123                 rcrs = crs;
124                 output("");
125                 lev = bindx = 0;
126         }
127
128 dlist:
129         tail
130 |       dlist _AUTO dlets tail
131
132 stat:
133         stat1
134 |       nase
135         {
136                 if(sflag)
137                         bundle(2, $1, "s.");
138         }
139
140 pstat:
141         stat1
142         {
143                 if(sflag)
144                         bundle(2, $1, "0");
145         }
146 |       nase
147         {
148                 if(!sflag)
149                         bundle(2, $1, "ps.");
150         }
151
152 stat1:
153         {
154                 bundle(1, "");
155         }
156 |       ase
157         {
158                 bundle(2, $1, "s.");
159         }
160 |       SCALE '=' e
161         {
162                 bundle(2, $3, "k");
163         }
164 |       SCALE EQOP e
165         {
166                 bundle(4, "K", $3, $2, "k");
167         }
168 |       BASE '=' e
169         {
170                 bundle(2, $3, "i");
171         }
172 |       BASE EQOP e
173         {
174                 bundle(4, "I", $3, $2, "i");
175         }
176 |       OBASE '=' e
177         {
178                 bundle(2, $3, "o");
179         }
180 |       OBASE EQOP e
181         {
182                 bundle(4, "O", $3, $2, "o");
183         }
184 |       QSTR
185         {
186                 bundle(3, "[", $1, "]P");
187         }
188 |       _BREAK
189         {
190                 bundle(2, numb[lev-bstack[bindx-1]], "Q");
191         }
192 |       _PRINT e
193         {
194                 bundle(2, $2, "ps.");
195         }
196 |       _RETURN e
197         {
198                 bundle(4, $2, post, numb[lev], "Q");
199         }
200 |       _RETURN
201         {
202                 bundle(4, "0", post, numb[lev], "Q");
203         }
204 |       '{' slist '}'
205         {
206                 $$ = $2;
207         }
208 |       FFF
209         {
210                 bundle(1, "fY");
211         }
212 |       _IF crs BLEV '(' re ')' stat
213         {
214                 conout($7, $2);
215                 bundle(3, $5, $2, " ");
216         }
217 |       _WHILE crs '(' re ')' stat BLEV
218         {
219                 bundle(3, $6, $4, $2);
220                 conout($$, $2);
221                 bundle(3, $4, $2, " ");
222         }
223 |       fprefix crs re ';' e ')' stat BLEV
224         {
225                 bundle(5, $7, $5, "s.", $3, $2);
226                 conout($$, $2);
227                 bundle(5, $1, "s.", $3, $2, " ");
228         }
229 |       '~' LETTER '=' e
230         {
231                 bundle(3, $4, "S", $2);
232         }
233
234 fprefix:
235         _FOR '(' e ';'
236         {
237                 $$ = $3;
238         }
239
240 BLEV:
241         =
242         {
243                 --bindx;
244         }
245
246 slist:
247         stat
248 |       slist tail stat
249         {
250                 bundle(2, $1, $3);
251         }
252
253 tail:
254         '\n'
255         {
256                 ln++;
257         }
258 |       ';'
259
260 re:
261         e EQ e
262         {
263                 $$ = bundle(3, $1, $3, "=");
264         }
265 |       e '<' e
266         {
267                 bundle(3, $1, $3, ">");
268         }
269 |       e '>' e
270         {
271                 bundle(3, $1, $3, "<");
272         }
273 |       e NE e
274         {
275                 bundle(3, $1, $3, "!=");
276         }
277 |       e GE e
278         {
279                 bundle(3, $1, $3, "!>");
280         }
281 |       e LE e
282         {
283                 bundle(3, $1, $3, "!<");
284         }
285 |       e
286         {
287                 bundle(2, $1, " 0!=");
288         }
289
290 nase:
291         '(' e ')'
292         {
293                 $$ = $2;
294         }
295 |       cons
296         {
297                 bundle(3, " ", $1, " ");
298         }
299 |       DOT cons
300         {
301                 bundle(3, " .", $2, " ");
302         }
303 |       cons DOT cons
304         {
305                 bundle(5, " ", $1, ".", $3, " ");
306         }
307 |       cons DOT
308         {
309                 bundle(4, " ", $1, ".", " ");
310         }
311 |       DOT
312         {
313                 $<cptr>$ = "l.";
314         }
315 |       LETTER '[' e ']'
316         {
317                 bundle(3, $3, ";", geta($1));
318         }
319 |       LETTER INCR
320         {
321                 bundle(4, "l", $1, "d1+s", $1);
322         }
323 |       INCR LETTER
324         {
325                 bundle(4, "l", $2, "1+ds", $2);
326         }
327 |       DECR LETTER
328         {
329                 bundle(4, "l", $2, "1-ds", $2);
330         }
331 |       LETTER DECR
332         {
333                 bundle(4, "l", $1, "d1-s", $1);
334         }
335 |       LETTER '[' e ']' INCR
336         {
337                 bundle(7, $3, ";", geta($1), "d1+" ,$3, ":" ,geta($1));
338         }
339 |       INCR LETTER '[' e ']'
340         {
341                 bundle(7, $4, ";", geta($2), "1+d", $4, ":", geta($2));
342         }
343 |       LETTER '[' e ']' DECR
344         {
345                 bundle(7, $3, ";", geta($1), "d1-", $3, ":", geta($1));
346         }
347 |       DECR LETTER '[' e ']'
348         {
349                 bundle(7, $4, ";", geta($2), "1-d", $4, ":" ,geta($2));
350         }
351 |       SCALE INCR
352         {
353                 bundle(1, "Kd1+k");
354         }
355 |       INCR SCALE
356         {
357                 bundle(1, "K1+dk");
358         }
359 |       SCALE DECR
360         {
361                 bundle(1, "Kd1-k");
362         }
363 |       DECR SCALE
364         {
365                 bundle(1, "K1-dk");
366         }
367 |       BASE INCR
368         {
369                 bundle(1, "Id1+i");
370         }
371 |       INCR BASE
372         {
373                 bundle(1, "I1+di");
374         }
375 |       BASE DECR
376         {
377                 bundle(1, "Id1-i");
378         }
379 |       DECR BASE
380         {
381                 bundle(1, "I1-di");
382         }
383 |       OBASE INCR
384         {
385                 bundle(1, "Od1+o");
386         }
387 |       INCR OBASE
388         {
389                 bundle(1, "O1+do");
390         }
391 |       OBASE DECR
392         {
393                 bundle(1, "Od1-o");
394         }
395 |       DECR OBASE
396         {
397                 bundle(1, "O1-do");
398         }
399 |       LETTER '(' cargs ')'
400         {
401                 bundle(4, $3, "l", getf($1), "x");
402         }
403 |       LETTER '(' ')'
404         {
405                 bundle(3, "l", getf($1), "x");
406         }
407 |       LETTER = {
408                 bundle(2, "l", $1);
409         }
410 |       LENGTH '(' e ')'
411         {
412                 bundle(2, $3, "Z");
413         }
414 |       SCALE '(' e ')'
415         {
416                 bundle(2, $3, "X");
417         }
418 |       '?'
419         {
420                 bundle(1, "?");
421         }
422 |       SQRT '(' e ')'
423         {
424                 bundle(2, $3, "v");
425         }
426 |       '~' LETTER
427         {
428                 bundle(2, "L", $2);
429         }
430 |       SCALE
431         {
432                 bundle(1, "K");
433         }
434 |       BASE
435         {
436                 bundle(1, "I");
437         }
438 |       OBASE
439         {
440                 bundle(1, "O");
441         }
442 |       '-' e
443         {
444                 bundle(3, " 0", $2, "-");
445         }
446 |       e '+' e
447         {
448                 bundle(3, $1, $3, "+");
449         }
450 |       e '-' e
451         {
452                 bundle(3, $1, $3, "-");
453         }
454 |       e '*' e
455         {
456                 bundle(3, $1, $3, "*");
457         }
458 |       e '/' e
459         {
460                 bundle(3, $1, $3, "/");
461         }
462 |       e '%' e
463         {
464                 bundle(3, $1, $3, "%%");
465         }
466 |       e '^' e
467         {
468                 bundle(3, $1, $3, "^");
469         }
470
471 ase:
472         LETTER '=' e
473         {
474                 bundle(3, $3, "ds", $1);
475         }
476 |       LETTER '[' e ']' '=' e
477         {
478                 bundle(5, $6, "d", $3, ":", geta($1));
479         }
480 |       LETTER EQOP e
481         {
482                 bundle(6, "l", $1, $3, $2, "ds", $1);
483         }
484 |       LETTER '[' e ']' EQOP e
485         {
486                 bundle(9, $3, ";", geta($1), $6, $5, "d", $3, ":", geta($1));
487         }
488
489 e:
490         ase
491 |       nase
492
493 cargs:
494         eora
495 |       cargs ',' eora
496         {
497                 bundle(2, $1, $3);
498         }
499
500 eora:
501         e
502 |       LETTER '[' ']'
503         {
504                 bundle(2, "l", geta($1));
505         }
506
507 cons:
508         constant
509         {
510                 *cp++ = 0;
511         }
512
513 constant:
514         '_'
515         {
516                 $<cptr>$ = cp;
517                 *cp++ = '_';
518         }
519 |       DIGIT
520         {
521                 $<cptr>$ = cp;
522                 *cp++ = $1;
523         }
524 |       constant DIGIT
525         {
526                 *cp++ = $2;
527         }
528
529 crs:
530         =
531         {
532                 $$ = cp;
533                 *cp++ = '<';
534                 *cp++ = crs/100+'0';
535                 *cp++ = (crs%100)/10+'0';
536                 *cp++ = crs%10+'0';
537                 *cp++ = '>';
538                 *cp++ = '\0';
539                 if(crs++ >= 220) {
540                         yyerror("program too big");
541                         getout();
542                 }
543                 bstack[bindx++] = lev++;
544         }
545
546 def:
547         _DEFINE LETTER '('
548         {
549                 $$ = getf($2);
550                 pre = (char*)"";
551                 post = (char*)"";
552                 lev = 1;
553                 bindx = 0;
554                 bstack[bindx] = 0;
555         }
556
557 dargs:
558 |       lora
559         {
560                 pp((char*)$1);
561         }
562 |       dargs ',' lora
563         {
564                 pp((char*)$3);
565         }
566
567 dlets:
568         lora
569         {
570                 tp((char*)$1);
571         }
572 |       dlets ',' lora
573         {
574                 tp((char*)$3);
575         }
576
577 lora:
578         LETTER
579         {
580                 $<cptr>$=$1;
581         }
582 |       LETTER '[' ']'
583         {
584                 $$ = geta($1);
585         }
586
587 %%
588
589 int
590 yylex(void)
591 {
592         int c, ch;
593
594 restart:
595         c = getch();
596         peekc = -1;
597         while(c == ' ' || c == '\t')
598                 c = getch();
599         if(c == '\\') {
600                 getch();
601                 goto restart;
602         }
603         if(c >= 'a' && c <= 'z') {
604                 /* look ahead to look for reserved words */
605                 peekc = getch();
606                 if(peekc >= 'a' && peekc <= 'z') { /* must be reserved word */
607                         if(c=='p' && peekc=='r') {
608                                 c = _PRINT;
609                                 goto skip;
610                         }
611                         if(c=='i' && peekc=='f') {
612                                 c = _IF;
613                                 goto skip;
614                         }
615                         if(c=='w' && peekc=='h') {
616                                 c = _WHILE;
617                                 goto skip;
618                         }
619                         if(c=='f' && peekc=='o') {
620                                 c = _FOR;
621                                 goto skip;
622                         }
623                         if(c=='s' && peekc=='q') {
624                                 c = SQRT;
625                                 goto skip;
626                         }
627                         if(c=='r' && peekc=='e') {
628                                 c = _RETURN;
629                                 goto skip;
630                         }
631                         if(c=='b' && peekc=='r') {
632                                 c = _BREAK;
633                                 goto skip;
634                         }
635                         if(c=='d' && peekc=='e') {
636                                 c = _DEFINE;
637                                 goto skip;
638                         }
639                         if(c=='s' && peekc=='c') {
640                                 c = SCALE;
641                                 goto skip;
642                         }
643                         if(c=='b' && peekc=='a') {
644                                 c = BASE;
645                                 goto skip;
646                         }
647                         if(c=='i' && peekc=='b') {
648                                 c = BASE;
649                                 goto skip;
650                         }
651                         if(c=='o' && peekc=='b') {
652                                 c = OBASE;
653                                 goto skip;
654                         }
655                         if(c=='d' && peekc=='i') {
656                                 c = FFF;
657                                 goto skip;
658                         }
659                         if(c=='a' && peekc=='u') {
660                                 c = _AUTO;
661                                 goto skip;
662                         }
663                         if(c=='l' && peekc=='e') {
664                                 c = LENGTH;
665                                 goto skip;
666                         }
667                         if(c=='q' && peekc=='u')
668                                 getout();
669                         /* could not be found */
670                         return ERROR;
671
672                 skip:   /* skip over rest of word */
673                         peekc = -1;
674                         for(;;) {
675                                 ch = getch();
676                                 if(ch < 'a' || ch > 'z')
677                                         break;
678                         }
679                         peekc = ch;
680                         return c;
681                 }
682
683                 /* usual case; just one single letter */
684                 yylval.cptr = letr[c-'a'];
685                 return LETTER;
686         }
687         if((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F')) {
688                 yylval.cc = c;
689                 return DIGIT;
690         }
691         switch(c) {
692         case '.':
693                 return DOT;
694         case '*':
695                 yylval.cptr = "*";
696                 return cpeek('=', EQOP, c);
697         case '%':
698                 yylval.cptr = "%%";
699                 return cpeek('=', EQOP, c);
700         case '^':
701                 yylval.cptr = "^";
702                 return cpeek('=', EQOP, c);
703         case '+':
704                 ch = cpeek('=', EQOP, c);
705                 if(ch == EQOP) {
706                         yylval.cptr = "+";
707                         return ch;
708                 }
709                 return cpeek('+', INCR, c);
710         case '-':
711                 ch = cpeek('=', EQOP, c);
712                 if(ch == EQOP) {
713                         yylval.cptr = "-";
714                         return ch;
715                 }
716                 return cpeek('-', DECR, c);
717         case '=':
718                 return cpeek('=', EQ, '=');
719         case '<':
720                 return cpeek('=', LE, '<');
721         case '>':
722                 return cpeek('=', GE, '>');
723         case '!':
724                 return cpeek('=', NE, '!');
725         case '/':
726                 ch = cpeek('=', EQOP, c);
727                 if(ch == EQOP) {
728                         yylval.cptr = "/";
729                         return ch;
730                 }
731                 if(peekc == '*') {
732                         peekc = -1;
733                         for(;;) {
734                                 ch = getch();
735                                 if(ch == '*') {
736                                         peekc = getch();
737                                         if(peekc == '/') {
738                                                 peekc = -1;
739                                                 goto restart;
740                                         }
741                                 }
742                         }
743                 }
744                 return c;
745         case '"':
746                 yylval.cptr = str;
747                 while((c=getch()) != '"'){
748                         *str++ = c;
749                         if(str >= &string[999]){
750                                 yyerror("string space exceeded");
751                                 getout();
752                         }
753                 }
754                 *str++ = 0;
755                 return QSTR;
756         default:
757                 return c;
758         }
759 }
760
761 int
762 cpeek(int c, int yes, int no)
763 {
764
765         peekc = getch();
766         if(peekc == c) {
767                 peekc = -1;
768                 return yes;
769         }
770         return no;
771 }
772
773 int
774 getch(void)
775 {
776         long ch;
777
778 loop:
779         ch = peekc;
780         if(ch < 0){
781                 if(in == 0)
782                         ch = -1;
783                 else
784                         ch = Bgetc(in);
785         }
786         peekc = -1;
787         if(ch >= 0)
788                 return ch;
789         ifile++;
790         if(ifile > sargc) {
791                 if(ifile >= sargc+2)
792                         getout();
793                 in = &bstdin;
794                 Binit(in, 0, OREAD);
795                 ln = 0;
796                 goto loop;
797         }
798         if(in)
799                 Bterm(in);
800         if((in = Bopen(sargv[ifile], OREAD)) != 0){
801                 ln = 0;
802                 ss = sargv[ifile];
803                 goto loop;
804         }
805         yyerror("cannot open input file");
806         return 0;               /* shut up ken */
807 }
808
809 char*
810 bundle(int a, ...)
811 {
812         int i;
813         char **q;
814         va_list arg;
815         
816         i = a;
817         va_start(arg, a);
818         q = bsp_nxt;
819         if(bdebug)
820                 fprint(2, "bundle %d elements at %lx\n", i, q);
821         while(i-- > 0) {
822                 if(bsp_nxt >= &bspace[bsp_max])
823                         yyerror("bundling space exceeded");
824                 *bsp_nxt++ = va_arg(arg, char*);
825         }
826         *bsp_nxt++ = 0;
827         va_end(arg);
828         yyval.cptr = (char*)q;
829         return (char*)q;
830 }
831
832 void
833 routput(char *p)
834 {
835         char **pp;
836         
837         if(bdebug)
838                 fprint(2, "routput(%lx)\n", p);
839         if((char**)p >= &bspace[0] && (char**)p < &bspace[bsp_max]) {
840                 /* part of a bundle */
841                 pp = (char**)p;
842                 while(*pp != 0)
843                         routput(*pp++);
844         } else
845                 Bprint(&bstdout, p);    /* character string */
846 }
847
848 void
849 output(char *p)
850 {
851         routput(p);
852         bsp_nxt = &bspace[0];
853         Bprint(&bstdout, "\n");
854         Bflush(&bstdout);
855         cp = cary;
856         crs = rcrs;
857 }
858
859 void
860 conout(char *p, char *s)
861 {
862         Bprint(&bstdout, "[");
863         routput(p);
864         Bprint(&bstdout, "]s%s\n", s);
865         Bflush(&bstdout);
866         lev--;
867 }
868
869 void
870 yyerror(char *s, ...)
871 {
872         if(ifile > sargc)
873                 ss = "stdin";
874         Bprint(&bstdout, "c[%s:%d %s]pc\n", ss, ln+1, s);
875         Bflush(&bstdout);
876         cp = cary;
877         crs = rcrs;
878         bindx = 0;
879         lev = 0;
880         bsp_nxt = &bspace[0];
881 }
882
883 void
884 pp(char *s)
885 {
886         /* puts the relevant stuff on pre and post for the letter s */
887         bundle(3, "S", s, pre);
888         pre = yyval.cptr;
889         bundle(4, post, "L", s, "s.");
890         post = yyval.cptr;
891 }
892
893 void
894 tp(char *s)
895 {
896         /* same as pp, but for temps */
897         bundle(3, "0S", s, pre);
898         pre = yyval.cptr;
899         bundle(4, post, "L", s, "s.");
900         post = yyval.cptr;
901 }
902
903 void
904 yyinit(int argc, char **argv)
905 {
906         Binit(&bstdout, 1, OWRITE);
907         sargv = argv;
908         sargc = argc - 1;
909         if(sargc == 0) {
910                 in = &bstdin;
911                 Binit(in, 0, OREAD);
912         } else if((in = Bopen(sargv[1], OREAD)) == 0)
913                 yyerror("cannot open input file");
914         ifile = 1;
915         ln = 0;
916         ss = sargv[1];
917 }
918
919 void
920 getout(void)
921 {
922         Bprint(&bstdout, "q");
923         Bflush(&bstdout);
924         exits(0);
925 }
926
927 char*
928 getf(char *p)
929 {
930         return funtab[*p - 'a'];
931 }
932
933 char*
934 geta(char *p)
935 {
936         return atab[*p - 'a'];
937 }
938
939 void
940 main(int argc, char **argv)
941 {
942         int p[2];
943
944         while(argc > 1 && *argv[1] == '-') {
945                 switch(argv[1][1]) {
946                 case 'd':
947                         bdebug++;
948                         break;
949                 case 'c':
950                         cflag++;
951                         break;
952                 case 'l':
953                         lflag++;
954                         break;
955                 case 's':
956                         sflag++;
957                         break;
958                 default:
959                         fprint(2, "Usage: bc [-cdls] [file ...]\n");
960                         exits("usage");
961                 }
962                 argc--;
963                 argv++;
964         }
965         if(lflag) {
966                 argv--;
967                 argc++;
968                 argv[1] = "/sys/lib/bclib";
969         }
970         if(cflag) {
971                 yyinit(argc, argv);
972                 for(;;)
973                         yyparse();
974                 /* not reached */
975         }
976         pipe(p);
977         if(fork() == 0) {
978                 dup(p[1], 1);
979                 close(p[0]);
980                 close(p[1]);
981                 yyinit(argc, argv);
982                 for(;;)
983                         yyparse();
984         }
985         dup(p[0], 0);
986         close(p[0]);
987         close(p[1]);
988         execl("/bin/dc", "dc", nil);
989 }