void cast_for_split(CELL * cp) { static char meta[] = "^$.*+?|[]()"; static char xbuff[] = "\\X"; int c; size_t len; if (cp->type < C_STRING) cast1_to_s(cp); if ((len = string(cp)->len) == 1) { if ((c = string(cp)->str[0]) == ' ') { free_STRING(string(cp)); cp->type = C_SPACE; return; } else if (c == 0) { #ifdef LOCAL_REGEXP char temp[1]; temp[0] = (char) c; free_STRING(string(cp)); cp->ptr = (PTR) new_STRING1(temp, (size_t) 1); #else /* * A null is not a meta character, but strchr will match it anyway. * For now, there's no reason to compile a null as a regular * expression - just return a string containing the single * character. That is used in a special case in set_rs_shadow(). */ char temp[2]; temp[0] = (char) c; free_STRING(string(cp)); cp->ptr = (PTR) new_STRING1(temp, (size_t) 1); return; #endif } else if (strchr(meta, c)) { xbuff[1] = (char) c; free_STRING(string(cp)); cp->ptr = (PTR) new_STRING(xbuff); } } else if (len == 0) { free_STRING(string(cp)); cp->type = C_SNULL; return; } cast_to_RE(cp); }
static int collect_string(void) { register char *p = string_buff; int c; int e_flag = 0; /* on if have an escape char */ size_t len_buff; while (1) { CheckStringSize(p); switch (scan_code[NextUChar(*p++)]) { case SC_DQUOTE: /* done */ *--p = 0; goto out; case SC_NL: p[-1] = 0; /* FALLTHRU */ case 0: /* unterminated string */ compile_error( "runaway string constant \"%.10s ...", string_buff); mawk_exit(2); case SC_ESCAPE: if ((c = next()) == '\n') { p--; lineno++; } else if (c == 0) un_next(); else { *p++ = (char) c; e_flag = 1; } break; default: break; } } out: if (e_flag) rm_escape(string_buff, &len_buff); else len_buff = (unsigned) ((char *) p - string_buff); yylval.ptr = (PTR) new_STRING1(string_buff, len_buff); return STRING_; }
static void process_cmdline(int argc, char **argv) { int i, j, nextarg; char *optArg; char *optNext; PFILE dummy; /* starts linked list of filenames */ PFILE *tail = &dummy; size_t length; if (argc <= 1) usage(); for (i = 1; i < argc && argv[i][0] == '-'; i = nextarg) { if (argv[i][1] == 0) /* - alone */ { if (!pfile_name) no_program(); break; /* the for loop */ } /* safe to look at argv[i][2] */ /* * Check for "long" options and decide how to handle them. */ if (strlen(argv[i]) > 2 && !strncmp(argv[i], "--", (size_t) 2)) { if (!allow_long_options(argv[i])) { nextarg = i + 1; continue; } } if (argv[i][2] == 0) { if (i == argc - 1 && argv[i][1] != '-') { if (strchr("WFvf", argv[i][1])) { errmsg(0, "option %s lacks argument", argv[i]); mawk_exit(2); } bad_option(argv[i]); } optArg = argv[i + 1]; nextarg = i + 2; } else { /* argument glued to option */ optArg = &argv[i][2]; nextarg = i + 1; } switch (argv[i][1]) { case 'W': for (j = 0; j < (int) strlen(optArg); j = (int) (optNext - optArg)) { switch (parse_w_opt(optArg + j, &optNext)) { case W_VERSION: print_version(); break; #if USE_BINMODE case W_BINMODE: if (haveValue(optNext)) { set_binmode(atoi(optNext + 1)); optNext = skipValue(optNext); } else { errmsg(0, "missing value for -W binmode"); mawk_exit(2); } break; #endif case W_DUMP: dump_code_flag = 1; break; case W_EXEC: if (pfile_name) { errmsg(0, "-W exec is incompatible with -f"); mawk_exit(2); } else if (nextarg == argc) { no_program(); } if (haveValue(optNext)) { pfile_name = optNext + 1; i = nextarg; } else { pfile_name = argv[nextarg]; i = nextarg + 1; } goto no_more_opts; case W_INTERACTIVE: interactive_flag = 1; setbuf(stdout, (char *) 0); break; case W_POSIX_SPACE: posix_space_flag = 1; break; case W_RANDOM: if (haveValue(optNext)) { int x = atoi(optNext + 1); CELL c[2]; memset(c, 0, sizeof(c)); c[1].type = C_DOUBLE; c[1].dval = (double) x; /* c[1] is input, c[0] is output */ bi_srand(c + 1); optNext = skipValue(optNext); } else { errmsg(0, "missing value for -W random"); mawk_exit(2); } break; case W_SPRINTF: if (haveValue(optNext)) { int x = atoi(optNext + 1); if (x > (int) sizeof(string_buff)) { if (sprintf_buff != string_buff && sprintf_buff != 0) { zfree(sprintf_buff, (size_t) (sprintf_limit - sprintf_buff)); } sprintf_buff = (char *) zmalloc((size_t) x); sprintf_limit = sprintf_buff + x; } optNext = skipValue(optNext); } else { errmsg(0, "missing value for -W sprintf"); mawk_exit(2); } break; case W_HELP: /* FALLTHRU */ case W_USAGE: usage(); /* NOTREACHED */ break; case W_UNKNOWN: errmsg(0, "vacuous option: -W %s", optArg + j); break; } while (*optNext == '=') { errmsg(0, "unexpected option value %s", optArg + j); optNext = skipValue(optNext); } } break; case 'v': if (!is_cmdline_assign(optArg)) { errmsg(0, "improper assignment: -v %s", optArg); mawk_exit(2); } break; case 'F': rm_escape(optArg, &length); /* recognize escape sequences */ cell_destroy(FS); FS->type = C_STRING; FS->ptr = (PTR) new_STRING1(optArg, length); cast_for_split(cellcpy(&fs_shadow, FS)); break; case '-': if (argv[i][2] != 0) { bad_option(argv[i]); } i++; goto no_more_opts; case 'f': /* first file goes in pfile_name ; any more go on a list */ if (!pfile_name) pfile_name = optArg; else { tail = tail->link = ZMALLOC(PFILE); tail->fname = optArg; } break; default: bad_option(argv[i]); } } no_more_opts: tail->link = (PFILE *) 0; pfile_list = dummy.link; if (pfile_name) { set_ARGV(argc, argv, i); scan_init((char *) 0); } else { /* program on command line */ if (i == argc) no_program(); set_ARGV(argc, argv, i + 1); #if defined(MSDOS) && ! HAVE_REARGV /* reversed quotes */ { char *p; for (p = argv[i]; *p; p++) if (*p == '\'') *p = '\"'; } #endif scan_init(argv[i]); /* #endif */ } }
int is_cmdline_assign(char *s) { register char *p; int c; SYMTAB *stp; CELL *cp = 0; size_t len; CELL cell; /* used if command line assign to pseudo field */ CELL *fp = (CELL *) 0; /* ditto */ size_t length; if (scan_code[*(unsigned char *) s] != SC_IDCHAR) return 0; p = s + 1; while ((c = scan_code[*(unsigned char *) p]) == SC_IDCHAR || c == SC_DIGIT) p++; if (*p != '=') return 0; *p = 0; stp = find(s); switch (stp->type) { case ST_NONE: stp->type = ST_VAR; stp->stval.cp = cp = ZMALLOC(CELL); break; case ST_VAR: case ST_NR: /* !! no one will do this */ cp = stp->stval.cp; cell_destroy(cp); break; case ST_FIELD: /* must be pseudo field */ fp = stp->stval.cp; cp = &cell; break; default: rt_error( "cannot command line assign to %s\n\ttype clash or keyword" ,s); } /* we need to keep ARGV[i] intact */ *p++ = '='; len = strlen(p) + 1; /* posix says escape sequences are on from command line */ p = rm_escape(strcpy((char *) zmalloc(len), p), &length); cp->ptr = (PTR) new_STRING1(p, length); zfree(p, len); check_strnum(cp); /* sets cp->type */ if (fp) /* move it from cell to pfield[] */ { field_assign(fp, cp); free_STRING(string(cp)); } return 1; }
CELL * bi_strftime(CELL *sp) { const char *format = "%c"; time_t rawtime; struct tm *ptm; int n_args; int utc; STRING *sval = 0; /* strftime(sval->str, timestamp, utc) */ char buff[128]; size_t result; TRACE_FUNC("bi_strftime", sp); n_args = sp->type; sp -= n_args; if (n_args > 0) { if (sp->type != C_STRING) cast1_to_s(sp); /* don't use < C_STRING shortcut */ sval = string(sp); if ((int) sval->len != 0) /* strftime on valid format */ format = sval->str; } else { sp->type = C_STRING; } if (n_args > 1) { if (sp[1].type != C_DOUBLE) cast1_to_d(sp + 1); rawtime = d_to_i(sp[1].dval); } else { time(&rawtime); } if (n_args > 2) { if (sp[2].type != C_DOUBLE) cast1_to_d(sp + 2); utc = d_to_i(sp[2].dval); } else { utc = 0; } if (utc != 0) ptm = gmtime(&rawtime); else ptm = localtime(&rawtime); result = strftime(buff, sizeof(buff) / sizeof(buff[0]), format, ptm); TRACE(("...bi_strftime (%s, \"%d.%d.%d %d.%d.%d %d\", %d) ->%s\n", format, ptm->tm_year, ptm->tm_mon, ptm->tm_mday, ptm->tm_hour, ptm->tm_min, ptm->tm_sec, ptm->tm_isdst, utc, buff)); if (sval) free_STRING(sval); sp->ptr = (PTR) new_STRING1(buff, result); while (n_args > 1) { n_args--; cell_destroy(sp + n_args); } return_CELL("bi_strftime", sp); }
/* * Note: caller must do CELL cleanup. * The format parameter is modified, but restored. * * This routine does both printf and sprintf (if fp==0) */ static STRING * do_printf( FILE *fp, char *format, unsigned argcnt, /* number of args on eval stack */ CELL *cp) /* ptr to an array of arguments (on the eval stack) */ { char save; char *p; register char *q = format; register char *target; int l_flag, h_flag; /* seen %ld or %hd */ int ast_cnt; int ast[2]; UInt Uval = 0; Int Ival = 0; int sfmt_width, sfmt_prec, sfmt_flags, s_format; int num_conversion = 0; /* for error messages */ const char *who; /*ditto */ int pf_type = 0; /* conversion type */ PRINTER printer; /* pts at fprintf() or sprintf() */ STRING onechr; #ifdef SHORT_INTS char xbuff[256]; /* splice in l qualifier here */ #endif if (fp == (FILE *) 0) { /* doing sprintf */ target = sprintf_buff; printer = (PRINTER) sprintf; who = "sprintf"; } else { /* doing printf */ target = (char *) fp; /* will never change */ printer = (PRINTER) fprintf; who = "printf"; } while (1) { if (fp) { /* printf */ while (*q != '%') { if (*q == 0) { if (ferror(fp)) write_error(); /* return is ignored */ return (STRING *) 0; } else { putc(*q, fp); q++; } } } else { /* sprintf */ while (*q != '%') { if (*q == 0) { if (target > sprintf_limit) /* damaged */ { /* hope this works */ rt_overflow("sprintf buffer", (unsigned) (sprintf_limit - sprintf_buff)); } else { /* really done */ return new_STRING1(sprintf_buff, (size_t) (target - sprintf_buff)); } } else { *target++ = *q++; } } } /* *q == '%' */ num_conversion++; if (*++q == '%') { /* %% */ if (fp) putc(*q, fp); else *target++ = *q; q++; continue; } /* mark the '%' with p */ p = q - 1; /* eat the flags */ while (*q == '-' || *q == '+' || *q == ' ' || *q == '#' || *q == '0') q++; ast_cnt = 0; ast[0] = 0; if (*q == '*') { if (cp->type != C_DOUBLE) cast1_to_d(cp); ast[ast_cnt++] = d_to_i(cp++->dval); argcnt--; q++; } else while (scan_code[*(unsigned char *) q] == SC_DIGIT) q++; /* width is done */ if (*q == '.') { /* have precision */ q++; if (*q == '*') { if (cp->type != C_DOUBLE) cast1_to_d(cp); ast[ast_cnt++] = d_to_i(cp++->dval); argcnt--; q++; } else { while (scan_code[*(unsigned char *) q] == SC_DIGIT) q++; } } if (argcnt <= 0) rt_error("not enough arguments passed to %s(\"%s\")", who, format); l_flag = h_flag = 0; if (*q == 'l') { q++; l_flag = 1; } else if (*q == 'h') { q++; h_flag = 1; } switch (*q++) { case 's': if (l_flag + h_flag) bad_conversion(num_conversion, who, format); if (cp->type < C_STRING) cast1_to_s(cp); pf_type = PF_S; break; case 'c': if (l_flag + h_flag) bad_conversion(num_conversion, who, format); switch (cp->type) { case C_NOINIT: Ival = 0; break; case C_STRNUM: case C_DOUBLE: Ival = d_to_I(cp->dval); break; case C_STRING: /* fall thru to check for bad number formats */ //Ival = string(cp)->str[0]; //break; /* fall thru */ case C_FIELDWIDTHS: case C_MBSTRN: check_strnum(cp); Ival = ((cp->type == C_STRING) ? string(cp)->str[0] : d_to_I(cp->dval)); break; default: bozo("printf %c"); } onechr.len = 1; onechr.str[0] = (char) Ival; pf_type = PF_C; break; case 'd': case 'i': if (cp->type != C_DOUBLE) cast1_to_d(cp); Ival = d_to_I(cp->dval); pf_type = PF_D; break; case 'o': case 'x': case 'X': case 'u': if (cp->type != C_DOUBLE) cast1_to_d(cp); Uval = d_to_U(cp->dval); pf_type = PF_U; break; case 'e': case 'g': case 'f': case 'E': case 'G': if (h_flag + l_flag) bad_conversion(num_conversion, who, format); if (cp->type != C_DOUBLE) cast1_to_d(cp); pf_type = PF_F; break; default: bad_conversion(num_conversion, who, format); } save = *q; *q = 0; #ifdef SHORT_INTS if (pf_type == PF_D) { /* need to splice in long modifier */ strcpy(xbuff, p); if (l_flag) /* do nothing */ ; else { int k = q - p; if (h_flag) { Ival = (short) Ival; /* replace the 'h' with 'l' (really!) */ xbuff[k - 2] = 'l'; if (xbuff[k - 1] != 'd' && xbuff[k - 1] != 'i') Ival &= 0xffff; } else { /* the usual case */ xbuff[k] = xbuff[k - 1]; xbuff[k - 1] = 'l'; xbuff[k + 1] = 0; } } } #endif #define PUTS_C_ARGS target, fp, 0, &onechr, sfmt_width, sfmt_prec, sfmt_flags #define PUTS_S_ARGS target, fp, cp, 0, sfmt_width, sfmt_prec, sfmt_flags /* ready to call printf() */ s_format = 0; switch (AST(ast_cnt, pf_type)) { case AST(0, PF_C): /* FALLTHRU */ case AST(1, PF_C): /* FALLTHRU */ case AST(2, PF_C): s_format = 1; make_sfmt(p, ast, &sfmt_width, &sfmt_prec, &sfmt_flags); target = puts_sfmt(PUTS_C_ARGS); break; case AST(0, PF_S): /* FALLTHRU */ case AST(1, PF_S): /* FALLTHRU */ case AST(2, PF_S): s_format = 1; make_sfmt(p, ast, &sfmt_width, &sfmt_prec, &sfmt_flags); target = puts_sfmt(PUTS_S_ARGS); break; #ifdef SHORT_INTS #define FMT xbuff /* format in xbuff */ #else #define FMT p /* p -> format */ #endif case AST(0, PF_D): if (cp->dval > Max_Int && l_flag == 0 && h_flag == 0) { STRING *newp; char *np; newp = new_STRING0(strlen(p)+5); np = (char *) newp->str; while (*p != '\0') { if (*p == 'd' || *p == 'i') { *np++ = '.'; *np++ = '0'; *np++ = 'f'; ++p; } else *np++ = *p++; } np = '\0'; (*printer) ((PTR) target, newp->str, cp->dval); free_STRING(newp); } else (*printer) ((PTR) target, FMT, Ival); break; case AST(1, PF_D): (*printer) ((PTR) target, FMT, ast[0], Ival); break; case AST(2, PF_D): (*printer) ((PTR) target, FMT, ast[0], ast[1], Ival); break; case AST(0, PF_U): if (*(p+1) == 'u' && cp->dval > Max_Int ) { STRING *newp; char *np; newp = new_STRING0(strlen(p)+5); np = (char *) newp->str; while (*p != '\0') { if (*p == 'u') { *np++ = '.'; *np++ = '0'; *np++ = 'f'; ++p; } else *np++ = *p++; } np = '\0'; (*printer) ((PTR) target, newp->str, cp->dval); free_STRING(newp); } else (*printer) ((PTR) target, FMT, Uval); break; case AST(1, PF_U): (*printer) ((PTR) target, FMT, ast[0], Uval); break; case AST(2, PF_U): (*printer) ((PTR) target, FMT, ast[0], ast[1], Uval); break; #undef FMT case AST(0, PF_F): (*printer) ((PTR) target, p, cp->dval); break; case AST(1, PF_F): (*printer) ((PTR) target, p, ast[0], cp->dval); break; case AST(2, PF_F): (*printer) ((PTR) target, p, ast[0], ast[1], cp->dval); break; } if (fp == (FILE *) 0 && !s_format) { while (*target) target++; } *q = save; argcnt--; cp++; } }