# 2.11BSD#431 - /usr/ingres/source/dbu/copy.c

##### Functions

    bread             X
    charmove          X
    copy              X
    copydone          X
    dumvalue          X
    file_rel          X
    mapfill           X
    rel_file          X
    transfer          X
    zcheck            X

##### Variables

    Baddoms           X
    Cpdomains         X
    Delimitor         X
    Des               X
    Duptuple          X
    Filename          X
    Inbuf             X
    Into              X
    Map               X
    Mapcount          X
    Outbuf            X
    Piped             X
    Relname           X
    Truncount         X
    Tupcount          X

##### Macros

    BUFSIZE           X
    DUMMY             X
    ESCAPE            X
    MAXMAP            X
    WBUFSIZE          X

##### struct's

    map               X

       1: #include    <stdio.h>
       2:
       3: # include   "../ingres.h"
       4: # include   "../aux.h"
       5: # include   "../access.h"
       6: # include   "../symbol.h"
       7: # include   "../lock.h"
       8:
       9: # define    BUFSIZE     1024
      10: # define    WBUFSIZE    512
      11: # define    MAXMAP      3 * MAXDOM
      12: # define    DUMMY       'd'
      13: # define    ESCAPE      '\\'
      14:
      15:
      16: struct map
      17: {
      18:     char    name[MAXNAME+1];    /* attribute name */
      19:     char    ftype;      /* attfrmt of file domain */
      20:     char    rtype;      /* attfrmt of relation domain */
      21:     int flen;       /* attfrml of file domain */
      22:     int rlen;       /* attfrml of relation domain */
      23:     int roffset;    /* attoff of relation domain */
      24:     int used;       /* tag for duplicate checking */
      25:     char    *fdelim;    /* pointer to list of file param delims */
      26:     char    *paramname; /* pointer to original parameter name */
      27:                 /* used for supplying domain name in case of error */
      28: };
      29: struct map  Map[MAXMAP];        /* one entry for each user
      30: 				   specified domain in copy statement. */
      31:
      32: int Mapcount;       /* number of Map entries   */
      33:
      34:
      35: struct descriptor Des;      /* descriptor for copied relation     */
      36:
      37: extern struct out_arg   Out_arg;    /* user defined formats for numeric output */
      38:
      39: FILE    *File_iop;      /* i/o file pointer */
      40: char    *Filename;      /* pointer to file name */
      41:
      42: int Into;           /* into is one if this is a copy into file */
      43:
      44: char    Inbuf[BUFSIZE];     /* input holder */
      45: char    Outbuf[BUFSIZE];    /* output holder */
      46:
      47: long    Tupcount;       /* number of tuples processed */
      48: char    *Relname;       /* name of relation */
      49: long    Duptuple;       /* number of duplicate tuples */
      50: long    Baddoms;        /* number of domains with control chars */
      51: long    Truncount;      /* number of truncations on a c0 field */
      52: int Piped[2];       /* pipe descriptor for copy communication */
      53: char    *Cpdomains[] =      /* dummy domain names for copy "into" */
      54: {
      55:     "nl",       "\n",
      56:     "tab",      "\t",
      57:     "sp",       " ",
      58:     "nul",      "\0",
      59:     "null",     "\0",
      60:     "comma",    ",",
      61:     "colon",    ":",
      62:     "dash",     "-",
      63:     "lparen",   "(",
      64:     "rparen",   ")",
      65:     0
      66: };
      67:
      68: char    Delimitor[] =   ",\n\t";    /* default delims for c0 & d0 */
      69:
      70:
      71: /*
      72: **  COPY -- Performs an ingres COPY.
      73: **
      74: **	History:
      75: **		9/12/78 -- (marc) modified to print
      76: **			an error message when trying to
      77: **			copy into a view.
      78: **			For this the error number 5518
      79: **			was added and the call on openr was split
      80: **			into two.
      81: */
      82:
      83:
      84: copy(pc,pv)
      85: int pc;
      86: char    **pv;
      87: {
      88:     extern char *Usercode;
      89:     extern int  Noupdt;
      90:     register int    i, pid;
      91:     register char   *cp;
      92:     int     stat;
      93:     int     copydone();
      94:     int     op;
      95:
      96: #	ifdef xZTR1
      97:     if (tTf(7,1))
      98:         printf("entered copy\n");
      99: #	endif
     100:     Duptuple = 0;
     101:     Truncount = 0;
     102:     Tupcount = 0;
     103:     Baddoms = 0;
     104:     Relname = pv[0];
     105:     Into = (pv[pc-2][0] == 'i');
     106:     Filename = pv[pc-1];
     107:
     108:     /* relation must exist and not be a system relation */
     109:     /* in addition a copy "from" can't be done if the user */
     110:     /* doesn't own the relation */
     111:     /* and furthermore it can't have an index */
     112:     i = 0;  /* assume all is well */
     113:     if (op = openr(&Des, 2, Relname))
     114:     {
     115:         if (op == AMOPNVIEW_ERR)
     116:             i = 5818;
     117:         else
     118:         {
     119:             if (op < 0)
     120:                 syserr("COPY: openr 1 (%.14s) %d", Relname, op);
     121:             else
     122:                 /* non-existant relation */
     123:                 i = 5800;
     124:         }
     125:     }
     126:     else
     127:     {
     128:         if (Into)
     129:         {
     130:             if ((Des.relstat & S_PROTALL)
     131:                 && (Des.relstat & S_PROTRET)
     132:                 && !bequal(Usercode, Des.relowner, 2))
     133:                 i = 5822;
     134:         }
     135:         else
     136:         {
     137:             /* extra checking if this is a copy "from" */
     138:
     139:             /* must be owned by the user */
     140:             if (!bequal(Usercode, Des.relowner, 2))
     141:                 i = 5814;
     142:             else
     143:                 /* must be updateable */
     144:                 if ((Des.relstat & S_NOUPDT) && Noupdt)
     145:                     i = 5813;
     146:                 else
     147:                     /* must not be indexed */
     148:                     if (Des.relindxd > 0)
     149:                         i = 5812;
     150:         }
     151:     }
     152:     if (i)
     153:     {
     154:         closer(&Des);
     155:         return (error(i, Relname, 0));  /* relation doesn't exist for this user */
     156:     }
     157:
     158:     /* check that file name begins with a "/" */
     159:     cp = Filename;
     160:     while (*cp == ' ')
     161:         cp++;
     162:     if (*cp != '/')
     163:     {
     164:         closer(&Des);
     165:         return (error(5816, Filename, 0));
     166:     }
     167:
     168:     /* fill map structures with transfer information */
     169:     if (i = mapfill(&pv[1]))
     170:     {
     171:         closer(&Des);
     172:         return (i); /* error in user semantics */
     173:     }
     174:
     175:     /* fork a child process which will run as the real user */
     176:     /* that child will complete the copy and exit */
     177:     if (pipe(Piped))
     178:         syserr("copy:can't make pipe");
     179:     if ((pid = fork()) < 0)
     180:         syserr("copy:can't fork");
     181:     if (pid)
     182:     {
     183:         /* the ingres parent */
     184:         close(Piped[1]);
     185:         ruboff(0);  /* interrupts off */
     186:         stat = fullwait(pid, "copy");
     187:         if (read(Piped[0], &Des.reladds, 4) != 4)
     188:             syserr("copy:can't read pipe");
     189:         close(Piped[0]);
     190:         closer(&Des);   /* close the rel */
     191:         rubon();
     192:         /* if stat is != 0 then add on 5800 for error */
     193:         if (stat)
     194:             stat += 5800;
     195:         return (stat);  /* done */
     196:     }
     197:
     198:     /* the child. change to run as the real user */
     199:     if (signal(2, 1) != 1)
     200:         signal(2, copydone);    /* clean up on rubout */
     201:     setuid(getuid());
     202: #	ifndef xB_UNIX
     203:     setgid(getgid());
     204: #	endif
     205:     if (Into)   /* from relation into file */
     206:     {
     207:         if ((File_iop = fopen(Filename, "w")) == NULL) /* create file for user */
     208:             i = error(5806, Filename, 0);   /* cant create file */
     209:         else
     210:         {
     211:             if (Lockrel)    /* set a shared lock on relation*/
     212:                 setrll(A_SLP, Des.reltid, M_SHARE);
     213:             i = rel_file();
     214:         }
     215:     }
     216:     else        /* from UNIX file into relation */
     217:     {
     218:         if ((File_iop = fopen(Filename, "r")) == NULL)
     219:             i = error(5805, Filename, 0);   /* cant open user file */
     220:         else
     221:         {
     222:             if (Lockrel)    /* set an exclusive lock on relat*/
     223:                 setrll(A_SLP, Des.reltid, M_EXCL);
     224:             i = file_rel();
     225:             if (Duptuple)
     226:                 error(5819, locv(Duptuple), 0); /* warning only */
     227:             if (Baddoms)
     228:                 error(5820, locv(Baddoms), 0);  /* warning only */
     229:         }
     230:     }
     231:     copydone(i);
     232: }
     233:
     234:
     235: copydone(i)
     236: int i;
     237:
     238: /*
     239: **	Finish up and exit after a copy or interrupt
     240: **
     241: **	I is the return code. Since only a byte can be
     242: **	returned, only the least significant 2 decimal
     243: **	digits are returned. i is either 0 or a number like 58??
     244: */
     245:
     246: {
     247:     if (Lockrel)    /* unlock relation */
     248:         unlrl(Des.reltid);
     249:     if (Truncount)
     250:         error(5821, locv(Truncount), 0);    /* warning only */
     251:     /*  force the updates to be flushed */
     252:     cleanrel(&Des);
     253:     if (File_iop)
     254:         fclose(File_iop);
     255:     if (write(Piped[1], &Des.reladds, 4) != 4)
     256:         syserr("copyc:can't writepipe");
     257:     exit (i % 100);
     258: }
     259:
     260:
     261:
     262: rel_file()
     263: {
     264:     int         j;
     265:     struct tup_id       tid, limtid;
     266:     char            *cp, save;
     267:     register int        offset;
     268:     register int        i;
     269:     register struct map *mp;
     270:
     271:     /* set scan limits to scan the entire relation */
     272:     if (find(&Des, NOKEY, &tid, &limtid))
     273:         syserr("find error");
     274:
     275:     while ((i = get(&Des, &tid, &limtid, Inbuf, 1)) == 0)
     276:     {
     277:         mp = Map;
     278:         offset = 0;
     279:         for (i = 0; i < Mapcount; i++)
     280:         {
     281:             /* For cases of char to numeric conversion,
     282: 			   there must be a null byte at the end of the
     283: 			   string. The character just past the current
     284: 			   domain is saved an a null byte inserted */
     285:             cp = &Inbuf[mp->roffset + mp->rlen];    /* compute address */
     286:             save = *cp; /* get the character */
     287:             *cp = '\0'; /* insert a null */
     288:             j = transfer(&Inbuf[mp->roffset], mp->rtype, mp->rlen,
     289:                      mp->ftype, mp->flen, offset);
     290:             if (j)
     291:             {
     292:                 /* bad ascii to numeric conversion or field length too small */
     293:                 return (error(j, mp->paramname, &Inbuf[mp->roffset], locv(Tupcount), Relname, Filename, 0));
     294:             }
     295:             *cp = save; /* restore the saved character */
     296:             offset += mp->flen;
     297:             mp++;
     298:         }
     299:         Tupcount++;
     300:         if (fwrite(Outbuf, 1, offset, File_iop) != offset)
     301:             syserr("copy:cant write to user file %s", Filename);
     302:     }
     303:     if (i < 0)
     304:         syserr("bad get from rel %d", i);
     305:     return (0);
     306: }
     307:
     308:
     309:
     310: file_rel()
     311: /*
     312: **	file_rel is called to transfer tuples from
     313: **	the input file and append them to the relation
     314: **
     315: **	Char domains are initialized to blank and numeric
     316: **	domains are initialized to zero.
     317: */
     318: {
     319:     register int        i, j;
     320:     register struct map *mp;
     321:     struct tup_id       tid;
     322:
     323:     clr_tuple(&Des, Outbuf);
     324:
     325:     /* copy domains until an end of file or an error */
     326:     for (;;)
     327:     {
     328:         mp = Map;
     329:         for (i = 0; i < Mapcount; i++)
     330:         {
     331:             if ((j = bread(mp)) <= 0)
     332:             {
     333:                 if (j < 0)
     334:                 {
     335:                     i = 1;  /* force an error */
     336:                     j = 5815;   /* unterminated string */
     337:                 }
     338:                 else
     339:                     j = 5810;   /* end of file */
     340:                 if (i)  /* error only if end of file during a tuple or unterminated string */
     341:                 {
     342:                     i = error(j, mp->paramname, locv(Tupcount), Filename, Relname, 0);
     343:                 }
     344:                 return (i);
     345:             }
     346:             j = transfer(Inbuf, mp->ftype, mp->flen, mp->rtype, mp->rlen, mp->roffset);
     347:             if (j)
     348:             {
     349:                 /* bad ascii to numeric or field length too small */
     350:                 return (error(j, mp->paramname, Inbuf, locv(Tupcount), Filename, Relname, 0));
     351:             }
     352:             mp++;
     353:         }
     354:         Tupcount++;
     355:         if ((j = insert(&Des, &tid, Outbuf, 1)) < 0)
     356:             syserr("insert error %d rel=%s", j, Relname);
     357:         if (j == 1)
     358:             Duptuple++;
     359:         mp++;
     360:     }
     361:     return (0);
     362: }
     363:
     364:
     365:
     366: transfer(in, sf, sl, df, dl, doff)
     367:
     368: char    *in;    /* pointer to input chars */
     369: char    sf; /* source format */
     370: int sl; /* source length */
     371: char    df; /* destination format */
     372: int dl; /* destination length */
     373: int doff;   /* destination offset */
     374:
     375: /*
     376: **	transfer copies data from "*in" to
     377: **	Outbuf doing conversions whenever
     378: **	necessary
     379: */
     380:
     381: {
     382:     double      d;
     383:     float       f;
     384:     register char   *inp, *outp;
     385:     register int    i;
     386:     int     j;
     387:     long        l;
     388:     char        temp[MAXFIELD]; /* holds char during conversions to ascii */
     389:
     390:
     391:     outp = &Outbuf[doff];
     392:     inp = in;
     393:
     394:     if (sf == DUMMY)
     395:         /* if source format is a dummy fields then
     396: 		   nothing else need be done */
     397:         return (0);
     398:
     399:     if (df == DUMMY)
     400:     {
     401:         /* fill field with dummy domain character */
     402:         i = dl; /* i equals the number of chars */
     403:         while (i--)
     404:             *outp++ = sf;   /* sf holds dummy char */
     405:         return (0);
     406:     }
     407:
     408:     if (sf != CHAR)
     409:     {
     410:         if (df == CHAR) /* numeric to char conversion */
     411:         {
     412:             switch (sl)
     413:             {
     414:
     415:               /* int of size 1 or 2 */
     416:               case 1:
     417:                 itoa(*inp, temp);
     418:                 break;
     419:
     420:               case 2:
     421:                 bmove(inp, &j, 2);  /* copy to an integer */
     422:                 itoa(j, temp);  /* convert to ascii */
     423:                 break;
     424:
     425:               /* int or float of size 4 */
     426:               case 4:
     427:                 if (sf == INT)
     428:                 {
     429:                     bmove(inp, &l, 4);  /* copy to a long */
     430:                     smove(locv(l), temp);   /* convert and copy */
     431:                 }
     432:
     433:                 else
     434:                 {
     435:                     bmove(inp, &f, 4);
     436:                     ftoa(f, temp, dl, Out_arg.f4prec, Out_arg.f4style);
     437:                 }
     438:                 break;
     439:
     440:               /* float of size 8 */
     441:               case 8:
     442:                 bmove(inp, &d, 8);  /* copy to a dbl variable */
     443:                 ftoa(d, temp, dl, Out_arg.f8prec, Out_arg.f8style);
     444:                 break;
     445:
     446:               /* there is no possible default */
     447:               default:
     448:                 syserr("bad domain length %d",sl);
     449:             }
     450:
     451:             j = length(temp);
     452:             if ((i = dl - j) < 0)
     453:                 return (5808);  /* field won't fit */
     454:
     455:             /* blank pad from left. Number will be right justified */
     456:             while (i--)
     457:                 *outp++ = ' ';
     458:
     459:             bmove(temp, outp, j);
     460:             return (0);
     461:         }
     462:
     463:         if (convert(inp, outp, sf, sl, df, dl)) /* numeric to numeric transfer */
     464:             return (5808);  /* numeric truncation error */
     465:         return (0);
     466:     }
     467:
     468:     /* character to numeric conversion */
     469:     /* and character to character conversion */
     470:     switch (df)
     471:     {
     472:
     473:       case CHAR:
     474:         i = sl;
     475:         if (!i)
     476:         {
     477:             i = length(inp);
     478:         }
     479:         if (i > dl)
     480:             i = dl;
     481:         if (charmove(inp, outp, i))
     482:             Baddoms++;
     483:         for (outp += i; i<dl; i++)
     484:             *outp++ = ' ';
     485:         return (0);
     486:
     487:       case FLOAT:
     488:         if (atof(inp, &d))
     489:             return (5809);  /* bad conversion to numeric */
     490:         if (dl == 8)
     491:             bmove(&d, outp, dl);
     492:         else
     493:         {
     494:             f = d;  /* f8 to f4 conversion */
     495:             bmove(&f, outp, dl);
     496:         }
     497:         return (0);
     498:
     499:       case INT:
     500:         if (dl == 4)
     501:         {
     502:             if (atol(inp, &l))
     503:                 return (5809);
     504:             bmove(&l, outp, 4);
     505:             return (0);
     506:         }
     507:         if (atoi(inp, &j))
     508:             return (5809);
     509:         if ((dl == 1) && ((j < -128) || (j > 127)))
     510:             return (5809);
     511:         bmove(&j, outp, dl);
     512:         return (0);
     513:     }
     514: }
     515:
     516: charmove(in, out, length)
     517: char    *in, *out;
     518: int length;
     519:
     520: /*
     521: **	moves a character string from "in"
     522: **	to "out" removing any control characters.
     523: **	returns true if any control characters were found
     524: */
     525:
     526: {
     527:     register char   *ip, *op;
     528:     register int    l;
     529:     int     bad;
     530:
     531:     bad = FALSE;
     532:     ip = in;
     533:     op = out;
     534:     l = length;
     535:
     536:     while (l--)
     537:         if ((*op++ = *ip++) < ' ')
     538:         {
     539:             *(op-1) = ' ';
     540:             bad = TRUE;
     541:         }
     542:     return (bad);
     543: }
     544:
     545:
     546:
     547: mapfill(aptr)
     548: /*
     549: **	Mapfill fills the Map structure with the list
     550: **	of user supplied attributes. It then reads
     551: **	the list of relation attributes and checks
     552: **	for matching attribute names.
     553: **
     554: **	if an error occures then mapfill returns -1
     555: **		else it returns 0
     556: **
     557: **	Mapfill performs special processing on
     558: **	dummy domains.
     559: **
     560: **	If no user attributes are given, then "given"=FALSE
     561: **	and each attribute in the relation is set up to be
     562: **	copied in the formats and order in which they
     563: **	exist in the relation
     564: */
     565:
     566: char    **aptr;
     567:
     568: {
     569:     register char       **ap;
     570:     register struct map *mp;
     571:     register int        i;
     572:     char            *fp;
     573:     extern struct descriptor Attdes;
     574:     struct  attribute   att;
     575:     struct tup_id       tid, limtid;
     576:     int         given, cnt;
     577:     char            *zcheck();
     578:     char            *dumvalue();
     579:
     580:     Mapcount = 0;
     581:     mp = Map;
     582:     ap = aptr;
     583:
     584:     /* Gather list of user supplied attributes */
     585:
     586:     while (**ap)
     587:     {
     588:         /* check for overflow */
     589:         if (Mapcount == MAXMAP)
     590:             return (error(5803, 0));    /* more than MAXMAP specifiers */
     591:
     592:         mp->paramname = *ap;    /* save pointer to user supplied name */
     593:         pmove(*ap++, mp->name, MAXNAME, ' ');
     594:         fp = *ap++; /* fp points to format string */
     595:         mp->used = 0;
     596:         mp->rlen = 0;   /* zero in case this is a dummy domain */
     597:         mp->roffset = 0;
     598:         mp->fdelim = 0;
     599:         /* check domain type in *fp */
     600:         switch (*fp++)
     601:         {
     602:
     603:           case 'c':
     604:             i =  CHAR;
     605:             if ((mp->fdelim = zcheck(fp)) == 0)
     606:                 return (-1);    /* bad delimitor */
     607:             break;
     608:
     609:           case 'f':
     610:             i = FLOAT;
     611:             break;
     612:
     613:           case 'i':
     614:             i = INT;
     615:             break;
     616:
     617:           case DUMMY:
     618:             i = DUMMY;
     619:             if ((mp->fdelim = zcheck(fp)) == 0)
     620:                 return (-1);
     621:             break;
     622:
     623:           default:
     624:             return (error(5811, mp->paramname, --fp, 0));
     625:         }
     626:         mp->ftype = i;
     627:
     628:
     629:         /* convert format length to binary */
     630:         if (atoi(fp, &mp->flen) ||
     631:             mp->flen < 0 ||
     632:             mp->flen > 511 ||
     633:             (mp->ftype == FLOAT && mp->flen != 4 && mp->flen != 8) ||
     634:             (mp->ftype == INT && mp->flen != 1 && mp->flen != 2 && mp->flen != 4))
     635:         {
     636:             return (error(5804, mp->paramname, --fp, 0));   /* bad length for attribute */
     637:         }
     638:
     639:         /* process dummy domain if any */
     640:         if (Into && mp->ftype == DUMMY && mp->flen)
     641:         {
     642:             if ((fp = dumvalue(mp->paramname)) == 0)
     643:                 return (5807);  /* bad dummy name */
     644:             mp->rtype = *fp;    /* use first char of string */
     645:         }
     646:
     647:         /* check for format of type "c0delim" on copy "into" */
     648:         if (Into && mp->flen == 0 && mp->fdelim != Delimitor)
     649:         {
     650:             fp = mp->fdelim;
     651:
     652:             /* is there room for a dummy domain? */
     653:             mp++;
     654:             if (++Mapcount == MAXMAP)
     655:                 return (error(5803, 0));    /* no room */
     656:
     657:             /* create a dummy entry */
     658:             mp->ftype = DUMMY;
     659:             mp->flen = 1;
     660:             mp->rtype = *fp;
     661:             mp->roffset = mp->rlen = 0;
     662:         }
     663:
     664:         mp++;
     665:         Mapcount++;
     666:     }
     667:     /* if no atributes were given, set flag */
     668:     if (Mapcount)
     669:         given = TRUE;
     670:     else
     671:         given = FALSE;
     672:
     673:     /* open attribute relation and prepare for scan */
     674:     opencatalog("attribute", 0);
     675:
     676:     setkey(&Attdes, &att, Des.relid, ATTRELID);
     677:     setkey(&Attdes, &att, Des.relowner, ATTOWNER);
     678:
     679:     if (find(&Attdes, EXACTKEY, &tid, &limtid, &att))
     680:         syserr("find error for att-rel");
     681:
     682:     /* scan Map for each relation attribute */
     683:     while ((i = get(&Attdes, &tid, &limtid, &att, 1)) == 0)
     684:     {
     685:         if (!bequal(&Des, &att, MAXNAME+2))
     686:             continue;
     687:         /* if no user attributes were supplied, fake an entry */
     688:         if (!given)
     689:         {
     690:             Mapcount++;
     691:             mp = &Map[att.attid -1];
     692:             mp->rtype = mp->ftype = att.attfrmt;
     693:             mp->rlen = mp->flen = att.attfrml & 0377;
     694:             mp->roffset = att.attoff;
     695:             mp->used = 1;
     696:             mp->paramname = mp->name;   /* point to name */
     697:             bmove(att.attname, mp->name, MAXNAME);  /* copy name */
     698:             continue;
     699:         }
     700:         mp = Map;
     701:
     702:         /* check each user domain for match with relation domain */
     703:         for (i = Mapcount; i--;  mp++)
     704:         {
     705:             if (mp->ftype == DUMMY)
     706:                 continue; /* ignore dummy */
     707:             if (!bequal(mp->name, att.attname, 12))
     708:                 continue;
     709:
     710:             mp->rtype = att.attfrmt;
     711:             mp->rlen = att.attfrml & 0377;
     712:             mp->roffset = att.attoff;
     713:             mp->used++;
     714:
     715:             /* check for special case of C0 in a copy "into" */
     716:             if (Into && (mp->flen == 0) && mp->ftype == CHAR)
     717:             {
     718:                 switch (mp->rtype)
     719:                 {
     720:                   case CHAR:
     721:                     mp->flen = mp->rlen;
     722:                     break;
     723:
     724:                   case INT:
     725:                     switch (mp->rlen)
     726:                     {
     727:
     728:                       case 1:
     729:                         mp->flen = Out_arg.i1width;
     730:                         break;
     731:
     732:                       case 2:
     733:                         mp->flen = Out_arg.i2width;
     734:                         break;
     735:
     736:                       case 4:
     737:                         mp->flen = Out_arg.i4width;
     738:                     }
     739:                     break;
     740:
     741:                   case FLOAT:
     742:                     if (mp->rlen == 4)
     743:                         mp->flen = Out_arg.f4width;
     744:                     else
     745:                         mp->flen = Out_arg.f8width;
     746:                 }
     747:             }
     748:             /*  if this is a copy "from" then break
     749: 			    otherwise continue. In a copy "into"
     750: 			    an attribute might be copied more than once */
     751:             if (!Into)
     752:                 break;
     753:         }
     754:     }
     755:     if (i < 0)
     756:         syserr("bad get from att-rel %d", i);
     757:
     758:     /* check that all user domains have been identified */
     759:     cnt = 0;
     760:     mp = Map;
     761:     for (i = Mapcount; i--; mp++)
     762:     {
     763:         cnt += mp->flen;
     764:         if (mp->ftype == DUMMY)
     765:             continue;
     766:         if (!mp->used)
     767:         {
     768:             return (error(5801, mp->paramname, Relname, 0));    /* unrecognizable domain name */
     769:         }
     770:     }
     771:     /* check that copy into doesn't exceed buffer size */
     772:     if (Into && cnt > BUFSIZE)
     773:         return (error(5817, 0));    /* cnt too large */
     774:     return (0);
     775: }
     776:
     777:
     778: bread(mp)
     779: struct map  *mp;
     780: {
     781:     register int    count,  i;
     782:     register char   *inp;
     783:     char        *dl;
     784:     int     esc;    /* escape flag */
     785:
     786:     count = mp->flen;
     787:     inp = Inbuf;
     788:
     789:     if (count)
     790:     {
     791:         /* block mode. read characters */
     792:         i = fread(inp, 1, count, File_iop);
     793:
     794:         /* null terminate */
     795:         *(inp + count) = '\0';
     796:
     797:         return (i == count);    /* true -> normal, false ->eof */
     798:     }
     799:
     800:     /* string mode read */
     801:     /*
     802: 	** Determine the maximum size the C0 field being read can be.
     803: 	** In the case where it is being copied into a CHAR field, then
     804: 	** the size is that of the char field (+1 for the delimitor).
     805: 	** In the case of a numeric, it is limited only by the size of the
     806: 	** buffer area.
     807: 	*/
     808:     count = mp->rtype == CHAR ? mp->rlen + 1 : BUFSIZE;
     809:     esc = FALSE;
     810:
     811:     for (;;)
     812:     {
     813:         if ((i = getc(File_iop)) == EOF)
     814:             return (inp == Inbuf ? 0 : -1); /* -1 -> unexpected EOF, 0 -> normal EOF */
     815:
     816:         if (count > 0)
     817:         {
     818:             count--;
     819:             *inp++ = i;
     820:         }
     821:         else
     822:         {
     823:             if (count == 0)
     824:             {
     825:                 /* determine type of overflow */
     826:                 if (mp->rtype == CHAR)
     827:                 {
     828:                     Truncount++;
     829:                     count--;    /* read until delim */
     830:                 }
     831:                 else
     832:                 {
     833:                     return (-1);
     834:                 }
     835:             }
     836:         }
     837:         if (esc)
     838:         {
     839:             esc = FALSE;
     840:             continue;
     841:         }
     842:         if (i == ESCAPE)
     843:         {
     844:             esc = TRUE;
     845:             /*
     846: 			** If esc was stored, back it up.
     847: 			*/
     848:             if (count >= 0)
     849:             {
     850:                 inp--;  /* remove escape char */
     851:                 count++;    /* restore counter */
     852:             }
     853:         }
     854:         else
     855:         {
     856:             for (dl = mp->fdelim; *dl; dl++)
     857:                 if (*dl == i)
     858:                 {
     859:                     *(inp-1) = '\0';
     860:                     return (1);
     861:                 }
     862:         }
     863:     }
     864: }
     865:
     866:
     867: char *zcheck(param)
     868: char    *param;
     869:
     870: /*
     871: **	Look for the existence of a param of the
     872: **	form "0nl" or "00comma" etc.
     873: **
     874: **	Returns the correct delim list or 0
     875: **	if there was a user error
     876: **
     877: **	If successful, a null is inserted at the
     878: **	rightmost '0' so the subsequent atoi will work.
     879: */
     880:
     881: {
     882:     register char   *np, *ret;
     883:     char *dumvalue();
     884:
     885:     np = param;
     886:     ret = Delimitor;    /* assume default delimitors */
     887:
     888:     if (*np++ == '0')
     889:     {
     890:
     891:         /* we have a starting zero. trim the rest */
     892:         while (*np == '0')
     893:             np++;
     894:
     895:         if (*np > '9' || (*np < '0' && *np >= ' '))
     896:         {
     897:             /* we have a special delim on a 0 width field */
     898:             if (ret = dumvalue(np))
     899:                 *(--np) = '\0'; /*
     900: 						** end string before delim
     901: 						** Do not alter delimitor but
     902: 						** instead destroy last '0'.
     903: 						*/
     904:         }
     905:     }
     906:     return (ret);
     907: }
     908:
     909:
     910: char *dumvalue(name)
     911: char    *name;
     912:
     913: /*
     914: **	Search list of valid dummy names looking
     915: **	for 'name'. If 'name' is a single char
     916: **	then use just that name else it is
     917: **	an error if the name is not found
     918: */
     919:
     920: {
     921:     register char   **dp, *np, *ret;
     922:
     923:     dp = Cpdomains; /* get list of valid dummy names */
     924:     np = name;
     925:     ret = 0;
     926:
     927:     /* first look for a matching key word */
     928:     while (*dp)
     929:     {
     930:         if (sequal(np, *dp++))
     931:         {
     932:             ret = *dp;
     933:             break;
     934:         }
     935:         dp++;
     936:     }
     937:
     938:     /* If single char, use that char */
     939:     if (length(np) == 1)
     940:         ret = np;   /* use first char of name */
     941:     if (ret == 0)
     942:         error(5807, np, 0);
     943:
     944:     return (ret);
     945: }

#### Defined functions

bread defined in line 778; used 1 times

- in line 331

charmove defined in line 516; used 1 times

- in line 481

copy defined in line 84; used 4 times

- in /usr/ingres/source/dbu/overlayc.c line 1-6(2)
- in /usr/ingres/source/dbu/overlayg.c line 7, 22

copydone defined in line 235; used 3 times

- in line 93, 200, 231

dumvalue defined in line 910; used 4 times

- in line 578, 642, 883, 898

file_rel defined in line 310; used 1 times

- in line 224

mapfill defined in line 547; used 1 times

- in line 169

rel_file defined in line 262; used 1 times

- in line 213

transfer defined in line 366; used 2 times

- in line 288, 346

zcheck defined in line 867; used 3 times

- in line 577, 605, 619

#### Defined variables

Baddoms defined in line 50; used 4 times

- in line 103, 227-228(2), 482

Cpdomains defined in line 53; used 1 times

- in line 923

Delimitor defined in line 68; used 2 times

- in line 648, 886

Des defined in line 35; used 24 times

- in line 113, 130-132(3), 140-148(3), 154, 164, 171, 187-190(2), 212, 223, 248-255(3), 272-275(2), 323, 355, 676-677(2), 685

Duptuple defined in line 49; used 4 times

- in line 100, 225-226(2), 358

Filename defined in line 40; used 11 times

- in line 106, 159, 165, 207-208(2), 218-219(2), 293, 301, 342, 350

Inbuf defined in line 44; used 8 times

- in line 275, 285-293(3), 346-350(2), 787, 814

Into defined in line 42; used 8 times

- in line 105, 128, 205, 640, 648, 716, 751, 772

Map defined in line 29; used 6 times

- in line 277, 328, 581, 691, 700, 760

Mapcount defined in line 32; used 10 times

- in line 279, 329, 580, 589, 654, 665-668(2), 690, 703, 761

Outbuf defined in line 45; used 4 times

- in line 300, 323, 355, 391

Piped defined in line 52; used 5 times

- in line 177, 184-189(3), 255

Relname defined in line 48; used 9 times

- in line 104, 113, 120, 155, 293, 342, 350, 356, 768

Truncount defined in line 51; used 4 times

- in line 101, 249-250(2), 828

Tupcount defined in line 47; used 6 times

- in line 102, 293, 299, 342, 350-354(2)

#### Defined struct's

map defined in line 16; used 10 times

- in line 29(2), 269(2), 320(2), 570(2), 779(2)

#### Defined macros

BUFSIZE defined in line 9; used 4 times

- in line 44-45(2), 772, 808

DUMMY defined in line 12; used 7 times

- in line 394-399(2), 618, 640, 658, 705, 764

ESCAPE defined in line 13; used 1 times

- in line 842

MAXMAP defined in line 11; used 3 times

- in line 29, 589, 654

WBUFSIZE defined in line 10; never used

Last modified: 1995-02-12 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 1873 |