コード例 #1
0
ファイル: cast.c プロジェクト: Imcraft/mawk-20121129
void
cast1_to_s(CELL * cp)
{
    register Int lval;
    char xbuff[260];

    switch (cp->type) {
    case C_NOINIT:
	null_str.ref_cnt++;
	cp->ptr = (PTR) & null_str;
	break;

    case C_DOUBLE:

	lval = d_to_I(cp->dval);
	if (lval == cp->dval)
	    sprintf(xbuff, INT_FMT, lval);
	else
	    sprintf(xbuff, string(CONVFMT)->str, cp->dval);

	cp->ptr = (PTR) new_STRING(xbuff);
	break;

    case C_STRING:
	return;

    case C_MBSTRN:
    case C_STRNUM:
	break;

    default:
	bozo("bad type on cast");
    }
    cp->type = C_STRING;
}
コード例 #2
0
ファイル: array.c プロジェクト: ThomasDickey/mawk-20120627
CELL* array_find(
    ARRAY A,
    CELL *cp,
    int create_flag)
{
    ANODE *ap ;
    int redid ;
    if (A->size == 0 && !create_flag)
        /* eliminating this trivial case early avoids unnecessary conversions later */
        return (CELL*) 0 ;
    switch (cp->type) {
    case C_DOUBLE:
    {
        double d = cp->dval ;
        Int ival = d_to_I(d) ;
        if ((double)ival == d) {
            if (A->type == AY_SPLIT) {
                if (ival >= 1 && ival <= (int) A->size)
                    return (CELL*)A->ptr+(ival-1) ;
                if (!create_flag) return (CELL*) 0 ;
                convert_split_array_to_table(A) ;
            }
            else if (A->type == AY_NULL) make_empty_table(A, AY_INT) ;
            ap = find_by_ival(A, ival, create_flag, &redid) ;
        }
        else {
            /* convert to string */
            char buff[260] ;
            STRING *sval ;
            sprintf(buff, string(CONVFMT)->str, d) ;
            sval = new_STRING(buff) ;
            ap = find_by_sval(A, sval, create_flag, &redid) ;
            free_STRING(sval) ;
        }
    }

    break ;
    case C_NOINIT:
        ap = find_by_sval(A, &null_str, create_flag, &redid) ;
        break ;
    default:
        ap = find_by_sval(A, string(cp), create_flag, &redid) ;
        break ;
    }
    return ap ? &ap->cell : (CELL *) 0 ;
}
コード例 #3
0
ファイル: print.c プロジェクト: jlp765/original-mawk
static void
print_cell(CELL *p, FILE *fp)
{
    size_t len;

    switch (p->type) {
    case C_NOINIT:
    break;
    case C_FIELDWIDTHS:
    case C_MBSTRN:
    case C_STRING:
    case C_STRNUM:
    switch (len = string(p)->len) {
    case 0:
        break;
    case 1:
        putc(string(p)->str[0], fp);
        break;

    default:
        fwrite(string(p)->str, (size_t) 1, len, fp);
    }
    break;

    case C_DOUBLE:
    {
        Int ival = d_to_I(p->dval);

        /* integers print as "%[l]d" */
        if ((double) ival == p->dval)
        fprintf(fp, INT_FMT, ival);
        else
        fprintf(fp, string(OFMT)->str, p->dval);
    }
    break;

    default:
    bozo("bad cell passed to print_cell");
    }
}
コード例 #4
0
ファイル: field.c プロジェクト: Imcraft/mawk-20121129
static void
build_field0(void)
{

#ifdef DEBUG
    if (nf < 0)
	bozo("nf <0 in build_field0");
#endif

    cell_destroy(field + 0);

    if (nf == 0) {
	field[0].type = C_STRING;
	field[0].ptr = (PTR) & null_str;
	null_str.ref_cnt++;
    } else if (nf == 1) {
	cellcpy(field, field + 1);
    } else {
	CELL c;
	STRING *ofs, *tail;
	size_t len;
	register CELL *cp;
	register char *p, *q;
	int cnt;
	CELL **fbp, *cp_limit;

	cast1_to_s(cellcpy(&c, OFS));
	ofs = (STRING *) c.ptr;
	cast1_to_s(cellcpy(&c, field_ptr(nf)));
	tail = (STRING *) c.ptr;
	cnt = nf - 1;

	len = ((size_t) cnt) * ofs->len + tail->len;

	fbp = fbank;
	cp_limit = field + FBANK_SZ;
	cp = field + 1;

	while (cnt-- > 0) {
	    if (cp->type < C_STRING) {	/* use the string field temporarily */
		if (cp->type == C_NOINIT) {
		    cp->ptr = (PTR) & null_str;
		    null_str.ref_cnt++;
		} else {	/* its a double */
		    Int ival;
		    char xbuff[260];

		    ival = d_to_I(cp->dval);
		    if (ival == cp->dval)
			sprintf(xbuff, INT_FMT, ival);
		    else
			sprintf(xbuff, string(CONVFMT)->str, cp->dval);

		    cp->ptr = (PTR) new_STRING(xbuff);
		}
	    }

	    len += string(cp)->len;

	    if (++cp == cp_limit) {
		cp = *++fbp;
		cp_limit = cp + FBANK_SZ;
	    }

	}

	field[0].type = C_STRING;
	field[0].ptr = (PTR) new_STRING0(len);

	p = string(field)->str;

	/* walk it again , putting things together */
	cnt = nf - 1;
	fbp = fbank;
	cp = field + 1;
	cp_limit = field + FBANK_SZ;
	while (cnt-- > 0) {
	    memcpy(p, string(cp)->str, string(cp)->len);
	    p += string(cp)->len;
	    /* if not really string, free temp use of ptr */
	    if (cp->type < C_STRING) {
		free_STRING(string(cp));
	    }
	    if (++cp == cp_limit) {
		cp = *++fbp;
		cp_limit = cp + FBANK_SZ;
	    }
	    /* add the separator */
	    q = ofs->str;
	    while (*q)
		*p++ = *q++;
	}
	/* tack tail on the end */
	memcpy(p, tail->str, tail->len);

	/* cleanup */
	free_STRING(tail);
	free_STRING(ofs);
    }
}
コード例 #5
0
ファイル: scan.c プロジェクト: ThomasDickey/mawk-snapshots
int
yylex(void)
{
    register int c;

    token_lineno = lineno;

#ifdef NO_LEAKS
    memset(&yylval, 0, sizeof(yylval));
#endif

  reswitch:

    switch (scan_code[NextUChar(c)]) {
    case 0:
	ct_ret(EOF);

    case SC_SPACE:
	goto reswitch;

    case SC_COMMENT:
	eat_comment();
	goto reswitch;

    case SC_NL:
	lineno++;
	eat_nl();
	ct_ret(NL);

    case SC_ESCAPE:
	while (scan_code[NextUChar(c)] == SC_SPACE) {
	    ;			/* empty */
	};
	if (c == '\n') {
	    token_lineno = ++lineno;
	    goto reswitch;
	}

	if (c == 0)
	    ct_ret(EOF);
	un_next();
	yylval.ival = '\\';
	ct_ret(UNEXPECTED);

    case SC_SEMI_COLON:
	eat_nl();
	ct_ret(SEMI_COLON);

    case SC_LBRACE:
	eat_nl();
	brace_cnt++;
	ct_ret(LBRACE);

    case SC_PLUS:
	switch (next()) {
	case '+':
	    yylval.ival = '+';
	    string_buff[0] =
		string_buff[1] = '+';
	    string_buff[2] = 0;
	    ct_ret(INC_or_DEC);

	case '=':
	    ct_ret(ADD_ASG);

	default:
	    un_next();
	    ct_ret(PLUS);
	}

    case SC_MINUS:
	switch (next()) {
	case '-':
	    yylval.ival = '-';
	    string_buff[0] =
		string_buff[1] = '-';
	    string_buff[2] = 0;
	    ct_ret(INC_or_DEC);

	case '=':
	    ct_ret(SUB_ASG);

	default:
	    un_next();
	    ct_ret(MINUS);
	}

    case SC_COMMA:
	eat_nl();
	ct_ret(COMMA);

    case SC_MUL:
	test1_ret('=', MUL_ASG, MUL);

    case SC_DIV:
	{
	    static const int can_precede_div[] =
	    {DOUBLE, STRING_, RPAREN, ID, D_ID, RE, RBOX, FIELD,
	     GETLINE, INC_or_DEC, -1};

	    const int *p = can_precede_div;

	    do {
		if (*p == current_token) {
		    if (*p != INC_or_DEC) {
			test1_ret('=', DIV_ASG, DIV);
		    }

		    if (next() == '=') {
			un_next();
			ct_ret(collect_RE());
		    }
		}
	    }
	    while (*++p != -1);

	    ct_ret(collect_RE());
	}

    case SC_MOD:
	test1_ret('=', MOD_ASG, MOD);

    case SC_POW:
	test1_ret('=', POW_ASG, POW);

    case SC_LPAREN:
	paren_cnt++;
	ct_ret(LPAREN);

    case SC_RPAREN:
	if (--paren_cnt < 0) {
	    compile_error("extra ')'");
	    paren_cnt = 0;
	    goto reswitch;
	}

	ct_ret(RPAREN);

    case SC_LBOX:
	ct_ret(LBOX);

    case SC_RBOX:
	ct_ret(RBOX);

    case SC_MATCH:
	string_buff[1] = '~';
	string_buff[0] = 0;
	yylval.ival = 1;
	ct_ret(MATCH);

    case SC_EQUAL:
	test1_ret('=', EQ, ASSIGN);

    case SC_NOT:		/* !  */
	if ((c = next()) == '~') {
	    string_buff[0] = '!';
	    string_buff[1] = '~';
	    string_buff[2] = 0;
	    yylval.ival = 0;
	    ct_ret(MATCH);
	} else if (c == '=')
	    ct_ret(NEQ);

	un_next();
	ct_ret(NOT);

    case SC_LT:		/* '<' */
	if (next() == '=')
	    ct_ret(LTE);
	else
	    un_next();

	if (getline_flag) {
	    getline_flag = 0;
	    ct_ret(IO_IN);
	} else
	    ct_ret(LT);

    case SC_GT:		/* '>' */
	if (print_flag && paren_cnt == 0) {
	    print_flag = 0;
	    /* there are 3 types of IO_OUT
	       -- build the error string in string_buff */
	    string_buff[0] = '>';
	    if (next() == '>') {
		yylval.ival = F_APPEND;
		string_buff[1] = '>';
		string_buff[2] = 0;
	    } else {
		un_next();
		yylval.ival = F_TRUNC;
		string_buff[1] = 0;
	    }
	    return current_token = IO_OUT;
	}

	test1_ret('=', GTE, GT);

    case SC_OR:
	if (next() == '|') {
	    eat_nl();
	    ct_ret(OR);
	} else {
	    un_next();

	    if (print_flag && paren_cnt == 0) {
		print_flag = 0;
		yylval.ival = PIPE_OUT;
		string_buff[0] = '|';
		string_buff[1] = 0;
		ct_ret(IO_OUT);
	    } else
		ct_ret(PIPE);
	}

    case SC_AND:
	if (next() == '&') {
	    eat_nl();
	    ct_ret(AND);
	} else {
	    un_next();
	    yylval.ival = '&';
	    ct_ret(UNEXPECTED);
	}

    case SC_QMARK:
	ct_ret(QMARK);

    case SC_COLON:
	ct_ret(COLON);

    case SC_RBRACE:
	if (--brace_cnt < 0) {
	    compile_error("extra '}'");
	    eat_semi_colon();
	    brace_cnt = 0;
	    goto reswitch;
	}

	if ((c = current_token) == NL || c == SEMI_COLON
	    || c == SC_FAKE_SEMI_COLON || c == RBRACE) {
	    /* if the brace_cnt is zero , we've completed
	       a pattern action block. If the user insists
	       on adding a semi-colon on the same line
	       we will eat it.  Note what we do below:
	       physical law -- conservation of semi-colons */

	    if (brace_cnt == 0)
		eat_semi_colon();
	    eat_nl();
	    ct_ret(RBRACE);
	}

	/* supply missing semi-colon to statement that
	   precedes a '}' */
	brace_cnt++;
	un_next();
	current_token = SC_FAKE_SEMI_COLON;
	return SEMI_COLON;

    case SC_DIGIT:
    case SC_DOT:
	{
	    double d;
	    int flag;

	    if ((d = collect_decimal(c, &flag)) == 0.0) {
		if (flag)
		    ct_ret(flag);
		else
		    yylval.ptr = (PTR) & double_zero;
	    } else if (d == 1.0) {
		yylval.ptr = (PTR) & double_one;
	    } else {
		yylval.ptr = (PTR) ZMALLOC(double);
		*(double *) yylval.ptr = d;
	    }
	    ct_ret(DOUBLE);
	}

    case SC_DOLLAR:		/* '$' */
	{
	    double d;
	    int flag;

	    while (scan_code[NextUChar(c)] == SC_SPACE) {
		;		/* empty */
	    };
	    if (scan_code[c] != SC_DIGIT &&
		scan_code[c] != SC_DOT) {
		un_next();
		ct_ret(DOLLAR);
	    }

	    /* compute field address at compile time */
	    if ((d = collect_decimal(c, &flag)) <= 0.0) {
		if (flag)
		    ct_ret(flag);	/* an error */
		else
		    yylval.cp = &field[0];
	    } else {
		int ival = d_to_I(d);
		double dval = (double) ival;
		if (dval != d) {
		    compile_error("$%g is invalid field index", d);
		}
		yylval.cp = field_ptr(ival);
	    }

	    ct_ret(FIELD);
	}

    case SC_DQUOTE:
	return current_token = collect_string();

    case SC_IDCHAR:		/* collect an identifier */
	{
	    char *p = string_buff + 1;
	    SYMTAB *stp;

	    string_buff[0] = (char) c;

	    while (1) {
		CheckStringSize(p);
		c = scan_code[NextUChar(*p++)];
		if (c != SC_IDCHAR && c != SC_DIGIT)
		    break;
	    }

	    un_next();
	    *--p = 0;

	    switch ((stp = find(string_buff))->type) {
	    case ST_NONE:
		/* check for function call before defined */
		if (next() == '(') {
		    stp->type = ST_FUNCT;
		    stp->stval.fbp = (FBLOCK *)
			zmalloc(sizeof(FBLOCK));
		    stp->stval.fbp->name = stp->name;
		    stp->stval.fbp->code = (INST *) 0;
		    stp->stval.fbp->size = 0;
		    yylval.fbp = stp->stval.fbp;
		    current_token = FUNCT_ID;
		} else {
		    yylval.stp = stp;
		    current_token =
			current_token == DOLLAR ? D_ID : ID;
		}
		un_next();
		break;

	    case ST_NR:
		NR_flag = 1;
		stp->type = ST_VAR;
		/* FALLTHRU */

	    case ST_VAR:
	    case ST_ARRAY:
	    case ST_LOCAL_NONE:
	    case ST_LOCAL_VAR:
	    case ST_LOCAL_ARRAY:

		yylval.stp = stp;
		current_token =
		    current_token == DOLLAR ? D_ID : ID;
		break;

	    case ST_ENV:
		stp->type = ST_ARRAY;
		stp->stval.array = new_ARRAY();
		load_environ(stp->stval.array);
		yylval.stp = stp;
		current_token =
		    current_token == DOLLAR ? D_ID : ID;
		break;

	    case ST_FUNCT:
		yylval.fbp = stp->stval.fbp;
		current_token = FUNCT_ID;
		break;

	    case ST_KEYWORD:
		current_token = stp->stval.kw;
		break;

	    case ST_BUILTIN:
		yylval.bip = stp->stval.bip;
		current_token = BUILTIN;
		break;

	    case ST_LENGTH:

		yylval.bip = stp->stval.bip;

		/* check for length alone, this is an ugly
		   hack */
		while (scan_code[NextUChar(c)] == SC_SPACE) {
		    ;		/* empty */
		};
		un_next();

		current_token = c == '(' ? BUILTIN : LENGTH;
		break;

	    case ST_FIELD:
		yylval.cp = stp->stval.cp;
		current_token = FIELD;
		break;

	    default:
		bozo("find returned bad st type");
	    }
	    return current_token;
	}

    case SC_UNEXPECTED:
	yylval.ival = c & 0xff;
	ct_ret(UNEXPECTED);
    }
    return 0;			/* never get here make lint happy */
}
コード例 #6
0
ファイル: array.c プロジェクト: ThomasDickey/mawk-20120627
void array_delete(
    ARRAY A,
    CELL *cp)
{
    ANODE *ap ;
    int redid ;
    if (A->size == 0) return ;
    switch(cp->type) {
    case C_DOUBLE :
    {
        double d = cp->dval ;
        Int ival = d_to_I(d) ;
        if ((double)ival == d) {
            if (A->type == AY_SPLIT)
            {
                if (ival >=1 && ival <= (int) A->size)
                    convert_split_array_to_table(A) ;
                else return ; /* ival not in range */
            }
            ap = find_by_ival(A, ival, NO_CREATE, &redid) ;
            if (ap) { /* remove from the front of the ilist */
                DUAL_LINK *table = (DUAL_LINK*) A->ptr ;
                table[(unsigned) ap->ival & A->hmask].ilink = ap->ilink ;
                if (ap->sval) {
                    ANODE *p, *q = 0 ;
                    unsigned indx = (unsigned) ap->hval & A->hmask ;
                    p = table[indx].slink ;
                    while(p != ap) {
                        q = p ;
                        p = q->slink ;
                    }
                    if (q) q->slink = p->slink ;
                    else table[indx].slink = p->slink ;
                    free_STRING(ap->sval) ;
                }

                cell_destroy(&ap->cell) ;
                ZFREE(ap) ;
                if (--A->size == 0) array_clear(A) ;


            }
            return ;
        }

        else { /* get the string value */
            char buff[260] ;
            STRING *sval ;
            sprintf(buff, string(CONVFMT)->str, d) ;
            sval = new_STRING(buff) ;
            ap = find_by_sval(A, sval, NO_CREATE, &redid) ;
            free_STRING(sval) ;
        }
    }
    break ;
    case C_NOINIT :
        ap = find_by_sval(A, &null_str, NO_CREATE, &redid) ;
        break ;
    default :
        ap = find_by_sval(A, string(cp), NO_CREATE, &redid) ;
        break ;
    }
    if (ap) { /* remove from the front of the slist */
        DUAL_LINK *table = (DUAL_LINK*) A->ptr ;
        table[ap->hval & A->hmask].slink = ap->slink ;
        if (ap->ival != NOT_AN_IVALUE) {
            ANODE *p, *q = 0 ;
            unsigned indx = (unsigned) ap->ival & A->hmask ;
            p = table[indx].ilink ;
            while(p != ap) {
                q = p ;
                p = q->ilink ;
            }
            if (q) q->ilink = p->ilink ;
            else table[indx].ilink = p->ilink ;
        }

        free_STRING(ap->sval) ;
        cell_destroy(&ap->cell) ;
        ZFREE(ap) ;
        if (--A->size == 0) array_clear(A) ;


    }
}
コード例 #7
0
ファイル: print.c プロジェクト: jlp765/original-mawk
/*
 * 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++;
    }
}