scc

simple c99 compiler
git clone git://git.simple-cc.org/scc
Log | Files | Refs | README | LICENSE

cpp.c (14532B)


      1 static char sccsid[] = "@(#) ./cc1/cpp.c";
      2 #include <ctype.h>
      3 #include <limits.h>
      4 #include <stdio.h>
      5 #include <stdlib.h>
      6 #include <string.h>
      7 #include <time.h>
      8 
      9 #include <scc/cstd.h>
     10 #include <scc/scc.h>
     11 #include "cc1.h"
     12 
     13 static char *argp, *macroname;
     14 static unsigned arglen;
     15 static unsigned ncmdlines;
     16 static Symbol *symline, *symfile;
     17 static unsigned char ifstatus[NR_COND];
     18 static int cppoff;
     19 static struct items dirinclude;
     20 
     21 unsigned cppctx;
     22 int disexpand;
     23 
     24 void
     25 defdefine(char *macro, char *val, char *source)
     26 {
     27 	char *def, *fmt = "#define %s %s\n";
     28 	Symbol dummy = {.flags = SDECLARED};
     29 
     30 	if (!val)
     31 		val = "";
     32 	def = xmalloc(strlen(fmt) + strlen(macro) + strlen(val));
     33 
     34 	sprintf(def, fmt, macro, val);
     35 	lineno = ++ncmdlines;
     36 	addinput(source, &dummy, def);
     37 	cpp();
     38 	delinput();
     39 }
     40 
     41 void
     42 undefmacro(char *s)
     43 {
     44 	killsym(lookup(NS_CPP, s, NOALLOC));
     45 }
     46 
     47 void
     48 icpp(void)
     49 {
     50 	static char sdate[14], stime[11];
     51 	struct tm *tm;
     52 	time_t t;
     53 	static char **bp, *list[] = {
     54 		"__STDC__",
     55 		"__STDC_HOSTED__",
     56 		"__SCC__",
     57 		NULL
     58 	};
     59 	static struct keyword keys[] = {
     60 		{"define", DEFINE, DEFINE},
     61 		{"include", INCLUDE, INCLUDE},
     62 		{"line", LINE, LINE},
     63 		{"ifdef", IFDEF, IFDEF},
     64 		{"if", IF, IF},
     65 		{"elif", ELIF, ELIF},
     66 		{"else", ELSE, ELSE},
     67 		{"ifndef", IFNDEF, IFNDEF},
     68 		{"endif", ENDIF, ENDIF},
     69 		{"undef", UNDEF, UNDEF},
     70 		{"pragma", PRAGMA, PRAGMA},
     71 		{"error", ERROR, ERROR},
     72 		{NULL, 0, 0}
     73 	};
     74 
     75 	keywords(keys, NS_CPPCLAUSES);
     76 
     77 	t = time(NULL);
     78 	tm = localtime(&t);
     79 	strftime(sdate, sizeof(sdate), "\"%b %d %Y\"", tm);
     80 	strftime(stime, sizeof(stime), "\"%H:%M:%S\"", tm);
     81 	defdefine("__DATE__", sdate, "built-in");
     82 	defdefine("__TIME__", stime, "built-in");
     83 	defdefine("__STDC_VERSION__", STDC_VERSION, "built-in");
     84 	defdefine("__LINE__", NULL, "built-in");
     85 	defdefine("__FILE__", NULL, "built-in");
     86 
     87 	symline = lookup(NS_CPP, "__LINE__", ALLOC);
     88 	symfile = lookup(NS_CPP, "__FILE__", ALLOC);
     89 
     90 	for (bp = list; *bp; ++bp)
     91 		defdefine(*bp, "1", "built-in");
     92 
     93 	ncmdlines = 0;
     94 }
     95 
     96 static void
     97 nextcpp(void)
     98 {
     99 	next();
    100 	if (yytoken == EOFTOK)
    101 		error("unterminated argument list invoking macro \"%s\"",
    102 		      macroname);
    103 	if (yylen + 1 > arglen)
    104 		error("argument overflow invoking macro \"%s\"",
    105 		      macroname);
    106 	if (yytoken == IDEN)
    107 		yylval.sym->flags |= SUSED;
    108 	memcpy(argp, yytext, yylen);
    109 	argp += yylen;
    110 	*argp++ = ' ';
    111 	arglen -= yylen + 1;
    112 }
    113 
    114 static void
    115 paren(void)
    116 {
    117 	for (;;) {
    118 		nextcpp();
    119 		switch (yytoken) {
    120 		case ')':
    121 			return;
    122 		case '(':
    123 			paren();
    124 			break;
    125 		}
    126 	}
    127 }
    128 
    129 static void
    130 parameter(void)
    131 {
    132 	for (;;) {
    133 		nextcpp();
    134 		switch (yytoken) {
    135 		case ')':
    136 		case ',':
    137 			argp -= 3;  /* remove " , "  or " ) "*/
    138 			*argp++ = '\0';
    139 			return;
    140 		case '(':
    141 			paren();
    142 			break;
    143 		}
    144 	}
    145 }
    146 
    147 static int
    148 parsepars(char *buffer, char **listp, int nargs)
    149 {
    150 	int n;
    151 
    152 	if (nargs == -1)
    153 		return -1;
    154 	if (ahead() != '(' && nargs > 0)
    155 		return 0;
    156 
    157 	disexpand = 1;
    158 	next();
    159 	n = 0;
    160 	argp = buffer;
    161 	arglen = INPUTSIZ;
    162 	if (ahead() == ')') {
    163 		next();
    164 	} else {
    165 		do {
    166 			*listp++ = argp;
    167 			parameter();
    168 		} while (++n < NR_MACROARG && yytoken == ',');
    169 	}
    170 	if (yytoken != ')')
    171 		error("incorrect macro function-alike invocation");
    172 	disexpand = 0;
    173 
    174 	if (n == NR_MACROARG)
    175 		error("too many parameters in macro \"%s\"", macroname);
    176 	if (n != nargs) {
    177 		error("macro \"%s\" received %d arguments, but it takes %d",
    178 		      macroname, n, nargs);
    179 	}
    180 
    181 	return 1;
    182 }
    183 
    184 static size_t
    185 copymacro(char *buffer, char *s, size_t bufsiz, char *arglist[])
    186 {
    187 	int delim, prevc, c;
    188 	char *p, *arg, *bp = buffer;
    189 	size_t size;
    190 
    191 	for (prevc = '\0'; c = *s; prevc = c, ++s) {
    192 		switch (c) {
    193 		case '$':
    194 			while (bp[-1] == ' ')
    195 				--bp, ++bufsiz;
    196 			while (s[1] == ' ')
    197 				++s;
    198 		case '#':
    199 			break;
    200 		case '\'':
    201 			delim = '\'';
    202 			goto search_delim;
    203 		case '\"':
    204 			delim = '"';
    205 		search_delim:
    206 			for (p = s; *++s != delim; )
    207 				;
    208 			size = s - p + 1;
    209 			if (size > bufsiz)
    210 				goto expansion_too_long;
    211 			memcpy(bp, p, size);
    212 			bufsiz -= size;
    213 			bp += size;
    214 			break;
    215 		case '@':
    216 			if (prevc == '#')
    217 				bufsiz -= 2;
    218 			arg = arglist[atoi(++s)];
    219 			size = strlen(arg);
    220 			if (size > bufsiz)
    221 				goto expansion_too_long;
    222 			if (prevc == '#')
    223 				*bp++ = '"';
    224 			memcpy(bp, arg, size);
    225 			bp += size;
    226 			if (prevc == '#')
    227 				*bp++ = '"';
    228 			bufsiz -= size;
    229 			s += 2;
    230 			break;
    231 		default:
    232 			if (bufsiz-- == 0)
    233 				goto expansion_too_long;
    234 			*bp++ = c;
    235 			break;
    236 		}
    237 	}
    238 	*bp = '\0';
    239 
    240 	return bp - buffer;
    241 
    242 expansion_too_long:
    243 	error("macro expansion of \"%s\" too long", macroname);
    244 }
    245 
    246 int
    247 expand(char *begin, Symbol *sym)
    248 {
    249 	size_t elen;
    250 	int n, i;
    251 	char *s = sym->u.s;
    252 	char *arglist[NR_MACROARG], arguments[INPUTSIZ], buffer[INPUTSIZ];
    253 
    254 	macroname = sym->name;
    255 	if (sym == symfile) {
    256 		elen = sprintf(buffer, "\"%s\" ", filenam);
    257 		goto substitute;
    258 	}
    259 	if (sym == symline) {
    260 		elen = sprintf(buffer, "%d ", lineno);
    261 		goto substitute;
    262 	}
    263 	if (!s)
    264 		return 1;
    265 
    266 	n = atoi(s);
    267 	if (!parsepars(arguments, arglist, n))
    268 		return 0;
    269 	for (i = 0; i < n; ++i)
    270 		DBG("MACRO par%d:%s", i, arglist[i]);
    271 
    272 	elen = copymacro(buffer, s+3, INPUTSIZ-1, arglist);
    273 
    274 substitute:
    275 	DBG("MACRO '%s' expanded to :'%s'", macroname, buffer);
    276 	buffer[elen] = '\0';
    277 	addinput(filenam, sym, xstrdup(buffer));
    278 
    279 	return 1;
    280 }
    281 
    282 static int
    283 getpars(Symbol *args[NR_MACROARG])
    284 {
    285 	int n, c;
    286 	Symbol *sym;
    287 
    288 	c = *input->p;
    289 	next();
    290 	if (c != '(')
    291 		return -1;
    292 	next(); /* skip the '(' */
    293 	if (accept(')'))
    294 		return 0;
    295 
    296 	n = 0;
    297 	do {
    298 		if (n == NR_MACROARG) {
    299 			cpperror("too many parameters in macro");
    300 			return NR_MACROARG;
    301 		}
    302 		if (accept(ELLIPSIS)) {
    303 			args[n++] = NULL;
    304 			break;
    305 		}
    306 		if (yytoken != IDEN) {
    307 			cpperror("macro arguments must be identifiers");
    308 			return NR_MACROARG;
    309 		}
    310 		sym = install(NS_IDEN, yylval.sym);
    311 		sym->flags |= SUSED;
    312 		args[n++] = sym;
    313 		next();
    314 	} while (accept(','));
    315 	expect(')');
    316 
    317 	return n;
    318 }
    319 
    320 static int
    321 getdefs(Symbol *args[NR_MACROARG], int nargs, char *bp, size_t bufsiz)
    322 {
    323 	Symbol **argp;
    324 	size_t len;
    325 	int prevc = 0, ispar;
    326 
    327 	if (yytoken == '$') {
    328 		cpperror("'##' cannot appear at either ends of a macro expansion");
    329 		return 0;
    330 	}
    331 
    332 	for (;;) {
    333 		ispar = 0;
    334 		if (yytoken == IDEN && nargs >= 0) {
    335 			for (argp = args; argp < &args[nargs]; ++argp) {
    336 				if (*argp == yylval.sym)
    337 					break;
    338 			}
    339 			if (argp != &args[nargs]) {
    340 				sprintf(yytext, "@%02d@", (int) (argp - args));
    341 				ispar = 1;
    342 			}
    343 		}
    344 		if (prevc == '#' && !ispar) {
    345 			cpperror("'#' is not followed by a macro parameter");
    346 			return 0;
    347 		}
    348 		if (yytoken == '\n')
    349 			break;
    350 
    351 		if ((len = strlen(yytext)) >= bufsiz) {
    352 			cpperror("macro too long");
    353 			return 0;
    354 		}
    355 		if (yytoken == '$') {
    356 			*bp++ = '$';
    357 			 --bufsiz;
    358 		} else {
    359 			memcpy(bp, yytext, len);
    360 			bp += len;
    361 			bufsiz -= len;
    362 		}
    363 		if ((prevc = yytoken) != '#') {
    364 			*bp++ = ' ';
    365 			--bufsiz;
    366 		}
    367 		next();
    368 	}
    369 	*bp = '\0';
    370 	return 1;
    371 }
    372 
    373 static void
    374 define(void)
    375 {
    376 	Symbol *sym,*args[NR_MACROARG];
    377 	char buff[LINESIZ+1];
    378 	int n;
    379 
    380 	if (cppoff)
    381 		return;
    382 
    383 	namespace = NS_CPP;
    384 	next();
    385 
    386 	if (yytoken != IDEN) {
    387 		cpperror("macro names must be identifiers");
    388 		return;
    389 	}
    390 	sym = yylval.sym;
    391 	if (sym->flags & SDECLARED) {
    392 		warn("'%s' redefined", yytext);
    393 		free(sym->u.s);
    394 	} else {
    395 		sym = install(NS_CPP, sym);
    396 		sym->flags |= SDECLARED|SSTRING;
    397 	}
    398 
    399 	namespace = NS_IDEN;       /* Avoid polution in NS_CPP */
    400 	if ((n = getpars(args)) == NR_MACROARG)
    401 		goto delete;
    402 	if (n > 0 && !args[n-1])  /* it is a variadic function */
    403 		--n;
    404 	sprintf(buff, "%02d#", n);
    405 	if (!getdefs(args, n, buff+3, LINESIZ-3))
    406 		goto delete;
    407 	sym->u.s = xstrdup(buff);
    408 	DBG("MACRO '%s' defined as '%s'", sym->name, buff);
    409 	return;
    410 
    411 delete:
    412 	killsym(sym);
    413 }
    414 
    415 void
    416 incdir(char *dir)
    417 {
    418 	if (!dir || *dir == '\0')
    419 		die("cc1: incorrect -I flag");
    420 	newitem(&dirinclude, dir);
    421 }
    422 
    423 static int
    424 includefile(char *dir, char *file, size_t filelen)
    425 {
    426 	size_t dirlen;
    427 	char path[FILENAME_MAX];
    428 
    429 	if (!dir) {
    430 		dirlen = 0;
    431 		if (filelen > FILENAME_MAX-1)
    432 			return 0;
    433 	} else {
    434 		dirlen = strlen(dir);
    435 		if (dirlen + filelen > FILENAME_MAX-2)
    436 			return 0;
    437 		memcpy(path, dir, dirlen);
    438 		if (dir[dirlen-1] != '/')
    439 			path[dirlen++] = '/';
    440 	}
    441 	memcpy(path+dirlen, file, filelen);
    442 	path[dirlen + filelen] = '\0';
    443 
    444 	addinput(path, NULL, NULL);
    445 	return 1;
    446 }
    447 
    448 static char *
    449 cwd(char *buf)
    450 {
    451 	char *p, *s = filenam;
    452 	size_t len;
    453 
    454 	if ((p = strrchr(s, '/')) == NULL)
    455 		return NULL;
    456 	if ((len = p - s) >= FILENAME_MAX)
    457 		die("cc1: current work directory too long");
    458 	memcpy(buf, s, len);
    459 	buf[len] = '\0';
    460 	return buf;
    461 }
    462 
    463 static void
    464 include(void)
    465 {
    466 	char dir[FILENAME_MAX], file[FILENAME_MAX], *p, **bp;
    467 	size_t filelen;
    468 	int n;
    469 
    470 	if (cppoff)
    471 		return;
    472 
    473 	namespace = NS_IDEN;
    474 	next();
    475 
    476 	switch (*yytext) {
    477 	case '<':
    478 		if ((p = strchr(input->begin, '>')) == NULL || p[-1] == '<')
    479 			goto bad_include;
    480 		filelen = p - input->begin;
    481 		if (filelen >= FILENAME_MAX)
    482 			goto too_long;
    483 		memcpy(file, input->begin, filelen);
    484 		file[filelen] = '\0';
    485 
    486 		input->begin = input->p = p+1;
    487 		if (next() != '\n')
    488 			goto trailing_characters;
    489 
    490 		break;
    491 	case '"':
    492 		if (yylen < 3)
    493 			goto bad_include;
    494 		filelen = yylen-2;
    495 		if (filelen >= FILENAME_MAX)
    496 			goto too_long;
    497 		memcpy(file, yytext+1, filelen);
    498 		file[filelen] = '\0';
    499 
    500 		if (next() != '\n')
    501 			goto trailing_characters;
    502 
    503 		if (includefile(cwd(dir), file, filelen))
    504 			goto its_done;
    505 		break;
    506 	default:
    507 		goto bad_include;
    508 	}
    509 
    510 	n = dirinclude.n;
    511 	for (bp = dirinclude.s; n--; ++bp) {
    512 		if (includefile(*bp, file, filelen))
    513 			goto its_done;
    514 	}
    515 	cpperror("included file '%s' not found", file);
    516 
    517 its_done:
    518 	return;
    519 
    520 trailing_characters:
    521 	cpperror("trailing characters after preprocessor directive");
    522 	return;
    523 
    524 too_long:
    525 	cpperror("too long file name in #include");
    526 	return;
    527 
    528 bad_include:
    529 	cpperror("#include expects \"FILENAME\" or <FILENAME>");
    530 	return;
    531 }
    532 
    533 static void
    534 line(void)
    535 {
    536 	long n;
    537 	char *endp, *fname;
    538 
    539 	if (cppoff)
    540 		return;
    541 
    542 	disexpand = 0;
    543 	next();
    544 	n = strtol(yytext, &endp, 10);
    545 	if (n <= 0 || n > USHRT_MAX || *endp != '\0') {
    546 		cpperror("first parameter of #line is not a positive integer");
    547 		return;
    548 	}
    549 
    550 	next();
    551 	if (yytoken == '\n') {
    552 		fname = NULL;
    553 	} else {
    554 		if (*yytext != '\"' || yylen == 1) {
    555 			cpperror("second parameter of #line is not a valid filename");
    556 			return;
    557 		}
    558 		fname = yylval.sym->u.s;
    559 	}
    560 	setloc(fname, n - 1);
    561 	if (yytoken != '\n')
    562 		next();
    563 }
    564 
    565 static void
    566 pragma(void)
    567 {
    568 	if (cppoff)
    569 		return;
    570 	next();
    571 	warn("ignoring pragma '%s'", yytext);
    572 	*input->p = '\0';
    573 	next();
    574 }
    575 
    576 static void
    577 usererr(void)
    578 {
    579 	if (cppoff)
    580 		return;
    581 	cpperror("#error %s", input->p);
    582 	*input->p = '\0';
    583 	next();
    584 }
    585 
    586 static void
    587 ifclause(int negate, int isifdef)
    588 {
    589 	Symbol *sym;
    590 	unsigned n;
    591 	int status;
    592 	Node *expr;
    593 
    594 	if (cppctx == NR_COND-1)
    595 		error("too many nesting levels of conditional inclusion");
    596 
    597 	n = cppctx++;
    598 	namespace = NS_CPP;
    599 	next();
    600 
    601 	if (isifdef) {
    602 		if (yytoken != IDEN) {
    603 			cpperror("no macro name given in #%s directive",
    604 			         (negate) ? "ifndef" : "ifdef");
    605 			return;
    606 		}
    607 		sym = yylval.sym;
    608 		next();
    609 		status = (sym->flags & SDECLARED) != 0;
    610 		if (!status)
    611 			killsym(sym);
    612 	} else {
    613 		/* TODO: catch recovery here */
    614 		if ((expr = constexpr()) == NULL) {
    615 			cpperror("parameter of #if is not an integer constant expression");
    616 			return;
    617 		}
    618 		status = expr->sym->u.i != 0;
    619 		freetree(expr);
    620 	}
    621 
    622 	if (negate)
    623 		status = !status;
    624 	if ((ifstatus[n] = status) == 0)
    625 		++cppoff;
    626 }
    627 
    628 static void
    629 cppif(void)
    630 {
    631 	disexpand = 0;
    632 	ifclause(0, 0);
    633 }
    634 
    635 static void
    636 ifdef(void)
    637 {
    638 	ifclause(0, 1);
    639 }
    640 
    641 static void
    642 ifndef(void)
    643 {
    644 	ifclause(1, 1);
    645 }
    646 
    647 static void
    648 elseclause(void)
    649 {
    650 	int status;
    651 
    652 	if (cppctx == 0) {
    653 		cpperror("#else without #ifdef/ifndef");
    654 		return;
    655 	}
    656 
    657 	status = ifstatus[cppctx-1];
    658 	ifstatus[cppctx-1] = !status;
    659 	cppoff += (status) ? 1 : -1;
    660 }
    661 
    662 static void
    663 cppelse(void)
    664 {
    665 	elseclause();
    666 	next();
    667 }
    668 
    669 static void
    670 elif(void)
    671 {
    672 	elseclause();
    673 	if (ifstatus[cppctx-1]) {
    674 		--cppctx;
    675 		cppif();
    676 	}
    677 }
    678 
    679 static void
    680 endif(void)
    681 {
    682 	if (cppctx == 0)
    683 		error("#endif without #if");
    684 	if (!ifstatus[--cppctx])
    685 		--cppoff;
    686 	next();
    687 }
    688 
    689 static void
    690 undef(void)
    691 {
    692 	if (cppoff)
    693 		return;
    694 
    695 	namespace = NS_CPP;
    696 	next();
    697 	if (yytoken != IDEN) {
    698 		error("no macro name given in #undef directive");
    699 		return;
    700 	}
    701 	killsym(yylval.sym);
    702 	next();
    703 }
    704 
    705 int
    706 cpp(void)
    707 {
    708 	static struct {
    709 		unsigned char token;
    710 		void (*fun)(void);
    711 	} *bp, clauses [] = {
    712 		{DEFINE, define},
    713 		{INCLUDE, include},
    714 		{LINE, line},
    715 		{IFDEF, ifdef},
    716 		{IF, cppif},
    717 		{ELIF, elif},
    718 		{IFNDEF, ifndef},
    719 		{ELSE, cppelse},
    720 		{ENDIF, endif},
    721 		{UNDEF, undef},
    722 		{PRAGMA, pragma},
    723 		{ERROR, usererr},
    724 		{0, NULL}
    725 	};
    726 	int ns;
    727 	char *p;
    728 
    729 	for (p = input->p; isspace(*p); ++p)
    730 		;
    731 
    732 	if (*p != '#')
    733 		return cppoff;
    734 	input->p = p+1;
    735 
    736 	disexpand = 1;
    737 	lexmode = CPPMODE;
    738 	ns = namespace;
    739 	namespace = NS_CPPCLAUSES;
    740 	next();
    741 	namespace = NS_IDEN;
    742 
    743 	for (bp = clauses; bp->token && bp->token != yytoken; ++bp)
    744 		;
    745 	if (!bp->token) {
    746 		errorp("incorrect preprocessor directive '%s'", yytext);
    747 		goto error;
    748 	}
    749 
    750 	DBG("CPP %s", yytext);
    751 
    752 	pushctx();              /* create a new context to avoid polish */
    753 	(*bp->fun)();           /* the current context, and to get all  */
    754 	popctx();               /* the symbols freed at the  end        */
    755 
    756 	/*
    757 	 * #include changes the content of input->line, so the correctness
    758 	 * of the line must be checked in the own include(), and we have
    759 	 * to skip this tests. For the same reason include() is the only
    760 	 * function which does not prepare the next token
    761 	 */
    762 	if (yytoken != '\n' && !cppoff && bp->token != INCLUDE)
    763 		errorp("trailing characters after preprocessor directive");
    764 
    765 error:
    766 	disexpand = 0;
    767 	lexmode = CCMODE;
    768 	namespace = ns;
    769 
    770 	return 1;
    771 }
    772 
    773 void
    774 ppragmaln(void)
    775 {
    776 	static char file[FILENAME_MAX];
    777 	static unsigned nline;
    778 	char *s;
    779 
    780 	putchar('\n');
    781 	if (strcmp(file, filenam)) {
    782 		strcpy(file, filenam);
    783 		s = "#line %u \"%s\"\n";
    784 	} else if (nline+1 != lineno) {
    785 		s = "#line %u\n";
    786 	} else {
    787 		s = "";
    788 	}
    789 	nline = lineno;
    790 	printf(s, nline, file);
    791 }
    792 
    793 void
    794 outcpp(void)
    795 {
    796 	int c;
    797 	char *s, *t;
    798 
    799 	for (next(); yytoken != EOFTOK; next()) {
    800 		if (onlyheader)
    801 			continue;
    802 		if (yytoken != STRING) {
    803 			printf("%s ", yytext);
    804 			continue;
    805 		}
    806 		for (s = yytext; c = *s; ++s) {
    807 			switch (c) {
    808 			case '\n':
    809 				t = "\\n";
    810 				goto print_str;
    811 			case '\v':
    812 				t = "\\v";
    813 				goto print_str;
    814 			case '\b':
    815 				t = "\\b";
    816 				goto print_str;
    817 			case '\t':
    818 				t = "\\t";
    819 				goto print_str;
    820 			case '\a':
    821 				t = "\\a";
    822 			print_str:
    823 				fputs(t, stdout);
    824 				break;
    825 			case '\\':
    826 				putchar('\\');
    827 			default:
    828 				if (!isprint(c))
    829 					printf("\\x%x", c);
    830 				else
    831 					putchar(c);
    832 				break;
    833 			}
    834 		}
    835 		putchar(' ');
    836 	}
    837 	putchar('\n');
    838 }
    839