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