|
7 | 7 | *
|
8 | 8 | *
|
9 | 9 | * IDENTIFICATION
|
10 |
| - * $Header: /cvsroot/pgsql/src/interfaces/libpgtcl/Attic/pgtclCmds.c,v 1.2 1996/07/23 03:38:44 scrappy Exp $ |
| 10 | + * $Header: /cvsroot/pgsql/src/interfaces/libpgtcl/Attic/pgtclCmds.c,v 1.3 1996/09/16 05:54:53 scrappy Exp $ |
11 | 11 | *
|
12 | 12 | *-------------------------------------------------------------------------
|
13 | 13 | */
|
|
23 | 23 | #include "pgtclCmds.h"
|
24 | 24 | #include "pgtclId.h"
|
25 | 25 |
|
| 26 | +#ifdef TCL_ARRAYS |
| 27 | +#define ISOCTAL(c) (((c) >= '0') && ((c) <= '7')) |
| 28 | +#define DIGIT(c) ((c) - '0') |
| 29 | + |
| 30 | +/* |
| 31 | + * translate_escape() -- |
| 32 | + * |
| 33 | + * This function performs in-place translation of a single C-style |
| 34 | + * escape sequence pointed by p. Curly braces { } and double-quote |
| 35 | + * are left escaped if they appear inside an array. |
| 36 | + * The value returned is the pointer to the last character (the one |
| 37 | + * just before the rest of the buffer). |
| 38 | + */ |
| 39 | + |
| 40 | +static inline char* |
| 41 | +translate_escape(char *p, int isArray) |
| 42 | +{ |
| 43 | + register char c, *q, *s; |
| 44 | + |
| 45 | +#ifdef DEBUG_ESCAPE |
| 46 | + printf(" escape = '%s'\n", p); |
| 47 | +#endif |
| 48 | + /* Address of the first character after the escape sequence */ |
| 49 | + s = p+2; |
| 50 | + switch (c = *(p+1)) { |
| 51 | + case '0': |
| 52 | + case '1': |
| 53 | + case '2': |
| 54 | + case '3': |
| 55 | + case '4': |
| 56 | + case '5': |
| 57 | + case '6': |
| 58 | + case '7': |
| 59 | + c = DIGIT(c); |
| 60 | + if (ISOCTAL(*s)) { |
| 61 | + c = (c<<3) + DIGIT(*s++); |
| 62 | + } |
| 63 | + if (ISOCTAL(*s)) { |
| 64 | + c = (c<<3) + DIGIT(*s++); |
| 65 | + } |
| 66 | + *p = c; |
| 67 | + break; |
| 68 | + case 'b': |
| 69 | + *p = '\b'; |
| 70 | + break; |
| 71 | + case 'f': |
| 72 | + *p = '\f'; |
| 73 | + break; |
| 74 | + case 'n': |
| 75 | + *p = '\n'; |
| 76 | + break; |
| 77 | + case 'r': |
| 78 | + *p = '\r'; |
| 79 | + break; |
| 80 | + case 't': |
| 81 | + *p = '\t'; |
| 82 | + break; |
| 83 | + case 'v': |
| 84 | + *p = '\v'; |
| 85 | + break; |
| 86 | + case '\\': |
| 87 | + case '{': |
| 88 | + case '}': |
| 89 | + case '"': |
| 90 | + /* |
| 91 | + * Backslahes, curly braces and double-quotes are left |
| 92 | + * escaped if they appear inside an array. They will be |
| 93 | + * unescaped by Tcl in Tcl_AppendElement. |
| 94 | + * The buffer position is advanced by 1 so that the this |
| 95 | + * character is not processed again by the caller. |
| 96 | + */ |
| 97 | + if (isArray) { |
| 98 | + return p+1; |
| 99 | + } else { |
| 100 | + *p = c; |
| 101 | + } |
| 102 | + break; |
| 103 | + case '\0': |
| 104 | + /* |
| 105 | + * This means a backslash at the end of the string. |
| 106 | + * It should never happen but in that case replace |
| 107 | + * the \ with a \0 but don't shift the rest of the |
| 108 | + * buffer so that the caller can see the end of the |
| 109 | + * string and terminate. |
| 110 | + */ |
| 111 | + *p = c; |
| 112 | + return p; |
| 113 | + break; |
| 114 | + default: |
| 115 | + /* |
| 116 | + * Default case, store the escaped character over the backslash |
| 117 | + * and shift the buffer over itself. |
| 118 | + */ |
| 119 | + *p = c; |
| 120 | + } |
| 121 | + /* Shift the rest of the buffer over itself after the current char */ |
| 122 | + q = p+1; |
| 123 | + for ( ; *s ; ) { |
| 124 | + *q++ = *s++; |
| 125 | + } |
| 126 | + *q = '\0'; |
| 127 | +#ifdef DEBUG_ESCAPE |
| 128 | + printf(" after = '%s'\n", p); |
| 129 | +#endif |
| 130 | + return p; |
| 131 | +} |
| 132 | + |
| 133 | +/* |
| 134 | + * tcl_value() -- |
| 135 | + * |
| 136 | + * This function does in-line conversion of a value returned by libpq |
| 137 | + * into a tcl string or into a tcl list if the value looks like the |
| 138 | + * representation of a postgres array. |
| 139 | + */ |
| 140 | + |
| 141 | +static char * |
| 142 | +tcl_value (char *value) |
| 143 | +{ |
| 144 | + int literal, last; |
| 145 | + register char c, *p, *q, *s; |
| 146 | + |
| 147 | + if (!value) { |
| 148 | + return ((char *) NULL); |
| 149 | + } |
| 150 | + |
| 151 | +#ifdef DEBUG |
| 152 | + printf("pq_value = '%s'\n", value); |
| 153 | +#endif |
| 154 | + last = strlen(value)-1; |
| 155 | + if ((last >= 1) && (value[0] == '{') && (value[last] == '}')) { |
| 156 | + /* Looks like an array, replace ',' with spaces */ |
| 157 | + /* Remove the outer pair of { }, the last first! */ |
| 158 | + value[last] = '\0'; |
| 159 | + value++; |
| 160 | + literal = 0; |
| 161 | + for (p=value; *p; p++) { |
| 162 | + if (!literal) { |
| 163 | + /* We are at the list level, look for ',' and '"' */ |
| 164 | + switch (*p) { |
| 165 | + case '"': /* beginning of literal */ |
| 166 | + literal = 1; |
| 167 | + break; |
| 168 | + case ',': /* replace the ',' with space */ |
| 169 | + *p = ' '; |
| 170 | + break; |
| 171 | + } |
| 172 | + } else { |
| 173 | + /* We are inside a C string */ |
| 174 | + switch (*p) { |
| 175 | + case '"': /* end of literal */ |
| 176 | + literal = 0; |
| 177 | + break; |
| 178 | + case '\\': |
| 179 | + /* |
| 180 | + * escape sequence, translate it |
| 181 | + */ |
| 182 | + p = translate_escape(p,1); |
| 183 | + break; |
| 184 | + } |
| 185 | + } |
| 186 | + if (!*p) { |
| 187 | + break; |
| 188 | + } |
| 189 | + } |
| 190 | + } else { |
| 191 | + /* Looks like a normal scalar value */ |
| 192 | + for (p=value; *p; p++) { |
| 193 | + if (*p == '\\') { |
| 194 | + /* |
| 195 | + * escape sequence, translate it |
| 196 | + */ |
| 197 | + p = translate_escape(p,0); |
| 198 | + } |
| 199 | + if (!*p) { |
| 200 | + break; |
| 201 | + } |
| 202 | + } |
| 203 | + } |
| 204 | +#ifdef DEBUG |
| 205 | + printf("tcl_value = '%s'\n\n", value); |
| 206 | +#endif |
| 207 | + return (value); |
| 208 | +} |
| 209 | + |
| 210 | +#endif |
| 211 | + |
26 | 212 | /**********************************
|
27 | 213 | * pg_connect
|
28 | 214 | make a connection to a backend.
|
@@ -264,7 +450,11 @@ Pg_result(ClientData cData, Tcl_Interp *interp, int argc, char* argv[])
|
264 | 450 | for (i=0;i<PQnfields(result);i++) {
|
265 | 451 | sprintf(arrayInd, "%d,%s", tupno, PQfname(result,i));
|
266 | 452 | Tcl_SetVar2(interp, arrVar, arrayInd,
|
| 453 | +#ifdef TCL_ARRAYS |
| 454 | + tcl_value(PQgetvalue(result,tupno,i)), |
| 455 | +#else |
267 | 456 | PQgetvalue(result,tupno,i),
|
| 457 | +#endif |
268 | 458 | TCL_LEAVE_ERR_MSG);
|
269 | 459 | }
|
270 | 460 | }
|
@@ -304,12 +494,19 @@ Pg_result(ClientData cData, Tcl_Interp *interp, int argc, char* argv[])
|
304 | 494 | return TCL_ERROR;
|
305 | 495 | }
|
306 | 496 |
|
| 497 | +#ifdef TCL_ARRAYS |
| 498 | + for (i=0; i<PQnfields(result); i++) { |
| 499 | + Tcl_AppendElement(interp, tcl_value(PQgetvalue(result,tupno,i))); |
| 500 | + } |
| 501 | +#else |
307 | 502 | /* Tcl_AppendResult(interp, PQgetvalue(result,tupno,0),NULL); */
|
308 | 503 | Tcl_AppendElement(interp, PQgetvalue(result,tupno,0));
|
309 | 504 | for (i=1;i<PQnfields(result);i++) {
|
310 | 505 | /* Tcl_AppendResult(interp, " ", PQgetvalue(result,tupno,i),NULL);*/
|
311 | 506 | Tcl_AppendElement(interp, PQgetvalue(result,tupno,i));
|
312 | 507 | }
|
| 508 | +#endif |
| 509 | + |
313 | 510 | return TCL_OK;
|
314 | 511 | }
|
315 | 512 | else if (strcmp(opt, "-attributes") == 0) {
|
|
0 commit comments