#include #include #include #include #include #include #include "wllib.h" #ifdef FOR_X11 #include "mop453.xpm" /* Ikona pro X Window System$^{\def\fntmag{\magstep.2}\rm TM}$ */ #endif #ifndef PI #ifdef M_PI #define PI M_PI #else #define PI 3.14159265358979323846 #endif #endif typedef long da_num; /* budeme {\I dyna-add}it \type{long}y */ #define NEED_DA_POS /* potęebujeme \func{da_putpos}() a \func{da_getpos}() */ #include "dyna-add.c" /* modul dynamického pęidávání */ float curX,curY; /* souęadnice pera */ int curA; /* úhel natoçení pera */ static void draw_seq(void) { /* vykresli posloupnost z~dyna-struktury */ long st1; /* první parametr dyna-struktury */ int i; /* pomocné */ for (;;) { /* pro neomezený poçet dvojic */ i=da_get(&st1); assert(!!i); /* poslední prvek bude 0 */ if (!st1) return; /* ukonçení posloupnosti */ if (st1<0) { /* prvek$<0$ $\Longrightarrow$ dvë çísla */ long p1; /* vzdálenost */ float k=0/*fake for GCC*/; /* úhel v~radiánech */ i=da_get(&p1); assert(!!i); /* tento parametr také musí existovat */ curX+=p1*sin(k=(float)curA*PI/180); /* îoupni pérem */ wl_line((long)rint(curX*16),(long)rint((curY+=p1*cos(k))*16)); /* táhni! (\dots çáru) */ if ((curA+=st1)<0) curA+=360; /* natoç pero a moůná pęeteç */ } else { /* opakuj posloupnost */ struct da_pos pos; /* zapamatování pozice pro opakování */ da_putpos(&pos); /* pamatuj! */ while (st1--) { /* \var{st1}-krát */ da_getpos(&pos); /* pro velký ohlas repríza */ draw_seq(); /* jedem znova posloupnost */ } } } } void drawgfx(void) { /* vykresli gfx */ long n; da_reset(); /* nainicializuj dyna-struktury na zaçátek */ wl_line((long)(curX=0),(long)(curY=0)); /* první bod je z~$(0,0)$ */ curA=0; /* natoçení Şna severş */ draw_seq(); /* zpracuj top-level posloupnost */ assert(!da_get(&n)); /* ujisti se, ůe to bylo vîe */ } static long get_lex(void) { /* naçti lexikální element a vraď çíslo, çi LONG_MIN pro \sign[ nebo LONG_MAX pro \sign] */ int c,isn=0,neg=0; /* naçtený znak, kousek çísla?, záporné? */ long n=0; /* sestavované çíslo */ for (;;) { /* \dots a v~ůivotë to nikdo nezastaví */ if ((c=getchar())==EOF) iofail(); /* EOF má pęijít v~\func{main}()u */ if (c=='\n'||c=='\t') c=' '; /* white-space */ if (c==' ') { if (isn) break; /* je-li kousek çísla, potom oddëlovaç */ else continue; /* jinak ignoruj */ } if (c=='['||c==']') break; /* terminují vůdy */ if (!neg&&c=='-') { neg=1; continue; } /* záporné çíslo? */ if (c<'0'||c>'9') iofailn(EINVAL); /* tady by to jiů mëla být cifra */ isn=1; /* jiů máme kousek çísla */ if (n>LONG_MAX/10) iofailn(ERANGE); /* nevyteçeme? */ n=n*10+c-'0'; /* pęedpoklady: desítková soustava a souvislé kódy cifer */ } if (isn) { /* terminace uprostęed çísla */ if (neg) n=-n; /* negativní numero */ if (n==LONG_MIN||n==LONG_MAX) iofailn(ERANGE); /* check kolize návratových hodnot */ ungetc(c,stdin); /* byla-li to hranatka, bude jeîtë potęeba, white-space se sveze */ } return(isn?n:(c=='['?LONG_MIN:LONG_MAX)); /* çíslo, çi typ hranatky */ } long p1,p2; /* pro chroustání posloupnosti jsou jako auto-variábly zbyteçnë expensive */ static void do_seq(void) { /* nachroustej jednu úroveń posloupnosti */ while ((p1=get_lex())!=LONG_MAX) { /* dokud nenarazíî na \sign] */ if (p1==LONG_MIN) iofailn(EINVAL); /* $P_1$ musí být çíslo */ if ((p2=get_lex())==LONG_MAX) iofailn(EINVAL); /* $P_2$ nesmí být \sign] */ if (p2==LONG_MIN) { /* bylo-li $P_2$ \sign[ */ if (p1<=0) iofailn(EINVAL); /* $P_1$ musí být kladné */ da_put(p1); /* uloů kladné çíslo jako opakovaní */ do_seq(); /* rekurzivnë zpracuj opakovanou posloupnost */ } else { /* budeme kreslit */ p2%=360; if (p2>=0) p2-=360; /* znormalizuj úhel do záporna */ da_put(p2); da_put(p1); /* nejdęív úhel ($P_2$ -- odliîení od opakování), potom délka ($P_1$) */ } } da_put(0); /* terminátor posloupnosti */ } int main(int argc,char **argv) { int i; wl_init(&argc,argv,"MOP453"); /* inicializuj gfx */ if (get_lex()!=LONG_MIN) iofailn(EINVAL); /* první element musí být \sign[ */ do_seq(); /* zpracuj top-level posloupnost */ do i=getchar(); while (i==' '||i=='\n'||i=='\t'); /* seůer white-spacy */ if (i!=EOF) iofailn(EINVAL); /* musí být EOF, jinak ERROR */ wl_done(); /* gfx okno */ return(0); /* hotovo */ }