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