github.com/razvanm/vanadium-go-1.3@v0.0.0-20160721203343-4a65068e5915/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  Sym*
   224  lookup(void)
   225  {
   226  	Sym *s;
   227  	uint32 h;
   228  	char *p;
   229  	int c, l;
   230  	char *r, *w;
   231  
   232  	if((uchar)symb[0] == 0xc2 && (uchar)symb[1] == 0xb7) {
   233  		// turn leading · into ""·
   234  		h = strlen(symb);
   235  		ensuresymb(h+2);
   236  		memmove(symb+2, symb, h+1);
   237  		symb[0] = '"';
   238  		symb[1] = '"';
   239  	}
   240  
   241  	for(r=w=symb; *r; r++) {
   242  		// turn · (U+00B7) into .
   243  		// turn ∕ (U+2215) into /
   244  		if((uchar)*r == 0xc2 && (uchar)*(r+1) == 0xb7) {
   245  			*w++ = '.';
   246  			r++;
   247  		}else if((uchar)*r == 0xe2 && (uchar)*(r+1) == 0x88 && (uchar)*(r+2) == 0x95) {
   248  			*w++ = '/';
   249  			r++;
   250  			r++;
   251  		}else
   252  			*w++ = *r;
   253  	}
   254  	*w = '\0';
   255  
   256  	h = 0;
   257  	for(p=symb; c = *p; p++)
   258  		h = h+h+h + c;
   259  	l = (p - symb) + 1;
   260  	h &= 0xffffff;
   261  	h %= NHASH;
   262  	c = symb[0];
   263  	for(s = hash[h]; s != S; s = s->link) {
   264  		if(s->name[0] != c)
   265  			continue;
   266  		if(strcmp(s->name, symb) == 0)
   267  			return s;
   268  	}
   269  	s = alloc(sizeof(*s));
   270  	s->name = alloc(l);
   271  	memmove(s->name, symb, l);
   272  
   273  	s->link = hash[h];
   274  	hash[h] = s;
   275  	syminit(s);
   276  	return s;
   277  }
   278  
   279  int
   280  ISALPHA(int c)
   281  {
   282  	if(isalpha(c))
   283  		return 1;
   284  	if(c >= Runeself)
   285  		return 1;
   286  	return 0;
   287  }
   288  
   289  int32
   290  yylex(void)
   291  {
   292  	int c, c1;
   293  	char *cp;
   294  	Sym *s;
   295  
   296  	c = peekc;
   297  	if(c != IGN) {
   298  		peekc = IGN;
   299  		goto l1;
   300  	}
   301  l0:
   302  	c = GETC();
   303  
   304  l1:
   305  	if(c == EOF) {
   306  		peekc = EOF;
   307  		return -1;
   308  	}
   309  	if(isspace(c)) {
   310  		if(c == '\n') {
   311  			lineno++;
   312  			return ';';
   313  		}
   314  		goto l0;
   315  	}
   316  	if(ISALPHA(c))
   317  		goto talph;
   318  	if(isdigit(c))
   319  		goto tnum;
   320  	switch(c)
   321  	{
   322  	case '\n':
   323  		lineno++;
   324  		return ';';
   325  
   326  	case '#':
   327  		domacro();
   328  		goto l0;
   329  
   330  	case '.':
   331  		c = GETC();
   332  		if(ISALPHA(c)) {
   333  			cp = symb;
   334  			*cp++ = '.';
   335  			goto aloop;
   336  		}
   337  		if(isdigit(c)) {
   338  			cp = symb;
   339  			*cp++ = '.';
   340  			goto casedot;
   341  		}
   342  		peekc = c;
   343  		return '.';
   344  
   345  	talph:
   346  	case '_':
   347  	case '@':
   348  		cp = symb;
   349  
   350  	aloop:
   351  		*cp++ = c;
   352  		c = GETC();
   353  		if(ISALPHA(c) || isdigit(c) || c == '_' || c == '$')
   354  			goto aloop;
   355  		*cp = 0;
   356  		peekc = c;
   357  		s = lookup();
   358  		if(s->macro) {
   359  			newio();
   360  			cp = ionext->b;
   361  			macexpand(s, cp);
   362  			pushio();
   363  			ionext->link = iostack;
   364  			iostack = ionext;
   365  			fi.p = cp;
   366  			fi.c = strlen(cp);
   367  			if(peekc != IGN) {
   368  				cp[fi.c++] = peekc;
   369  				cp[fi.c] = 0;
   370  				peekc = IGN;
   371  			}
   372  			goto l0;
   373  		}
   374  		if(s->type == 0)
   375  			s->type = LNAME;
   376  		if(s->type == LNAME ||
   377  		   s->type == LVAR ||
   378  		   s->type == LLAB) {
   379  			yylval.sym = s;
   380  			return s->type;
   381  		}
   382  		yylval.lval = s->value;
   383  		return s->type;
   384  
   385  	tnum:
   386  		cp = symb;
   387  		if(c != '0')
   388  			goto dc;
   389  		*cp++ = c;
   390  		c = GETC();
   391  		c1 = 3;
   392  		if(c == 'x' || c == 'X') {
   393  			c1 = 4;
   394  			c = GETC();
   395  		} else
   396  		if(c < '0' || c > '7')
   397  			goto dc;
   398  		yylval.lval = 0;
   399  		for(;;) {
   400  			if(c >= '0' && c <= '9') {
   401  				if(c > '7' && c1 == 3)
   402  					break;
   403  				yylval.lval = (uvlong)yylval.lval << c1;
   404  				yylval.lval += c - '0';
   405  				c = GETC();
   406  				continue;
   407  			}
   408  			if(c1 == 3)
   409  				break;
   410  			if(c >= 'A' && c <= 'F')
   411  				c += 'a' - 'A';
   412  			if(c >= 'a' && c <= 'f') {
   413  				yylval.lval = (uvlong)yylval.lval << c1;
   414  				yylval.lval += c - 'a' + 10;
   415  				c = GETC();
   416  				continue;
   417  			}
   418  			break;
   419  		}
   420  		goto ncu;
   421  
   422  	dc:
   423  		for(;;) {
   424  			if(!isdigit(c))
   425  				break;
   426  			*cp++ = c;
   427  			c = GETC();
   428  		}
   429  		if(c == '.')
   430  			goto casedot;
   431  		if(c == 'e' || c == 'E')
   432  			goto casee;
   433  		*cp = 0;
   434  		if(sizeof(yylval.lval) == sizeof(vlong))
   435  			yylval.lval = strtoll(symb, nil, 10);
   436  		else
   437  			yylval.lval = strtol(symb, nil, 10);
   438  
   439  	ncu:
   440  		while(c == 'U' || c == 'u' || c == 'l' || c == 'L')
   441  			c = GETC();
   442  		peekc = c;
   443  		return LCONST;
   444  
   445  	casedot:
   446  		for(;;) {
   447  			*cp++ = c;
   448  			c = GETC();
   449  			if(!isdigit(c))
   450  				break;
   451  		}
   452  		if(c == 'e' || c == 'E')
   453  			goto casee;
   454  		goto caseout;
   455  
   456  	casee:
   457  		*cp++ = 'e';
   458  		c = GETC();
   459  		if(c == '+' || c == '-') {
   460  			*cp++ = c;
   461  			c = GETC();
   462  		}
   463  		while(isdigit(c)) {
   464  			*cp++ = c;
   465  			c = GETC();
   466  		}
   467  
   468  	caseout:
   469  		*cp = 0;
   470  		peekc = c;
   471  		if(FPCHIP) {
   472  			yylval.dval = atof(symb);
   473  			return LFCONST;
   474  		}
   475  		yyerror("assembler cannot interpret fp constants");
   476  		yylval.lval = 1L;
   477  		return LCONST;
   478  
   479  	case '"':
   480  		memcpy(yylval.sval, nullgen.u.sval, sizeof(yylval.sval));
   481  		cp = yylval.sval;
   482  		c1 = 0;
   483  		for(;;) {
   484  			c = escchar('"');
   485  			if(c == EOF)
   486  				break;
   487  			if(c1 < sizeof(yylval.sval))
   488  				*cp++ = c;
   489  			c1++;
   490  		}
   491  		if(c1 > sizeof(yylval.sval))
   492  			yyerror("string constant too long");
   493  		return LSCONST;
   494  
   495  	case '\'':
   496  		c = escchar('\'');
   497  		if(c == EOF)
   498  			c = '\'';
   499  		if(escchar('\'') != EOF)
   500  			yyerror("missing '");
   501  		yylval.lval = c;
   502  		return LCONST;
   503  
   504  	case '/':
   505  		c1 = GETC();
   506  		if(c1 == '/') {
   507  			for(;;) {
   508  				c = GETC();
   509  				if(c == '\n')
   510  					goto l1;
   511  				if(c == EOF) {
   512  					yyerror("eof in comment");
   513  					errorexit();
   514  				}
   515  			}
   516  		}
   517  		if(c1 == '*') {
   518  			for(;;) {
   519  				c = GETC();
   520  				while(c == '*') {
   521  					c = GETC();
   522  					if(c == '/')
   523  						goto l0;
   524  				}
   525  				if(c == EOF) {
   526  					yyerror("eof in comment");
   527  					errorexit();
   528  				}
   529  				if(c == '\n')
   530  					lineno++;
   531  			}
   532  		}
   533  		break;
   534  
   535  	default:
   536  		return c;
   537  	}
   538  	peekc = c1;
   539  	return c;
   540  }
   541  
   542  int
   543  getc(void)
   544  {
   545  	int c;
   546  
   547  	c = peekc;
   548  	if(c != IGN) {
   549  		peekc = IGN;
   550  		return c;
   551  	}
   552  	c = GETC();
   553  	if(c == '\n')
   554  		lineno++;
   555  	if(c == EOF) {
   556  		yyerror("End of file");
   557  		errorexit();
   558  	}
   559  	return c;
   560  }
   561  
   562  int
   563  getnsc(void)
   564  {
   565  	int c;
   566  
   567  	for(;;) {
   568  		c = getc();
   569  		if(!isspace(c) || c == '\n')
   570  			return c;
   571  	}
   572  }
   573  
   574  void
   575  unget(int c)
   576  {
   577  
   578  	peekc = c;
   579  	if(c == '\n')
   580  		lineno--;
   581  }
   582  
   583  int
   584  escchar(int e)
   585  {
   586  	int c, l;
   587  
   588  loop:
   589  	c = getc();
   590  	if(c == '\n') {
   591  		yyerror("newline in string");
   592  		return EOF;
   593  	}
   594  	if(c != '\\') {
   595  		if(c == e)
   596  			return EOF;
   597  		return c;
   598  	}
   599  	c = getc();
   600  	if(c >= '0' && c <= '7') {
   601  		l = c - '0';
   602  		c = getc();
   603  		if(c >= '0' && c <= '7') {
   604  			l = l*8 + c-'0';
   605  			c = getc();
   606  			if(c >= '0' && c <= '7') {
   607  				l = l*8 + c-'0';
   608  				return l;
   609  			}
   610  		}
   611  		peekc = c;
   612  		return l;
   613  	}
   614  	switch(c)
   615  	{
   616  	case '\n':	goto loop;
   617  	case 'n':	return '\n';
   618  	case 't':	return '\t';
   619  	case 'b':	return '\b';
   620  	case 'r':	return '\r';
   621  	case 'f':	return '\f';
   622  	case 'a':	return 0x07;
   623  	case 'v':	return 0x0b;
   624  	case 'z':	return 0x00;
   625  	}
   626  	return c;
   627  }
   628  
   629  void
   630  pinit(char *f)
   631  {
   632  	int i;
   633  	Sym *s;
   634  
   635  	lineno = 1;
   636  	newio();
   637  	newfile(f, -1);
   638  	pc = 0;
   639  	peekc = IGN;
   640  	sym = 1;
   641  	for(i=0; i<NHASH; i++)
   642  		for(s = hash[i]; s != S; s = s->link)
   643  			s->macro = 0;
   644  }
   645  
   646  int
   647  filbuf(void)
   648  {
   649  	Io *i;
   650  
   651  loop:
   652  	i = iostack;
   653  	if(i == I)
   654  		return EOF;
   655  	if(i->f < 0)
   656  		goto pop;
   657  	fi.c = read(i->f, i->b, BUFSIZ) - 1;
   658  	if(fi.c < 0) {
   659  		close(i->f);
   660  		linklinehist(ctxt, lineno, 0, 0);
   661  		goto pop;
   662  	}
   663  	fi.p = i->b + 1;
   664  	return i->b[0] & 0xff;
   665  
   666  pop:
   667  	iostack = i->link;
   668  	i->link = iofree;
   669  	iofree = i;
   670  	i = iostack;
   671  	if(i == I)
   672  		return EOF;
   673  	fi.p = i->p;
   674  	fi.c = i->c;
   675  	if(--fi.c < 0)
   676  		goto loop;
   677  	return *fi.p++ & 0xff;
   678  }
   679  
   680  void
   681  yyerror(char *a, ...)
   682  {
   683  	char buf[200];
   684  	va_list arg;
   685  
   686  	/*
   687  	 * hack to intercept message from yaccpar
   688  	 */
   689  	if(strcmp(a, "syntax error") == 0) {
   690  		yyerror("syntax error, last name: %s", symb);
   691  		return;
   692  	}
   693  	prfile(lineno);
   694  	va_start(arg, a);
   695  	vseprint(buf, buf+sizeof(buf), a, arg);
   696  	va_end(arg);
   697  	print("%s\n", buf);
   698  	nerrors++;
   699  	if(nerrors > 10) {
   700  		print("too many errors\n");
   701  		errorexit();
   702  	}
   703  }
   704  
   705  void
   706  prfile(int32 l)
   707  {
   708  	linkprfile(ctxt, l);
   709  }