root/05/release-0.5k/sgfpars.cc

Revision 65, 21.6 kB (checked in by ug, 5 years ago)

Another typo

Line 
1 // File: sgfpars.cc
2
3 //   Copyright (C) 2001-4 Ulrich Goertz (u@g0ertz.de)
4
5 //   This is part of Kombilo, a go database program.
6
7 //   This program is free software; you can redistribute it and/or modify
8 //   it under the terms of the GNU General Public License as published by
9 //   the Free Software Foundation; either version 2 of the License, or
10 //   (at your option) any later version.
11
12 //   This program is distributed in the hope that it will be useful,
13 //   but WITHOUT ANY WARRANTY; without even the implied warranty of
14 //   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 //   GNU General Public License for more details.
16
17 //   You should have received a copy of the GNU General Public License
18 //   along with this program (see doc/license.txt); if not, write to the Free Software
19 //   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20 //   The GNU GPL is also currently available at
21 //   http://www.gnu.org/copyleft/gpl.html
22
23
24
25 #include "sgfpars.h"
26 // #include <cstring>
27
28 intN::intN(int i, intN* p) {
29   data = i;
30   prev = p;
31 }
32
33 IntStack::IntStack() {
34   root = 0;
35 }
36
37 void IntStack::push(int i) {
38   intN* n = new intN(i, root);
39   root = n;
40 }
41
42 void IntStack::pop() {
43   intN* d = root;
44   root = d->prev;
45   delete d;
46 }
47
48 int IntStack::top() {
49   if (root) return root->data;
50   else return -1;
51 }
52
53 bool IntStack::nonempty() {
54   if (root) return 1;
55   else return 0;
56 }
57
58
59 nodeN::nodeN(Node* i, nodeN* p) {
60   data = i;
61   prev = p;
62 }
63
64 NodeStack::NodeStack() {
65   root = 0;
66 }
67
68 void NodeStack::push(Node* i) {
69   nodeN* n = new nodeN(i, root);
70   root = n;
71 }
72
73 void NodeStack::pop() {
74   nodeN* d = root;
75   root = d->prev;
76   delete d;
77 }
78
79 Node* NodeStack::top() {
80   if (root) return root->data;
81   else return 0;
82 }
83
84 bool NodeStack::nonempty() {
85   if (root) return 1;
86   else return 0;
87 }
88
89
90
91
92 SGFError::SGFError() {}
93
94 char* SGFescape(char* s) {
95   char* t = new char[2*strlen(s)+1];
96   int j = 0;
97   for(int i = 0; i<strlen(s); i++) {
98     if (s[i] == '\\' || s[i] == ']') t[j++]='\\';
99     t[j++] = s[i];
100   }
101                                    
102   t[j++] = 0;
103
104   char* result = new char[j];
105   strcpy(result, t);
106   delete t;
107   return result;
108 }
109
110 Node::Node(Node* prev, char* SGFst, int lvl=0) throw(SGFError) {
111   next = NULL;
112   previous = prev;
113   up = NULL;
114   down = NULL;
115
116   numChildren = 0;
117   level = lvl;
118        
119   parsed = 0;
120
121   if (SGFst) {
122     SGFstring = new char[strlen(SGFst)+1];
123     strcpy(SGFstring, SGFst);
124     if (!(data=PyDict_New())) throw SGFError();
125     parseNode();
126   }
127   else {
128     SGFstring = new char[1];
129     SGFstring[0] = 0;
130     if (!(data = PyDict_New())) throw SGFError();
131   }
132    
133   posyD = 0;
134 }
135        
136 Node::~Node() {
137   delete [] SGFstring;
138   Py_DECREF(data);
139 }
140
141
142 PyObject* Node::getData() {
143   if (!parsed) parseNode();
144   Py_INCREF(data);
145   return data;
146 }
147
148 PyObject* Node::pathToNode() {
149   PyObject* l = PyList_New(0);
150   Node* n = this;
151
152   while (n->previous) {
153     PyList_Append(l, PyInt_FromLong(n->level));
154     n = n->previous;
155   }       
156   PyList_Reverse(l);
157   return l;
158 }
159
160
161 void Node::parseNode() throw(SGFError) {
162   // printf("Parse node, %s\n", SGFstring);
163
164   if (!parsed) {
165
166     char* s = SGFstring;
167     int lSGFstring = strlen(s);
168     int i = 0;
169    
170     while (i < lSGFstring && s[i] != ';' && (s[i]==' ' || s[i]=='\n' || s[i]=='\r' || s[i]=='\t'))
171       i++;
172    
173     if (i>=lSGFstring) {
174       throw SGFError();
175     }
176     if (s[i] != ';') {
177       throw SGFError();
178     }
179     i++;
180    
181     while (i < lSGFstring) {
182       while (i < lSGFstring && (s[i]==' ' || s[i]=='\n' || s[i]=='\r' || s[i]=='\t'))
183         i++;
184      
185       if (i >= lSGFstring) break;
186      
187       char ID[20];
188       int IDindex = 0;
189      
190       while (i < lSGFstring && s[i] != '[') {
191         if (65 <= s[i] && s[i] <= 90)
192           ID[IDindex++] = s[i];
193         else if (!(97 <= s[i] && s[i] <= 122) && !(s[i]==' ' || s[i]=='\n' || s[i]=='\r' || s[i]=='\t')) {
194           throw SGFError();
195         }
196        
197         i++;
198       }
199      
200       i++;
201      
202       if (i >= lSGFstring) {
203         throw SGFError();
204       }
205      
206       if (!IDindex) {
207         throw SGFError();
208       }
209       ID[IDindex] = 0;
210      
211       if (PyDict_GetItemString(data, ID)) {
212         if (!Node::sloppy) {
213           throw SGFError();
214         }
215       }
216       else {
217         PyObject* nl = PyList_New(0);
218         if (!nl) {
219           throw SGFError();
220         }
221         if (PyDict_SetItemString(data, ID, nl)==-1) {
222           throw SGFError();
223         }
224         Py_DECREF(nl);
225       }
226      
227       PyObject* propertyValueList = PyDict_GetItemString(data, ID);
228       if (!propertyValueList) {
229         throw SGFError();
230       }
231      
232       while (i < lSGFstring) {
233         char* propValue = new char[lSGFstring+1];
234         int propValueIndex = 0;
235        
236         while (s[i] != ']') {
237          
238           //printf("i, s[i]: %d, %c\n", i, s[i]);
239           if (s[i] == '\t') {
240             propValue[propValueIndex++] = ' ';
241             i++;
242             continue;
243           }
244           if (s[i] == '\\') {
245             i++;
246            
247             if ((s[i]=='\n' && s[i+1]=='\r') || (s[i]=='\r' && s[i+1]=='\n')) {
248               i += 2;
249               continue;
250             }
251             else if (s[i]=='\n' || s[i]=='\r') {
252               i++;
253               continue;
254             }
255           }
256           propValue[propValueIndex++] = s[i];
257           i++;
258          
259           if (i >= lSGFstring) {
260             throw SGFError();
261           }
262         }
263        
264         propValue[propValueIndex] = 0;
265         PyObject* hlp = PyString_FromString(propValue);
266         PyList_Append(propertyValueList, hlp);
267         delete [] propValue;
268         Py_DECREF(hlp);
269        
270         i++;
271        
272         while (i < lSGFstring && (s[i]==' ' || s[i]=='\n' || s[i]=='\r' || s[i]=='\t'))
273           i++;
274        
275         if (i >= lSGFstring || s[i] != '[') break;
276         else i++;
277       }
278      
279       if (!strcmp(ID, "B") || !strcmp(ID, "W") || !strcmp(ID, "AW") || !strcmp(ID, "AB")) {
280         for(int N=0; N < PyList_Size(propertyValueList); N++) {
281           char* en = PyString_AsString(PyList_GetItem(propertyValueList, N));
282           char* en1 = new char[strlen(en)+1];
283           int jj = 0;
284          
285           for (int ii=0; ii<strlen(en); ii++) {
286             if (!Node::sloppy || !(en[ii]=='\n' || en[ii]=='\r'))
287               en1[jj++] = en[ii];
288           }
289           en1[jj] = 0;
290          
291           if (!(strlen(en1) == 2 || (strlen(en) == 0 && (!strcmp(ID,"B") || !strcmp(ID,"W"))))) {
292             throw SGFError();
293           }
294          
295           PyList_SetItem(propertyValueList, N, PyString_FromString(en1));
296           delete en1;
297         }
298       }                                       
299      
300     }
301     parsed = 1;
302   }
303 }   
304    
305
306 int Node::sloppy = 1;
307
308 Cursor::Cursor(char* sgf, int sloppy) throw(SGFError) {
309   Node::sloppy = sloppy;
310
311   height = 0;
312   width = 0;
313   posx = 0;
314   posy = 0;
315
316   root = new Node(NULL, NULL, 0);
317   parse(sgf);
318
319   currentN = root->next;
320   setFlags();       
321
322   if (!currentN->parsed) currentN->parseNode();
323
324   PyObject* val = PyDict_GetItemString(currentN->data, "CA");
325   PyObject* v = 0;
326
327   if (val && PyList_Check(val) && PyList_Size(val)) v = PyList_GetItem(val, 0);
328   if (v && PyString_Check(v)) {
329     char* s = PyString_AsString(v);
330     encoding = new char[strlen(s)+1];
331     strcpy(encoding, s);
332   }
333   else {
334     encoding = new char[1];
335     encoding[0] = 0;
336   }
337 }
338
339
340
341 Cursor::~Cursor() {
342   deltree(root);
343   delete [] encoding;
344 }
345
346 void Cursor::setFlags() {
347   if (currentN->next) atEnd = 0;
348   else atEnd = 1;
349   if (currentN->previous) atStart = 0;
350   else atStart = 1;
351 }
352  
353 int Cursor::noChildren() {
354   return currentN->numChildren;
355 }
356
357 PyObject* Cursor::currentNode() {
358   if (!currentN->parsed)
359     currentN->parseNode();
360
361   Py_INCREF(currentN->data);
362   return currentN->data;
363 }
364
365 void Cursor::parse(char* s) throw(SGFError) {
366
367   Node* curr = root;       
368   int p = -1;           // start of the currently parsed node
369   NodeStack c;       // stack of nodes from which variations started
370   IntStack c_width;
371   IntStack c_height;
372
373   int height_previous = 0;
374   int width_currentVar = 0;
375
376   char last = ')';      // type of last parsed bracked ('(' or ')')
377   bool inbrackets = false;   // are the currently parsed characters in []'s?
378
379   int i = 0;  // current parser position
380   int lSGFstring = strlen(s);
381
382   int found_par = 0;
383   while (i < lSGFstring) {
384     if (s[i]=='(') {
385       found_par = i+1;
386       i++;
387       continue;
388     }
389     if (found_par && s[i]==';') break;
390    
391     if (found_par && !(s[i]==' ' || s[i]=='\n' || s[i]=='\r' || s[i]=='\t'))
392       found_par = 0;
393     i++;
394   }
395
396   if (i >= lSGFstring) throw SGFError();
397
398   i = found_par-1; // found beginning of SGF file
399         
400   while (i < lSGFstring) {
401     while (i < lSGFstring && !(s[i]=='(' || s[i]==')' || s[i]=='[' || s[i]==']' || s[i]==';')) i++;
402     if (i >= lSGFstring) break;
403
404     if (inbrackets) {
405       if (s[i]==']') {
406         int numberBackslashes = 0;
407         int j = i-1;
408         while (s[j] == '\\') {
409           numberBackslashes++;
410           j--;
411         }
412         if (!(numberBackslashes % 2))
413           inbrackets = 0;
414       }
415       i++;
416       continue;
417     }
418          
419     if (s[i] == '[') inbrackets = 1;
420        
421     if (s[i] == '(') {
422       if (last != ')' && p != -1) {
423         delete[] curr->SGFstring;
424         curr->SGFstring = new char[i-p+1];
425         curr->SGFstring = strncpy(curr->SGFstring, s+p, i-p);       
426         curr->SGFstring[i-p] = 0;
427         // curr->parseNode();
428       }
429
430       Node* nn = new Node(0,0,0);
431       nn->previous = curr;
432
433       if (++width_currentVar > width) width = width_currentVar;
434       if (curr->next) {
435         Node* last = curr->next;
436         while (last->down) last = last->down;
437         nn->up = last;                                 
438         last->down = nn;
439         nn->level = last->level + 1;
440         height++;
441         nn->posyD = height - height_previous;
442       }
443       else {
444         curr->next = nn;
445         nn->posyD = 0;
446         height_previous = height;
447       }
448
449       curr->numChildren++;
450      
451       c.push(curr);
452       c_width.push(width_currentVar-1);
453       c_height.push(height);
454          
455       curr = nn;
456                
457       p = -1;
458       last = '(';
459     }
460
461     if (s[i] == ')') {
462       if (last != ')' && p != -1) {
463         delete[] curr->SGFstring;
464         curr->SGFstring = new char[i-p+1];
465         curr->SGFstring = strncpy(curr->SGFstring, s+p, i-p);       
466         curr->SGFstring[i-p] = 0;
467         // curr->parseNode();
468       }
469       if (c.nonempty()) {
470         curr = c.top();
471         c.pop();
472         width_currentVar = c_width.top();
473         c_width.pop();
474         height_previous = c_height.top();
475         c_height.pop();
476       }
477       else {
478         throw SGFError();
479       }
480       last = ')';
481     }
482    
483     if (s[i] == ';') {
484       if (p != -1) {
485         delete[] curr->SGFstring;
486         curr->SGFstring = new char[i-p+1];
487         curr->SGFstring = strncpy(curr->SGFstring, s+p, i-p);       
488         curr->SGFstring[i-p] = 0;
489         // curr->parseNode();
490
491         Node* nn = new Node(0,0,0);
492         nn->previous = curr;
493
494         if (++width_currentVar > width) width = width_currentVar;
495         nn->posyD = 0;
496         curr->numChildren = 1;
497         curr->next = nn;
498         curr = nn;
499       }
500       p = i;
501     }
502
503     i++;
504   }
505
506   if (inbrackets || c.nonempty()) throw SGFError();
507  
508   Node* n = curr->next;
509   n->previous = NULL;
510   n->up = NULL;
511
512   while (n->down) {
513     n = n->down;
514     n->previous = NULL;
515   }
516 }
517
518 void Cursor::game(int n) throw(SGFError) {
519   if (n < root->numChildren) {
520     posx = 0;
521     posy = 0;
522     currentN = root->next;
523     for(int i=0; i<n; i++) currentN = currentN->down;
524     setFlags();
525   }
526   else throw SGFError();
527 }
528
529
530
531
532 void Cursor::deltree(Node* node) {
533   Node* n;
534
535   if (node->next) {
536     n = node->next;
537
538     while (n->down) {
539       n = n->down;
540       deltree(n->up);
541     }
542
543     deltree(n);
544   }
545
546   delete node;
547 }
548
549
550
551
552 void Cursor::delVariation(Node* c) {
553
554   if (c->previous) {
555     delVar(c);
556   }
557   else {
558     if (c->next) {
559       Node* node = c->next;
560       while (node->down) {
561         node = node->down;
562         delVar(node->up);
563       } 
564       delVar(node);
565     }
566     c->next = 0;
567   }
568
569   setFlags();
570 }
571
572 void Cursor::delVar(Node* node) {
573
574   if (node->up) node->up->down = node->down;
575   else {
576     node->previous->next = node->down;
577   }
578   if (node->down) {
579     node->down->up = node->up;
580     node->down->posyD = node->posyD;
581     Node* n = node->down;
582     while (n) {
583       n->level--;
584       n = n->down;
585     }
586   }
587
588   int h = 0;
589   Node* n = node;
590   while (n->next) {
591     n = n->next;
592     while (n->down) {
593       n = n->down;
594       h += n->posyD;
595     }
596   }
597
598   if (node->up || node->down) h++;
599
600   Node* p = node->previous;
601   p->numChildren--;
602
603   while (p) {
604     if (p->down) p->down->posyD -= h;
605     p = p->previous;
606   }
607
608   height -= h;
609
610   // p = node->down;
611   deltree(node);
612   // node = 0;
613 }
614
615
616 void Cursor::add(char* st) {
617
618   Node* node = new Node(currentN,st,0);
619
620   node->down = 0;
621   node->next = 0;
622   node->numChildren = 0;
623
624   if (!currentN->next) {
625     // printf("new %s at %s\n", node->SGFstring, currentN->SGFstring);
626     node->level = 0;
627     node->posyD = 0;
628     node->up = 0;
629
630     currentN->next = node;
631     currentN->numChildren = 1;
632   }
633   else {
634     // printf("adding %s at %s\n", node->SGFstring, currentN->SGFstring);
635     Node* n = currentN->next;
636     while (n->down) {
637       n = n->down;
638       posy+=n->posyD;
639     }
640    
641     n->down = node;
642     node->up = n;
643     node->level = n->level + 1;
644     node->next= 0;
645     currentN->numChildren++;
646
647     node->posyD = 1;
648     while (n->next) {
649       n = n->next;
650       while (n->down) {
651         n = n->down;
652         node->posyD += n->posyD;
653       }
654     }
655     posy += node->posyD;
656
657     height++;
658
659     n = node;
660     while (n->previous) {
661       n = n->previous;
662       if (n->down) n->down->posyD++;
663     }
664
665   }
666
667   currentN = node;
668
669   posx++;
670   setFlags();
671
672   if (posx > width) width++;
673
674 }
675
676
677 PyObject* Cursor::next(int n) throw(SGFError) {
678
679   if (n >= noChildren()) {
680     throw SGFError();
681   }
682   posx++;
683   currentN = currentN->next;
684   for (int i=0; i<n; i++) {
685     currentN = currentN->down;
686     posy += currentN->posyD;
687   }
688   setFlags();
689
690   return currentNode();
691 }
692    
693 PyObject* Cursor::previous() throw(SGFError) {
694   if (currentN->previous) {
695     while (currentN->up) {
696       posy -= currentN->posyD;
697       currentN = currentN->up;
698     }
699     currentN = currentN->previous;
700     posx--;
701   }
702   else throw SGFError();
703   setFlags();
704   return currentNode();
705 }
706
707 PyObject* Cursor::getRootNode(int n) throw(SGFError) {
708   if (!root) {
709     Py_INCREF(Py_None);
710     return Py_None;
711   }
712
713   if (n >= root->numChildren) throw SGFError();
714   Node* nn = root->next;
715   for(int i=0; i<n; i++) nn = nn->down; 
716  
717   if (!nn->parsed) nn->parseNode();
718   Py_INCREF(nn->data);
719   return nn->data;
720 }
721
722
723 void Cursor::updateCurrentNode() throw(SGFError) {
724   delete[] currentN->SGFstring;
725   currentN->SGFstring = nodeToString(currentN->data);
726   if (!currentN->parsed) {
727     currentN->parsed = 1;
728   }
729
730   // Py_DECREF(currentN->data);
731   // if (!(currentN->data=PyDict_New())) throw SGFError();
732   // currentN->parseNode();
733 }
734
735 void Cursor::updateRootNode(PyObject* data, int n) throw(SGFError) {
736   if (n >= root->numChildren) throw SGFError();
737   Node* nn = root->next;
738   for(int i=0; i<n; i++) nn = nn->down;
739   delete[] nn->SGFstring;
740   nn->SGFstring = rootNodeToString(data);
741   Py_DECREF(nn->data);
742   if (!(nn->data=PyDict_New())) throw SGFError();
743   nn->parsed = 0;
744   nn->parseNode();
745 }
746
747
748 char* Cursor::rootNodeToString(PyObject* data) {
749   char result[10000];
750   result[0] = 0;
751   strcat(result, ";");
752  
753   PyObject* item;
754   if ((item=PyDict_GetItem(data, PyString_FromString("GM")))) {
755     strcat(result, "GM[");
756     char* t = SGFescape(PyString_AsString(PyList_GetItem(item, 0)));
757     strcat(result, t);
758     delete[] t;
759     strcat(result, "]\n");
760   }
761   if ((item=PyDict_GetItem(data, PyString_FromString("FF")))) {
762     strcat(result, "FF[");
763     char* t = SGFescape(PyString_AsString(PyList_GetItem(item, 0)));
764     strcat(result, t);
765     delete[] t;
766     strcat(result, "]\n");
767   }
768   if ((item=PyDict_GetItem(data, PyString_FromString("SZ")))) {
769     strcat(result, "SZ[");
770     char* t = SGFescape(PyString_AsString(PyList_GetItem(item, 0)));
771     strcat(result, t);
772     delete[] t;
773     strcat(result, "]\n");
774   }
775   if ((item=PyDict_GetItem(data, PyString_FromString("PW")))) {
776     strcat(result, "PW[");
777     char* t = SGFescape(PyString_AsString(PyList_GetItem(item, 0)));
778     strcat(result, t);
779     delete[] t;
780     strcat(result, "]\n");
781   }
782   if ((item=PyDict_GetItem(data, PyString_FromString("WR")))) {
783     strcat(result, "WR[");
784     char* t = SGFescape(PyString_AsString(PyList_GetItem(item, 0)));
785     strcat(result, t);
786     delete[] t;
787     strcat(result, "]\n");
788   }
789   if ((item=PyDict_GetItem(data, PyString_FromString("PB")))) {
790     strcat(result, "PB[");
791     char* t = SGFescape(PyString_AsString(PyList_GetItem(item, 0)));
792     strcat(result, t);
793     delete[] t;
794     strcat(result, "]\n");
795   }
796   if ((item=PyDict_GetItem(data, PyString_FromString("BR")))) {
797     strcat(result, "BR[");
798     char* t = SGFescape(PyString_AsString(PyList_GetItem(item, 0)));
799     strcat(result, t);
800     delete[] t;
801     strcat(result, "]\n");
802   }
803   if ((item=PyDict_GetItem(data, PyString_FromString("EV")))) {
804     strcat(result, "EV[");
805     char* t = SGFescape(PyString_AsString(PyList_GetItem(item, 0)));
806     strcat(result, t);
807     delete[] t;
808     strcat(result, "]\n");
809   }
810   if ((item=PyDict_GetItem(data, PyString_FromString("RO")))) {
811     strcat(result, "RO[");
812     char* t = SGFescape(PyString_AsString(PyList_GetItem(item, 0)));
813     strcat(result, t);
814     delete[] t;
815     strcat(result, "]\n");
816   }
817   if ((item=PyDict_GetItem(data, PyString_FromString("DT")))) {
818     strcat(result, "DT[");
819     char* t = SGFescape(PyString_AsString(PyList_GetItem(item, 0)));
820     strcat(result, t);
821     delete[] t;
822     strcat(result, "]\n");
823   }
824   if ((item=PyDict_GetItem(data, PyString_FromString("PC")))) {
825     strcat(result, "PC[");
826     char* t = SGFescape(PyString_AsString(PyList_GetItem(item, 0)));
827     strcat(result, t);
828     delete[] t;
829     strcat(result, "]\n");
830   }
831   if ((item=PyDict_GetItem(data, PyString_FromString("KM")))) {
832     strcat(result, "KM[");
833     char* t = SGFescape(PyString_AsString(PyList_GetItem(item, 0)));
834     strcat(result, t);
835     delete[] t;
836     strcat(result, "]\n");
837   }
838   if ((item=PyDict_GetItem(data, PyString_FromString("RE")))) {
839     strcat(result, "RE[");
840     char* t = SGFescape(PyString_AsString(PyList_GetItem(item, 0)));
841     strcat(result, t);
842     delete[] t;
843     strcat(result, "]\n");
844   }
845   if ((item=PyDict_GetItem(data, PyString_FromString("US")))) {
846     strcat(result, "US[");
847     char* t = SGFescape(PyString_AsString(PyList_GetItem(item, 0)));
848     strcat(result, t);
849     delete[] t;
850     strcat(result, "]\n");
851   }
852   if ((item=PyDict_GetItem(data, PyString_FromString("GC")))) {
853     strcat(result, "GC[");
854     char* t = SGFescape(PyString_AsString(PyList_GetItem(item, 0)));
855     strcat(result, t);
856     delete[] t;
857     strcat(result, "]\n");
858   }
859
860   int l = 0;
861
862   PyObject *key, *value;
863   int pos = 0;
864
865   while (PyDict_Next(data, &pos, &key, &value)) {
866     char* s = PyString_AsString(key);
867     if (strcmp(s, "GM") && strcmp(s, "FF") && strcmp(s, "SZ") && strcmp(s, "PW") && strcmp(s, "WR") &&
868         strcmp(s, "PB") && strcmp(s, "BR") && strcmp(s, "EV") && strcmp(s, "RO") && strcmp(s, "DT") &&
869         strcmp(s, "PC") && strcmp(s, "KM") && strcmp(s, "RE") && strcmp(s, "US") && strcmp(s, "GC")) {
870      
871       strcat(result, s);
872
873       for(int k = 0; k < PyList_Size(value); k++) {
874         PyObject* item = PyList_GetItem(value, k);
875         char* t = SGFescape(PyString_AsString(item));
876         strcat(result, "[");
877         strcat(result, t);
878         strcat(result, "]");
879         l += strlen(t) + 2;
880         delete[] t;
881         if (l>72) {
882           strcat(result, "\n");
883           l = 0;
884         }
885       }
886     }
887   }
888   strcat(result, "\n");
889   char* t = new char[strlen(result)+1];
890   strcpy(t, result);
891   return t;
892 }
893
894 char* Cursor::nodeToString(PyObject* data) throw(SGFError) {
895
896   char result[50000];
897   result[0] = 0;
898   strcat(result, ";");
899
900   int l = 0;
901
902   PyObject *key, *value;
903   int pos = 0;
904
905   while (PyDict_Next(data, &pos, &key, &value)) {
906     char* s = PyString_AsString(key);
907    
908     if (!PyList_Check(value)) {
909       throw SGFError();
910     }
911
912     if (PyList_Size(value) == 0) continue;
913  
914     strcat(result, s);
915
916     for(int k = 0; k < PyList_Size(value); k++) {
917       PyObject* item = PyList_GetItem(value, k);
918       if (!PyString_Check(item)) {
919         throw SGFError();
920       }
921
922       char* t = SGFescape(PyString_AsString(item));
923       strcat(result, "[");
924       strcat(result, t);
925       strcat(result, "]");
926       l += strlen(t) + 2;
927       delete[] t;
928       if (l>72) {
929         strcat(result, "\n");
930         l = 0;
931       }
932    
933     }
934   }
935  
936   strcat(result, "\n");
937   // printf("strlen(result) == %d\n", strlen(result));
938   char* t = new char[strlen(result)+1];
939   strcpy(t, result);
940   return t;
941 }
942
943
944 char* Cursor::outputVar(Node* node) {
945   int s = 1000;
946   char* result = new char[s];
947   result[0] = 0;
948
949   if (strlen(node->SGFstring) + strlen(result) >= s-5) {
950     s += 1000 + strlen(node->SGFstring);
951     char* res = new char[s];
952     strcpy(res, result);
953     delete [] result;
954     result = res;
955   }
956
957   strcat(result, node->SGFstring);
958   // printf("%s\n", node->SGFstring);
959
960   while (node->next) {
961     node = node->next;
962     if (node->down) {
963       strcat(result, "(");
964
965       char* r = outputVar(node);
966
967       if (strlen(r) + strlen(result) >= s-5) {
968         s += 1000 + strlen(r);
969         char* res = new char[s];
970         strcpy(res, result);
971         delete [] result;
972         result = res;
973       }
974
975       strcat(result, r);
976       delete [] r;
977
978       while(node->down) {
979         node = node->down;
980         strcat(result, ")(");
981        
982         char* r = outputVar(node);
983
984         if (strlen(r) + strlen(result) >= s-5) {
985           s += 1000 + strlen(r);
986           char* res = new char[s];
987           strcpy(res, result);
988           delete [] result;
989           result = res;
990         }
991        
992         strcat(result, r);
993         delete [] r;
994       }
995       strcat(result, ")");
996       break;
997     }
998     else {
999       if (strlen(node->SGFstring) + strlen(result) >= s) {
1000         s += 1000 + strlen(node->SGFstring);
1001         char* res = new char[s];
1002         strcpy(res, result);
1003         delete [] result;
1004         result = res;
1005       }
1006       strcat(result, node->SGFstring);
1007       // printf("%s\n", node->SGFstring);
1008     }
1009   }
1010
1011   // printf("r: %d \n", strlen(result));
1012
1013   char* t = new char[strlen(result)+1];
1014   strcpy(t, result);
1015
1016   delete result;
1017   return t;
1018 }
1019
1020
1021 char* Cursor::output() {
1022
1023   int s = 2000;
1024   char* result = new char[s];
1025   result[0] = 0;
1026
1027   Node* n = root->next;
1028
1029   while (n) {
1030     char* t = outputVar(n);
1031
1032     if (strlen(t) + strlen(result) >= s-5) {
1033       s += 2000 + strlen(t);
1034       char* res = new char[s];
1035       strcpy(res, result);
1036       delete [] result;
1037       result = res;
1038     }
1039
1040     strcat(result, "(");
1041     strcat(result, t);
1042     strcat(result, ")\n");
1043     delete [] t;   
1044     n = n->down;
1045   } 
1046
1047   char* t = new char[strlen(result)+1];
1048   strcpy(t, result);
1049   delete [] result;
1050   return t;
1051 }
1052
1053
1054
Note: