scc

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

cpp.c (14524B)


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