rework keyframe hide popup, keyframe auto render, textbox set_selection wide text
[goodguy/history.git] / cinelerra-5.1 / db / xsch.C
1 #include <cstdio>
2 #include <cstring>
3 #include <cstdlib>
4 #include <string>
5 #include <list>
6
7 using namespace std;
8
9 #define MAX_LINE_SZ 256
10 #define expect(c) do { if( ch != c ) return -1; ++cp; } while(0)
11
12 class iline {
13 public:
14   FILE *fp;  long pos;
15   char line[MAX_LINE_SZ];
16   int no;
17   iline(FILE *f) : fp(f), pos(0), no(0) {}
18   iline(iline &i) {
19     fp = i.fp;  pos = i.pos;
20     strcpy(line,i.line);  no = i.no;
21   }
22 };
23
24 class ichar : public virtual iline {
25 public:
26   int i, n;
27   ichar(FILE *f) : iline(f) { i = n = 0; }
28   ~ichar() {}
29   ichar tws();
30   char &operator *();
31   char &operator [](int n) { return line[i+n]; }
32   char &operator +=(int n) { i+=n; return operator*(); }
33   char &operator -=(int n) { i-=n; return operator*(); }
34   friend ichar &operator ++(ichar &t);
35   friend char operator ++(ichar &t,int);
36 };
37
38 ichar &operator ++(ichar &t) { ++t.i; return t; }
39 char operator ++(ichar &t,int) { return t.line[t.i++]; }
40
41 char &ichar::operator *()
42 {
43   if( i == n ) {
44     int ch;  fseek(fp, pos, SEEK_SET);
45     for( i=n=0; n<MAX_LINE_SZ; ) {
46       if( (ch=fgetc(fp)) < 0 ) ch = 0;
47       if( (line[n++]=ch) == '\n' || !ch ) break;
48     }
49     if( ch == '\n' ) ++no;
50     pos = ftell(fp);
51   }
52   return line[i];
53 }
54
55 class tobj;
56 class iobj;
57 typedef list<string *> eobjs;
58
59 class dobj {
60 public:
61   tobj *top;
62   string *name;
63   enum { ty_none, ty_bit, ty_boolean,
64     ty_tinyint, ty_smallint, ty_mediumint, ty_decimal,
65     ty_integer, ty_bigint, ty_real, ty_double, ty_float,
66     ty_date, ty_time, ty_timestamp, ty_datetime, ty_year,
67     ty_char, ty_varchar, ty_binary, ty_varbinary,
68     ty_blob, ty_tinyblob, ty_mediumblob, ty_longblob,
69     ty_text, ty_tinytext, ty_mediumtext, ty_longtext,
70     ty_enum, ty_set, ty_media } ty;
71   enum {
72     var_types = (1<<ty_varchar) | (1<<ty_varbinary) | (1<<ty_blob) |
73       (1<<ty_tinyblob) | (1<<ty_mediumblob) | (1<<ty_longblob) |
74       (1<<ty_media),
75     text_types = (1<<ty_text) |
76       (1<<ty_tinytext) | (1<<ty_mediumtext) | (1<<ty_longtext),
77   };
78   int is_var() { return (var_types>>ty) & 1; }
79   int is_text() { return (text_types>>ty) & 1; }
80   int length, zeroed, is_null, is_autoincr, is_binary, is_unsign, has_def;
81   iobj *idx;
82   eobjs eop;
83   enum def_type { def_none, def_integer, def_double, def_string, def_null, };
84   union { int i; double d; string *s; } def;
85   dobj(tobj *tp) : top(tp) {
86     ty = ty_none;  idx = 0;
87     length = zeroed = is_null = is_autoincr = is_binary = is_unsign = has_def = -1;
88   }
89   ~dobj() {}
90 };
91
92 typedef list<dobj*> dobjs;
93
94 class tobj {
95 public:
96   string *name;
97   dobjs dop;
98
99   tobj() : name(0), dop(0) {}
100   ~tobj() {};
101 };
102
103 list<tobj*> tables;
104
105
106 class kobj {
107 public:
108   string *name;
109
110   kobj(string *s) : name(s) {}
111   ~kobj() {};
112 };
113
114 typedef list<kobj> kobjs;
115
116 class iobj {
117 public:
118   string *name;
119   string *tbl;
120   list<string *> keys;
121   short unique;
122   short primary;
123   int length;
124
125   iobj() : name(0), tbl(0), unique(0), primary(0), length(-1) {}
126   ~iobj() {};
127 };
128
129 list<iobj*> indecies;
130
131
132 class robj {
133 public:
134   string *name;
135   enum { xref_no_action, xref_restrict, xref_cascade, xref_set_null, };
136   int on_delete, on_update;
137   list<string *> keys;
138   robj() : on_delete(xref_no_action), on_update(xref_no_action) {}
139   ~robj() {}
140 };
141
142
143 // trim white space
144 ichar &tws(ichar &c)
145 {
146   ichar b = c;
147   for(;;) {
148     if( isspace(*b) ) { ++b; continue; }
149     if( *b == '/' && b[1] == '*' ) {
150       ++b;  do { ++b; } while( *b != '*' || b[1] != '/' );
151       b += 2;  continue;
152     }
153     else if( *b == '-' && b[1] == '-' ) {
154       ++b;  do { ++b; } while( *b != '\n' );
155       ++b;  continue;
156     }
157     break;
158   }
159   c = b;
160   return c;
161 }
162
163 // scan id
164 string *tid(ichar &c, string *sp=0)
165 {
166   string *rp = 0;
167   ichar b = tws(c);
168   if( *b && (isalpha(*b) || *b == '_') ) {
169     rp = !sp ? new string() : sp;
170     rp->push_back(toupper(b++));
171     while( *b && (isalpha(*b) || isdigit(*b) ||  *b == '_') ) {
172       rp->push_back(tolower(b++));
173     }
174   }
175   if( rp ) c = b;
176   return rp;
177 }
178
179 // scan string '..' or ".."
180 int str_value(ichar &cp, string *&sp)
181 {
182   ichar bp = cp;  sp = 0;
183   int ch = *cp;
184   if( ch != '\'' && ch != '"' ) return -1;
185   int delim = ch;  ++cp;
186   for( sp=new string(); (ch=*cp) && ch != delim; ++cp ) {
187     if( ch == '\\' && !(ch=*++cp) ) break;
188     sp->push_back(ch);
189   }
190   if( ch != delim ) {
191     delete sp;  sp = 0;
192     cp = bp;
193     return -1;
194   }
195   ++cp;
196   return 0;
197 }
198
199 // scan string '..' or "..", or number, or NULL
200 int def_value(ichar &cp, dobj *dp)
201 {
202   ichar bp = cp;
203   if( str_value(cp,dp->def.s) >= 0 ) {
204     dp->has_def = dobj::def_string;
205     return 0;
206   }
207   int ch = *tws(cp);
208   if( isdigit(ch) || ch == '-' || ch == '+' ) {
209     int sign = 0;
210     if( ch == '-' ) sign = -1;
211     if( ch == '+' ) sign = 1;
212     if( sign ) ++cp; else sign = 1;
213     int n = 0;
214     while( (ch-='0') >= 0 && ch <= 9 ) {
215       n = n*10 + ch;  ch = *++cp;
216     }
217     if( ch == '.' ) {
218       double v = n;
219       double frac = 1.;
220       while( (ch-='0') >= 0 && ch <= 9 ) {
221         v = v + ch/(frac*=10);  ch = *++cp;
222       }
223       dp->has_def = dobj::def_double;
224       dp->def.d = v * sign;
225     }
226     else {
227       dp->has_def = dobj::def_integer;
228       dp->def.i = n * sign;
229     }
230     return 0;
231   }
232   string *id = tid(cp);
233   if( id ) {
234     if( *id == "Null" ) {
235       dp->has_def = dobj::def_null;
236       dp->def.s = 0;
237       return 0;
238     }
239     delete id;
240   }
241   cp = bp;
242   return -1;
243 }
244
245 // scan (number)
246 int dimen(ichar &cp, dobj *dp)
247 {
248   int n = 0;
249   int ch = *tws(cp);
250   if( ch == '(' ) {
251     ++cp;  ch = *tws(cp);
252     while( (ch-='0') >= 0 && ch <= 9 ) {
253       n = n*10 + ch;  ch = *++cp;
254     }
255     ch = *tws(cp);  expect(')');
256     dp->length = n;
257   }
258   return 0;
259 }
260
261 // scan Unsigned or Signed, Zerofill
262 int numeric(ichar &cp, dobj *dp)
263 {
264   ichar bp = cp;
265   string *id = tid(cp);
266   if( id && *id == "Unsigned" ) {
267     dp->is_unsign = 1;
268     bp = cp;  id = tid(cp);
269   }
270   else if( id && *id == "Signed" ) {
271     dp->is_unsign = 0;
272     bp = cp;  id = tid(cp);
273   }
274   if( id && *id == "Zerofill" ) {
275     dp->zeroed = 1;
276   }
277   else
278     cp = bp;
279   return 0;
280 }
281
282 // (number) or numeric qualifier
283 int dimen0(ichar &cp, dobj *dp)
284 {
285   return dimen(cp, dp) < 0 || numeric(cp, dp) < 0 ? -1 : 0;
286 }
287
288 // scan data type
289 int dtype(ichar &cp, dobj *dp)
290 {
291   string *id = tid(cp);
292
293   if( id ) {
294     if( *id == "Bit" ) {
295       dp->ty = dobj::ty_bit;
296       if( dimen0(cp, dp) < 0 ) return -1;
297       return 0;
298     }
299
300     if( *id == "Tinyint" ) {
301       dp->ty = dobj::ty_tinyint;
302       if( dimen0(cp, dp) < 0 ) return -1;
303       return 0;
304     }
305
306     if( *id == "Smallint" ) {
307       dp->ty = dobj::ty_smallint;
308       if( dimen0(cp, dp) < 0 ) return -1;
309       return 0;
310     }
311
312     if( *id == "Mediumint" ) {
313       dp->ty = dobj::ty_mediumint;
314       if( dimen0(cp, dp) < 0 ) return -1;
315       return 0;
316     }
317
318     if( *id == "Int" || *id == "Integer" ) {
319       dp->ty = dobj::ty_integer;
320       if( dimen0(cp, dp) < 0 ) return -1;
321       return 0;
322     }
323
324     if( *id == "Bigint" ) {
325       dp->ty = dobj::ty_bigint;
326       if( dimen0(cp, dp) < 0 ) return -1;
327       return 0;
328     }
329
330     if( *id == "Real" ) {
331       dp->ty = dobj::ty_real;
332       if( dimen0(cp, dp) < 0 ) return -1;
333       return 0;
334     }
335
336     if( *id == "Double" ) {
337       dp->ty = dobj::ty_double;
338       if( dimen0(cp, dp) < 0 ) return -1;
339       return 0;
340     }
341
342     if( *id == "Float" ) {
343       dp->ty = dobj::ty_float;
344       if( dimen0(cp, dp) < 0 ) return -1;
345       return 0;
346     }
347
348     if( *id == "Decimal" ) {
349       dp->ty = dobj::ty_decimal;
350       if( dimen0(cp, dp) < 0 ) return -1;
351       return 0;
352     }
353
354     if( *id == "Date" ) {
355       dp->ty = dobj::ty_date;
356       return 0;
357     }
358     else if( *id == "Time" ) {
359       dp->ty = dobj::ty_time;
360       return 0;
361     }
362     else if( *id == "Timestamp" ) {
363       dp->ty = dobj::ty_timestamp;
364       return 0;
365     }
366     else if( *id == "Datetime" ) {
367       dp->ty = dobj::ty_datetime;
368       return 0;
369     }
370     else if( *id == "Year" ) {
371       dp->ty = dobj::ty_year;
372       return 0;
373     }
374
375     if( *id == "Char" ) {
376       dp->ty = dobj::ty_char;
377       if( dimen(cp, dp) < 0 ) return -1;
378       return 0;
379     }
380
381     if( *id == "Varchar" ) {
382       dp->ty = dobj::ty_varchar;
383       if( dimen(cp, dp) < 0 ) return -1;
384       if( (id=tid(cp)) != 0 ) {
385         ichar bp = cp;
386         if( *id == "Binary" ) {
387           dp->is_binary = 1;
388         }
389         else
390           cp = bp;
391       }
392       return 0;
393     }
394
395     if( *id == "Binary" ) {
396       dp->ty = dobj::ty_binary;
397       if( dimen(cp, dp) < 0 ) return -1;
398       return 0;
399     }
400
401     if( *id == "Varbinary" ) {
402       dp->ty = dobj::ty_varbinary;
403       if( dimen(cp, dp) < 0 ) return -1;
404       return 0;
405     }
406
407     if( *id == "Tinyblob" ) {
408       dp->ty = dobj::ty_tinyblob;
409       return 0;
410     }
411
412     if( *id == "Blob" ) {
413       dp->ty = dobj::ty_blob;
414       return 0;
415     }
416
417     if( *id == "Mediumblob" ) {
418       dp->is_unsign = 1;
419       dp->ty = dobj::ty_mediumblob;
420       return 0;
421     }
422
423     if( *id == "Longblob" ) {
424       dp->ty = dobj::ty_longblob;
425       return 0;
426     }
427
428     if( *id == "Tinytext" ) {
429       dp->ty = dobj::ty_tinytext;
430       return 0;
431     }
432
433     if( *id == "Text" ) {
434       dp->ty = dobj::ty_text;
435       return 0;
436     }
437
438     if( *id == "Mediumtext" ) {
439       dp->ty = dobj::ty_mediumtext;
440       return 0;
441     }
442
443     if( *id == "Longtext" ) {
444       dp->ty = dobj::ty_longtext;
445       return 0;
446     }
447
448     if( *id == "Bool" || *id == "Boolean" ) {
449       dp->ty = dobj::ty_boolean;
450       return 0;
451     }
452
453     if( *id == "Enum" ) {
454       dp->ty = dobj::ty_enum;
455       int ch = *tws(cp);  expect('(');
456       if( str_value(tws(cp),id) < 0 ) return -1;
457       dp->eop.push_back(id);
458       while( *tws(cp) == ',' ) {
459         if( str_value(tws(++cp),id) < 0 ) return -1;
460         dp->eop.push_back(id);
461       }
462       ch = *tws(cp);  expect(')');
463       return 0;
464     }
465
466     if( *id == "Media" ) {
467       dp->ty = dobj::ty_media;
468       return 0;
469     }
470   }
471
472   return -1;
473 }
474
475 // scan reference
476 int xrefer(ichar &cp, robj *rp)
477 {
478   string *id = tid(cp);
479   if( !id ) return -1;
480   rp->name = id;
481   int ch = *tws(cp);  expect('(');
482   if( !(id=tid(cp)) ) return -1;
483   rp->keys.push_back(id);
484   while( *tws(cp) == ',' ) {
485     if( !(id=tid(++cp)) ) return -1;
486     rp->keys.push_back(id);
487   }
488   ch = *tws(cp);  expect(')');
489   if( !(id=tid(cp)) ) return -1;
490   if( *id != "On" ) return -1;
491   if( !(id=tid(cp)) ) return -1;
492   int *pp = 0;
493   if( *id == "Delete" ) {
494     pp = &rp->on_delete;
495   }
496   else if( *id == "Update" ) {
497     pp = &rp->on_update;
498   }
499   if( !pp ) return -1;
500   if( !(id=tid(cp)) ) return -1;
501   if( *id == "Restrict" ) {
502     rp->on_delete = robj::xref_restrict;
503     return 0;
504   }
505   if( *id == "Cascade" ) {
506     rp->on_delete = robj::xref_cascade;
507     return 0;
508   }
509   if( *id == "Set" ) {
510     if( !(id=tid(cp)) ) return -1;
511     if( *id != "Null" ) return -1;
512     rp->on_delete = robj::xref_set_null;
513     return 0;
514   }
515   if( *id == "No" ) {
516     if( !(id=tid(cp)) ) return -1;
517     if( *id != "Action" ) return -1;
518     rp->on_delete = robj::xref_no_action;
519     return 0;
520   }
521   return -1;
522 }       
523
524 // scan datatype extension
525 int xtype(ichar &cp, dobj *dp)
526 {
527   string *id = tid(cp);
528   if( id ) {
529     if( *id == "Not" ) {
530       if( *tid(cp) != "Null" ) return -1;
531       dp->is_null = 0;
532       return 0;
533     }
534
535     if( *id == "Null" ) {
536       dp->is_null = 1;
537       return 0;
538     }
539
540     if( *id == "Default" ) {
541       if( def_value(tws(cp),dp) < 0 ) return -1;
542       return 0;
543     }
544
545     if( *id == "Auto_increment" ) {
546       dp->is_autoincr = 1;
547       if( dp->idx ) dp->idx->unique = 1;
548       return 0;
549     }
550
551     if( *id == "Unique" || *id == "Primary" ) {
552       int unique = dp->is_autoincr > 0 ? 1 : 0;
553       int primary = 0;
554       if( *id == "Unique" ) {
555         unique = 1;  id = tid(cp);
556       }
557       if( *id == "Primary" ) primary = 1;
558       ichar bp = cp;
559       if( *tid(cp) != "Key" ) cp = bp;
560       iobj *idx = new iobj();
561       dp->idx = idx;
562       idx->name = new string(*dp->name);
563       idx->name->push_back('_');
564       idx->tbl = new string(*dp->top->name);
565       idx->unique = unique;
566       idx->primary = primary;
567       idx->keys.push_back(dp->name);
568       indecies.push_back(idx);
569       return 0;
570     }
571
572 #if 0
573     if( *id == "Comment" ) {
574       return 0;
575     }
576
577     if( *id == "Column_format" ) {
578       return 0;
579     }
580
581     if( *id == "Storage" ) {
582       return 0;
583     }
584 #endif
585
586     if( *id == "References" ) {
587       ichar bp = cp;
588       robj *rop = new robj();
589       if ( xrefer(cp, rop) < 0 ) {
590         cp = bp;
591         return -1;
592       }
593       return 0;
594     }
595   }
596   return -1;
597 }
598
599 // scan table member line
600 int member(ichar &cp, dobj *dp)
601 {
602   dp->name = tid(cp);
603   if( dtype(cp,dp) < 0 ) return -1;
604
605   for( int ch=*tws(cp); (ch=*tws(cp)) && isalpha(ch); ) {
606     if( xtype(cp,dp) < 0 ) return -1;
607   }
608
609   return 0;
610 }
611
612 // scan create table line
613 int table(ichar &cp, tobj *top)
614 {
615   string *id = tid(cp);
616   if( !id ) return -1;
617   top->name = id;
618   int ch = *tws(cp);  expect('(');
619   for(;;) {
620     dobj *dp = new dobj(top);
621     if( member(cp,dp) < 0 ) return -1;
622     top->dop.push_back(dp);
623     if( (ch=*tws(cp)) == ')' ) break;
624     expect(',');
625   }
626   expect(')');
627   while( (id=tid(cp)) ) {
628     ch = *tws(cp);  expect('=');
629     printf("  skipping %s at %d\n",id->c_str(),cp.no);
630     if( isdigit(*tws(cp)) ) while( isdigit(*++cp) );
631     else if( !tid(cp) ) return -1;
632   }
633  ch = *tws(cp);  expect(';');
634   return 0;
635 }
636
637 // scan (number)
638 int keylen(ichar &cp, iobj *ip)
639 {
640   int n = 0;
641   int ch = *tws(cp);
642   if( ch == '(' ) {
643     ++cp;  ch = *tws(cp);
644     while( (ch-='0') >= 0 && ch <= 9 ) {
645       n = n*10 + ch;  ch = *++cp;
646     }
647     ch = *tws(cp);  expect(')');
648     ip->length = n;
649   }
650   return 0;
651 }
652
653 // scan create index line
654 int index(ichar &cp, iobj *iop)
655 {
656   string *id = tid(cp);
657   if( !id ) return -1;
658   iop->name = id;
659   if( !(id=tid(cp)) ) return -1;
660   if( *id != "On" ) return -1;
661   if( !(id=tid(cp)) ) return -1;
662   iop->tbl = id;
663   int ch = *tws(cp);  expect('(');
664   if( !(id=tid(cp)) ) return -1;
665   iop->keys.push_back(id);
666   if( keylen(cp,iop) < 0 ) return -1;
667   while( *tws(cp) == ',' ) {
668     if( !(id=tid(++cp)) ) return -1;
669     iop->keys.push_back(id);
670     if( keylen(cp,iop) < 0 ) return -1;
671   }
672   ch = *tws(cp);  expect(')');
673   ch = *tws(cp);  expect(';');
674   return 0;
675 }
676
677 // process create line
678 int create(ichar &cp)
679 {
680   int online = -1; (void) online; // avoid unused warn
681   enum { none, unique, fulltext, spatial } modifier = none;
682
683   string *tp = tid(cp);
684   if( *tp == "Table" ) {
685     printf("Create Table at %d\n",cp.no);
686     tobj *top = new tobj();
687     if( table(cp, top) < 0 ) {
688       delete top;
689       return -1;
690     }
691     tables.push_back(top);
692     return 0;
693   }
694   if( *tp == "Online" ) {
695     online = 1;
696     tp = tid(cp);
697   }
698   else if( *tp == "Offine" ) {
699     online = 0;
700     tp = tid(cp);
701   }
702   if( *tp == "Unique" ) {
703     modifier = unique;
704     tp = tid(cp);
705   }
706   else if( *tp == "Fulltext" ) {
707     modifier = fulltext;
708     tp = tid(cp);
709   }
710   else if( *tp == "Spatial" ) {
711     modifier = spatial;
712     tp = tid(cp);
713   }
714   if( *tp == "Index" ) {
715     printf("Create index at %d\n",cp.no);
716     iobj *iop = new iobj();
717     if( index(cp, iop) < 0 ) {
718       delete iop;
719       return -1;
720     }
721     if( modifier == unique ) iop->unique = 1;
722     indecies.push_back(iop);
723     return 0;
724   }
725   fprintf(stderr,"unknown keyword - %s\n", tp->c_str());
726   return -1;
727 }
728
729 #if 0
730 void put_args(FILE *sp, tobj *tp, iobj *ip)
731 {
732   list<string*>::iterator ekey=ip->keys.end();
733   list<string*>::iterator key=ip->keys.begin();
734   if( key == ekey ) return;
735
736   for(;;) {
737     const char *knm = (*key)->c_str();
738
739     list<dobj*>::iterator eid = tp->dop.end();
740     list<dobj*>::iterator id = tp->dop.begin();
741     while( id!=eid && *(*id)->name!=knm ) ++id;
742     if( id == eid ) {
743       fprintf(stderr,"  error: cant find index key %s in %s\n",knm,tp->name->c_str());
744       continue;
745     }
746
747     dobj *dp = *id;
748     const char *nm = dp->name->c_str();
749     fprintf(sp,"%s::t_%s &%s",tp->name->c_str(),nm,nm);
750     if( ++key == ekey ) break;
751     fprintf(sp, ", ");
752   }
753 }
754 #endif
755
756 #if 0
757 void varg_dobj(FILE *sp, dobj *dp, const char *ty, int is_unsign=-1)
758 {
759   if( is_unsign < 0 ) is_unsign = dp->is_unsign;
760   if( is_unsign > 0 ) fprintf(sp, "unsigned ");
761   fprintf(sp,"%s *%s", ty, dp->name->c_str());
762 }
763 #else
764 void varg_dobj(FILE *sp, dobj *dp, const char *ty, int is_unsign=-1)
765 {
766   const char *tnm = dp->top->name->c_str();
767   const char *nm = dp->name->c_str();
768   fprintf(sp,"const %sObj::t_%s &%s", tnm, nm, nm);
769 }
770 #endif
771
772 void arg_dobj(FILE *sp, dobj *dp, const char *ty, int is_unsign=-1)
773 {
774   if( is_unsign < 0 ) is_unsign = dp->is_unsign;
775   if( is_unsign > 0 ) fprintf(sp, "unsigned ");
776   fprintf(sp,"%s ", ty);
777   if( dp->length > 0 ) fprintf(sp, "*");
778   fprintf(sp,"%s", dp->name->c_str());
779 }
780
781 void arg_dobj(FILE *sp, dobj *dp)
782 {
783   switch( dp->ty ) {
784   case dobj::ty_boolean:
785   case dobj::ty_bit:
786   case dobj::ty_binary:   arg_dobj(sp, dp, "char", 1); break;
787   case dobj::ty_char:
788   case dobj::ty_tinyint:  arg_dobj(sp, dp, "char"); break;
789   case dobj::ty_enum:
790   case dobj::ty_smallint: arg_dobj(sp, dp, "short"); break;
791   case dobj::ty_decimal:
792   case dobj::ty_mediumint:
793   case dobj::ty_integer:  arg_dobj(sp, dp, "int"); break;
794   case dobj::ty_bigint:   arg_dobj(sp, dp, "long"); break;
795   case dobj::ty_real:
796   case dobj::ty_double:   arg_dobj(sp, dp, "double", 0); break;
797   case dobj::ty_float:    arg_dobj(sp, dp, "float", 0); break;
798   case dobj::ty_date:
799   case dobj::ty_time:
800   case dobj::ty_timestamp:
801   case dobj::ty_datetime:
802   case dobj::ty_year:     varg_dobj(sp, dp, "char",0); break;
803   case dobj::ty_varchar:
804     if( dp->is_binary ) { varg_dobj(sp, dp, "char",1); break; }
805   case dobj::ty_tinytext:
806   case dobj::ty_text:
807   case dobj::ty_mediumtext:
808   case dobj::ty_longtext: varg_dobj(sp, dp, "char",0); break;
809   case dobj::ty_varbinary:
810   case dobj::ty_tinyblob:
811   case dobj::ty_blob:
812   case dobj::ty_mediumblob:
813   case dobj::ty_longblob:
814   case dobj::ty_media:    varg_dobj(sp, dp, "char",1); break;
815   default:
816     fprintf(sp,"unimplemented %s,", dp->name->c_str());
817     break;
818   }
819 }
820
821 void put_targs(FILE *sp, tobj *tp, iobj *ip)
822 {
823   list<string*>::iterator ekey=ip->keys.end();
824   list<string*>::iterator key=ip->keys.begin();
825
826   for( ; key != ekey; ) {
827     const char *knm = (*key)->c_str();  ++key;
828     list<dobj*>::iterator eid = tp->dop.end();
829     list<dobj*>::iterator id = tp->dop.begin();
830     while( id!=eid && *(*id)->name!=knm ) ++id;
831     if( id == eid ) {
832       fprintf(stderr,"  error: cant find index key %s in %s\n",knm,tp->name->c_str());
833       continue;
834     }
835     dobj *dp = *id;
836     if( dp->ty == dobj::ty_none ) {
837       fprintf(stderr," %s member %s error: ty_none\n",
838         tp->name->c_str(),dp->name->c_str());
839       continue;
840     }
841     fprintf(sp,"        ");
842     arg_dobj(sp, dp);
843     if( key == ekey ) continue;
844     fprintf(sp,",\n");
845   }
846 }
847
848 void typ_dobj(FILE *sp, dobj *dp)
849 {
850   const char *cp;
851   switch( dp->ty ) {
852   case dobj::ty_boolean:
853   case dobj::ty_bit:
854   case dobj::ty_binary:    cp = "unsigned char"; break;
855   case dobj::ty_char:
856   case dobj::ty_tinyint:   cp = dp->is_unsign > 0 ? "unsigned char" : "char"; break;
857   case dobj::ty_enum:
858   case dobj::ty_smallint:  cp = dp->is_unsign > 0 ? "unsigned short" : "short"; break;
859   case dobj::ty_decimal:
860   case dobj::ty_mediumint:
861   case dobj::ty_integer:   cp = dp->is_unsign > 0 ? "unsigned int" : "int"; break;
862   case dobj::ty_bigint:    cp = dp->is_unsign > 0 ? "unsigned long" : "long"; break;
863   case dobj::ty_real:
864   case dobj::ty_double:    cp = "double"; break;
865   case dobj::ty_float:     cp = "float"; break;
866   case dobj::ty_date:
867   case dobj::ty_time:
868   case dobj::ty_timestamp:
869   case dobj::ty_datetime:
870   case dobj::ty_year:      cp = "char"; break;
871   case dobj::ty_varchar:
872     if( dp->is_binary ) {  cp = "unsigned char"; break; }
873   case dobj::ty_tinytext:
874   case dobj::ty_text:
875   case dobj::ty_mediumtext:
876   case dobj::ty_longtext:  cp = "char"; break;
877   case dobj::ty_varbinary:
878   case dobj::ty_tinyblob:
879   case dobj::ty_blob:
880   case dobj::ty_mediumblob:
881   case dobj::ty_longblob:
882   case dobj::ty_media:     cp = "unsigned char"; break;
883   default:                 cp = "unimplemented"; break;
884   }
885   fprintf(sp,"%s",cp);
886 }
887
888 void put_keys(FILE *sp, tobj *tp, iobj *ip)
889 {
890   list<string*>::iterator ekey=ip->keys.end();
891   list<string*>::iterator key=ip->keys.begin();
892   const char *tnm = tp->name->c_str();
893
894   for( ; key != ekey; ++key ) {
895     const char *knm = (*key)->c_str();
896
897     list<dobj*>::iterator eid = tp->dop.end();
898     list<dobj*>::iterator id = tp->dop.begin();
899     while( id!=eid && *(*id)->name!=knm ) ++id;
900     if( id == eid ) {
901       fprintf(stderr,"  error: cant find index key %s in %s\n", knm, tnm);
902       continue;
903     }
904
905     dobj *dp = *id;
906     const char *nm = dp->name->c_str();
907     fprintf(sp,"    %sObj::t_%s v_%s;\n", tnm, nm, nm);
908   }
909   if( ip->unique <= 0 ) fprintf(sp,"    int v_id;\n");
910 }
911
912 void put_init(FILE *sp, tobj *tp, iobj *ip)
913 {
914   list<string*>::iterator ekey=ip->keys.end();
915   list<string*>::iterator key;
916
917   for( key=ip->keys.begin(); key!=ekey; ++key ) {
918     const char *knm = (*key)->c_str();
919
920     list<dobj*>::iterator eid = tp->dop.end();
921     list<dobj*>::iterator id = tp->dop.begin();
922     while( id!=eid && *(*id)->name!=knm ) ++id;
923     if( id == eid ) {
924       fprintf(stderr,"  error: cant find index key %s in %s\n",knm,tp->name->c_str());
925       continue;
926     }
927
928     dobj *dp = *id;
929     const char *nm = dp->name->c_str();
930     fprintf(sp,",\n      v_%s(%s)", nm, nm);
931   }
932 }
933
934 void put_cmpr(FILE *sp, dobj *dp)
935 {
936   const char *cp;
937   switch( dp->ty ) {
938   case dobj::ty_boolean:
939   case dobj::ty_bit:
940   case dobj::ty_binary:    cp = "uchar"; break;
941   case dobj::ty_char:
942   case dobj::ty_tinyint:   cp = dp->is_unsign > 0 ? "uchar" : "char"; break;
943   case dobj::ty_enum:
944   case dobj::ty_smallint:  cp = dp->is_unsign > 0 ? "ushort" : "short"; break;
945   case dobj::ty_decimal:
946   case dobj::ty_mediumint:
947   case dobj::ty_integer:   cp = dp->is_unsign > 0 ? "uint" : "int"; break;
948   case dobj::ty_bigint:    cp = dp->is_unsign > 0 ? "ulong" : "long"; break;
949   case dobj::ty_real:
950   case dobj::ty_double:    cp = "double"; break;
951   case dobj::ty_float:     cp = "float"; break;
952   case dobj::ty_date:
953   case dobj::ty_time:
954   case dobj::ty_timestamp:
955   case dobj::ty_datetime:
956   case dobj::ty_year:      cp = "char"; break;
957   case dobj::ty_varchar:
958     if( dp->is_binary ) {  cp = "uchar"; break; }
959   case dobj::ty_tinytext:
960   case dobj::ty_text:
961   case dobj::ty_mediumtext:
962   case dobj::ty_longtext:  cp = "char"; break;
963   case dobj::ty_varbinary:
964   case dobj::ty_tinyblob:
965   case dobj::ty_blob:
966   case dobj::ty_mediumblob:
967   case dobj::ty_longblob:  cp = "uchar"; break;
968   case dobj::ty_media:     cp = "media"; break;
969   default:                 cp = "unimplemented"; break;
970   }
971   fprintf(sp,"%s",cp);
972 }
973
974 void put_rcmpr(FILE *sp, tobj *tp, iobj *ip)
975 {
976   list<string*>::iterator ekey=ip->keys.end();
977   list<string*>::iterator skey=ip->keys.begin();
978   list<string*>::iterator key;
979
980   for( key=skey; key!=ekey; ++key ) {
981     const char *knm = (*key)->c_str();
982
983     list<dobj*>::iterator eid = tp->dop.end();
984     list<dobj*>::iterator id = tp->dop.begin();
985     while( id!=eid && *(*id)->name!=knm ) ++id;
986     if( id == eid ) {
987       fprintf(stderr,"  error: cant find index key %s in %s\n",knm,tp->name->c_str());
988       continue;
989     }
990
991     dobj *dp = *id;
992     const char *nm = dp->name->c_str();
993     fprintf(sp,"  v = cmpr_");  put_cmpr(sp,dp);
994     fprintf(sp,"( kloc._%s(), kloc->v_%s.size(),\n", nm, nm);
995     fprintf(sp,"                   vloc._%s(), vloc->v_%s.size());\n", nm, nm);
996     fprintf(sp,"  if( v != 0 ) return v;\n");
997   }
998   if( ip->unique <= 0 ) {
999     fprintf(sp,"  v = cmpr_int(kloc._id(), kloc._id_size(),\n");
1000     fprintf(sp,"               vloc._id(), vloc._id_size());\n");
1001     fprintf(sp,"  if( v != 0 ) return v;\n");
1002   }
1003 }
1004
1005 void put_icmpr(FILE *sp, tobj *tp, iobj *ip)
1006 {
1007   list<string*>::iterator ekey=ip->keys.end();
1008   list<string*>::iterator skey=ip->keys.begin();
1009   list<string*>::iterator key;
1010
1011   for( key=skey; key!=ekey; ++key ) {
1012     const char *knm = (*key)->c_str();
1013
1014     list<dobj*>::iterator eid = tp->dop.end();
1015     list<dobj*>::iterator id = tp->dop.begin();
1016     while( id!=eid && *(*id)->name!=knm ) ++id;
1017     if( id == eid ) {
1018       fprintf(stderr,"  error: cant find index key %s in %s\n",knm,tp->name->c_str());
1019       continue;
1020     }
1021
1022     dobj *dp = *id;
1023     const char *nm = dp->name->c_str();
1024     fprintf(sp,"  v = cmpr_");  put_cmpr(sp,dp);
1025     fprintf(sp,"( kp->v_%s.addr(), kp->v_%s.size(),\n", nm, nm);
1026     fprintf(sp,"                  vloc._%s(), vloc->v_%s.size());\n", nm, nm);
1027     fprintf(sp,"  if( v != 0 ) return v;\n");
1028   }
1029   if( ip->unique <= 0 ) {
1030     fprintf(sp,"  if( kp->v_id >= 0 ) {\n");
1031     fprintf(sp,"    v = cmpr_int(&kp->v_id, sizeof(kp->v_id),\n");
1032     fprintf(sp,"                 vloc._id(), vloc._id_size());\n");
1033     fprintf(sp,"    if( v != 0 ) return v;\n");
1034     fprintf(sp,"  }\n");
1035   }
1036 }
1037
1038 void put_dobj(FILE *sp, dobj *dp, const char *dty, int n)
1039 {
1040   fprintf(sp,"  array_%s(char,%s,%d);\n", dty, dp->name->c_str(), n);
1041 }
1042
1043 void put_dobj(FILE *sp, dobj *dp, const char *dty, const char *ty, int is_unsign=-1)
1044 {
1045   fprintf(sp,"  %s_%s(", dp->length > 0 ? "array" : "basic", dty);
1046   if( is_unsign < 0 ) is_unsign = dp->is_unsign;
1047   if( is_unsign > 0 ) fprintf(sp, "unsigned ");
1048   fprintf(sp,"%s,%s", ty, dp->name->c_str());
1049   if( dp->length > 0 ) fprintf(sp, ",%d", dp->length);
1050   fprintf(sp, ");\n");
1051 }
1052
1053 void put_decl(FILE *sp, dobj *dp, const char *dty)
1054 {
1055   switch( dp->ty ) {
1056   case dobj::ty_boolean:
1057   case dobj::ty_bit:
1058   case dobj::ty_binary:   put_dobj(sp, dp, dty, "char", 1); break;
1059   case dobj::ty_char:
1060   case dobj::ty_tinyint:  put_dobj(sp, dp, dty, "char"); break;
1061   case dobj::ty_enum:
1062   case dobj::ty_smallint: put_dobj(sp, dp, dty, "short"); break;
1063   case dobj::ty_decimal:
1064   case dobj::ty_mediumint:
1065   case dobj::ty_integer:  put_dobj(sp, dp, dty, "int"); break;
1066   case dobj::ty_bigint:   put_dobj(sp, dp, dty, "long"); break;
1067   case dobj::ty_real:
1068   case dobj::ty_double:   put_dobj(sp, dp, dty, "double", 0); break;
1069   case dobj::ty_float:    put_dobj(sp, dp, dty, "float", 0); break;
1070   case dobj::ty_date:     put_dobj(sp, dp, dty, 8); break;
1071   case dobj::ty_time:     put_dobj(sp, dp, dty, 6); break;
1072   case dobj::ty_timestamp:
1073   case dobj::ty_datetime: put_dobj(sp, dp, dty, 14); break;
1074   case dobj::ty_year:     put_dobj(sp, dp, dty, 4); break;
1075   case dobj::ty_text:
1076   case dobj::ty_tinytext:
1077   case dobj::ty_mediumtext:
1078   case dobj::ty_longtext:
1079     fprintf(sp,"  sarray_%s(char,%s);\n", dty, dp->name->c_str());
1080     break;
1081   case dobj::ty_varchar:
1082     if( !dp->is_binary ) {
1083       fprintf(sp,"  varray_%s(char,%s);\n", dty, dp->name->c_str());
1084       break;
1085     }
1086   case dobj::ty_varbinary:
1087   case dobj::ty_blob:
1088   case dobj::ty_tinyblob:
1089   case dobj::ty_mediumblob:
1090   case dobj::ty_longblob:
1091   case dobj::ty_media:
1092     fprintf(sp,"  varray_%s(unsigned char,%s);\n", dty, dp->name->c_str());
1093     dp->is_unsign = 1;
1094     break;
1095   default:
1096     fprintf(sp," %s %s unimplemented;\n", dty, dp->name->c_str());
1097     break;
1098   }
1099 }
1100
1101
1102 int main(int ac, char **av)
1103 {
1104   const char *tdb = ac > 1 ? av[1] : "theDb";
1105   const char *sfn = ac > 2 ? av[2] : "./s";
1106
1107   setbuf(stdout,0);
1108   setbuf(stderr,0);
1109   ichar cp(stdin);
1110
1111   for( string *sp=tid(cp); sp!=0; sp=tid(cp) ) {
1112     if( *sp == "Create" ) create(cp);
1113   }
1114
1115   printf(" %d Tables\n",(int)tables.size());
1116   printf(" %d Indecies\n",(int)indecies.size());
1117
1118   char fn[512];  sprintf(fn,"%s.h",sfn);
1119   FILE *sp = fopen(fn,"w");
1120
1121   // get basename for sfn.h, _SFN_H_
1122   const char *bp = 0;
1123   for( const char *ap=sfn; *ap; ++ap )
1124     if( *ap == '/' ) bp = ap+1;
1125   if( !bp ) bp = sfn;
1126   char ups[512], *up = ups;  *up++ = '_';
1127   for( const char *cp=bp; *cp; ++cp ) *up++ = toupper(*cp);
1128   *up++ = '_';  *up++ = 'H';  *up++ = '_';  *up = 0;
1129
1130   fprintf(sp,"#ifndef %s\n",ups);
1131   fprintf(sp,"#define %s\n",ups);
1132   fprintf(sp,"#include <cstdio>\n");
1133   fprintf(sp,"#include <stdlib.h>\n");
1134   fprintf(sp,"#include <unistd.h>\n");
1135   fprintf(sp,"#include <fcntl.h>\n");
1136   fprintf(sp,"#include <errno.h>\n");
1137   fprintf(sp,"\n");
1138   fprintf(sp,"#include \"tdb.h\"\n");
1139   fprintf(sp,"\n");
1140   fprintf(sp,"\n");
1141
1142   list<tobj*>::iterator sit = tables.begin();
1143   list<tobj*>::iterator eit = tables.end();
1144   list<tobj*>::iterator it;
1145
1146   int i=0;
1147   for( it=sit ; it!=eit; ++i, ++it ) {
1148     tobj *tp = *it;
1149     const char *tnm = tp->name->c_str();
1150     printf(" %2d. %s (",i,tnm);
1151     fprintf(sp,"// %s\n",tnm);
1152     fprintf(sp,"DbObj(%s)\n",tnm);
1153
1154     list<dobj*>::iterator sid = tp->dop.begin();
1155     list<dobj*>::iterator eid = tp->dop.end();
1156     list<dobj*>::iterator id;
1157
1158     // output table member declarations
1159     for( id=sid ; id!=eid; ++id ) {
1160       dobj *dp = *id;
1161       printf(" %s",dp->name->c_str());
1162       if( dp->ty == dobj::ty_none ) {
1163         fprintf(stderr," %s member %s error: ty_none\n",
1164           tnm,dp->name->c_str());
1165         continue;
1166       }
1167       put_decl(sp,dp,"def");
1168     }
1169     printf(" )\n");
1170
1171     fprintf(sp,"};\n");
1172     fprintf(sp,"\n");
1173
1174     list<iobj*>::iterator sidx=indecies.begin();
1175     list<iobj*>::iterator eidx=indecies.end();
1176     list<iobj*>::iterator idx;
1177
1178     int j = 0, n = 0;
1179     for( idx=sidx; idx!=eidx; ++idx ) {
1180       if( *(*idx)->tbl != *(*it)->name ) continue;
1181       ++n;
1182       printf("   %2d.%d. %s on %s(",i,j++,
1183         (*idx)->name->c_str(),(*idx)->tbl->c_str());
1184       list<string*>::iterator skey=(*idx)->keys.begin();
1185       list<string*>::iterator ekey=(*idx)->keys.end();
1186       list<string*>::iterator key;
1187       for( key=skey; key!=ekey; ++key )
1188         printf(" %s", (*key)->c_str());
1189       printf(" )\n");
1190     }
1191     if( n > 0 ) printf("\n");
1192
1193     // output table member accessors
1194     fprintf(sp,"DbLoc(%s)\n",tnm);
1195     for( id=sid ; id!=eid; ++id ) {
1196       dobj *dp = *id;
1197       if( dp->ty == dobj::ty_none ) {
1198         fprintf(stderr," %s member %s error: ty_none\n",
1199           tnm,dp->name->c_str());
1200         continue;
1201       }
1202       put_decl(sp, dp, "ref");
1203     }
1204
1205     for( idx=sidx; idx!=eidx; ++idx ) {
1206       if( *(*idx)->tbl != *(*it)->name ) continue;
1207       const char *knm = (*idx)->name->c_str();
1208       fprintf(sp,"\n");
1209       fprintf(sp,"  class ikey_%s : public Db::iKey { public:\n", knm);
1210       put_keys(sp, *it, *idx);
1211       fprintf(sp,"    static int cmpr(char *a, char *b);\n");
1212       // key constructors
1213       fprintf(sp,"    ikey_%s(ObjectLoc &loc,\n", knm);
1214       put_targs(sp, *it, *idx);
1215       if( (*idx)->unique <= 0 ) fprintf(sp,", int id=-1");
1216       fprintf(sp,")\n    : iKey(\"%s\",loc,cmpr)", knm);
1217       put_init(sp, *it, *idx);
1218       if( (*idx)->unique <= 0 ) fprintf(sp,",\n      v_id(id)");
1219       fprintf(sp," {}\n");
1220       fprintf(sp,"  };\n");
1221       fprintf(sp,"  class rkey_%s : public Db::rKey { public:\n", knm);
1222       fprintf(sp,"    static int cmpr(char *a, char *b);\n");
1223       fprintf(sp,"    rkey_%s(ObjectLoc &loc) : rKey(\"%s\",loc,cmpr)", knm, knm);
1224       fprintf(sp," {}\n");
1225       fprintf(sp,"  };\n");
1226     }
1227     fprintf(sp,"\n");
1228     fprintf(sp,"  int Allocate();\n");
1229     fprintf(sp,"  int Construct();\n");
1230     fprintf(sp,"  int Destruct();\n");
1231     fprintf(sp,"  void Deallocate();\n");
1232 #ifdef COPY
1233     fprintf(sp,"  int Copy(ObjectLoc &that);\n");
1234 #endif
1235     fprintf(sp,"};\n");
1236   }
1237   fprintf(sp,"\n");
1238
1239   fprintf(sp,"\n");
1240   fprintf(sp,"class %s : public Db {\n",tdb);
1241   fprintf(sp,"  int dfd, dkey, no_atime;\n");
1242   fprintf(sp,"  int db_create();\n");
1243   fprintf(sp,"  int db_open();\n");
1244   fprintf(sp,"  int db_access();\n");
1245   fprintf(sp,"public:\n");
1246   fprintf(sp,"  Objects objects;\n");
1247   for( it=sit ; it!=eit; ++it ) {
1248     tobj *tp = *it;
1249     const char *tnm = tp->name->c_str();
1250     fprintf(sp,"  Entity %s;  %sLoc %c%s;\n", tnm, tnm, tolower(tnm[0]), &tnm[1]);
1251   }
1252   fprintf(sp,"\n");
1253   fprintf(sp,"  int create(const char *dfn);\n");
1254   fprintf(sp,"  int open(const char *dfn, int key=-1);\n");
1255   fprintf(sp,"  int access(const char *dfn, int key=-1, int rw=0);\n");
1256   fprintf(sp,"  void close();\n");
1257   fprintf(sp,"  int attach(int rw=0) { return Db::attach(rw); }\n");
1258   fprintf(sp,"  int detach() { return Db::detach(); }\n");
1259   fprintf(sp,"\n");
1260   fprintf(sp,"  %s();\n",tdb);
1261   fprintf(sp,"  ~%s() { finit(objects); }\n",tdb);
1262   fprintf(sp,"};\n");
1263   fprintf(sp,"\n");
1264   fprintf(sp,"#endif\n");
1265   fclose(sp);
1266
1267   sprintf(fn,"%s.C",sfn);
1268   sp = fopen(fn,"w");
1269   fprintf(sp,"#include \"%s.h\"\n",bp);
1270   fprintf(sp,"\n");
1271
1272   for( it=sit ; it!=eit; ++it ) {
1273     tobj *tp = *it;
1274     const char * tnm = tp->name->c_str();
1275     list<iobj*>::iterator sidx=indecies.begin();
1276     list<iobj*>::iterator eidx=indecies.end();
1277     list<iobj*>::iterator idx;
1278
1279     for( idx=sidx; idx!=eidx; ++idx ) {
1280       if( *(*idx)->tbl != *(*it)->name ) continue;
1281       const char *knm = (*idx)->name->c_str();
1282       fprintf(sp,"\n");
1283       fprintf(sp,"int %sLoc::ikey_%s::\n", tnm, knm);
1284       fprintf(sp,"cmpr(char *a, char *b)\n");
1285       fprintf(sp,"{\n");
1286       fprintf(sp,"  ikey_%s *kp = (ikey_%s *)a;\n", knm, knm);
1287       fprintf(sp,"  int v = *(int*)b;\n");
1288       if( (*idx)->unique <= 0 ) fprintf(sp,"  if( kp->v_id == v ) return 0;\n");
1289       fprintf(sp,"  %sLoc vloc(kp->loc.entity);\n", tnm);
1290       fprintf(sp,"  if( vloc.FindId(v) )\n");
1291       fprintf(sp,"    vloc.err_(Db::errCorrupt);\n");
1292       put_icmpr(sp, tp, *idx);
1293       fprintf(sp,"  return 0;\n");
1294       fprintf(sp,"}\n");
1295       fprintf(sp,"\n");
1296       fprintf(sp,"int %sLoc::rkey_%s::\n", tnm, knm);
1297       fprintf(sp,"cmpr(char *a, char *b)\n");
1298       fprintf(sp,"{\n");
1299       fprintf(sp,"  rkey_%s *kp = (rkey_%s *)a;\n", knm, knm);
1300       fprintf(sp,"  %sLoc &kloc = (%sLoc&)kp->loc;\n", tnm, tnm);
1301       fprintf(sp,"  int v = kloc->id, b_id = *(int*)b;\n");
1302       fprintf(sp,"  if( v == b_id ) return 0;\n");
1303       fprintf(sp,"  %sLoc vloc(kloc.entity);\n", tnm);
1304       fprintf(sp,"  if( vloc.FindId(b_id) )\n");
1305       fprintf(sp,"    kloc.err_(Db::errCorrupt);\n");
1306       put_rcmpr(sp, tp, *idx);
1307       fprintf(sp,"  return 0;\n");
1308       fprintf(sp,"}\n");
1309     }
1310     fprintf(sp,"\n");
1311     fprintf(sp,"int %sLoc::Allocate()\n", tnm);
1312     fprintf(sp,"{\n");
1313     fprintf(sp,"  if_err( allocate() );\n");
1314     fprintf(sp,"  if( !addr_wr() ) return err_(Db::errNoMemory);\n");
1315
1316     int n = 0;
1317     list<dobj*>::iterator sid = tp->dop.begin();
1318     list<dobj*>::iterator eid = tp->dop.end();
1319     list<dobj*>::iterator id;
1320
1321     for( id=sid ; !n && id!=eid; ++id ) {
1322       dobj *dp = *id;
1323       switch( dp->ty ) {
1324       case dobj::ty_varchar:
1325       case dobj::ty_tinytext:
1326       case dobj::ty_text:
1327       case dobj::ty_mediumtext:
1328       case dobj::ty_longtext:
1329       case dobj::ty_varbinary:
1330       case dobj::ty_tinyblob:
1331       case dobj::ty_blob:
1332       case dobj::ty_mediumblob:
1333       case dobj::ty_longblob:
1334       case dobj::ty_media:
1335         if( !n++ ) fprintf(sp,"  v_init();\n");
1336         break;
1337       default:
1338         break;
1339       }
1340     }
1341
1342     for( id=sid ; id!=eid; ++id ) {
1343       dobj *dp = *id;
1344       const char *dnm = dp->name->c_str();
1345       if( dp->is_autoincr > 0 && dp->idx ) {
1346         const char *inm = dp->idx->name->c_str();
1347         fprintf(sp,"  { ");  typ_dobj(sp, dp);
1348         fprintf(sp," (%sLoc::*fn)() = &%sLoc::%s;\n", tnm, tnm, dnm);
1349         fprintf(sp,"    "); typ_dobj(sp, dp);
1350         fprintf(sp," v = last(\"%s\",(", inm); typ_dobj(sp, dp);
1351         fprintf(sp," (Db::ObjectLoc::*)())fn);  %s(v+1); }\n", dnm);
1352       }
1353       if( dp->has_def > 0 ) {
1354         switch( dp->has_def ) {
1355         case dobj::def_integer:
1356           fprintf(sp,"  %s(%d);\n", dnm, dp->def.i);
1357           break;
1358         case dobj::def_double:
1359           fprintf(sp,"  %s(%f);\n", dnm, dp->def.d);
1360           break;
1361         case dobj::def_string:
1362           switch( dp->ty ) {
1363           case dobj::ty_enum: {
1364             list<string*>::iterator snm = dp->eop.begin();
1365             list<string*>::iterator enm = dp->eop.end();
1366             list<string*>::iterator nm;
1367             for( n=0,nm=snm; nm!=enm && *(*nm)!=*dp->def.s; ++nm ) ++n;
1368             fprintf(sp,"  %s(%d);\n", dnm, n);
1369             break; }
1370           case dobj::ty_boolean:
1371           case dobj::ty_bit:
1372           case dobj::ty_tinyint:
1373           case dobj::ty_smallint:
1374           case dobj::ty_decimal:
1375           case dobj::ty_mediumint:
1376           case dobj::ty_integer:
1377           case dobj::ty_bigint: {
1378             fprintf(sp,"  %s(%ld);\n", dnm, strtol(dp->def.s->c_str(),0,0));
1379             break; }
1380           case dobj::ty_real:
1381           case dobj::ty_double:
1382           case dobj::ty_float: {
1383             fprintf(sp,"  %s(%f);\n", dnm, strtod(dp->def.s->c_str(),0));
1384             break; }
1385           case dobj::ty_date:
1386           case dobj::ty_time:
1387           case dobj::ty_timestamp:
1388           case dobj::ty_binary:
1389           case dobj::ty_char:
1390           case dobj::ty_datetime:
1391           case dobj::ty_year:
1392           case dobj::ty_varchar:
1393           case dobj::ty_tinytext:
1394           case dobj::ty_text:
1395           case dobj::ty_mediumtext:
1396           case dobj::ty_longtext:
1397           case dobj::ty_varbinary:
1398           case dobj::ty_tinyblob:
1399           case dobj::ty_blob:
1400           case dobj::ty_mediumblob:
1401           case dobj::ty_longblob:
1402           case dobj::ty_media: {
1403             fprintf(sp,"  %s((", dnm); typ_dobj(sp,dp);
1404             fprintf(sp," *)\"%s\",%d);\n", dp->def.s->c_str(), (int)dp->def.s->size());
1405             break; }
1406           default:
1407             break;
1408           }
1409           break;
1410         default:
1411           break;
1412         }
1413       }
1414     }
1415     fprintf(sp,"  return 0;\n");
1416     fprintf(sp,"}\n");
1417     fprintf(sp,"\n");
1418     fprintf(sp,"int %sLoc::Construct()\n", tnm);
1419     fprintf(sp,"{\n");
1420     fprintf(sp,"  if_err( insertProhibit() );\n");
1421     fprintf(sp,"  if_err( construct() );\n");
1422     n = 0;
1423     for( idx=sidx; idx!=eidx; ++idx ) {
1424       if( *(*idx)->tbl != *(*it)->name ) continue;
1425       if( !n++ ) fprintf(sp,"  int id = this->id();\n");
1426       const char *knm = (*idx)->name->c_str();
1427       fprintf(sp,"  { rkey_%s rkey(*this);\n",knm);
1428         fprintf(sp,"    if_err( entity->index(\"%s\")->Insert(rkey,&id) ); }\n",knm);
1429     }
1430     fprintf(sp,"  if_err( insertCascade() );\n");
1431     fprintf(sp,"  return 0;\n");
1432     fprintf(sp,"}\n");
1433     fprintf(sp,"\n");
1434     fprintf(sp,"int %sLoc::Destruct()\n", tnm);
1435     fprintf(sp,"{\n");
1436     fprintf(sp,"  if_err( deleteProhibit() );\n");
1437     for( idx=sidx; idx!=eidx; ++idx ) {
1438       if( *(*idx)->tbl != *(*it)->name ) continue;
1439       const char *knm = (*idx)->name->c_str();
1440       fprintf(sp,"  { rkey_%s rkey(*this);\n",knm);
1441       fprintf(sp,"    if_err( entity->index(\"%s\")->Delete(rkey) ); }\n",knm);
1442     }
1443     fprintf(sp,"  if_err( destruct() );\n");
1444     fprintf(sp,"  if_err( deleteCascade() );\n");
1445     fprintf(sp,"  return 0;\n");
1446     fprintf(sp,"}\n");
1447     fprintf(sp,"\n");
1448     fprintf(sp,"void %sLoc::Deallocate()\n", tnm);
1449     fprintf(sp,"{\n");
1450     n = 0;
1451     for( id=sid ; !n && id!=eid; ++id ) {
1452       dobj *dp = *id;
1453       switch( dp->ty ) {
1454       case dobj::ty_varchar:
1455       case dobj::ty_tinytext:
1456       case dobj::ty_text:
1457       case dobj::ty_mediumtext:
1458       case dobj::ty_longtext:
1459       case dobj::ty_varbinary:
1460       case dobj::ty_tinyblob:
1461       case dobj::ty_blob:
1462       case dobj::ty_mediumblob:
1463       case dobj::ty_longblob:
1464       case dobj::ty_media:
1465         if( !n++ ) fprintf(sp,"  v_del();\n");
1466         break;
1467       default:
1468         break;
1469       }
1470     }
1471     fprintf(sp,"  deallocate();\n");
1472     fprintf(sp,"}\n");
1473     fprintf(sp,"\n");
1474   }
1475
1476   fprintf(sp,"\n");
1477   fprintf(sp,"int %s::\n",tdb);
1478   fprintf(sp,"create(const char *dfn)\n");
1479   fprintf(sp,"{\n");
1480   fprintf(sp,"  dfd = ::open(dfn,O_RDWR+O_CREAT+O_TRUNC+no_atime,0666);\n");
1481   fprintf(sp,"  if( dfd < 0 ) { perror(dfn); return -1; }\n");
1482   fprintf(sp,"  int ret = db_create();\n");
1483   fprintf(sp,"  close();\n");
1484   fprintf(sp,"  return ret;\n");
1485   fprintf(sp,"}\n");
1486   fprintf(sp,"\n");
1487   fprintf(sp,"int %s::\n",tdb);
1488   fprintf(sp,"db_create()\n");
1489   fprintf(sp,"{\n");
1490   fprintf(sp,"  if_ret( Db::make(dfd) );\n");
1491   for( it=sit ; it!=eit; ++it ) {
1492     tobj *tp = *it;
1493     const char *tnm = tp->name->c_str();
1494     fprintf(sp,"  if_ret( %s.new_entity(\"%s\", sizeof(%sObj)) );\n", tnm, tnm, tnm);
1495     list<iobj*>::iterator sidx=indecies.begin();
1496     list<iobj*>::iterator eidx=indecies.end();
1497     list<iobj*>::iterator idx;
1498     for( idx=sidx; idx!=eidx; ++idx ) {
1499       if( *(*idx)->tbl != *(*it)->name ) continue;
1500       const char *nm = (*idx)->name->c_str();
1501       fprintf(sp,"  if_ret( %s.add_kindex(\"%s\") );\n", tnm, nm);
1502     }
1503     fprintf(sp,"\n");
1504   }
1505   fprintf(sp,"  if_ret( Db::commit(1) );\n");
1506   fprintf(sp,"  return 0;\n");
1507   fprintf(sp,"}\n");
1508   fprintf(sp,"\n");
1509
1510   fprintf(sp,"%s::\n", tdb);
1511   fprintf(sp,"%s()\n", tdb);
1512   fprintf(sp," : dfd(-1), dkey(-1), no_atime(getuid()?0:O_NOATIME), objects(0)");
1513   for( it=sit ; it!=eit; ++it ) {
1514     tobj *tp = *it;
1515     const char *tnm = tp->name->c_str();
1516     fprintf(sp,",\n   %s(this)", tnm);
1517     fprintf(sp,", %c%s(%s)", tolower(tnm[0]), &tnm[1], tnm);
1518   }
1519   fprintf(sp,"\n");
1520   fprintf(sp,"{");
1521   for( it=sit ; it!=eit; ++it ) {
1522     tobj *tp = *it;
1523     const char *tnm = tp->name->c_str();
1524     fprintf(sp,"\n  objects = new ObjectList(objects, %c%s);",
1525       tolower(tnm[0]), &tnm[1]);
1526   }
1527   fprintf(sp,"\n");
1528   for( it=sit ; it!=eit; ++it ) {
1529     tobj *tp = *it;
1530     const char *tnm = tp->name->c_str();
1531     list<dobj*>::iterator sid = tp->dop.begin();
1532     list<dobj*>::iterator eid = tp->dop.end();
1533     list<dobj*>::iterator id;
1534     for( id=sid ; id!=eid; ++id ) {
1535       dobj *dp = *id;
1536       const char *dnm = dp->name->c_str();
1537       switch( dp->ty ) {
1538       case dobj::ty_varchar:
1539       case dobj::ty_tinytext:
1540       case dobj::ty_text:
1541       case dobj::ty_mediumtext:
1542       case dobj::ty_longtext:
1543       case dobj::ty_varbinary:
1544       case dobj::ty_tinyblob:
1545       case dobj::ty_blob:
1546       case dobj::ty_mediumblob:
1547       case dobj::ty_longblob:
1548       case dobj::ty_media: {
1549         fprintf(sp,"  %s.add_vref((vRef)&%sObj::v_%s);\n", tnm, tnm, dnm);
1550         break; }
1551       default:
1552         break;
1553       }
1554     }
1555   }
1556   fprintf(sp,"}\n");
1557   fprintf(sp,"\n");
1558
1559   fprintf(sp,"int %s::\n",tdb);
1560   fprintf(sp,"open(const char *dfn, int key)\n");
1561   fprintf(sp,"{\n");
1562   fprintf(sp,"  dfd = ::open(dfn,O_RDWR+no_atime);\n");
1563   fprintf(sp,"  if( dfd < 0 ) { perror(dfn); return errNotFound; }\n");
1564   fprintf(sp,"  if( (dkey=key) >= 0 ) Db::use_shm(1);\n");
1565   fprintf(sp,"  int ret = Db::open(dfd, dkey);\n");
1566   fprintf(sp,"  if( !ret ) ret = db_open();\n");
1567   fprintf(sp,"  if( ret ) close();\n");
1568   fprintf(sp,"  return ret;\n");
1569   fprintf(sp,"}\n");
1570   fprintf(sp,"\n");
1571
1572   fprintf(sp,"int %s::\n",tdb);
1573   fprintf(sp,"db_open()\n");
1574   fprintf(sp,"{\n");
1575   for( it=sit ; it!=eit; ++it ) {
1576     tobj *tp = *it;
1577     const char *tnm = tp->name->c_str();
1578     fprintf(sp,"  if_ret( %s.get_entity(\"%s\") );\n", tnm, tnm);
1579     list<iobj*>::iterator sidx=indecies.begin();
1580     list<iobj*>::iterator eidx=indecies.end();
1581     list<iobj*>::iterator idx;
1582     for( idx=sidx; idx!=eidx; ++idx ) {
1583       if( *(*idx)->tbl != *(*it)->name ) continue;
1584       const char *nm = (*idx)->name->c_str();
1585       fprintf(sp,"  if_ret( %s.key_index(\"%s\") );\n", tnm, nm);
1586     }
1587     fprintf(sp,"\n");
1588   }
1589   fprintf(sp,"  if_ret( Db::start_transaction() );\n");
1590   fprintf(sp,"  return 0;\n");
1591   fprintf(sp,"}\n");
1592   fprintf(sp,"\n");
1593   fprintf(sp,"void %s::\n",tdb);
1594   fprintf(sp,"close()\n");
1595   fprintf(sp,"{\n");
1596   fprintf(sp,"  Db::close();\n");
1597   fprintf(sp,"  if( dfd >= 0 ) { ::close(dfd); dfd = -1; }\n");
1598   fprintf(sp,"}\n");
1599   fprintf(sp,"\n");
1600   fprintf(sp,"int %s::\n",tdb);
1601   fprintf(sp,"access(const char *dfn, int key, int rw)\n");
1602   fprintf(sp,"{\n");
1603   fprintf(sp,"  if( key < 0 ) return Db::errInvalid;\n");
1604   fprintf(sp,"  dfd = ::open(dfn,O_RDWR+no_atime);\n");
1605   fprintf(sp,"  if( dfd < 0 ) { perror(dfn); return Db::errNotFound; }\n");
1606   fprintf(sp,"  dkey = key;  Db::use_shm(1);\n");
1607   fprintf(sp,"  int ret = Db::attach(dfd, dkey, rw);\n");
1608   fprintf(sp,"  if( !ret ) ret = db_access();\n");
1609   fprintf(sp,"  else if( ret == errNotFound ) {\n");
1610   fprintf(sp,"    ret = Db::open(dfd, dkey);\n");
1611   fprintf(sp,"    if( !ret ) ret = db_open();\n");
1612   fprintf(sp,"    if( !ret ) ret = Db::attach(rw);\n");
1613   fprintf(sp,"  }\n");
1614   fprintf(sp,"  if( ret ) close();\n");
1615   fprintf(sp,"  return ret;\n");
1616   fprintf(sp,"}\n");
1617   fprintf(sp,"\n");
1618   fprintf(sp,"int %s::\n",tdb);
1619   fprintf(sp,"db_access()\n");
1620   fprintf(sp,"{\n");
1621   for( it=sit ; it!=eit; ++it ) {
1622     tobj *tp = *it;
1623     const char *tnm = tp->name->c_str();
1624     fprintf(sp,"  if_ret( %s.get_entity(\"%s\") );\n", tnm, tnm);
1625   }
1626   fprintf(sp,"  return 0;\n");
1627   fprintf(sp,"}\n");
1628   fprintf(sp,"\n");
1629   fprintf(sp,"\n");
1630   printf("ended on line %d - ",cp.no);
1631   for( int i=0, n=cp.i; i<n; ++i ) printf("%c",cp.line[i]);
1632   printf("|");
1633   for( int i=cp.i, n=cp.n; i<n; ++i ) printf("%c",cp.line[i]);
1634   printf("\n");
1635   return 0;
1636 }
1637