github.com/akaros/go-akaros@v0.0.0-20181004170632-85005d477eab/src/cmd/cc/lex.c (about)

     1  // Inferno utils/cc/lex.c
     2  // http://code.google.com/p/inferno-os/source/browse/utils/cc/lex.c
     3  //
     4  //	Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
     5  //	Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
     6  //	Portions Copyright © 1997-1999 Vita Nuova Limited
     7  //	Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
     8  //	Portions Copyright © 2004,2006 Bruce Ellis
     9  //	Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
    10  //	Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
    11  //	Portions Copyright © 2009 The Go Authors.  All rights reserved.
    12  //
    13  // Permission is hereby granted, free of charge, to any person obtaining a copy
    14  // of this software and associated documentation files (the "Software"), to deal
    15  // in the Software without restriction, including without limitation the rights
    16  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    17  // copies of the Software, and to permit persons to whom the Software is
    18  // furnished to do so, subject to the following conditions:
    19  //
    20  // The above copyright notice and this permission notice shall be included in
    21  // all copies or substantial portions of the Software.
    22  //
    23  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    24  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    25  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
    26  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    27  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    28  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    29  // THE SOFTWARE.
    30  
    31  #include	<u.h>
    32  #include	"cc.h"
    33  #include	"y.tab.h"
    34  #include	"../ld/textflag.h"
    35  
    36  #ifndef	CPP
    37  #define	CPP	"cpp"
    38  #endif
    39  
    40  int
    41  systemtype(int sys)
    42  {
    43  #ifdef _WIN32
    44  	return sys&Windows;
    45  #else
    46  	return sys&Plan9;
    47  #endif
    48  }
    49  
    50  int
    51  pathchar(void)
    52  {
    53  	return '/';
    54  }
    55  
    56  /*
    57   * known debug flags
    58   *	-a		acid declaration output
    59   *	-A		!B
    60   *	-B		non ANSI
    61   *	-d		print declarations
    62   *	-D name		define
    63   *	-F		format specification check
    64   *	-G		print pgen stuff
    65   *	-g		print cgen trees
    66   *	-i		print initialization
    67   *	-I path		include
    68   *	-l		generate little-endian code
    69   *	-L		print every NAME symbol
    70   *	-M		constant multiplication
    71   *	-m		print add/sub/mul trees
    72   *	-n		print acid or godefs to file (%.c=%.acid) (with -a or -aa)
    73   *	-o file		output file
    74   *	-p		use standard cpp ANSI preprocessor (not on windows)
    75   *	-p		something with peepholes
    76   *	-q		print equivalent Go code for variables and types (lower-case identifiers)
    77   *	-Q		print equivalent Go code for variables and types (upper-case identifiers)
    78   *	-r		print registerization
    79   *	-s		print structure offsets (with -a or -aa)
    80   *	-S		print assembly
    81   *	-t		print type trees
    82   *	-V		enable void* conversion warnings
    83   *	-v		verbose printing
    84   *	-w		print warnings
    85   *	-X		abort on error
    86   *	-.		Inhibit search for includes in source directory
    87   */
    88  
    89  void
    90  usage(void)
    91  {
    92  	print("usage: %cc [options] file.c...\n", thechar);
    93  	flagprint(1);
    94  	errorexit();
    95  }
    96  
    97  void
    98  dospim(void)
    99  {
   100  	thechar = '0';
   101  	thestring = "spim";
   102  }
   103  
   104  char **defs;
   105  int ndef;
   106  
   107  void
   108  dodef(char *p)
   109  {
   110  	if(ndef%8 == 0)
   111  		defs = allocn(defs, ndef*sizeof(char *),
   112  			8*sizeof(char *));
   113  	defs[ndef++] = p;
   114  	dodefine(p);
   115  }
   116  
   117  void
   118  main(int argc, char *argv[])
   119  {
   120  	int c;
   121  	char *p;
   122  
   123  	// Allow GOARCH=thestring or GOARCH=thestringsuffix,
   124  	// but not other values.	
   125  	p = getgoarch();
   126  	if(strncmp(p, thestring, strlen(thestring)) != 0)
   127  		sysfatal("cannot use %cc with GOARCH=%s", thechar, p);
   128  	if(strcmp(p, "amd64p32") == 0) // must be before cinit
   129  		ewidth[TIND] = 4;
   130  		
   131  	nacl = strcmp(getgoos(), "nacl") == 0;
   132  	if(nacl)
   133  		flag_largemodel = 1;
   134  
   135  	quotefmtinstall(); // before cinit, which overrides %Q
   136  
   137  	linkarchinit();
   138  	ctxt = linknew(thelinkarch);
   139  	ctxt->diag = yyerror;
   140  	ctxt->bso = &bstdout;
   141  	Binit(&bstdout, 1, OWRITE);
   142  
   143  	ensuresymb(NSYMB);
   144  	memset(debug, 0, sizeof(debug));
   145  	tinit();
   146  	cinit();
   147  	ginit();
   148  	arginit();
   149  	
   150  	fmtstrinit(&pragcgobuf);
   151  
   152  	tufield = simplet((1L<<tfield->etype) | BUNSIGNED);
   153  	ndef = 0;
   154  	defs = nil;
   155  	outfile = 0;
   156  	setinclude(".");
   157  
   158  	flagcount("+", "pass -+ to preprocessor", &debug['+']);	
   159  	flagcount(".", "pass -. to preprocessor", &debug['.']);	
   160  	flagcount("<", "debug shift", &debug['<']);
   161  	flagcount("A", "debug alignment", &debug['A']);
   162  	flagcount("B", "allow pre-ANSI code", &debug['B']);
   163  	if(thechar == '5')
   164  		flagcount("C", "debug constant propagation", &debug['C']);
   165  	flagfn1("D", "name[=value]: add #define", dodef);
   166  	flagcount("F", "enable print format checks", &debug['F']);
   167  	if(thechar == '5')
   168  		flagcount("H", "debug shift propagation", &debug['H']);
   169  	flagfn1("I", "dir: add dir to include path", setinclude);
   170  	flagcount("L", "debug lexer", &debug['L']);
   171  	flagcount("M", "debug move generation", &debug['M']);
   172  	flagcount("N", "disable optimizations", &debug['N']);
   173  	flagcount("P", "debug peephole optimizer", &debug['P']);
   174  	flagcount("Q", "print exported Go definitions", &debug['Q']);
   175  	flagcount("R", "debug register optimizer", &debug['R']);
   176  	flagcount("S", "print assembly", &debug['S']);
   177  	flagcount("T", "enable type signatures", &debug['T']);
   178  	flagcount("V", "enable pointer type checks", &debug['V']);
   179  	flagcount("W", "debug switch generation", &debug['W']);
   180  	flagcount("X", "abort on error", &debug['X']);
   181  	flagcount("Y", "debug index generation", &debug['Y']);
   182  	flagcount("Z", "skip code generation", &debug['Z']);
   183  	flagcount("a", "print acid definitions", &debug['a']);
   184  	flagcount("c", "debug constant evaluation", &debug['c']);
   185  	flagcount("d", "debug declarations", &debug['d']);
   186  	flagcount("e", "debug macro expansion", &debug['e']);
   187  	flagcount("f", "debug pragmas", &debug['f']);
   188  	flagcount("g", "debug code generation", &debug['g']);
   189  	flagcount("i", "debug initialization", &debug['i']);
   190  	if(thechar == 'v')
   191  		flagfn0("l", "little-endian mips mode", dospim);
   192  	flagcount("m", "debug multiplication", &debug['m']);
   193  	flagcount("n", "print acid/Go to file, not stdout", &debug['n']);
   194  	flagstr("o", "file: set output file", &outfile);
   195  	flagcount("p", "invoke C preprocessor", &debug['p']);	
   196  	flagcount("q", "print Go definitions", &debug['q']);
   197  	flagcount("s", "print #define assembly offsets", &debug['s']);
   198  	flagcount("t", "debug code generation", &debug['t']);
   199  	flagstr("trimpath", "prefix: remove prefix from recorded source file paths", &ctxt->trimpath);
   200  	flagcount("w", "enable warnings", &debug['w']);
   201  	flagcount("v", "increase debug verbosity", &debug['v']);	
   202  	if(thechar == '6')
   203  		flagcount("largemodel", "generate code that assumes a large memory model", &flag_largemodel);
   204  	
   205  	flagparse(&argc, &argv, usage);
   206  	ctxt->debugasm = debug['S'];
   207  	ctxt->debugvlog = debug['v'];
   208  
   209  	if(argc < 1 && outfile == 0)
   210  		usage();
   211  
   212  	if(argc > 1){
   213  		print("can't compile multiple files\n");
   214  		errorexit();
   215  	}
   216  
   217  	if(argc == 0)
   218  		c = compile("stdin", defs, ndef);
   219  	else
   220  		c = compile(argv[0], defs, ndef);
   221  
   222  	Bflush(&bstdout);
   223  	if(c)
   224  		errorexit();
   225  	exits(0);
   226  }
   227  
   228  int
   229  compile(char *file, char **defs, int ndef)
   230  {
   231  	char *ofile;
   232  	char *p, **av, opt[256];
   233  	int i, c, fd[2];
   234  	static int first = 1;
   235  
   236  	ofile = alloc(strlen(file)+10);
   237  	strcpy(ofile, file);
   238  	p = utfrrune(ofile, pathchar());
   239  	if(p) {
   240  		*p++ = 0;
   241  		if(!debug['.'])
   242  			include[0] = strdup(ofile);
   243  	} else
   244  		p = ofile;
   245  
   246  	if(outfile == 0) {
   247  		outfile = p;
   248  		if(outfile) {
   249  			if(p = utfrrune(outfile, '.'))
   250  				if(p[1] == 'c' && p[2] == 0)
   251  					p[0] = 0;
   252  			p = utfrune(outfile, 0);
   253  			if(debug['a'] && debug['n'])
   254  				strcat(p, ".acid");
   255  			else if((debug['q'] || debug['Q']) && debug['n'])
   256  				strcat(p, ".go");
   257  			else {
   258  				p[0] = '.';
   259  				p[1] = thechar;
   260  				p[2] = 0;
   261  			}
   262  		} else
   263  			outfile = "/dev/null";
   264  	}
   265  
   266  	if (first)
   267  		Binit(&diagbuf, 1, OWRITE);
   268  	/*
   269  	 * if we're writing acid to standard output, don't keep scratching
   270  	 * outbuf.
   271  	 */
   272  	if((debug['a'] || debug['q'] || debug['Q']) && !debug['n']) {
   273  		if (first) {
   274  			outfile = 0;
   275  			Binit(&outbuf, dup(1, -1), OWRITE);
   276  			dup(2, 1);
   277  		}
   278  	} else {
   279  		c = create(outfile, OWRITE, 0664);
   280  		if(c < 0) {
   281  			diag(Z, "cannot open %s - %r", outfile);
   282  			outfile = 0;
   283  			errorexit();
   284  		}
   285  		Binit(&outbuf, c, OWRITE);
   286  		outfile = strdup(outfile);
   287  	}
   288  	newio();
   289  	first = 0;
   290  
   291  	/* Use an ANSI preprocessor */
   292  	if(debug['p']) {
   293  		if(systemtype(Windows)) {
   294  			diag(Z, "-p option not supported on windows");
   295  			errorexit();
   296  		}
   297  		if(access(file, AREAD) < 0) {
   298  			diag(Z, "%s does not exist", file);
   299  			errorexit();
   300  		}
   301  		if(pipe(fd) < 0) {
   302  			diag(Z, "pipe failed");
   303  			errorexit();
   304  		}
   305  		switch(fork()) {
   306  		case -1:
   307  			diag(Z, "fork failed");
   308  			errorexit();
   309  		case 0:
   310  			close(fd[0]);
   311  			dup(fd[1], 1);
   312  			close(fd[1]);
   313  			av = alloc((ndef+ninclude+5)*sizeof(char *));
   314  			av[0] = CPP;
   315  			i = 1;
   316  			if(debug['.']){
   317  				sprint(opt, "-.");
   318  				av[i++] = strdup(opt);
   319  			}
   320  			if(debug['+']) {
   321  				sprint(opt, "-+");
   322  				av[i++] = strdup(opt);
   323  			}
   324  			for(c = 0; c < ndef; c++)
   325  				av[i++] = smprint("-D%s", defs[c]);
   326  			for(c = 0; c < ninclude; c++)
   327  				av[i++] = smprint("-I%s", include[c]);
   328  			if(strcmp(file, "stdin") != 0)
   329  				av[i++] = file;
   330  			av[i] = 0;
   331  			if(debug['p'] > 1) {
   332  				for(c = 0; c < i; c++)
   333  					fprint(2, "%s ", av[c]);
   334  				fprint(2, "\n");
   335  			}
   336  			exec(av[0], av);
   337  			fprint(2, "can't exec C preprocessor %s: %r\n", CPP);
   338  			errorexit();
   339  		default:
   340  			close(fd[1]);
   341  			newfile(file, fd[0]);
   342  			break;
   343  		}
   344  	} else {
   345  		if(strcmp(file, "stdin") == 0)
   346  			newfile(file, 0);
   347  		else
   348  			newfile(file, -1);
   349  	}
   350  	yyparse();
   351  	if(!debug['a'] && !debug['q'] && !debug['Q'])
   352  		gclean();
   353  	return nerrors;
   354  }
   355  
   356  void
   357  errorexit(void)
   358  {
   359  	Bflush(&bstdout);
   360  	if(outfile)
   361  		remove(outfile);
   362  	exits("error");
   363  }
   364  
   365  void
   366  pushio(void)
   367  {
   368  	Io *i;
   369  
   370  	i = iostack;
   371  	if(i == I) {
   372  		yyerror("botch in pushio");
   373  		errorexit();
   374  	}
   375  	i->p = fi.p;
   376  	i->c = fi.c;
   377  }
   378  
   379  void
   380  newio(void)
   381  {
   382  	Io *i;
   383  	static int pushdepth = 0;
   384  
   385  	i = iofree;
   386  	if(i == I) {
   387  		pushdepth++;
   388  		if(pushdepth > 1000) {
   389  			yyerror("macro/io expansion too deep");
   390  			errorexit();
   391  		}
   392  		i = alloc(sizeof(*i));
   393  	} else
   394  		iofree = i->link;
   395  	i->c = 0;
   396  	i->f = -1;
   397  	ionext = i;
   398  }
   399  
   400  void
   401  newfile(char *s, int f)
   402  {
   403  	Io *i;
   404  
   405  	if(debug['e'])
   406  		print("%L: %s\n", lineno, s);
   407  
   408  	i = ionext;
   409  	i->link = iostack;
   410  	iostack = i;
   411  	i->f = f;
   412  	if(f < 0)
   413  		i->f = open(s, 0);
   414  	if(i->f < 0) {
   415  		yyerror("%cc: %r: %s", thechar, s);
   416  		errorexit();
   417  	}
   418  	fi.c = 0;
   419  	linklinehist(ctxt, lineno, s, 0);
   420  }
   421  
   422  Sym*
   423  slookup(char *s)
   424  {
   425  	ensuresymb(strlen(s));
   426  	strcpy(symb, s);
   427  	return lookup();
   428  }
   429  
   430  Sym*
   431  lookup(void)
   432  {
   433  	Sym *s;
   434  	uint32 h;
   435  	char *p;
   436  	int c, n;
   437  	char *r, *w;
   438  
   439  	if((uchar)symb[0] == 0xc2 && (uchar)symb[1] == 0xb7) {
   440  		// turn leading · into ""·
   441  		h = strlen(symb);
   442  		ensuresymb(h+2);
   443  		memmove(symb+2, symb, h+1);
   444  		symb[0] = '"';
   445  		symb[1] = '"';
   446  	}
   447  
   448  	for(r=w=symb; *r; r++) {
   449  		// turn · (U+00B7) into .
   450  		// turn ∕ (U+2215) into /
   451  		if((uchar)*r == 0xc2 && (uchar)*(r+1) == 0xb7) {
   452  			*w++ = '.';
   453  			r++;
   454  		}else if((uchar)*r == 0xe2 && (uchar)*(r+1) == 0x88 && (uchar)*(r+2) == 0x95) {
   455  			*w++ = '/';
   456  			r++;
   457  			r++;
   458  		}else
   459  			*w++ = *r;
   460  	}
   461  	*w = '\0';
   462  
   463  	h = 0;
   464  	for(p=symb; *p;) {
   465  		h = h * 3;
   466  		h += *p++;
   467  	}
   468  	n = (p - symb) + 1;
   469  	h &= 0xffffff;
   470  	h %= NHASH;
   471  	c = symb[0];
   472  	for(s = hash[h]; s != S; s = s->link) {
   473  		if(s->name[0] != c)
   474  			continue;
   475  		if(strcmp(s->name, symb) == 0)
   476  			return s;
   477  	}
   478  	s = alloc(sizeof(*s));
   479  	s->name = alloc(n);
   480  	memmove(s->name, symb, n);
   481  	s->link = hash[h];
   482  	hash[h] = s;
   483  	syminit(s);
   484  
   485  	return s;
   486  }
   487  
   488  void
   489  syminit(Sym *s)
   490  {
   491  	s->lexical = LNAME;
   492  	s->block = 0;
   493  	s->offset = 0;
   494  	s->type = T;
   495  	s->suetag = T;
   496  	s->class = CXXX;
   497  	s->aused = 0;
   498  	s->sig = SIGNONE;
   499  }
   500  
   501  #define	EOF	(-1)
   502  #define	IGN	(-2)
   503  #define	ESC	(1<<20)
   504  #define	GETC()	((--fi.c < 0)? filbuf(): (*fi.p++ & 0xff))
   505  
   506  enum
   507  {
   508  	Numdec		= 1<<0,
   509  	Numlong		= 1<<1,
   510  	Numuns		= 1<<2,
   511  	Numvlong	= 1<<3,
   512  	Numflt		= 1<<4,
   513  };
   514  
   515  int32
   516  yylex(void)
   517  {
   518  	vlong vv;
   519  	int32 c, c1, t;
   520  	char *cp;
   521  	Rune rune;
   522  	Sym *s;
   523  
   524  	if(peekc != IGN) {
   525  		c = peekc;
   526  		peekc = IGN;
   527  		goto l1;
   528  	}
   529  l0:
   530  	c = GETC();
   531  
   532  l1:
   533  	if(c >= Runeself) {
   534  		/*
   535  		 * extension --
   536  		 *	all multibyte runes are alpha
   537  		 */
   538  		cp = symb;
   539  		goto talph;
   540  	}
   541  	if(isspace(c)) {
   542  		if(c == '\n')
   543  			lineno++;
   544  		goto l0;
   545  	}
   546  	if(isalpha(c)) {
   547  		cp = symb;
   548  		if(c != 'L')
   549  			goto talph;
   550  		*cp++ = c;
   551  		c = GETC();
   552  		if(c == '\'') {
   553  			/* L'x' */
   554  			c = escchar('\'', 1, 0);
   555  			if(c == EOF)
   556  				c = '\'';
   557  			c1 = escchar('\'', 1, 0);
   558  			if(c1 != EOF) {
   559  				yyerror("missing '");
   560  				peekc = c1;
   561  			}
   562  			yylval.vval = convvtox(c, TRUNE);
   563  			return LUCONST;
   564  		}
   565  		if(c == '"') {
   566  			goto caselq;
   567  		}
   568  		goto talph;
   569  	}
   570  	if(isdigit(c))
   571  		goto tnum;
   572  	switch(c)
   573  	{
   574  
   575  	case EOF:
   576  		peekc = EOF;
   577  		return -1;
   578  
   579  	case '_':
   580  		cp = symb;
   581  		goto talph;
   582  
   583  	case '#':
   584  		domacro();
   585  		goto l0;
   586  
   587  	case '.':
   588  		c1 = GETC();
   589  		if(isdigit(c1)) {
   590  			cp = symb;
   591  			*cp++ = c;
   592  			c = c1;
   593  			c1 = 0;
   594  			goto casedot;
   595  		}
   596  		break;
   597  
   598  	case '"':
   599  		strcpy(symb, "\"<string>\"");
   600  		cp = alloc(0);
   601  		c1 = 0;
   602  
   603  		/* "..." */
   604  		for(;;) {
   605  			c = escchar('"', 0, 1);
   606  			if(c == EOF)
   607  				break;
   608  			if(c & ESC) {
   609  				cp = allocn(cp, c1, 1);
   610  				cp[c1++] = c;
   611  			} else {
   612  				rune = c;
   613  				c = runelen(rune);
   614  				cp = allocn(cp, c1, c);
   615  				runetochar(cp+c1, &rune);
   616  				c1 += c;
   617  			}
   618  		}
   619  		yylval.sval.l = c1;
   620  		do {
   621  			cp = allocn(cp, c1, 1);
   622  			cp[c1++] = 0;
   623  		} while(c1 & MAXALIGN);
   624  		yylval.sval.s = cp;
   625  		return LSTRING;
   626  
   627  	caselq:
   628  		/* L"..." */
   629  		strcpy(symb, "\"L<string>\"");
   630  		cp = alloc(0);
   631  		c1 = 0;
   632  		for(;;) {
   633  			c = escchar('"', 1, 0);
   634  			if(c == EOF)
   635  				break;
   636  			cp = allocn(cp, c1, sizeof(TRune));
   637  			*(TRune*)(cp + c1) = c;
   638  			c1 += sizeof(TRune);
   639  		}
   640  		yylval.sval.l = c1;
   641  		do {
   642  			cp = allocn(cp, c1, sizeof(TRune));
   643  			*(TRune*)(cp + c1) = 0;
   644  			c1 += sizeof(TRune);
   645  		} while(c1 & MAXALIGN);
   646  		yylval.sval.s = cp;
   647  		return LLSTRING;
   648  
   649  	case '\'':
   650  		/* '.' */
   651  		c = escchar('\'', 0, 0);
   652  		if(c == EOF)
   653  			c = '\'';
   654  		c1 = escchar('\'', 0, 0);
   655  		if(c1 != EOF) {
   656  			yyerror("missing '");
   657  			peekc = c1;
   658  		}
   659  		vv = c;
   660  		yylval.vval = convvtox(vv, TUCHAR);
   661  		if(yylval.vval != vv)
   662  			yyerror("overflow in character constant: 0x%x", c);
   663  		else
   664  		if(c & 0x80){
   665  			nearln = lineno;
   666  			warn(Z, "sign-extended character constant");
   667  		}
   668  		yylval.vval = convvtox(vv, TCHAR);
   669  		return LCONST;
   670  
   671  	case '/':
   672  		c1 = GETC();
   673  		if(c1 == '*') {
   674  			for(;;) {
   675  				c = getr();
   676  				while(c == '*') {
   677  					c = getr();
   678  					if(c == '/')
   679  						goto l0;
   680  				}
   681  				if(c == EOF) {
   682  					yyerror("eof in comment");
   683  					errorexit();
   684  				}
   685  			}
   686  		}
   687  		if(c1 == '/') {
   688  			for(;;) {
   689  				c = getr();
   690  				if(c == '\n')
   691  					goto l0;
   692  				if(c == EOF) {
   693  					yyerror("eof in comment");
   694  					errorexit();
   695  				}
   696  			}
   697  		}
   698  		if(c1 == '=')
   699  			return LDVE;
   700  		break;
   701  
   702  	case '*':
   703  		c1 = GETC();
   704  		if(c1 == '=')
   705  			return LMLE;
   706  		break;
   707  
   708  	case '%':
   709  		c1 = GETC();
   710  		if(c1 == '=')
   711  			return LMDE;
   712  		break;
   713  
   714  	case '+':
   715  		c1 = GETC();
   716  		if(c1 == '+')
   717  			return LPP;
   718  		if(c1 == '=')
   719  			return LPE;
   720  		break;
   721  
   722  	case '-':
   723  		c1 = GETC();
   724  		if(c1 == '-')
   725  			return LMM;
   726  		if(c1 == '=')
   727  			return LME;
   728  		if(c1 == '>')
   729  			return LMG;
   730  		break;
   731  
   732  	case '>':
   733  		c1 = GETC();
   734  		if(c1 == '>') {
   735  			c = LRSH;
   736  			c1 = GETC();
   737  			if(c1 == '=')
   738  				return LRSHE;
   739  			break;
   740  		}
   741  		if(c1 == '=')
   742  			return LGE;
   743  		break;
   744  
   745  	case '<':
   746  		c1 = GETC();
   747  		if(c1 == '<') {
   748  			c = LLSH;
   749  			c1 = GETC();
   750  			if(c1 == '=')
   751  				return LLSHE;
   752  			break;
   753  		}
   754  		if(c1 == '=')
   755  			return LLE;
   756  		break;
   757  
   758  	case '=':
   759  		c1 = GETC();
   760  		if(c1 == '=')
   761  			return LEQ;
   762  		break;
   763  
   764  	case '!':
   765  		c1 = GETC();
   766  		if(c1 == '=')
   767  			return LNE;
   768  		break;
   769  
   770  	case '&':
   771  		c1 = GETC();
   772  		if(c1 == '&')
   773  			return LANDAND;
   774  		if(c1 == '=')
   775  			return LANDE;
   776  		break;
   777  
   778  	case '|':
   779  		c1 = GETC();
   780  		if(c1 == '|')
   781  			return LOROR;
   782  		if(c1 == '=')
   783  			return LORE;
   784  		break;
   785  
   786  	case '^':
   787  		c1 = GETC();
   788  		if(c1 == '=')
   789  			return LXORE;
   790  		break;
   791  
   792  	default:
   793  		return c;
   794  	}
   795  	peekc = c1;
   796  	return c;
   797  
   798  talph:
   799  	/*
   800  	 * cp is set to symb and some
   801  	 * prefix has been stored
   802  	 */
   803  	for(;;) {
   804  		if(c >= Runeself) {
   805  			for(c1=0;;) {
   806  				cp[c1++] = c;
   807  				if(fullrune(cp, c1))
   808  					break;
   809  				c = GETC();
   810  			}
   811  			cp += c1;
   812  			c = GETC();
   813  			continue;
   814  		}
   815  		if(!isalnum(c) && c != '_')
   816  			break;
   817  		*cp++ = c;
   818  		c = GETC();
   819  	}
   820  	*cp = 0;
   821  	if(debug['L'])
   822  		print("%L: %s\n", lineno, symb);
   823  	peekc = c;
   824  	s = lookup();
   825  	if(s->macro) {
   826  		newio();
   827  		cp = ionext->b;
   828  		macexpand(s, cp);
   829  		pushio();
   830  		ionext->link = iostack;
   831  		iostack = ionext;
   832  		fi.p = cp;
   833  		fi.c = strlen(cp);
   834  		if(peekc != IGN) {
   835  			cp[fi.c++] = peekc;
   836  			cp[fi.c] = 0;
   837  			peekc = IGN;
   838  		}
   839  		goto l0;
   840  	}
   841  	yylval.sym = s;
   842  	if(s->class == CTYPEDEF || s->class == CTYPESTR)
   843  		return LTYPE;
   844  	return s->lexical;
   845  
   846  tnum:
   847  	c1 = 0;
   848  	cp = symb;
   849  	if(c != '0') {
   850  		c1 |= Numdec;
   851  		for(;;) {
   852  			*cp++ = c;
   853  			c = GETC();
   854  			if(isdigit(c))
   855  				continue;
   856  			goto dc;
   857  		}
   858  	}
   859  	*cp++ = c;
   860  	c = GETC();
   861  	if(c == 'x' || c == 'X')
   862  		for(;;) {
   863  			*cp++ = c;
   864  			c = GETC();
   865  			if(isdigit(c))
   866  				continue;
   867  			if(c >= 'a' && c <= 'f')
   868  				continue;
   869  			if(c >= 'A' && c <= 'F')
   870  				continue;
   871  			if(cp == symb+2)
   872  				yyerror("malformed hex constant");
   873  			goto ncu;
   874  		}
   875  	if(c < '0' || c > '7')
   876  		goto dc;
   877  	for(;;) {
   878  		if(c >= '0' && c <= '7') {
   879  			*cp++ = c;
   880  			c = GETC();
   881  			continue;
   882  		}
   883  		goto ncu;
   884  	}
   885  
   886  dc:
   887  	if(c == '.')
   888  		goto casedot;
   889  	if(c == 'e' || c == 'E')
   890  		goto casee;
   891  
   892  ncu:
   893  	if((c == 'U' || c == 'u') && !(c1 & Numuns)) {
   894  		c = GETC();
   895  		c1 |= Numuns;
   896  		goto ncu;
   897  	}
   898  	if((c == 'L' || c == 'l') && !(c1 & Numvlong)) {
   899  		c = GETC();
   900  		if(c1 & Numlong)
   901  			c1 |= Numvlong;
   902  		c1 |= Numlong;
   903  		goto ncu;
   904  	}
   905  	*cp = 0;
   906  	peekc = c;
   907  	if(mpatov(symb, &yylval.vval))
   908  		yyerror("overflow in constant");
   909  
   910  	vv = yylval.vval;
   911  	if(c1 & Numvlong) {
   912  		if((c1 & Numuns) || convvtox(vv, TVLONG) < 0) {
   913  			c = LUVLCONST;
   914  			t = TUVLONG;
   915  			goto nret;
   916  		}
   917  		c = LVLCONST;
   918  		t = TVLONG;
   919  		goto nret;
   920  	}
   921  	if(c1 & Numlong) {
   922  		if((c1 & Numuns) || convvtox(vv, TLONG) < 0) {
   923  			c = LULCONST;
   924  			t = TULONG;
   925  			goto nret;
   926  		}
   927  		c = LLCONST;
   928  		t = TLONG;
   929  		goto nret;
   930  	}
   931  	if((c1 & Numuns) || convvtox(vv, TINT) < 0) {
   932  		c = LUCONST;
   933  		t = TUINT;
   934  		goto nret;
   935  	}
   936  	c = LCONST;
   937  	t = TINT;
   938  	goto nret;
   939  
   940  nret:
   941  	yylval.vval = convvtox(vv, t);
   942  	if(yylval.vval != vv){
   943  		nearln = lineno;
   944  		warn(Z, "truncated constant: %T %s", types[t], symb);
   945  	}
   946  	return c;
   947  
   948  casedot:
   949  	for(;;) {
   950  		*cp++ = c;
   951  		c = GETC();
   952  		if(!isdigit(c))
   953  			break;
   954  	}
   955  	if(c != 'e' && c != 'E')
   956  		goto caseout;
   957  
   958  casee:
   959  	*cp++ = 'e';
   960  	c = GETC();
   961  	if(c == '+' || c == '-') {
   962  		*cp++ = c;
   963  		c = GETC();
   964  	}
   965  	if(!isdigit(c))
   966  		yyerror("malformed fp constant exponent");
   967  	while(isdigit(c)) {
   968  		*cp++ = c;
   969  		c = GETC();
   970  	}
   971  
   972  caseout:
   973  	if(c == 'L' || c == 'l') {
   974  		c = GETC();
   975  		c1 |= Numlong;
   976  	} else
   977  	if(c == 'F' || c == 'f') {
   978  		c = GETC();
   979  		c1 |= Numflt;
   980  	}
   981  	*cp = 0;
   982  	peekc = c;
   983  	yylval.dval = strtod(symb, nil);
   984  	if(isInf(yylval.dval, 1) || isInf(yylval.dval, -1)) {
   985  		yyerror("overflow in float constant");
   986  		yylval.dval = 0;
   987  	}
   988  	if(c1 & Numflt)
   989  		return LFCONST;
   990  	return LDCONST;
   991  }
   992  
   993  /*
   994   * convert a string, s, to vlong in *v
   995   * return conversion overflow.
   996   * required syntax is [0[x]]d*
   997   */
   998  int
   999  mpatov(char *s, vlong *v)
  1000  {
  1001  	vlong n, nn;
  1002  	int c;
  1003  
  1004  	n = 0;
  1005  	c = *s;
  1006  	if(c == '0')
  1007  		goto oct;
  1008  	while(c = *s++) {
  1009  		if(c >= '0' && c <= '9')
  1010  			nn = n*10 + c-'0';
  1011  		else
  1012  			goto bad;
  1013  		if(n < 0 && nn >= 0)
  1014  			goto bad;
  1015  		n = nn;
  1016  	}
  1017  	goto out;
  1018  
  1019  oct:
  1020  	s++;
  1021  	c = *s;
  1022  	if(c == 'x' || c == 'X')
  1023  		goto hex;
  1024  	while(c = *s++) {
  1025  		if(c >= '0' || c <= '7')
  1026  			nn = n*8 + c-'0';
  1027  		else
  1028  			goto bad;
  1029  		if(n < 0 && nn >= 0)
  1030  			goto bad;
  1031  		n = nn;
  1032  	}
  1033  	goto out;
  1034  
  1035  hex:
  1036  	s++;
  1037  	while(c = *s++) {
  1038  		if(c >= '0' && c <= '9')
  1039  			c += 0-'0';
  1040  		else
  1041  		if(c >= 'a' && c <= 'f')
  1042  			c += 10-'a';
  1043  		else
  1044  		if(c >= 'A' && c <= 'F')
  1045  			c += 10-'A';
  1046  		else
  1047  			goto bad;
  1048  		nn = (uvlong)n*16 + c;
  1049  		if(n < 0 && nn >= 0)
  1050  			goto bad;
  1051  		n = nn;
  1052  	}
  1053  out:
  1054  	*v = n;
  1055  	return 0;
  1056  
  1057  bad:
  1058  	*v = ~0;
  1059  	return 1;
  1060  }
  1061  
  1062  int
  1063  getc(void)
  1064  {
  1065  	int c;
  1066  
  1067  	if(peekc != IGN) {
  1068  		c = peekc;
  1069  		peekc = IGN;
  1070  	} else
  1071  		c = GETC();
  1072  	if(c == '\n')
  1073  		lineno++;
  1074  	if(c == EOF) {
  1075  		yyerror("End of file");
  1076  		errorexit();
  1077  	}
  1078  	return c;
  1079  }
  1080  
  1081  int32
  1082  getr(void)
  1083  {
  1084  	int c, i;
  1085  	char str[UTFmax+1];
  1086  	Rune rune;
  1087  
  1088  
  1089  	c = getc();
  1090  	if(c < Runeself)
  1091  		return c;
  1092  	i = 0;
  1093  	str[i++] = c;
  1094  
  1095  loop:
  1096  	c = getc();
  1097  	str[i++] = c;
  1098  	if(!fullrune(str, i))
  1099  		goto loop;
  1100  	c = chartorune(&rune, str);
  1101  	if(rune == Runeerror && c == 1) {
  1102  		nearln = lineno;
  1103  		diag(Z, "illegal rune in string");
  1104  		for(c=0; c<i; c++)
  1105  			print(" %.2x", *(uchar*)(str+c));
  1106  		print("\n");
  1107  	}
  1108  	return rune;
  1109  }
  1110  
  1111  int
  1112  getnsc(void)
  1113  {
  1114  	int c;
  1115  
  1116  	if(peekc != IGN) {
  1117  		c = peekc;
  1118  		peekc = IGN;
  1119  	} else
  1120  		c = GETC();
  1121  	for(;;) {
  1122  		if(c >= Runeself || !isspace(c))
  1123  			return c;
  1124  		if(c == '\n') {
  1125  			lineno++;
  1126  			return c;
  1127  		}
  1128  		c = GETC();
  1129  	}
  1130  }
  1131  
  1132  void
  1133  unget(int c)
  1134  {
  1135  
  1136  	peekc = c;
  1137  	if(c == '\n')
  1138  		lineno--;
  1139  }
  1140  
  1141  int32
  1142  escchar(int32 e, int longflg, int escflg)
  1143  {
  1144  	int32 c, l;
  1145  	int i;
  1146  
  1147  loop:
  1148  	c = getr();
  1149  	if(c == '\n') {
  1150  		yyerror("newline in string");
  1151  		return EOF;
  1152  	}
  1153  	if(c != '\\') {
  1154  		if(c == e)
  1155  			c = EOF;
  1156  		return c;
  1157  	}
  1158  	c = getr();
  1159  	if(c == 'x') {
  1160  		/*
  1161  		 * note this is not ansi,
  1162  		 * supposed to only accept 2 hex
  1163  		 */
  1164  		i = 2;
  1165  		if(longflg)
  1166  			i = 6;
  1167  		l = 0;
  1168  		for(; i>0; i--) {
  1169  			c = getc();
  1170  			if(c >= '0' && c <= '9') {
  1171  				l = l*16 + c-'0';
  1172  				continue;
  1173  			}
  1174  			if(c >= 'a' && c <= 'f') {
  1175  				l = l*16 + c-'a' + 10;
  1176  				continue;
  1177  			}
  1178  			if(c >= 'A' && c <= 'F') {
  1179  				l = l*16 + c-'A' + 10;
  1180  				continue;
  1181  			}
  1182  			unget(c);
  1183  			break;
  1184  		}
  1185  		if(escflg)
  1186  			l |= ESC;
  1187  		return l;
  1188  	}
  1189  	if(c >= '0' && c <= '7') {
  1190  		/*
  1191  		 * note this is not ansi,
  1192  		 * supposed to only accept 3 oct
  1193  		 */
  1194  		i = 2;
  1195  		if(longflg)
  1196  			i = 8;
  1197  		l = c - '0';
  1198  		for(; i>0; i--) {
  1199  			c = getc();
  1200  			if(c >= '0' && c <= '7') {
  1201  				l = l*8 + c-'0';
  1202  				continue;
  1203  			}
  1204  			unget(c);
  1205  		}
  1206  		if(escflg)
  1207  			l |= ESC;
  1208  		return l;
  1209  	}
  1210  	switch(c)
  1211  	{
  1212  	case '\n':	goto loop;
  1213  	case 'n':	return '\n';
  1214  	case 't':	return '\t';
  1215  	case 'b':	return '\b';
  1216  	case 'r':	return '\r';
  1217  	case 'f':	return '\f';
  1218  	case 'a':	return '\a';
  1219  	case 'v':	return '\v';
  1220  	}
  1221  	return c;
  1222  }
  1223  
  1224  struct
  1225  {
  1226  	char	*name;
  1227  	ushort	lexical;
  1228  	ushort	type;
  1229  } itab[] =
  1230  {
  1231  	"auto",		LAUTO,		0,
  1232  	"break",	LBREAK,		0,
  1233  	"case",		LCASE,		0,
  1234  	"char",		LCHAR,		TCHAR,
  1235  	"const",	LCONSTNT,	0,
  1236  	"continue",	LCONTINUE,	0,
  1237  	"default",	LDEFAULT,	0,
  1238  	"do",		LDO,		0,
  1239  	"double",	LDOUBLE,	TDOUBLE,
  1240  	"else",		LELSE,		0,
  1241  	"enum",		LENUM,		0,
  1242  	"extern",	LEXTERN,	0,
  1243  	"float",	LFLOAT,		TFLOAT,
  1244  	"for",		LFOR,		0,
  1245  	"goto",		LGOTO,		0,
  1246  	"if",		LIF,		0,
  1247  	"inline",	LINLINE,	0,
  1248  	"int",		LINT,		TINT,
  1249  	"long",		LLONG,		TLONG,
  1250  	"PREFETCH",	LPREFETCH,	0,
  1251  	"register",	LREGISTER,	0,
  1252  	"restrict",	LRESTRICT,	0,
  1253  	"return",	LRETURN,	0,
  1254  	"SET",		LSET,		0,
  1255  	"short",	LSHORT,		TSHORT,
  1256  	"signed",	LSIGNED,	0,
  1257  	"signof",	LSIGNOF,	0,
  1258  	"sizeof",	LSIZEOF,	0,
  1259  	"static",	LSTATIC,	0,
  1260  	"struct",	LSTRUCT,	0,
  1261  	"switch",	LSWITCH,	0,
  1262  	"typedef",	LTYPEDEF,	0,
  1263  	"typestr",	LTYPESTR,	0,
  1264  	"union",	LUNION,		0,
  1265  	"unsigned",	LUNSIGNED,	0,
  1266  	"USED",		LUSED,		0,
  1267  	"void",		LVOID,		TVOID,
  1268  	"volatile",	LVOLATILE,	0,
  1269  	"while",	LWHILE,		0,
  1270  	0
  1271  };
  1272  
  1273  void
  1274  cinit(void)
  1275  {
  1276  	Sym *s;
  1277  	int i;
  1278  	Type *t;
  1279  
  1280  	nerrors = 0;
  1281  	lineno = 1;
  1282  	iostack = I;
  1283  	iofree = I;
  1284  	peekc = IGN;
  1285  	nhunk = 0;
  1286  
  1287  	types[TXXX] = T;
  1288  	types[TCHAR] = typ(TCHAR, T);
  1289  	types[TUCHAR] = typ(TUCHAR, T);
  1290  	types[TSHORT] = typ(TSHORT, T);
  1291  	types[TUSHORT] = typ(TUSHORT, T);
  1292  	types[TINT] = typ(TINT, T);
  1293  	types[TUINT] = typ(TUINT, T);
  1294  	types[TLONG] = typ(TLONG, T);
  1295  	types[TULONG] = typ(TULONG, T);
  1296  	types[TVLONG] = typ(TVLONG, T);
  1297  	types[TUVLONG] = typ(TUVLONG, T);
  1298  	types[TFLOAT] = typ(TFLOAT, T);
  1299  	types[TDOUBLE] = typ(TDOUBLE, T);
  1300  	types[TVOID] = typ(TVOID, T);
  1301  	types[TENUM] = typ(TENUM, T);
  1302  	types[TFUNC] = typ(TFUNC, types[TINT]);
  1303  	types[TIND] = typ(TIND, types[TVOID]);
  1304  
  1305  	for(i=0; i<NHASH; i++)
  1306  		hash[i] = S;
  1307  	for(i=0; itab[i].name; i++) {
  1308  		s = slookup(itab[i].name);
  1309  		s->lexical = itab[i].lexical;
  1310  		if(itab[i].type != 0)
  1311  			s->type = types[itab[i].type];
  1312  	}
  1313  	blockno = 0;
  1314  	autobn = 0;
  1315  	autoffset = 0;
  1316  
  1317  	t = typ(TARRAY, types[TCHAR]);
  1318  	t->width = 0;
  1319  	symstring = slookup(".string");
  1320  	symstring->class = CSTATIC;
  1321  	symstring->dataflag = NOPTR;
  1322  	symstring->type = t;
  1323  
  1324  	t = typ(TARRAY, types[TCHAR]);
  1325  	t->width = 0;
  1326  
  1327  	nodproto = new(OPROTO, Z, Z);
  1328  	dclstack = D;
  1329  
  1330  	fmtinstall('O', Oconv);
  1331  	fmtinstall('T', Tconv);
  1332  	fmtinstall('F', FNconv);
  1333  	fmtinstall('L', Lconv);
  1334  	fmtinstall('Q', Qconv);
  1335  	fmtinstall('|', VBconv);
  1336  	fmtinstall('U', Uconv);
  1337  	fmtinstall('B', Bconv);
  1338  }
  1339  
  1340  int
  1341  filbuf(void)
  1342  {
  1343  	Io *i;
  1344  
  1345  loop:
  1346  	i = iostack;
  1347  	if(i == I)
  1348  		return EOF;
  1349  	if(i->f < 0)
  1350  		goto pop;
  1351  	fi.c = read(i->f, i->b, BUFSIZ) - 1;
  1352  	if(fi.c < 0) {
  1353  		close(i->f);
  1354  		linklinehist(ctxt, lineno, nil, 0);
  1355  		goto pop;
  1356  	}
  1357  	fi.p = i->b + 1;
  1358  	return i->b[0] & 0xff;
  1359  
  1360  pop:
  1361  	iostack = i->link;
  1362  	i->link = iofree;
  1363  	iofree = i;
  1364  	i = iostack;
  1365  	if(i == I)
  1366  		return EOF;
  1367  	fi.p = i->p;
  1368  	fi.c = i->c;
  1369  	if(--fi.c < 0)
  1370  		goto loop;
  1371  	return *fi.p++ & 0xff;
  1372  }
  1373  
  1374  int
  1375  Oconv(Fmt *fp)
  1376  {
  1377  	int a;
  1378  
  1379  	a = va_arg(fp->args, int);
  1380  	if(a < OXXX || a > OEND)
  1381  		return fmtprint(fp, "***badO %d***", a);
  1382  
  1383  	return fmtstrcpy(fp, onames[a]);
  1384  }
  1385  
  1386  int
  1387  Lconv(Fmt *fp)
  1388  {
  1389  	return linklinefmt(ctxt, fp);
  1390  }
  1391  
  1392  int
  1393  Tconv(Fmt *fp)
  1394  {
  1395  	char str[STRINGSZ+20], s[STRINGSZ+20];
  1396  	Type *t, *t1;
  1397  	int et;
  1398  	int32 n;
  1399  
  1400  	str[0] = 0;
  1401  	for(t = va_arg(fp->args, Type*); t != T; t = t->link) {
  1402  		et = t->etype;
  1403  		if(str[0])
  1404  			strcat(str, " ");
  1405  		if(t->garb&~GINCOMPLETE) {
  1406  			sprint(s, "%s ", gnames[t->garb&~GINCOMPLETE]);
  1407  			if(strlen(str) + strlen(s) < STRINGSZ)
  1408  				strcat(str, s);
  1409  		}
  1410  		sprint(s, "%s", tnames[et]);
  1411  		if(strlen(str) + strlen(s) < STRINGSZ)
  1412  			strcat(str, s);
  1413  		if(et == TFUNC && (t1 = t->down)) {
  1414  			sprint(s, "(%T", t1);
  1415  			if(strlen(str) + strlen(s) < STRINGSZ)
  1416  				strcat(str, s);
  1417  			while(t1 = t1->down) {
  1418  				sprint(s, ", %T", t1);
  1419  				if(strlen(str) + strlen(s) < STRINGSZ)
  1420  					strcat(str, s);
  1421  			}
  1422  			if(strlen(str) + strlen(s) < STRINGSZ)
  1423  				strcat(str, ")");
  1424  		}
  1425  		if(et == TARRAY) {
  1426  			n = t->width;
  1427  			if(t->link && t->link->width)
  1428  				n /= t->link->width;
  1429  			sprint(s, "[%d]", n);
  1430  			if(strlen(str) + strlen(s) < STRINGSZ)
  1431  				strcat(str, s);
  1432  		}
  1433  		if(t->nbits) {
  1434  			sprint(s, " %d:%d", t->shift, t->nbits);
  1435  			if(strlen(str) + strlen(s) < STRINGSZ)
  1436  				strcat(str, s);
  1437  		}
  1438  		if(typesu[et]) {
  1439  			if(t->tag) {
  1440  				strcat(str, " ");
  1441  				if(strlen(str) + strlen(t->tag->name) < STRINGSZ)
  1442  					strcat(str, t->tag->name);
  1443  			} else
  1444  				strcat(str, " {}");
  1445  			break;
  1446  		}
  1447  	}
  1448  	return fmtstrcpy(fp, str);
  1449  }
  1450  
  1451  int
  1452  FNconv(Fmt *fp)
  1453  {
  1454  	char *str;
  1455  	Node *n;
  1456  
  1457  	n = va_arg(fp->args, Node*);
  1458  	str = "<indirect>";
  1459  	if(n != Z && (n->op == ONAME || n->op == ODOT || n->op == OELEM))
  1460  		str = n->sym->name;
  1461  	return fmtstrcpy(fp, str);
  1462  }
  1463  
  1464  int
  1465  Qconv(Fmt *fp)
  1466  {
  1467  	char str[STRINGSZ+20], *s;
  1468  	int32 b;
  1469  	int i;
  1470  
  1471  	str[0] = 0;
  1472  	for(b = va_arg(fp->args, int32); b;) {
  1473  		i = bitno(b);
  1474  		if(str[0])
  1475  			strcat(str, " ");
  1476  		s = qnames[i];
  1477  		if(strlen(str) + strlen(s) >= STRINGSZ)
  1478  			break;
  1479  		strcat(str, s);
  1480  		b &= ~(1L << i);
  1481  	}
  1482  	return fmtstrcpy(fp, str);
  1483  }
  1484  
  1485  int
  1486  VBconv(Fmt *fp)
  1487  {
  1488  	char str[STRINGSZ];
  1489  	int i, n, t, pc;
  1490  
  1491  	n = va_arg(fp->args, int);
  1492  	pc = 0;	/* BUG: was printcol */
  1493  	i = 0;
  1494  	while(pc < n) {
  1495  		t = (pc+4) & ~3;
  1496  		if(t <= n) {
  1497  			str[i++] = '\t';
  1498  			pc = t;
  1499  			continue;
  1500  		}
  1501  		str[i++] = ' ';
  1502  		pc++;
  1503  	}
  1504  	str[i] = 0;
  1505  
  1506  	return fmtstrcpy(fp, str);
  1507  }
  1508  
  1509  int
  1510  Bconv(Fmt *fp)
  1511  {
  1512  	char str[STRINGSZ], ss[STRINGSZ], *s;
  1513  	Bits bits;
  1514  	int i;
  1515  
  1516  	str[0] = 0;
  1517  	bits = va_arg(fp->args, Bits);
  1518  	while(bany(&bits)) {
  1519  		i = bnum(bits);
  1520  		if(str[0])
  1521  			strcat(str, " ");
  1522  		if(var[i].sym == nil) {
  1523  			sprint(ss, "$%lld", var[i].offset);
  1524  			s = ss;
  1525  		} else
  1526  			s = var[i].sym->name;
  1527  		if(strlen(str) + strlen(s) + 1 >= STRINGSZ)
  1528  			break;
  1529  		strcat(str, s);
  1530  		bits.b[i/32] &= ~(1L << (i%32));
  1531  	}
  1532  	return fmtstrcpy(fp, str);
  1533  }
  1534  
  1535  void
  1536  setinclude(char *p)
  1537  {
  1538  	int i;
  1539  
  1540  	if(*p != 0) {
  1541  		for(i=1; i < ninclude; i++)
  1542  			if(strcmp(p, include[i]) == 0)
  1543  				return;
  1544  
  1545  		if(ninclude%8 == 0)
  1546  			include = allocn(include, ninclude*sizeof(char *),
  1547  				8*sizeof(char *));
  1548  		include[ninclude++] = p;
  1549  	}
  1550  }
  1551  
  1552  void*
  1553  alloc(int32 n)
  1554  {
  1555  	void *p;
  1556  
  1557  	p = malloc(n);
  1558  	if(p == nil) {
  1559  		print("alloc out of mem\n");
  1560  		exits("alloc: out of mem");
  1561  	}
  1562  	memset(p, 0, n);
  1563  	return p;
  1564  }
  1565  
  1566  void*
  1567  allocn(void *p, int32 n, int32 d)
  1568  {
  1569  	if(p == nil)
  1570  		return alloc(n+d);
  1571  	p = realloc(p, n+d);
  1572  	if(p == nil) {
  1573  		print("allocn out of mem\n");
  1574  		exits("allocn: out of mem");
  1575  	}
  1576  	if(d > 0)
  1577  		memset((char*)p+n, 0, d);
  1578  	return p;
  1579  }
  1580  
  1581  void
  1582  ensuresymb(int32 n)
  1583  {
  1584  	if(symb == nil) {
  1585  		symb = alloc(NSYMB+1);
  1586  		nsymb = NSYMB;
  1587  	}
  1588  
  1589  	if(n > nsymb) {
  1590  		symb = allocn(symb, nsymb, n+1-nsymb);
  1591  		nsymb = n;
  1592  	}
  1593  }