github.com/yanyiwu/go@v0.0.0-20150106053140-03d6637dbb7f/src/cmd/cc/lexbody (about)

     1  // Inferno utils/cc/lexbody
     2  // http://code.google.com/p/inferno-os/source/browse/utils/cc/lexbody
     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  /*
    32   * common code for all the assemblers
    33   */
    34  
    35  void
    36  pragpack(void)
    37  {
    38  	while(getnsc() != '\n')
    39  		;
    40  }
    41  
    42  void
    43  pragvararg(void)
    44  {
    45  	while(getnsc() != '\n')
    46  		;
    47  }
    48  
    49  void
    50  pragcgo(char *name)
    51  {
    52  	USED(name);
    53  	while(getnsc() != '\n')
    54  		;
    55  }
    56  
    57  void
    58  pragfpround(void)
    59  {
    60  	while(getnsc() != '\n')
    61  		;
    62  }
    63  
    64  void
    65  pragtextflag(void)
    66  {
    67  	while(getnsc() != '\n')
    68  		;
    69  }
    70  
    71  void
    72  pragdataflag(void)
    73  {
    74  	while(getnsc() != '\n')
    75  		;
    76  }
    77  
    78  void
    79  pragprofile(void)
    80  {
    81  	while(getnsc() != '\n')
    82  		;
    83  }
    84  
    85  void
    86  pragincomplete(void)
    87  {
    88  	while(getnsc() != '\n')
    89  		;
    90  }
    91  
    92  void*
    93  alloc(int32 n)
    94  {
    95  	void *p;
    96  
    97  	p = malloc(n);
    98  	if(p == nil) {
    99  		print("alloc out of mem\n");
   100  		exits("alloc: out of mem");
   101  	}
   102  	memset(p, 0, n);
   103  	return p;
   104  }
   105  
   106  void*
   107  allocn(void *p, int32 n, int32 d)
   108  {
   109  	if(p == nil)
   110  		return alloc(n+d);
   111  	p = realloc(p, n+d);
   112  	if(p == nil) {
   113  		print("allocn out of mem\n");
   114  		exits("allocn: out of mem");
   115  	}
   116  	if(d > 0)
   117  		memset((char*)p+n, 0, d);
   118  	return p;
   119  }
   120  
   121  void
   122  ensuresymb(int32 n)
   123  {
   124  	if(symb == nil) {
   125  		symb = alloc(NSYMB+1);
   126  		nsymb = NSYMB;
   127  	}
   128  
   129  	if(n > nsymb) {
   130  		symb = allocn(symb, nsymb, n+1-nsymb);
   131  		nsymb = n;
   132  	}
   133  }
   134  
   135  void
   136  setinclude(char *p)
   137  {
   138  	int i;
   139  
   140  	if(p == 0)
   141  		return;
   142  	for(i=1; i < ninclude; i++)
   143  		if(strcmp(p, include[i]) == 0)
   144  			return;
   145  	
   146  	if(ninclude%8 == 0)
   147  		include = allocn(include, ninclude*sizeof(char *), 
   148  			8*sizeof(char *));
   149  	include[ninclude++] = p;
   150  }
   151  
   152  void
   153  errorexit(void)
   154  {
   155  	Bflush(&bstdout);
   156  	if(outfile)
   157  		remove(outfile);
   158  	exits("error");
   159  }
   160  
   161  void
   162  pushio(void)
   163  {
   164  	Io *i;
   165  
   166  	i = iostack;
   167  	if(i == I) {
   168  		yyerror("botch in pushio");
   169  		errorexit();
   170  	}
   171  	i->p = fi.p;
   172  	i->c = fi.c;
   173  }
   174  
   175  void
   176  newio(void)
   177  {
   178  	Io *i;
   179  	static int pushdepth = 0;
   180  
   181  	i = iofree;
   182  	if(i == I) {
   183  		pushdepth++;
   184  		if(pushdepth > 1000) {
   185  			yyerror("macro/io expansion too deep");
   186  			errorexit();
   187  		}
   188  		i = alloc(sizeof(*i));
   189  	} else
   190  		iofree = i->link;
   191  	i->c = 0;
   192  	i->f = -1;
   193  	ionext = i;
   194  }
   195  
   196  void
   197  newfile(char *s, int f)
   198  {
   199  	Io *i;
   200  
   201  	i = ionext;
   202  	i->link = iostack;
   203  	iostack = i;
   204  	i->f = f;
   205  	if(f < 0)
   206  		i->f = open(s, 0);
   207  	if(i->f < 0) {
   208  		yyerror("%ca: %r: %s", thechar, s);
   209  		errorexit();
   210  	}
   211  	fi.c = 0;
   212  	linklinehist(ctxt, lineno, s, 0);
   213  }
   214  
   215  Sym*
   216  slookup(char *s)
   217  {
   218  	ensuresymb(strlen(s));
   219  	strcpy(symb, s);
   220  	return lookup();
   221  }
   222  
   223  LSym *thetext;
   224  
   225  void
   226  settext(LSym *s)
   227  {
   228  	thetext = s;
   229  }
   230  
   231  Sym*
   232  labellookup(Sym *s)
   233  {
   234  	char *p;
   235  	Sym *lab;
   236  	
   237  	if(thetext == nil) {
   238  		s->labelname = s->name;
   239  		return s;
   240  	}
   241  	p = smprint("%s.%s", thetext->name, s->name);
   242  	lab = slookup(p);
   243  	free(p);
   244  	lab->labelname = s->name;
   245  	return lab;
   246  }
   247  
   248  Sym*
   249  lookup(void)
   250  {
   251  	Sym *s;
   252  	uint32 h;
   253  	char *p;
   254  	int c, l;
   255  	char *r, *w;
   256  
   257  	if((uchar)symb[0] == 0xc2 && (uchar)symb[1] == 0xb7) {
   258  		// turn leading · into ""·
   259  		h = strlen(symb);
   260  		ensuresymb(h+2);
   261  		memmove(symb+2, symb, h+1);
   262  		symb[0] = '"';
   263  		symb[1] = '"';
   264  	}
   265  
   266  	for(r=w=symb; *r; r++) {
   267  		// turn · (U+00B7) into .
   268  		// turn ∕ (U+2215) into /
   269  		if((uchar)*r == 0xc2 && (uchar)*(r+1) == 0xb7) {
   270  			*w++ = '.';
   271  			r++;
   272  		}else if((uchar)*r == 0xe2 && (uchar)*(r+1) == 0x88 && (uchar)*(r+2) == 0x95) {
   273  			*w++ = '/';
   274  			r++;
   275  			r++;
   276  		}else
   277  			*w++ = *r;
   278  	}
   279  	*w = '\0';
   280  
   281  	h = 0;
   282  	for(p=symb; c = *p; p++)
   283  		h = h+h+h + c;
   284  	l = (p - symb) + 1;
   285  	h &= 0xffffff;
   286  	h %= NHASH;
   287  	c = symb[0];
   288  	for(s = hash[h]; s != S; s = s->link) {
   289  		if(s->name[0] != c)
   290  			continue;
   291  		if(strcmp(s->name, symb) == 0)
   292  			return s;
   293  	}
   294  	s = alloc(sizeof(*s));
   295  	s->name = alloc(l);
   296  	memmove(s->name, symb, l);
   297  
   298  	s->link = hash[h];
   299  	hash[h] = s;
   300  	syminit(s);
   301  	return s;
   302  }
   303  
   304  int
   305  ISALPHA(int c)
   306  {
   307  	if(isalpha(c))
   308  		return 1;
   309  	if(c >= Runeself)
   310  		return 1;
   311  	return 0;
   312  }
   313  
   314  int32
   315  yylex(void)
   316  {
   317  	int c, c1;
   318  	char *cp;
   319  	Sym *s;
   320  
   321  	c = peekc;
   322  	if(c != IGN) {
   323  		peekc = IGN;
   324  		goto l1;
   325  	}
   326  l0:
   327  	c = GETC();
   328  
   329  l1:
   330  	if(c == EOF) {
   331  		peekc = EOF;
   332  		return -1;
   333  	}
   334  	if(isspace(c)) {
   335  		if(c == '\n') {
   336  			lineno++;
   337  			return ';';
   338  		}
   339  		goto l0;
   340  	}
   341  	if(ISALPHA(c))
   342  		goto talph;
   343  	if(isdigit(c))
   344  		goto tnum;
   345  	switch(c)
   346  	{
   347  	case '\n':
   348  		lineno++;
   349  		return ';';
   350  
   351  	case '#':
   352  		domacro();
   353  		goto l0;
   354  
   355  	case '.':
   356  		c = GETC();
   357  		if(ISALPHA(c)) {
   358  			cp = symb;
   359  			*cp++ = '.';
   360  			goto aloop;
   361  		}
   362  		if(isdigit(c)) {
   363  			cp = symb;
   364  			*cp++ = '.';
   365  			goto casedot;
   366  		}
   367  		peekc = c;
   368  		return '.';
   369  
   370  	talph:
   371  	case '_':
   372  	case '@':
   373  		cp = symb;
   374  
   375  	aloop:
   376  		*cp++ = c;
   377  		c = GETC();
   378  		if(ISALPHA(c) || isdigit(c) || c == '_' || c == '$')
   379  			goto aloop;
   380  		*cp = 0;
   381  		peekc = c;
   382  		s = lookup();
   383  		if(s->macro) {
   384  			newio();
   385  			cp = ionext->b;
   386  			macexpand(s, cp);
   387  			pushio();
   388  			ionext->link = iostack;
   389  			iostack = ionext;
   390  			fi.p = cp;
   391  			fi.c = strlen(cp);
   392  			if(peekc != IGN) {
   393  				cp[fi.c++] = peekc;
   394  				cp[fi.c] = 0;
   395  				peekc = IGN;
   396  			}
   397  			goto l0;
   398  		}
   399  		if(s->type == 0)
   400  			s->type = LNAME;
   401  		if(s->type == LNAME ||
   402  		   s->type == LVAR ||
   403  		   s->type == LLAB) {
   404  			yylval.sym = s;
   405  			return s->type;
   406  		}
   407  		yylval.lval = s->value;
   408  		return s->type;
   409  
   410  	tnum:
   411  		cp = symb;
   412  		if(c != '0')
   413  			goto dc;
   414  		*cp++ = c;
   415  		c = GETC();
   416  		c1 = 3;
   417  		if(c == 'x' || c == 'X') {
   418  			c1 = 4;
   419  			c = GETC();
   420  		} else
   421  		if(c < '0' || c > '7')
   422  			goto dc;
   423  		yylval.lval = 0;
   424  		for(;;) {
   425  			if(c >= '0' && c <= '9') {
   426  				if(c > '7' && c1 == 3)
   427  					break;
   428  				yylval.lval = (uvlong)yylval.lval << c1;
   429  				yylval.lval += c - '0';
   430  				c = GETC();
   431  				continue;
   432  			}
   433  			if(c1 == 3)
   434  				break;
   435  			if(c >= 'A' && c <= 'F')
   436  				c += 'a' - 'A';
   437  			if(c >= 'a' && c <= 'f') {
   438  				yylval.lval = (uvlong)yylval.lval << c1;
   439  				yylval.lval += c - 'a' + 10;
   440  				c = GETC();
   441  				continue;
   442  			}
   443  			break;
   444  		}
   445  		goto ncu;
   446  
   447  	dc:
   448  		for(;;) {
   449  			if(!isdigit(c))
   450  				break;
   451  			*cp++ = c;
   452  			c = GETC();
   453  		}
   454  		if(c == '.')
   455  			goto casedot;
   456  		if(c == 'e' || c == 'E')
   457  			goto casee;
   458  		*cp = 0;
   459  		if(sizeof(yylval.lval) == sizeof(vlong))
   460  			yylval.lval = strtoll(symb, nil, 10);
   461  		else
   462  			yylval.lval = strtol(symb, nil, 10);
   463  
   464  	ncu:
   465  		while(c == 'U' || c == 'u' || c == 'l' || c == 'L')
   466  			c = GETC();
   467  		peekc = c;
   468  		return LCONST;
   469  
   470  	casedot:
   471  		for(;;) {
   472  			*cp++ = c;
   473  			c = GETC();
   474  			if(!isdigit(c))
   475  				break;
   476  		}
   477  		if(c == 'e' || c == 'E')
   478  			goto casee;
   479  		goto caseout;
   480  
   481  	casee:
   482  		*cp++ = 'e';
   483  		c = GETC();
   484  		if(c == '+' || c == '-') {
   485  			*cp++ = c;
   486  			c = GETC();
   487  		}
   488  		while(isdigit(c)) {
   489  			*cp++ = c;
   490  			c = GETC();
   491  		}
   492  
   493  	caseout:
   494  		*cp = 0;
   495  		peekc = c;
   496  		if(FPCHIP) {
   497  			yylval.dval = atof(symb);
   498  			return LFCONST;
   499  		}
   500  		yyerror("assembler cannot interpret fp constants");
   501  		yylval.lval = 1L;
   502  		return LCONST;
   503  
   504  	case '"':
   505  		memcpy(yylval.sval, nullgen.u.sval, sizeof(yylval.sval));
   506  		cp = yylval.sval;
   507  		c1 = 0;
   508  		for(;;) {
   509  			c = escchar('"');
   510  			if(c == EOF)
   511  				break;
   512  			if(c1 < sizeof(yylval.sval))
   513  				*cp++ = c;
   514  			c1++;
   515  		}
   516  		if(c1 > sizeof(yylval.sval))
   517  			yyerror("string constant too long");
   518  		return LSCONST;
   519  
   520  	case '\'':
   521  		c = escchar('\'');
   522  		if(c == EOF)
   523  			c = '\'';
   524  		if(escchar('\'') != EOF)
   525  			yyerror("missing '");
   526  		yylval.lval = c;
   527  		return LCONST;
   528  
   529  	case '/':
   530  		c1 = GETC();
   531  		if(c1 == '/') {
   532  			for(;;) {
   533  				c = GETC();
   534  				if(c == '\n')
   535  					goto l1;
   536  				if(c == EOF) {
   537  					yyerror("eof in comment");
   538  					errorexit();
   539  				}
   540  			}
   541  		}
   542  		if(c1 == '*') {
   543  			for(;;) {
   544  				c = GETC();
   545  				while(c == '*') {
   546  					c = GETC();
   547  					if(c == '/')
   548  						goto l0;
   549  				}
   550  				if(c == EOF) {
   551  					yyerror("eof in comment");
   552  					errorexit();
   553  				}
   554  				if(c == '\n')
   555  					lineno++;
   556  			}
   557  		}
   558  		break;
   559  
   560  	default:
   561  		return c;
   562  	}
   563  	peekc = c1;
   564  	return c;
   565  }
   566  
   567  int
   568  getc(void)
   569  {
   570  	int c;
   571  
   572  	c = peekc;
   573  	if(c != IGN) {
   574  		peekc = IGN;
   575  		return c;
   576  	}
   577  	c = GETC();
   578  	if(c == '\n')
   579  		lineno++;
   580  	if(c == EOF) {
   581  		yyerror("End of file");
   582  		errorexit();
   583  	}
   584  	return c;
   585  }
   586  
   587  int
   588  getnsc(void)
   589  {
   590  	int c;
   591  
   592  	for(;;) {
   593  		c = getc();
   594  		if(!isspace(c) || c == '\n')
   595  			return c;
   596  	}
   597  }
   598  
   599  void
   600  unget(int c)
   601  {
   602  
   603  	peekc = c;
   604  	if(c == '\n')
   605  		lineno--;
   606  }
   607  
   608  int
   609  escchar(int e)
   610  {
   611  	int c, l;
   612  
   613  loop:
   614  	c = getc();
   615  	if(c == '\n') {
   616  		yyerror("newline in string");
   617  		return EOF;
   618  	}
   619  	if(c != '\\') {
   620  		if(c == e)
   621  			return EOF;
   622  		return c;
   623  	}
   624  	c = getc();
   625  	if(c >= '0' && c <= '7') {
   626  		l = c - '0';
   627  		c = getc();
   628  		if(c >= '0' && c <= '7') {
   629  			l = l*8 + c-'0';
   630  			c = getc();
   631  			if(c >= '0' && c <= '7') {
   632  				l = l*8 + c-'0';
   633  				return l;
   634  			}
   635  		}
   636  		peekc = c;
   637  		return l;
   638  	}
   639  	switch(c)
   640  	{
   641  	case '\n':	goto loop;
   642  	case 'n':	return '\n';
   643  	case 't':	return '\t';
   644  	case 'b':	return '\b';
   645  	case 'r':	return '\r';
   646  	case 'f':	return '\f';
   647  	case 'a':	return 0x07;
   648  	case 'v':	return 0x0b;
   649  	case 'z':	return 0x00;
   650  	}
   651  	return c;
   652  }
   653  
   654  void
   655  pinit(char *f)
   656  {
   657  	int i;
   658  	Sym *s;
   659  
   660  	lineno = 1;
   661  	newio();
   662  	newfile(f, -1);
   663  	pc = 0;
   664  	peekc = IGN;
   665  	sym = 1;
   666  	for(i=0; i<NHASH; i++)
   667  		for(s = hash[i]; s != S; s = s->link)
   668  			s->macro = 0;
   669  }
   670  
   671  int
   672  filbuf(void)
   673  {
   674  	Io *i;
   675  
   676  loop:
   677  	i = iostack;
   678  	if(i == I)
   679  		return EOF;
   680  	if(i->f < 0)
   681  		goto pop;
   682  	fi.c = read(i->f, i->b, BUFSIZ) - 1;
   683  	if(fi.c < 0) {
   684  		close(i->f);
   685  		linklinehist(ctxt, lineno, 0, 0);
   686  		goto pop;
   687  	}
   688  	fi.p = i->b + 1;
   689  	return i->b[0] & 0xff;
   690  
   691  pop:
   692  	iostack = i->link;
   693  	i->link = iofree;
   694  	iofree = i;
   695  	i = iostack;
   696  	if(i == I)
   697  		return EOF;
   698  	fi.p = i->p;
   699  	fi.c = i->c;
   700  	if(--fi.c < 0)
   701  		goto loop;
   702  	return *fi.p++ & 0xff;
   703  }
   704  
   705  void
   706  yyerror(char *a, ...)
   707  {
   708  	char buf[200];
   709  	va_list arg;
   710  
   711  	/*
   712  	 * hack to intercept message from yaccpar
   713  	 */
   714  	if(strcmp(a, "syntax error") == 0) {
   715  		yyerror("syntax error, last name: %s", symb);
   716  		return;
   717  	}
   718  	prfile(lineno);
   719  	va_start(arg, a);
   720  	vseprint(buf, buf+sizeof(buf), a, arg);
   721  	va_end(arg);
   722  	print("%s\n", buf);
   723  	nerrors++;
   724  	if(nerrors > 10) {
   725  		print("too many errors\n");
   726  		errorexit();
   727  	}
   728  }
   729  
   730  void
   731  prfile(int32 l)
   732  {
   733  	linkprfile(ctxt, l);
   734  }