]> gitweb.ps.run Git - iftint/blob - main3.c
update
[iftint] / main3.c
1 #include <stdint.h>
2 #include <stdbool.h>
3 #include <stdio.h>
4 #include <stdarg.h>
5 #include <string.h>
6 #include <assert.h>
7
8
9 // Global defines
10
11 #define STR_SIZE 128
12 #define MEMORY_SIZE 1024*1024
13 #define EDIT_QUEUE_SIZE 10
14
15 // Memory
16
17 static char g_memory[1024*1024];
18 static int g_memory_index = 0;
19
20 void * alloc(int num, int size) {
21     assert(g_memory_index + num*size < MEMORY_SIZE);
22
23     void * result = g_memory + g_memory_index;
24     for (int i = 0; i < num*size; i++)
25         g_memory[g_memory_index+i] = 0;
26     g_memory_index += num*size;
27     return result;
28 }
29
30 #define NEW(TYPE) ((TYPE *)alloc(1, sizeof(TYPE)))
31 #define NEWARR(TYPE, NUM) ((TYPE *)alloc(NUM, sizeof(TYPE)))
32 #define NEWSTR NEWARR(char, STR_SIZE)
33
34 // getch
35
36 #ifdef _WIN32
37 #include <windows.h>
38 #include <conio.h>
39 #else
40 #include <sys/ioctl.h>
41 #include <termios.h>
42 #include <unistd.h>
43 #include <stdio.h>
44
45 /* reads from keypress, doesn't echo */
46 int getch(void)
47 {
48     struct termios oldattr, newattr;
49     int ch;
50     tcgetattr( STDIN_FILENO, &oldattr );
51     newattr = oldattr;
52     newattr.c_lflag &= ~( ICANON | ECHO ); // no ECHO for echo(?)
53     tcsetattr( STDIN_FILENO, TCSANOW, &newattr );
54     ch = getchar();
55     tcsetattr( STDIN_FILENO, TCSANOW, &oldattr );
56     return ch;
57 }
58
59 /* ungets keypress */
60 void ungetch(int ch)
61 {
62     struct termios oldattr, newattr;
63     tcgetattr( STDIN_FILENO, &oldattr );
64     newattr = oldattr;
65     newattr.c_lflag &= ~( ICANON | ECHO );
66     tcsetattr( STDIN_FILENO, TCSANOW, &newattr );
67     ungetc(ch, stdin);
68     tcsetattr( STDIN_FILENO, TCSANOW, &oldattr );
69 }
70 #endif
71
72 int
73 peekch() {
74     int c = getch();
75     ungetch(c);
76     return c;
77 }
78
79 // VT100
80
81 #define ASCII_ESC 27
82
83 void vt100Escape(const char * str, ...) {
84     va_list args;
85     va_start(args, str);
86
87     printf("%c", ASCII_ESC);
88     vprintf(str, args);
89 }
90
91 void vt100ClearScreen() { vt100Escape("[2J"); }
92 void vt100CursorHome() { vt100Escape("[H"); }
93 void vt100CursorPos(int v, int h) { vt100Escape("[%d;%df", v, h); }
94 void vt100SaveCursor() { vt100Escape("7"); }
95 void vt100RestoreCursor() { vt100Escape("8"); }
96 void vt100EnableAlternateBuffer() { vt100Escape("[?1049h"); }
97 void vt100DisableAlternateBuffer() { vt100Escape("[?1049l"); }
98 void vt100EnableNegative() { vt100Escape("[7m"); }
99 void vt100DisableNegative() { vt100Escape("[27m"); }
100 void vt100ShowCursor() { vt100Escape("[?25h"); }
101 void vt100HideCursor() { vt100Escape("[?25l"); }
102 void vt100GetScreenSize(int * v, int * h) {
103 #ifdef _WIN32
104     CONSOLE_SCREEN_BUFFER_INFO csbi;
105     GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi);
106     *h = csbi.srWindow.Right - csbi.srWindow.Left + 1;
107     *v = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
108 #else
109     struct winsize w;
110     ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
111     *h = w.ws_col;
112     *v = w.ws_row;
113 #endif
114 }
115
116 // Node
117
118 typedef enum NodeKind {
119     NK_Namespace,
120     NK_Struct,
121     NK_Func,
122     NK_VarList,
123     NK_ExprList,
124     NK_Var,
125     NK_VarDecl,
126     NK_VarType,
127     NK_Type,
128     NK_Body,
129     NK_If,
130     NK_While,
131     NK_Num,
132     NK_Str,
133     NK_Call,
134     NK_Op,
135
136     NK_COUNT
137 } NodeKind;
138
139 const char *NK_STRINGS[NK_COUNT] = {
140     "NK_Namespace",
141     "NK_Struct",
142     "NK_Func",
143     "NK_VarList",
144     "NK_ExprList",
145     "NK_Var",
146     "NK_VarDecl",
147     "NK_VarType",
148     "NK_Type",
149     "NK_Body",
150     "NK_If",
151     "NK_While",
152     "NK_Num",
153     "NK_Str",
154     "NK_Call",
155     "NK_Op",
156 };
157
158 typedef struct Node Node;
159 struct Node {
160     NodeKind kind;
161     void * data;
162
163     int childCount;
164     Node *next, *prev, *prnt, *chld;
165 };
166
167 Node *NodeGetChild(Node *n, unsigned int index) {
168     if (index >= n->childCount)
169         return NULL;
170     
171     Node *result = n->chld;
172     for (int i = 0; i < index; i++)
173         result = result->next;
174     return result;
175 }
176
177 void NodeAppend(Node *n1, Node *n2) {
178     if (n1->childCount == 0) {
179         n1->chld = n2;
180     }
181     else {
182         Node *lastChild = NodeGetChild(n1, n1->childCount-1);
183
184         lastChild->next = n2;
185         n2->prev = lastChild;
186         n2->next = NULL;
187     }
188     n2->prnt = n1;
189     n1->childCount += 1;
190 }
191
192 void NodeInsert(Node *n1, Node *n2, unsigned int index) {
193     if (index >= n1->childCount-1) {
194         NodeAppend(n1, n2);
195         return;
196     }
197
198     Node *insertAfter = NodeGetChild(n1, index);
199     Node *insertBefore = NodeGetChild(n1, index+1);
200
201     insertAfter->next = n2;
202     insertBefore->prev = n2;
203     n2->prev = insertAfter;
204     n2->next = insertBefore;
205
206     n1->childCount += 1;
207 }
208
209 Node *NodeRemove(Node *n1, Node *n2) {
210     if (n1 == NULL)
211         return n2;
212     
213     Node *prev = n2->prev;
214     Node *next = n2->next;
215
216     if (prev != NULL)
217         prev->next = next;
218     if (next != NULL)
219         next->prev = prev;
220     
221     n2->prev = n2->next = n2->prnt = NULL;
222
223     if (n2 == n1->chld)
224         n1->chld = next;
225
226     n1->childCount -= 1;
227     
228     if (prev == NULL)
229         return n1;
230     else
231         return prev;
232 }
233
234 void NodeDraw(Node *n);
235 Node *g_NodeDrawSelected;
236
237 void Printf(Node *n, char* format, ...)
238 {
239   va_list argp;
240   va_start(argp, format);
241   while (*format != '\0') {
242     if (*format == '%') {
243       format++;
244       if (*format == '%') {
245         putchar('%');
246       } else if (*format == 'n') {
247         Node *n = va_arg(argp, Node*);
248         NodeDraw(n);
249       } else if (*format == 's') {
250         char *s = va_arg(argp, char*);
251         printf("%s", s);
252         if (g_NodeDrawSelected == n && s == n->data)
253             printf("%c", ' ');
254       } else if (*format == ',' && format[1] == 'n') {
255         Node *n = va_arg(argp, Node*);
256         for (int i = 0; i < n->childCount; i++) {
257             if (i > 0) printf(", ");
258             NodeDraw(NodeGetChild(n, i));
259         }
260         format++;
261       } else if (*format == ';' && format[1] == 'n') {
262         Node *n = va_arg(argp, Node*);
263         for (int i = 0; i < n->childCount; i++) {
264             if (i == 0) printf("\n");
265             NodeDraw(NodeGetChild(n, i));
266             printf("\n");
267         }
268         format++;
269       } else {
270         fputs("Not implemented", stderr);
271       }
272     } else if (*format == '_') {
273         static bool highlighted = false;
274         // Node *n = va_arg(argp, Node*);
275         if (highlighted) {
276             vt100DisableNegative();
277             highlighted = false;
278         }
279         else if (g_NodeDrawSelected == n) {
280             vt100EnableNegative();
281             highlighted = true;
282         }
283     } else {
284       putchar(*format);
285     }
286     format++;
287   }
288   va_end(argp);
289 }
290
291 void NodeDraw(Node *n) {
292     static int indent = 0;
293     #define INDENT printf("\n"); for (int i = 0; i < indent; i++) printf("  ");
294     
295     #define PRINTF(...) do { if (n == g_NodeDrawSelected) vt100EnableNegative(); printf(__VA_ARGS__); vt100DisableNegative(); } while(0);
296
297     switch (n->kind) {
298     case NK_Namespace: { Printf(n, "_namespace %s {_%;n_}_\n", n->data, n); break; }
299     case NK_Struct:    { Printf(n, "_struct %s {_%;n_}_\n", n->data, n); break; }
300     case NK_Func:      { Printf(n, "_fn %s_ %n %n", n->data, NodeGetChild(n, 0), NodeGetChild(n, 1)); break; }
301     case NK_VarList:
302     case NK_ExprList:  { Printf(n, "_(_%,n_)_", n); break; }
303     case NK_Var:       { Printf(n, "_%s_", n->data); break; }
304     case NK_VarDecl:   { Printf(n, "_%s:_ %n", n->data, NodeGetChild(n, 0)); break; }
305     case NK_VarType:
306     case NK_Type:      { Printf(n, "_%s%s%,n%s_", n->data, (n->childCount > 0 ? "<" : ""), n, (n->childCount > 0 ? ">" : "")); break; }
307     case NK_Body:      { Printf(n, "_{_%;n_}_", n); break; }
308     case NK_If:        { Printf(n, "_if_ %n %n", NodeGetChild(n, 0), NodeGetChild(n, 1)); break; }
309     case NK_While:     { Printf(n, "_while_ %n %n", NodeGetChild(n, 0), NodeGetChild(n, 1)); break; }
310     case NK_Num:       { Printf(n, "_%s_", n->data); break; }
311     case NK_Str:       { Printf(n, "_'%s'_", n->data); break; }
312     case NK_Call:      { Printf(n, "_%s_(%n)", n->data, NodeGetChild(n, 0)); break; }
313     case NK_Op:        { for (int i = 0; i < n->childCount; i++) { if (n->childCount == 0 || i != 0) { Printf(n, " _%s_ ", n->data); } NodeDraw(NodeGetChild(n, i)); } break; }
314     }
315 }
316
317 // Input
318
319 #define KEY_CTRL_C 3
320 #define KEY_BACKSPACE1 8
321 #define KEY_BACKSPACE2 127
322
323 typedef enum Input {
324     IN_None,
325
326     IN_H,
327     IN_J,
328     IN_K,
329     IN_L,
330
331     IN_SPACE,
332     IN_D,
333     IN_A,
334
335     IN_F,
336     IN_V,
337     IN_T,
338     IN_I,
339     IN_W,
340     IN_N,
341     IN_S,
342     IN_C,
343     IN_O,
344
345     IN_Quit,
346
347     IN_COUNT
348 } Input;
349
350 const char *IN_STRINGS[IN_COUNT] = {
351     "IN_None",
352
353     "IN_H",
354     "IN_J",
355     "IN_K",
356     "IN_L",
357
358     "IN_SPACE",
359     "IN_D",
360     "IN_A",
361
362     "IN_F",
363     "IN_V",
364     "IN_T",
365     "IN_I",
366     "IN_W",
367     "IN_N",
368     "IN_S",
369     "IN_C",
370     "IN_O",
371
372     "IN_Quit",
373 };
374
375 Input InputGet() {
376     int c;
377
378     while (true) {
379         c = getch();
380         switch (c) {
381             case 'h': return IN_H;
382             case 'j': return IN_J;
383             case 'k': return IN_K;
384             case 'l': return IN_L;
385
386             case ' ': return IN_SPACE;
387             case 'd': return IN_D;
388             
389             case 'f': return IN_F;
390             case 'v': return IN_V;
391             case 't': return IN_T;
392             case 'i': return IN_I;
393             case 'w': return IN_W;
394             case 'n': return IN_N;
395             case 's': return IN_S;
396             case 'c': return IN_C;
397             case 'o': return IN_O;
398
399             case 'q': return IN_Quit;
400         }
401     }
402 }
403
404 typedef enum InputAction {
405     IA_None,
406
407     IA_MoveLeft,
408     IA_MoveUp,
409     IA_MoveDown,
410     IA_MoveRight,
411
412     IA_StartEditing,
413     IA_Delete,
414
415     IA_AddNamespace,
416     IA_AddStruct,
417     IA_AddFunc,
418     IA_AddVar,
419     IA_AddVarDecl,
420     IA_AddType,
421     IA_AddIf,
422     IA_AddWhile,
423     IA_AddNum,
424     IA_AddStr,
425     IA_AddCall,
426     IA_AddOp,
427
428     IA_COUNT
429 } InputAction;
430
431 const char *IA_STRINGS[IA_COUNT] = {
432     "IA_None",
433
434     "IA_MoveLeft",
435     "IA_MoveUp",
436     "IA_MoveDown",
437     "IA_MoveRight",
438
439     "IA_StartEditing",
440     "IA_Delete",
441
442     "IA_AddNamespace",
443     "IA_AddStruct",
444     "IA_AddFunc",
445     "IA_AddVar",
446     "IA_AddVarDecl",
447     "IA_AddType",
448     "IA_AddIf",
449     "IA_AddWhile",
450     "IA_AddNum",
451     "IA_AddStr",
452     "IA_AddCall",
453     "IA_AddOp",
454 };
455
456 typedef enum InputMode {
457     IM_Normal,
458     IM_Editing,
459 } InputMode;
460
461 void DrawInfo(InputAction actions[NK_COUNT][IN_COUNT], NodeKind nk, InputMode mode) {
462     int v, h;
463     vt100GetScreenSize(&v, &h);
464
465     int line = 2;
466
467     vt100CursorPos(line++, h-30);
468     printf("%d:%d", v, h);
469     vt100CursorPos(line++, h-30);
470
471     printf("%s:%s", NK_STRINGS[nk], (mode == IM_Normal ? "" : " (editing)"));
472
473     for (int i = IN_L+1; i < IN_COUNT; i++) {
474         InputAction action = actions[nk][i];
475         if (action != IA_None) {
476             vt100CursorPos(line++, h-30);
477             printf("%s %s", IN_STRINGS[i], IA_STRINGS[action]);
478         }
479     }
480 }
481
482 bool ValidChar(NodeKind nk, int c) {
483     const char *allow = NULL;
484     const char *block = NULL;
485     
486     switch (nk) {
487     case NK_Namespace:
488     case NK_Struct:
489     case NK_Func:
490     case NK_Var:
491     case NK_VarDecl:
492     case NK_VarType:
493     case NK_Type:
494     case NK_Str:
495     case NK_Call:
496     case NK_Op:
497         block = "";
498         break;
499        
500     case NK_Num:
501         allow = "+-.0123456789";
502         break;
503
504     case NK_VarList:
505     case NK_ExprList:
506     case NK_Body:
507     case NK_If:
508     case NK_While:
509         allow = "";
510         break;
511     }
512
513     if (allow != NULL) {
514         char a;
515         for (int i = 0; (a = allow[i]) != '\0'; i++) {
516             if (a == c) return true;
517         }
518         return false;
519     }
520     else if (block != NULL) {
521         char b;
522         for (int i = 0; (b = block[i]) != '\0'; i++) {
523             if (b == c) return false;
524         }
525         return true;
526     }
527     else {
528         return false;
529     }
530 }
531
532 Node *PopEditQueue(Node ** q) {
533     Node *result = q[0];
534     for (int i = 0; i < EDIT_QUEUE_SIZE-1 && q[i] != NULL; i++) {
535         q[i] = q[i+1];
536     }
537     return result;
538 }
539
540 Node *GetNode(InputAction actions[NK_COUNT][IN_COUNT]) {
541     Node *result = NEW(Node); result->data = NEWSTR; result->kind = NK_Namespace;
542
543     Node * n = result;
544     Node * q[EDIT_QUEUE_SIZE] = {0};
545
546     Input in;
547     InputAction action;
548
549     InputMode mode = IM_Normal;
550
551     while (true) {
552         vt100ClearScreen();
553         vt100CursorHome();
554         g_NodeDrawSelected = n;
555         NodeDraw(result);
556         g_NodeDrawSelected = NULL;
557         DrawInfo(actions, n->kind, mode);
558
559         if (mode == IM_Editing) {
560             int c = getch();
561             char *s = (char*)n->data;
562             int slen = strlen(s);
563             
564             if (c == KEY_BACKSPACE1 || c == KEY_BACKSPACE2) {
565                 s[slen-1] = '\0';
566             }
567             else if (c == '\n' || c == '\r') {
568                 if (q[0] == NULL)
569                     mode = IM_Normal;
570                 else
571                     n = PopEditQueue(q);
572             }
573             else if (slen < STR_SIZE && ValidChar(n->kind, c)) {
574                 s[slen++] = (char)c;
575             }
576         }
577         else if (mode == IM_Normal) {
578             in = InputGet();
579
580             if (in == IN_Quit)
581                 break;
582
583             action = actions[n->kind][in];
584
585             #define N(NAME, PARENT, KIND) Node *NAME = NEW(Node); NAME->kind = KIND; NodeAppend(PARENT, NAME);
586             #define S(NAME, PARENT, KIND) Node *NAME = NEW(Node); NAME->kind = KIND; NAME->data = NEWSTR; NodeAppend(PARENT, NAME);
587
588             switch (action) {
589             case IA_MoveLeft:  { if (n->prev != NULL) n = n->prev; break; }
590             case IA_MoveDown:  { if (n->chld != NULL) n = n->chld; break; }
591             case IA_MoveUp:    { if (n->prnt != NULL) n = n->prnt; break; }
592             case IA_MoveRight: { if (n->next != NULL) n = n->next; break; }
593             
594             case IA_StartEditing: { mode = IM_Editing; break; }
595             case IA_Delete:       { n = NodeRemove(n->prnt, n); break; }
596
597             case IA_AddNamespace: { S(n1, n, NK_Namespace) n=n1;    mode=IM_Editing; break; }
598             case IA_AddStruct:    { S(n1, n, NK_Struct)    n=n1;    mode=IM_Editing; break; }
599             case IA_AddFunc:      { S(n1, n, NK_Func)
600                                     N(n2, n1, NK_VarList)
601                                     N(n3, n1, NK_Body)     n=n1;    mode=IM_Editing; break; }
602             case IA_AddVar:       { S(n1, n, NK_Var)       n=n1;    mode=IM_Editing; break; }
603             case IA_AddVarDecl:   { S(n1, n, NK_VarDecl)   n=n1;
604                                     S(n2, n1, NK_VarType)  q[0]=n2; mode=IM_Editing; break; }
605             case IA_AddType:      { S(n1, n, NK_Type)      n=n1;    mode=IM_Editing; break; }
606             case IA_AddIf:        { N(n1, n, NK_If)
607                                     N(n2, n1, NK_ExprList)
608                                     N(n3, n1, NK_Body)     n=n2;                     break; }
609             case IA_AddWhile:     { N(n1, n, NK_While)
610                                     N(n2, n1, NK_ExprList)
611                                     N(n3, n1, NK_Body)     n=n2;                     break; }
612             case IA_AddNum:       { S(n1, n, NK_Num)       n=n1;    mode=IM_Editing; break; }
613             case IA_AddStr:       { S(n1, n, NK_Str)       n=n1;    mode=IM_Editing; break; }
614             case IA_AddCall:      { S(n1, n, NK_Call)
615                                     N(n2, n1, NK_ExprList) n=n1;    mode=IM_Editing; break; }
616             case IA_AddOp:        { S(n1, n, NK_Op)        n=n1;    mode=IM_Editing; break; }
617             }
618
619             #undef N
620             #undef S
621         }
622     }
623
624     return result;
625 }
626
627
628 void SetupInputActions(InputAction actions[NK_COUNT][IN_COUNT]) {
629     for (int i = 0; i < NK_COUNT; i++) {
630         actions[i][IN_H] = IA_MoveLeft;
631         actions[i][IN_J] = IA_MoveDown;
632         actions[i][IN_K] = IA_MoveUp;
633         actions[i][IN_L] = IA_MoveRight;
634     }
635
636     actions[NK_Namespace][IN_D] = IA_Delete;
637     actions[NK_Namespace][IN_SPACE] = IA_StartEditing;
638     actions[NK_Namespace][IN_N] = IA_AddNamespace;
639     actions[NK_Namespace][IN_S] = IA_AddStruct;
640     actions[NK_Namespace][IN_F] = IA_AddFunc;
641     
642     actions[NK_Struct][IN_D] = IA_Delete;
643     actions[NK_Struct][IN_SPACE] = IA_StartEditing;
644     actions[NK_Struct][IN_V] = IA_AddVarDecl;
645     actions[NK_Struct][IN_F] = IA_AddFunc;
646
647     actions[NK_Func][IN_D] = IA_Delete;
648     actions[NK_Func][IN_SPACE] = IA_StartEditing;
649
650     actions[NK_VarList][IN_V] = IA_AddVarDecl;
651     
652     actions[NK_ExprList][IN_V] = IA_AddVar;
653     actions[NK_ExprList][IN_I] = IA_AddIf;
654     actions[NK_ExprList][IN_W] = IA_AddWhile;
655     actions[NK_ExprList][IN_N] = IA_AddNum;
656     actions[NK_ExprList][IN_S] = IA_AddStr;
657     actions[NK_ExprList][IN_C] = IA_AddCall;
658     actions[NK_ExprList][IN_O] = IA_AddOp;
659
660     actions[NK_Var][IN_D] = IA_Delete;
661     actions[NK_Var][IN_SPACE] = IA_StartEditing;
662
663     actions[NK_VarDecl][IN_D] = IA_Delete;
664     actions[NK_VarDecl][IN_SPACE] = IA_StartEditing;
665
666     actions[NK_VarType][IN_SPACE] = IA_StartEditing;
667     actions[NK_VarType][IN_T] = IA_AddType;
668
669     actions[NK_Type][IN_D] = IA_Delete;
670     actions[NK_Type][IN_SPACE] = IA_StartEditing;
671     actions[NK_Type][IN_T] = IA_AddType;
672
673     actions[NK_Body][IN_F] = IA_AddFunc;
674     actions[NK_Body][IN_V] = IA_AddVarDecl;
675     actions[NK_Body][IN_I] = IA_AddIf;
676     actions[NK_Body][IN_W] = IA_AddWhile;
677     actions[NK_Body][IN_N] = IA_AddNum;
678     actions[NK_Body][IN_S] = IA_AddStr;
679     actions[NK_Body][IN_C] = IA_AddCall;
680     actions[NK_Body][IN_O] = IA_AddOp;
681
682     actions[NK_If][IN_D] = IA_Delete;
683
684     actions[NK_While][IN_D] = IA_Delete;
685
686     actions[NK_Num][IN_D] = IA_Delete;
687     actions[NK_Num][IN_SPACE] = IA_StartEditing;
688
689     actions[NK_Str][IN_D] = IA_Delete;
690     actions[NK_Str][IN_SPACE] = IA_StartEditing;
691
692     actions[NK_Call][IN_D] = IA_Delete;
693     actions[NK_Call][IN_SPACE] = IA_StartEditing;
694
695     actions[NK_Op][IN_D] = IA_Delete;
696     actions[NK_Op][IN_SPACE] = IA_StartEditing;
697     actions[NK_Op][IN_V] = IA_AddVar;
698     actions[NK_Op][IN_I] = IA_AddIf;
699     actions[NK_Op][IN_W] = IA_AddWhile;
700     actions[NK_Op][IN_N] = IA_AddNum;
701     actions[NK_Op][IN_S] = IA_AddStr;
702     actions[NK_Op][IN_C] = IA_AddCall;
703     actions[NK_Op][IN_O] = IA_AddOp;
704 }
705
706 int main() {
707     // Setup
708     static InputAction actions[NK_COUNT][IN_COUNT];
709     SetupInputActions(actions);
710
711     // Main
712     vt100EnableAlternateBuffer();
713     vt100HideCursor();
714
715     Node *n = GetNode(actions);
716
717     vt100DisableAlternateBuffer();
718     vt100ShowCursor();
719
720     NodeDraw(n);
721     printf("\n");
722
723     return 0;
724 }