makegr.c
上传用户:dgyhgb
上传日期:2007-01-07
资源大小:676k
文件大小:15k
源码类别:

SQL Server

开发平台:

Unix_Linux

  1. /*
  2.  *  makegr.c  - Make a group
  3.  *              Kernel of GNU SQL-server
  4.  *
  5.  *
  6.  *  This file is a part of GNU SQL Server
  7.  *
  8.  *  Copyright (c) 1996, 1997, Free Software Foundation, Inc
  9.  *  Developed at the Institute of System Programming
  10.  *  This file is written by  Vera Ponomarenko
  11.  *
  12.  *  This program is free software; you can redistribute it and/or modify
  13.  *  it under the terms of the GNU General Public License as published by
  14.  *  the Free Software Foundation; either version 2 of the License, or
  15.  *  (at your option) any later version.
  16.  *
  17.  *  This program is distributed in the hope that it will be useful,
  18.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  19.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  20.  *  GNU General Public License for more details.
  21.  *
  22.  *  You should have received a copy of the GNU General Public License
  23.  *  along with this program; if not, write to the Free Software
  24.  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  25.  *
  26.  *  Contacts:   gss@ispras.ru
  27.  *
  28.  */
  29. /* $Id: makegr.c,v 1.248 1997/04/10 06:57:28 vera Exp $ */
  30. #include "xmem.h"
  31. #include "destrn.h"
  32. #include "agrflg.h"
  33. #include "strml.h"
  34. #include "fdcltrn.h"
  35. extern struct des_nseg desnseg;
  36. static u2_t
  37. fgr_val (char **agrl, char *tuple, char *cort, struct des_trel *destrel,
  38.          u2_t ng, u2_t * glist, u2_t nf, u2_t * mnf, char *flaglist)
  39. {
  40.   char *gval;
  41.   u2_t k, fn, kg, sz, kagr, f_n, fdf;
  42.   struct des_field *df;
  43.   char *arrpnt[BD_PAGESIZE];
  44.   u2_t arrsz[BD_PAGESIZE];
  45.   fdf = destrel->fdftr;
  46.   f_n = destrel->fieldn;
  47.   df = (struct des_field *) (destrel + 1);
  48.   tuple_break (cort, arrpnt, arrsz, df, fdf, f_n);
  49.   gval = tuple;
  50.   *gval++ = CORT;
  51.   for (k = 0, kg = 0, *gval = 0; kg < ng; kg++)
  52.     {
  53.       if (arrpnt[glist[kg]] != NULL) /* a value is present */
  54. *gval |= BITVL(k);
  55.       k++;
  56.       if (k == 7)
  57. {
  58.   k = 0;
  59.   gval++;
  60.   *gval = 0;
  61. }
  62.     }
  63.   for (kagr = 0; kagr < nf; kagr++)
  64.     if (k == 7)
  65.       {
  66.         k = 0;
  67.         gval++;
  68.         *gval = 0;
  69.       }
  70.   if (k == 0)
  71.     gval--;
  72.   *gval++ |= EOSC;
  73.   for (kg = 0; kg < ng; kg++)
  74.     {
  75.       fn = glist[kg];
  76.       if ((sz = arrsz[fn]) != 0)
  77.         {
  78.           bcopy (arrpnt[fn], gval, sz);
  79.           gval += sz;
  80.         }
  81.     }
  82.   sz = gval - tuple;
  83.   for (kagr = 0; kagr < nf; kagr++)
  84.     {
  85.       fn = mnf[kagr];
  86.       agr_frm (agrl[kagr], flaglist[kagr], arrpnt[fn], (df + fn)->field_type);
  87.     }
  88.   return (sz);
  89. }
  90. static void
  91. clear_ttab(u2_t ntab)
  92. {     
  93.   char *asp;
  94.   struct des_trel *destrel;
  95.   u2_t pn, *b;
  96.   struct listtob *l;
  97.   struct A inpage;
  98.     
  99.   destrel = (struct des_trel *) * (desnseg.tobtab + ntab);
  100.   pn = destrel->tobtr.firstpn;
  101.   destrel->tobtr.prdt.prsort = NSORT;
  102.   destrel->tobtr.lastpn = pn;
  103.   asp = getnew (&inpage, NRSNUM, pn);
  104.   l = (struct listtob *) asp;
  105.   l->prevpn = (u2_t) ~ 0;
  106.   l->nextpn = (u2_t) ~ 0;
  107.   b = (u2_t *) (*asp + sizeof (struct listtob));
  108.   destrel->tobtr.free_sz = BD_PAGESIZE - phtrsize;
  109.   *b++ = 0;
  110.   *b = 0;
  111.   putwul (&inpage, 'm');  
  112. }
  113. static void
  114. get_new_trel (char **agrl, u2_t nf, char *flaglist)
  115. {
  116.   u2_t i;
  117.   char *a;
  118.   float avrg = 0;
  119.   for (i = 0; i < nf; i++)
  120.     {
  121.       a = agrl[i];
  122.       switch (flaglist[i])
  123. {
  124. case FN_COUNT:
  125.   a = agrl[i];
  126.   *a++ = 1;
  127.   t4bpack (0, a);
  128.   break;
  129. case FN_SUMM:
  130.   a = agrl[i]; 
  131.   *a++ = 0;
  132.   t4bpack (0, a);
  133.   break;
  134. case FN_MAX:
  135. case FN_MIN:
  136.   a = agrl[i];   
  137.   *a++ = 0;
  138.   t4bpack (0, a);
  139.   break;
  140. case FN_AVG:
  141.   a = agrl[i];   
  142.   *a++ = 0;
  143.   bcopy ((char *)&avrg, a, sizeof (float));
  144.   t4bpack (0, a + size4b);
  145.   break;
  146. case FN_DT_SUMM:
  147.   clear_ttab ( t2bunpack (a));
  148.   a += size2b;   
  149.   *a++ = 0;
  150.   t4bpack (0, a);
  151.   break;
  152. case FN_DT_COUNT:
  153.   clear_ttab ( t2bunpack (a));
  154.   a += size2b;
  155.   *a++ = 1;
  156.   t4bpack (0, a);   
  157.   break;
  158. case FN_DT_AVG:
  159.   clear_ttab ( t2bunpack (a));   
  160.   a += size2b;      
  161.   *a++ = 0;
  162.           bcopy ((char *)&avrg, a, sizeof (float));
  163.   t4bpack (0, a + size4b);   
  164.   break;
  165. default:
  166.   continue;
  167.   break;
  168. }
  169.     }
  170. }
  171. static int
  172. gr_crt_frm (char *tuple, u2_t tsize, char **agrl, struct des_field *df,
  173.             u2_t ng, u2_t nf, u2_t * mnf, char *flaglist)
  174. {
  175.   char *gval;
  176.   char *loc, *sc, flag;
  177.   u2_t k, kk;
  178.   distagr_frm (agrl, nf, flaglist);
  179.   loc = tuple + tsize;
  180.   for (df += ng, k = 0; k < nf; k++)
  181.     {
  182.       if ((flag = flaglist[k]) == FN_DT_COUNT || flag == FN_DT_SUMM ||
  183.           flag == FN_DT_AVG)
  184. gval = agrl[k] + size2b;
  185.       else
  186. gval = agrl[k];
  187.       if (*gval++ != 0)
  188. {
  189.   kk = (ng + k) / 7;
  190.   sc = tuple + 1 + kk;
  191.   kk = (ng + k) % 7;   
  192.   *sc |= BITVL(kk);
  193.           
  194.           if (flag == FN_AVG || flag == FN_DT_AVG)
  195.             loc = write_average ((df + (mnf[k]-ng))->field_type, gval, loc);
  196.           else
  197.             gval = remval (gval, &loc, (df + k)->field_type);
  198. }
  199.     }
  200.   get_new_trel (agrl, nf, flaglist);
  201.   return (loc - tuple);
  202. }
  203. static int
  204. cmp_grval (char *tuple, char *cort, struct des_field *df, u2_t fdf,
  205.            u2_t fields_n, u2_t ng, u2_t * glist)
  206. {
  207.   char *gsc, *gaval;
  208.   u2_t k, fn, kg;
  209.   i4_t v;
  210.   char *gval, *aval;
  211.   u2_t n;
  212.   char *arrpnt[BD_PAGESIZE];
  213.   u2_t arrsz[BD_PAGESIZE];
  214.   tuple_break (cort, arrpnt, arrsz, df, fdf, fields_n);
  215.   gsc = tuple + 1;
  216.   gval = gaval = tuple + scscal (tuple);
  217.   for (k = 0, kg = 0; kg < ng && gsc < gaval; kg++)
  218.     {
  219.       fn = glist[kg];
  220.       if ((aval = arrpnt[fn]) != NULL)
  221. {
  222.   if ((*gsc & BITVL(k)) != 0)
  223.     {
  224.       v = cmpval (gval, aval, (df + fn)->field_type, &n);
  225.       if (v != 0)
  226. return (v);
  227.     }
  228.   else
  229.     return (-1);
  230. }
  231.       else
  232. {
  233.   if ((*gsc & BITVL(k)) != 0)
  234.     return (1);
  235.   else
  236.     return (-1);
  237. }
  238.       k++;
  239.       if (k == 7)
  240. {
  241.   k = 0;
  242.   gsc++;
  243. }
  244.     }
  245.   return (0);
  246. }
  247. static void
  248. df_frm (struct des_field *df_out, struct des_field *df, u2_t ng,
  249.         u2_t * glist, u2_t nf, u2_t * mfn, char *flaglist)
  250. {
  251.   u2_t i;
  252.   struct des_field *df_out2;
  253.   df_out2 = df_out;
  254.   for (i = 0; i < ng; i++)
  255.     *df_out++ = df[glist[i]];
  256.   for (i = 0; i < nf; i++, df_out++)
  257.     {
  258.       switch (flaglist[i])
  259. {
  260. case FN_COUNT:
  261. case FN_DT_COUNT:
  262.   df_out->field_type = T4B;
  263.   df_out->field_size = size4b;
  264.   break;
  265. case FN_MAX:
  266. case FN_MIN:
  267. case FN_SUMM:
  268. case FN_DT_SUMM:
  269.   *df_out = df[mfn[i]];
  270.   break;
  271. case FN_AVG:
  272. case FN_DT_AVG:
  273.   df_out->field_type = TFLOAT;
  274.   df_out->field_size = size4b;
  275.   break;
  276. default:
  277.   break;
  278. }
  279.     }
  280. }
  281. struct ans_ctob
  282. makegroup (struct id_rel *pidrel, u2_t ng, u2_t * glist, u2_t nf,
  283.            u2_t * mnf, char *flaglist, char *order)
  284. {
  285.   u2_t pn, *ai, *afi, *ali, fdf, fn, fn_out, tsize = 0;
  286.   char *cort;
  287.   u2_t i;
  288.   struct des_field *df, *df_out;
  289.   struct des_trel *destrel;
  290.   struct ans_ctob ans;
  291.   u2_t size;
  292.   i2_t ntob;
  293.   struct des_tob *dt;
  294.   struct A inpage, outpg;
  295.   char flag;
  296.   struct id_ob destob;  
  297.   char *outasp, **agrl, *asp, tuple[BD_PAGESIZE];
  298.   if (pidrel->urn.segnum != NRSNUM)
  299.     {
  300.       ans.cpncob = NIOB;
  301.       return (ans);
  302.     }
  303.   destrel = (struct des_trel *) * (desnseg.tobtab + pidrel->urn.obnum);
  304.   if (destrel->row_number > 1)
  305.     {
  306.       ans = trsort (pidrel, ng, glist, order, DBL);
  307.       if (ans.cpncob != OK)
  308.         return (ans);
  309.       destrel = (struct des_trel *) * (desnseg.tobtab + ans.idob.obnum);
  310.     }
  311.   else
  312.     ans.cpncob = OK;
  313.   df = (struct des_field *) (destrel + 1);
  314.   fdf = destrel->fdftr;
  315.   fn = destrel->fieldn;
  316.   if (fdf < glist[0])
  317.     {
  318.       ans.cpncob = NCF;
  319.       return (ans);
  320.     }
  321.   fn_out = ng + nf;
  322.   size = dtrsize + fn_out * rfsize + ng * size2b;
  323.   dt = gettob (&outpg, size, &ntob, TREL);
  324.   outasp = outpg.p_shm;
  325.   pn = destrel->tobtr.firstpn;
  326.   agrl = (char **) xmalloc (nf * sizeof (void *));
  327.   agrl_frm (agrl, df, (u2_t) nf, mnf, flaglist);
  328.   destrel = (struct des_trel *) dt;  
  329.   df_out = (struct des_field *) (destrel + 1);
  330.   df_frm (df_out, df, ng, glist, nf, mnf, flaglist);
  331.   asp = getwl (&inpage, NRSNUM, pn);
  332.   afi = (u2_t *) (asp + phtrsize);
  333.   ali = afi + ((struct p_h_tr *) asp)->linptr;
  334.   for (ai = afi; ai <= ali; ai++)
  335.     if (*ai != 0)
  336.       {
  337. tsize = fgr_val (agrl, tuple, asp + *ai, destrel, ng,
  338.                          glist, nf, mnf, flaglist);
  339. break;
  340.       }
  341.   for (ai++; ai <= ali; ai++)
  342.     if (*ai != 0)
  343.       {
  344. cort = asp + *ai;
  345. if (cmp_grval (tuple, cort, df, fdf, fn, ng, glist) != 0)
  346.   {
  347.     size = gr_crt_frm (tuple, tsize, agrl, df_out, ng, nf, mnf, flaglist);
  348.     minstr (&outpg, tuple, size, dt);
  349.     tsize = fgr_val (agrl, tuple, cort, destrel, ng, glist, nf, mnf, flaglist);
  350.   }
  351. else
  352.           agrcount (agrl, cort, df, fdf, fn, nf, mnf, flaglist);
  353.       }
  354.   pn = ((struct listtob *) asp)->nextpn;
  355.   putwul (&inpage, 'n');
  356.   while (pn != (u2_t) ~ 0)
  357.     {
  358.       asp = getwl (&inpage, NRSNUM, pn);
  359.       afi = (u2_t *) (asp + phtrsize);
  360.       ali = afi + ((struct p_h_tr *) asp)->linptr;
  361.       for (ai = afi; ai <= ali; ai++)
  362. if (*ai != 0)
  363.   {
  364.     cort = asp + *ai;
  365.     if (cmp_grval (tuple, cort, df, fdf, fn, ng, glist) != 0)
  366.       {
  367. size = gr_crt_frm (tuple, tsize, agrl, df_out, ng, nf, mnf, flaglist);
  368. minstr (&outpg, tuple, size, dt);
  369. tsize = fgr_val (agrl, tuple, cort, destrel, ng, glist, nf, mnf, flaglist);
  370.       }
  371.     else
  372.       agrcount (agrl, cort, df, fdf, fn, nf, mnf, flaglist);
  373.   }
  374.       pn = ((struct listtob *) asp)->nextpn;
  375.       putwul (&inpage, 'n');
  376.     }
  377.   size = gr_crt_frm (tuple, tsize, agrl, df_out, ng, nf, mnf, flaglist);
  378.   minstr (&outpg, tuple, size, dt);
  379.   putwul (&outpg, 'm');
  380.   destob.segnum = NRSNUM;  
  381.   for (i = 0; i < nf; i++)
  382.     {
  383.       flag = flaglist[i];
  384.       if (flag == FN_DT_COUNT || flag == FN_DT_SUMM || flag == FN_DT_AVG)
  385. {
  386.   destob.obnum = t2bunpack(agrl[i]);     
  387.   deltob (&destob);
  388. }
  389.       xfree ((void *) agrl[i]);
  390.     }
  391.   xfree ((void *) agrl);
  392.   destrel->fieldn = fn_out;
  393.   destrel->fdftr = 0;
  394.   dt->prdt.prsort = SORT;
  395.   dt->prdt.prdbl = DBL;
  396.   dt->prdt.prdrctn =  *order;
  397.   destrel->keysntr = ng;
  398.   size = dtrsize + fn_out * rfsize;
  399.   for (i = 0, ai = (u2_t *) ((char *) destrel + size); i < ng; i++)
  400.     *ai++ = *glist++;
  401.   ans.idob.segnum = NRSNUM;
  402.   ans.idob.obnum = ntob;
  403.   return (ans);
  404. }
  405. int
  406. tuple_break (char *tuple, char **arrpnt, u2_t * arrsz, struct des_field * df,
  407.                        u2_t fdf, u2_t field_num)
  408. {
  409.   char *sc, *val, *aval, *newval;
  410.   u2_t k, fn;
  411.   int tuple_size;
  412.   sc = tuple + 1;
  413.   tuple_size = scscal (tuple);
  414.   aval = val = tuple + tuple_size;
  415.   for (k = 0, fn = 0; sc < val; fn++)
  416.     {
  417.       if (fn < fdf || (*sc & BITVL(k)) != 0)
  418. { /* a value is present */
  419.   newval = proval (aval, (df + fn)->field_type);
  420.   arrpnt[fn] = aval;
  421.   arrsz[fn] = newval - aval;
  422.           tuple_size += arrsz[fn];
  423.   aval = newval;
  424. }
  425.       else
  426. {
  427.   arrpnt[fn] = NULL;
  428.   arrsz[fn] = 0;
  429. }
  430.       if (fn >= fdf)
  431. {
  432.   k++;
  433.   if (k == 7)
  434.     {
  435.       k = 0;
  436.       sc++;
  437.     }
  438. }
  439.     }
  440.   for (; fn < field_num; fn++)
  441.     {
  442.       arrpnt[fn] = NULL;
  443.       arrsz[fn] = 0;
  444.     }
  445.   return (tuple_size);
  446. }
  447. void
  448. agrl_frm (char **agrl, struct des_field *df, u2_t nf, u2_t * mnf,
  449.           char *flaglist)
  450. {
  451.   u2_t i, size = 0;
  452.   struct des_trel *destrel;
  453.   struct des_field *dftr;
  454.   i2_t n;
  455.   char *a;
  456.   float avrg = 0;
  457.   struct A pg;
  458.   for (i = 0; i < nf; i++)
  459.     {
  460.       switch (flaglist[i])
  461. {
  462. case FN_COUNT:
  463.   size = size4b + 1;
  464.   agrl[i] = (char *) xmalloc (size);
  465.   a = agrl[i];
  466.   *a++ = 1;
  467.   t4bpack (0, a);
  468.   break;
  469. case FN_SUMM:
  470.   size = gmax((df + mnf[i])->field_size,size4b) + 1;
  471.   agrl[i] = (char *) xmalloc (size);
  472.   a = agrl[i];   
  473.   *a++ = 0;
  474.   t4bpack (0, a);
  475.   break;
  476. case FN_MAX:
  477. case FN_MIN:
  478.   size = gmax((df + mnf[i])->field_size,size4b) + 1;
  479.   agrl[i] = (char *) xmalloc (size);
  480.   a = agrl[i];   
  481.   *a++ = 0;
  482.   t4bpack (0, a);
  483.   break;
  484. case FN_AVG:
  485.   size = sizeof (float) + size4b + 1;
  486.   agrl[i] = (char *) xmalloc (size);
  487.   a = agrl[i];   
  488.   *a++ = 0;
  489.   bcopy ((char *)&avrg, a, sizeof (float));
  490.   t4bpack (0, a + size4b);
  491.   break;
  492. case FN_DT_SUMM:
  493.   destrel = (struct des_trel *) gettob (&pg, dtrsize + rfsize, &n, TREL);
  494.   putwul (&pg, 'm');
  495.   destrel->fieldn = 1;
  496.   destrel->fdftr = 0;
  497.           /*
  498.            * dftr = (struct des_field *) (destrel + 1);
  499.            * *dftr = *(df + mnf[i]);
  500.            */
  501.   dftr = (df + mnf[i]);
  502.   size = gmax(dftr->field_size,size4b) + size2b + 1;
  503.   agrl[i] = (char *) xmalloc (size);
  504.   t2bpack (n, agrl[i]);   
  505.   a = agrl[i] + size2b;   
  506.   *a++ = 0;
  507.   t4bpack (0, a);
  508.   break;
  509. case FN_DT_COUNT:
  510.   destrel = (struct des_trel *) gettob (&pg, dtrsize + rfsize, &n, TREL);
  511.   putwul (&pg, 'm');
  512.   destrel->fieldn = 1;
  513.   destrel->fdftr = 0;
  514.   dftr = (struct des_field *) (destrel + 1);
  515.   dftr->field_type = T4B;
  516.   dftr->field_size = size4b;
  517.   size = size4b + size2b + 1;
  518.   agrl[i] = (char *) xmalloc (size);
  519.   t2bpack (n, agrl[i]);   
  520.   a = agrl[i] + size2b;   
  521.   *a++ = 1;
  522.   t4bpack (0, a);
  523.   break;
  524. case FN_DT_AVG:
  525.   destrel = (struct des_trel *) gettob (&pg, dtrsize + rfsize, &n, TREL);
  526.   putwul (&pg, 'm');
  527.   destrel->fieldn = 1;
  528.   destrel->fdftr = 0;
  529.   dftr = (struct des_field *) (destrel + 1);
  530.   dftr->field_type = TFLOAT;
  531.   dftr->field_size = size4b;
  532.   size = sizeof (float) + size4b + 1 + size2b;
  533.   agrl[i] = (char *) xmalloc (size);
  534.   t2bpack (n, agrl[i]);   
  535.   a = agrl[i] + size2b;   
  536.   *a++ = 0;
  537.           bcopy ((char *)&avrg, a, sizeof (float));
  538.   t4bpack (0, a + size4b);   
  539.   break;
  540. default:
  541.   break;
  542. }
  543.     }
  544. }
  545. static void
  546. dist_count (char *agrl, char flag)
  547. {
  548.   u2_t *ai, *afi, *ali, pn;
  549.   struct des_field *df;
  550.   u2_t fdf, fn;
  551.   struct des_trel *destrel;
  552.   char *arrpnt[BD_PAGESIZE];
  553.   u2_t arrsz[BD_PAGESIZE];  
  554.   struct A inpage;
  555.   char *pnt, *asp;
  556.   
  557.   destrel = (struct des_trel *) * (desnseg.tobtab + t2bunpack( agrl));
  558.   df = (struct des_field *) (destrel + 1);
  559.   pn = destrel->tobtr.firstpn;
  560.   fdf = destrel->fdftr;
  561.   fn = destrel->fieldn;  
  562.   pnt = agrl + size2b;
  563.   for (; pn != (u2_t) ~ 0;)
  564.     {
  565.       asp = getwl (&inpage, NRSNUM, pn);
  566.       afi = (u2_t *) (asp + phtrsize);
  567.       ali = afi + ((struct p_h_tr *) asp)->linptr;
  568.       for (ai = afi; ai <= ali; ai++)
  569. if (*ai != 0)
  570.   {
  571.     tuple_break (asp + *ai, arrpnt, arrsz, df, fdf, fn);
  572.     agr_frm (pnt, flag, arrpnt[0], df->field_type);
  573.   }
  574.       pn = ((struct listtob *) asp)->nextpn;
  575.       putwul (&inpage, 'n');
  576.     }
  577. }
  578. void
  579. distagr_frm (char **agrl, u2_t nf, char *flaglist)
  580. {
  581.   u2_t i;
  582.   i2_t n;
  583.   struct des_trel *destrel;
  584.   char *pnt, flag;
  585.   struct id_rel idrel;
  586.   idrel.urn.segnum = NRSNUM;
  587.   for (i = 0; i < nf; i++)
  588.     {
  589.       pnt = agrl[i];
  590.       switch (flaglist[i])
  591. {
  592. case FN_DT_SUMM:
  593.   flag = FN_SUMM;
  594.   break;
  595. case FN_DT_COUNT:
  596.   flag = FN_COUNT;
  597.   break;
  598. case FN_DT_AVG:
  599.   flag = FN_AVG;
  600.   break;
  601. default:
  602.   continue;
  603.   break;
  604. }
  605.       n = t2bunpack (pnt);
  606.       destrel = (struct des_trel *) * (desnseg.tobtab + n);
  607.       if (destrel->row_number > 1)
  608.         {
  609.           char order;
  610.           u2_t nfs = 0;
  611.           i2_t nnew;
  612.           struct ans_ctob ans;
  613.           idrel.urn.obnum = n;
  614.           order = GROW;
  615.           ans = trsort (&idrel, 1, &nfs, &order, NODBL);
  616.           nnew = ans.idob.obnum;
  617.           if (n != nnew)
  618.             {
  619.               t2bpack(nnew, pnt);
  620.               deltob (&idrel.urn);
  621.             }
  622.         }
  623.       dist_count (pnt, flag);
  624.     }
  625. }