1: # include "../ingres.h" 2: # include "../aux.h" 3: # include "../symbol.h" 4: # include "../tree.h" 5: # include "../pipes.h" 6: # include "ovqp.h" 7: 8: /* 9: ** This file contains the string 10: ** manipulation routines 11: */ 12: 13: 14: 15: extern char *Ovqpbuf; 16: 17: 18: concatsym(ss1, ss2) 19: struct symbol *ss1, *ss2; 20: 21: /* 22: ** Concat takes the two character strings in 23: ** ss1 and ss2 and concatenates them together 24: ** into a new location. 25: ** 26: ** trailing blanks are removed from the first symbol. 27: ** The size of the concatenation equals the sum of 28: ** the two original strings. 29: */ 30: 31: { 32: register struct symbol *s1, *s2; 33: register char *p; 34: int size1, size2, i; 35: char *px; 36: char *bmove(); 37: char *need(); 38: 39: s1 = ss1; 40: s2 = ss2; 41: 42: size1 = size(s1); /* compute size w/o trailing blanks */ 43: if (size1 == 0 && s1->len != 0) 44: size1++; /* don't allow string to be trunc to zero length */ 45: size2 = s2->len & 0377; /* size of second string remains the same */ 46: i = (s1->len & 0377) + size2; /* i equals sum of original sizes */ 47: if (i > 255) 48: i = 255; /* a string can't exceed this size */ 49: if (size2 + size1 > 255) 50: size2 = 255 - size1; /* adjust size2 to not exceed 255 */ 51: 52: px = p = need(Ovqpbuf, i); /* request the needed space */ 53: p = bmove(cpderef(s1->value), p, size1); /* copy first string */ 54: p = bmove(cpderef(s2->value), p, size2); 55: cpderef(s1->value) = px; 56: s1->len = i; 57: /* pad with blanks if necessary */ 58: i -= size1 - size2; 59: while (i--) 60: *p++ = ' '; 61: 62: # ifdef xOTR1 63: if (tTf(32, 1)) 64: { 65: printf("Concat:"); 66: prstack(s1); 67: } 68: # endif 69: } 70: 71: 72: size(sym) 73: struct symbol *sym; 74: 75: /* 76: ** Size determines the size of a character symbol 77: ** without trailing blanks. 78: */ 79: { 80: register char *c; 81: register int i; 82: register struct symbol *s; 83: 84: s = sym; 85: c = cpderef(s->value); 86: i = s->len & 0377; 87: 88: for (c += i; i; i--) 89: if(*--c != ' ') 90: break; 91: 92: return (i); 93: } 94: 95: 96: /* 97: ** Converts the numeric symbol to 98: ** ascii. Formats to be used are determined 99: ** by Out_arg. 100: */ 101: 102: ascii(ss) 103: struct symbol *ss; 104: { 105: register struct symbol *s; 106: register int i; 107: register char *p; 108: char temp[MAXFIELD]; 109: extern struct out_arg Out_arg; /* used for float conversions */ 110: char *locv(); 111: char *need(); 112: 113: s = ss; 114: p = temp; 115: switch(s->type) 116: { 117: 118: case INT: 119: if (s->len == 4) 120: { 121: i = Out_arg.i4width; 122: p = locv(i4deref(s->value)); 123: } 124: else 125: { 126: itoa(i2deref(s->value), p); 127: if (s->len == 2) 128: i = Out_arg.i2width; 129: else 130: i = Out_arg.i1width; 131: } 132: break; 133: 134: case CHAR: 135: return; 136: 137: case FLOAT: 138: if (s->len == 4) 139: { 140: i = Out_arg.f4width; 141: ftoa(f4deref(s->value), p, i, Out_arg.f4prec, Out_arg.f4style); 142: } 143: else 144: { 145: i = Out_arg.f8width; 146: ftoa(f8deref(s->value), p, i, Out_arg.f8prec, Out_arg.f8style); 147: } 148: } 149: cpderef(s->value) = need(Ovqpbuf, i); 150: pmove(p, cpderef(s->value), i, ' '); /* blank pad to fixed length i */ 151: s->type = CHAR; 152: s->len = i; 153: } 154: 155: 156: /* 157: ** LEXCOMP performs character comparisons between the two 158: ** strings ss1 and ss2. All blanks and null are ignored in 159: ** both strings. In addition pattern matching is performed 160: ** using the "shell syntax". Pattern matching characters 161: ** are converted to the pattern matching symbols PAT_ANY etc. 162: ** by the scanner. 163: ** 164: ** Pattern matching characters can appear in either or 165: ** both strings. Since they cannot be stored in relations, 166: ** pattern matching chars in both strings can only happen 167: ** if the user types in such an expression. 168: ** 169: ** examples: 170: ** 171: ** "Smith, Homer" = "Smith,Homer" 172: ** 173: ** "abcd" < "abcdd" 174: ** 175: ** "abcd" = "aPAT_ANYd" 176: ** 177: ** returns <0 if s1 < s2 178: ** 0 if s1 = s2 179: ** >0 if s1 > s2 180: */ 181: 182: lexcomp(ss1, len1, ss2, len2) 183: char *ss1, *ss2; 184: int len1, len2; 185: { 186: register char *s1, *s2; 187: register int l1; 188: int l2; 189: char c1, c2; 190: 191: s1 = ss1; 192: s2 = ss2; 193: l1 = len1; 194: l2 = len2; 195: 196: loop: 197: while (l1--) 198: { 199: switch (c1 = *s1++) 200: { 201: 202: case ' ': 203: case '\0': 204: break; 205: 206: case PAT_ANY: 207: return (pmatch(s1, l1, s2, l2)); 208: 209: case PAT_LBRAC: 210: return (lmatch(s1, l1, s2, l2)); 211: 212: default: 213: while (l2--) 214: { 215: switch (c2 = *s2++) 216: { 217: 218: case ' ': 219: case '\0': 220: continue; 221: 222: case PAT_ANY: 223: return (pmatch(s2, l2, --s1, ++l1)); 224: 225: case PAT_LBRAC: 226: return (lmatch(s2, l2, --s1, ++l1)); 227: 228: default: 229: if (c1 == c2) 230: goto loop; 231: if (c1 == PAT_ONE || c2 == PAT_ONE) 232: goto loop; 233: return (c1 - c2); 234: } 235: } 236: return (1); /* s1 > s2 */ 237: } 238: } 239: 240: /* examine remainder of s2 for any characters */ 241: while (l2--) 242: if ((c1 = *s2++) != ' ' && (c1 != '\0') && (c1 != PAT_ANY)) 243: return (-1); /* s1 < s2 */ 244: return (0); 245: } 246: 247: 248: pmatch(pat, plen, str, slength) 249: char *pat; /* the string holding the pattern matching char */ 250: char *str; /* the string to be checked */ 251: int plen, slength; /* the lengths */ 252: { 253: register char d, *s; 254: register int slen; 255: char c; 256: 257: s = str; 258: slen = slength; 259: 260: if (plen == 0) 261: return (0); /* a match if no more chars in p */ 262: 263: /* 264: ** If the next character in "pat" is not another 265: ** pattern matching character, then scan until 266: ** first matching char and continue comparison. 267: */ 268: if ((c = *pat) != PAT_ANY && c != PAT_LBRAC && c != PAT_ONE) 269: { 270: while (slen--) 271: { 272: if ((d = *s) == c || d == PAT_ANY || d == PAT_LBRAC && d != PAT_ONE) 273: { 274: if (lexcomp(pat, plen, s, slen + 1) == 0) 275: return (0); 276: } 277: s++; 278: } 279: } 280: else 281: { 282: while (slen) 283: if (lexcomp(pat, plen, s++, slen--) == 0) 284: return (0); /* match */ 285: } 286: return (-1); /* no match */ 287: } 288: 289: lmatch(pat, plen, str, slen) 290: char *pat; /* the string holding the pattern matching char */ 291: char *str; /* the other string */ 292: int plen, slen; /* their respective sizes */ 293: { 294: register char *p, *s; 295: register int cc; 296: int oldc, c, found; 297: 298: p = pat; 299: s = str; 300: 301: /* find a non-blank, non-null char in s */ 302: while (slen--) 303: { 304: if ((c = *s++) != ' ' && c != '\0') 305: { 306: /* search for a match on 'c' */ 307: found = 0; /* assume failure */ 308: oldc = 0777; /* make previous char large */ 309: 310: while (plen--) 311: { 312: 313: switch(cc = *p++) 314: { 315: 316: case PAT_RBRAC: 317: if (found) 318: return (lexcomp(p, plen, s, slen)); 319: return (-1); 320: 321: case '-': 322: if (plen-- == 0) 323: return (-1); /* not found */ 324: if (oldc <= c && c <= (cc = *p++)) 325: found++; 326: break; 327: 328: default: 329: if (c == (oldc = cc)) 330: found++; 331: } 332: } 333: return (-1); /* no match */ 334: } 335: } 336: return (1); 337: }