00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "awk.h"
00027
00028
00029
00030 AWKNUM
00031 r_force_number(register NODE *n)
00032 {
00033 register char *cp;
00034 register char *cpend;
00035 char save;
00036 char *ptr;
00037 unsigned int newflags;
00038 extern double strtod();
00039
00040 #ifdef GAWKDEBUG
00041 if (n == NULL)
00042 cant_happen();
00043 if (n->type != Node_val)
00044 cant_happen();
00045 if (n->flags == 0)
00046 cant_happen();
00047 if (n->flags & NUMCUR)
00048 return n->numbr;
00049 #endif
00050
00051
00052
00053 n->numbr = 0.0;
00054 n->flags |= NUMCUR;
00055
00056 if (n->stlen == 0) {
00057 if (0 && do_lint)
00058 lintwarn(_("can't convert string to float"));
00059 return 0.0;
00060 }
00061
00062 cp = n->stptr;
00063 if (ISALPHA(*cp)) {
00064 if (0 && do_lint)
00065 lintwarn(_("can't convert string to float"));
00066 return 0.0;
00067 }
00068
00069 cpend = cp + n->stlen;
00070 while (cp < cpend && ISSPACE(*cp))
00071 cp++;
00072 if (cp == cpend || ISALPHA(*cp)) {
00073 if (0 && do_lint)
00074 lintwarn(_("can't convert string to float"));
00075 return 0.0;
00076 }
00077
00078 if (n->flags & MAYBE_NUM) {
00079 newflags = NUMBER;
00080 n->flags &= ~MAYBE_NUM;
00081 } else
00082 newflags = 0;
00083 if (cpend - cp == 1) {
00084 if (ISDIGIT(*cp)) {
00085 n->numbr = (AWKNUM)(*cp - '0');
00086 n->flags |= newflags;
00087 } else if (0 && do_lint)
00088 lintwarn(_("can't convert string to float"));
00089 return n->numbr;
00090 }
00091
00092 if (do_non_decimal_data) {
00093 errno = 0;
00094 if (! do_traditional && isnondecimal(cp)) {
00095 n->numbr = nondec2awknum(cp, cpend - cp);
00096 goto finish;
00097 }
00098 }
00099
00100 errno = 0;
00101 save = *cpend;
00102 *cpend = '\0';
00103 n->numbr = (AWKNUM) strtod((const char *) cp, &ptr);
00104
00105
00106 while (ISSPACE(*ptr))
00107 ptr++;
00108 *cpend = save;
00109 finish:
00110
00111 if (errno == 0 && ptr >= cpend) {
00112 n->flags |= newflags;
00113 } else {
00114 if (0 && do_lint && ptr < cpend)
00115 lintwarn(_("can't convert string to float"));
00116 errno = 0;
00117 }
00118
00119 return n->numbr;
00120 }
00121
00122
00123
00124
00125
00126
00127 static const char *const values[] = {
00128 "0",
00129 "1",
00130 "2",
00131 "3",
00132 "4",
00133 "5",
00134 "6",
00135 "7",
00136 "8",
00137 "9",
00138 };
00139 #define NVAL (sizeof(values)/sizeof(values[0]))
00140
00141
00142
00143 NODE *
00144 format_val(const char *format, int index, register NODE *s)
00145 {
00146 char buf[BUFSIZ];
00147 register char *sp = buf;
00148 double val;
00149 char *orig, *trans, save;
00150
00151 if (! do_traditional && (s->flags & INTLSTR) != 0) {
00152 save = s->stptr[s->stlen];
00153 s->stptr[s->stlen] = '\0';
00154
00155 orig = s->stptr;
00156 trans = dgettext(TEXTDOMAIN, orig);
00157
00158 s->stptr[s->stlen] = save;
00159 return tmp_string(trans, strlen(trans));
00160 }
00161
00162
00163 if ((val = double_to_int(s->numbr)) != s->numbr
00164 || val < LONG_MIN || val > LONG_MAX) {
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175 NODE *dummy, *r;
00176 unsigned short oflags;
00177 extern NODE **fmt_list;
00178
00179
00180 getnode(dummy);
00181 dummy->type = Node_expression_list;
00182 dummy->lnode = s;
00183 dummy->rnode = NULL;
00184 oflags = s->flags;
00185 s->flags |= PERM;
00186 r = format_tree(format, fmt_list[index]->stlen, dummy, 2);
00187 s->flags = oflags;
00188 s->stfmt = (char) index;
00189 s->stlen = r->stlen;
00190 s->stptr = r->stptr;
00191 freenode(r);
00192 freenode(dummy);
00193
00194 goto no_malloc;
00195 } else {
00196
00197
00198 register long num = (long) val;
00199 if (num < NVAL && num >= 0) {
00200 sp = (char *) values[num];
00201 s->stlen = 1;
00202 } else {
00203 (void) sprintf(sp, "%ld", num);
00204 s->stlen = strlen(sp);
00205 }
00206 s->stfmt = -1;
00207 }
00208 emalloc(s->stptr, char *, s->stlen + 2, "format_val");
00209 memcpy(s->stptr, sp, s->stlen+1);
00210 no_malloc:
00211 s->stref = 1;
00212 s->flags |= STRCUR;
00213 return s;
00214 }
00215
00216
00217
00218 NODE *
00219 r_force_string(register NODE *s)
00220 {
00221 NODE *ret;
00222 #ifdef GAWKDEBUG
00223 if (s == NULL)
00224 cant_happen();
00225 if (s->type != Node_val)
00226 cant_happen();
00227 if (s->stref <= 0)
00228 cant_happen();
00229 if ((s->flags & STRCUR) != 0
00230 && (s->stfmt == -1 || s->stfmt == CONVFMTidx))
00231 return s;
00232 #endif
00233
00234 ret = format_val(CONVFMT, CONVFMTidx, s);
00235 return ret;
00236 }
00237
00238
00239
00240
00241
00242
00243
00244 NODE *
00245 r_dupnode(NODE *n)
00246 {
00247 register NODE *r;
00248
00249 #ifndef DUPNODE_MACRO
00250 if ((n->flags & TEMP) != 0) {
00251 n->flags &= ~TEMP;
00252 n->flags |= MALLOC;
00253 return n;
00254 }
00255 if ((n->flags & PERM) != 0)
00256 return n;
00257 #endif
00258 if ((n->flags & (MALLOC|STRCUR)) == (MALLOC|STRCUR)) {
00259 if (n->stref < LONG_MAX)
00260 n->stref++;
00261 else
00262 n->flags |= PERM;
00263 return n;
00264 } else if ((n->flags & MALLOC) != 0 && n->type == Node_ahash) {
00265 if (n->ahname_ref < LONG_MAX)
00266 n->ahname_ref++;
00267 else
00268 n->flags |= PERM;
00269 return n;
00270 }
00271 getnode(r);
00272 *r = *n;
00273 r->flags &= ~(PERM|TEMP|FIELD);
00274 r->flags |= MALLOC;
00275 if (n->type == Node_val && (n->flags & STRCUR) != 0) {
00276 r->stref = 1;
00277 emalloc(r->stptr, char *, r->stlen + 2, "dupnode");
00278 memcpy(r->stptr, n->stptr, r->stlen);
00279 r->stptr[r->stlen] = '\0';
00280 } else if (n->type == Node_ahash && (n->flags & MALLOC) != 0) {
00281 r->ahname_ref = 1;
00282 emalloc(r->ahname_str, char *, r->ahname_len + 2, "dupnode");
00283 memcpy(r->ahname_str, n->ahname_str, r->ahname_len);
00284 r->ahname_str[r->ahname_len] = '\0';
00285 }
00286 return r;
00287 }
00288
00289
00290
00291 NODE *
00292 copynode(NODE *old)
00293 {
00294 NODE *new;
00295 int saveflags;
00296
00297 assert(old != NULL);
00298 saveflags = old->flags;
00299 old->flags &= ~(MALLOC|PERM);
00300 new = dupnode(old);
00301 old->flags = saveflags;
00302 return new;
00303 }
00304
00305
00306
00307 NODE *
00308 mk_number(AWKNUM x, unsigned int flags)
00309 {
00310 register NODE *r;
00311
00312 getnode(r);
00313 r->type = Node_val;
00314 r->numbr = x;
00315 r->flags = flags;
00316 #ifdef GAWKDEBUG
00317 r->stref = 1;
00318 r->stptr = NULL;
00319 r->stlen = 0;
00320 #endif
00321 return r;
00322 }
00323
00324
00325
00326 NODE *
00327 make_str_node(char *s, unsigned long len, int flags)
00328 {
00329 register NODE *r;
00330
00331 getnode(r);
00332 r->type = Node_val;
00333 r->flags = (STRING|STRCUR|MALLOC);
00334 if (flags & ALREADY_MALLOCED)
00335 r->stptr = s;
00336 else {
00337 emalloc(r->stptr, char *, len + 2, s);
00338 memcpy(r->stptr, s, len);
00339 }
00340 r->stptr[len] = '\0';
00341
00342 if ((flags & SCAN) != 0) {
00343 const char *pf;
00344 register char *ptm;
00345 register int c;
00346 register const char *end;
00347
00348 end = &(r->stptr[len]);
00349 for (pf = ptm = r->stptr; pf < end;) {
00350 c = *pf++;
00351 if (c == '\\') {
00352 c = parse_escape(&pf);
00353 if (c < 0) {
00354 if (do_lint)
00355 lintwarn(_("backslash at end of string"));
00356 c = '\\';
00357 }
00358 *ptm++ = c;
00359 } else
00360 *ptm++ = c;
00361 }
00362 len = ptm - r->stptr;
00363 erealloc(r->stptr, char *, len + 1, "make_str_node");
00364 r->stptr[len] = '\0';
00365 r->flags |= PERM;
00366 }
00367 r->stlen = len;
00368 r->stref = 1;
00369 r->stfmt = -1;
00370
00371 return r;
00372 }
00373
00374
00375
00376 NODE *
00377 tmp_string(char *s, size_t len)
00378 {
00379 register NODE *r;
00380
00381 r = make_string(s, len);
00382 r->flags |= TEMP;
00383 return r;
00384 }
00385
00386
00387
00388 #define NODECHUNK 100
00389
00390 NODE *nextfree = NULL;
00391
00392 NODE *
00393 more_nodes()
00394 {
00395 register NODE *np;
00396
00397
00398 emalloc(nextfree, NODE *, NODECHUNK * sizeof(NODE), "more_nodes");
00399 for (np = nextfree; np <= &nextfree[NODECHUNK - 1]; np++) {
00400 np->flags = 0;
00401 #ifndef NO_PROFILING
00402 np->exec_count = 0;
00403 #endif
00404 np->nextp = np + 1;
00405 }
00406 --np;
00407 np->nextp = NULL;
00408 np = nextfree;
00409 nextfree = nextfree->nextp;
00410 return np;
00411 }
00412
00413 #ifdef MEMDEBUG
00414 #undef freenode
00415
00416
00417 void
00418 freenode(NODE *it)
00419 {
00420 #ifdef MPROF
00421 it->stref = 0;
00422 free((char *) it);
00423 #else
00424 #ifndef NO_PROFILING
00425 it->exec_count = 0;
00426 #endif
00427
00428 it->nextp = nextfree;
00429 nextfree = it;
00430 #endif
00431 }
00432 #endif
00433
00434
00435
00436 void
00437 unref(register NODE *tmp)
00438 {
00439 if (tmp == NULL)
00440 return;
00441 if ((tmp->flags & PERM) != 0)
00442 return;
00443 tmp->flags &= ~TEMP;
00444 if ((tmp->flags & MALLOC) != 0) {
00445 if (tmp->type == Node_ahash) {
00446 if (tmp->ahname_ref > 1) {
00447 tmp->ahname_ref--;
00448 return;
00449 }
00450 free(tmp->ahname_str);
00451 } else if ((tmp->flags & STRCUR) != 0) {
00452 if (tmp->stref > 1) {
00453 tmp->stref--;
00454 return;
00455 }
00456 free(tmp->stptr);
00457 }
00458 freenode(tmp);
00459 return;
00460 }
00461 if ((tmp->flags & FIELD) != 0) {
00462 freenode(tmp);
00463 return;
00464 }
00465 }
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486 int
00487 parse_escape(const char **string_ptr)
00488 {
00489 register int c = *(*string_ptr)++;
00490 register int i;
00491 register int count;
00492
00493 switch (c) {
00494 case 'a':
00495 return BELL;
00496 case 'b':
00497 return '\b';
00498 case 'f':
00499 return '\f';
00500 case 'n':
00501 return '\n';
00502 case 'r':
00503 return '\r';
00504 case 't':
00505 return '\t';
00506 case 'v':
00507 return '\v';
00508 case '\n':
00509 return -2;
00510 case 0:
00511 (*string_ptr)--;
00512 return -1;
00513 case '0':
00514 case '1':
00515 case '2':
00516 case '3':
00517 case '4':
00518 case '5':
00519 case '6':
00520 case '7':
00521 i = c - '0';
00522 count = 0;
00523 while (++count < 3) {
00524 if ((c = *(*string_ptr)++) >= '0' && c <= '7') {
00525 i *= 8;
00526 i += c - '0';
00527 } else {
00528 (*string_ptr)--;
00529 break;
00530 }
00531 }
00532 return i;
00533 case 'x':
00534 if (do_lint) {
00535 static int didwarn = FALSE;
00536
00537 if (! didwarn) {
00538 didwarn = TRUE;
00539 lintwarn(_("POSIX does not allow `\\x' escapes"));
00540 }
00541 }
00542 if (do_posix)
00543 return ('x');
00544 if (! ISXDIGIT((*string_ptr)[0])) {
00545 warning(_("no hex digits in `\\x' escape sequence"));
00546 return ('x');
00547 }
00548 i = 0;
00549 for (;;) {
00550
00551 c = *(*string_ptr)++;
00552 if (ISXDIGIT(c)) {
00553 i *= 16;
00554 if (ISDIGIT(c))
00555 i += c - '0';
00556 else if (ISUPPER(c))
00557 i += c - 'A' + 10;
00558 else
00559 i += c - 'a' + 10;
00560 } else {
00561 (*string_ptr)--;
00562 break;
00563 }
00564 }
00565 return i;
00566 case '\\':
00567 case '"':
00568 return c;
00569 default:
00570 {
00571 static short warned[256];
00572 unsigned char uc = (unsigned char) c;
00573
00574
00575
00576 if (! warned[uc]) {
00577 warned[uc] = TRUE;
00578
00579 warning(_("escape sequence `\\%c' treated as plain `%c'"), uc, uc);
00580 }
00581 }
00582 return c;
00583 }
00584 }