github.com/rsc/tmp@v0.0.0-20240517235954-6deaab19748b/bootstrap/internal/asm/lexbody.go (about)

     1  // Do not edit. Bootstrap copy of /Users/rsc/g/go/src/cmd/internal/asm/lexbody.go
     2  
     3  // Inferno utils/cc/lexbody
     4  // http://code.Google.Com/p/inferno-os/source/browse/utils/cc/lexbody
     5  //
     6  //	Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
     7  //	Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.Net)
     8  //	Portions Copyright © 1997-1999 Vita Nuova Limited
     9  //	Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.Vitanuova.Com)
    10  //	Portions Copyright © 2004,2006 Bruce Ellis
    11  //	Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.Net)
    12  //	Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
    13  //	Portions Copyright © 2009 The Go Authors.  All rights reserved.
    14  //
    15  // Permission is hereby granted, free of charge, to any person obtaining a copy
    16  // of this software and associated documentation files (the "Software"), to deal
    17  // in the Software without restriction, including without limitation the rights
    18  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    19  // copies of the Software, and to permit persons to whom the Software is
    20  // furnished to do so, subject to the following conditions:
    21  //
    22  // The above copyright notice and this permission notice shall be included in
    23  // all copies or substantial portions of the Software.
    24  //
    25  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    26  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    27  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
    28  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    29  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    30  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    31  // THE SOFTWARE.
    32  
    33  package asm
    34  
    35  import (
    36  	"bytes"
    37  	"fmt"
    38  	"os"
    39  	"strconv"
    40  	"strings"
    41  	"unicode/utf8"
    42  
    43  	"rsc.io/tmp/bootstrap/internal/obj"
    44  )
    45  
    46  /*
    47   * common code for all the assemblers
    48   */
    49  func pragpack() {
    50  	for getnsc() != '\n' {
    51  	}
    52  }
    53  
    54  func pragvararg() {
    55  	for getnsc() != '\n' {
    56  	}
    57  }
    58  
    59  func pragcgo(name string) {
    60  	for getnsc() != '\n' {
    61  	}
    62  }
    63  
    64  func pragfpround() {
    65  	for getnsc() != '\n' {
    66  	}
    67  }
    68  
    69  func pragtextflag() {
    70  	for getnsc() != '\n' {
    71  	}
    72  }
    73  
    74  func pragdataflag() {
    75  	for getnsc() != '\n' {
    76  	}
    77  }
    78  
    79  func pragprofile() {
    80  	for getnsc() != '\n' {
    81  	}
    82  }
    83  
    84  func pragincomplete() {
    85  	for getnsc() != '\n' {
    86  	}
    87  }
    88  
    89  func setinclude(p string) {
    90  	if p == "" {
    91  		return
    92  	}
    93  	for i := 1; i < len(include); i++ {
    94  		if p == include[i] {
    95  			return
    96  		}
    97  	}
    98  
    99  	include = append(include, p)
   100  }
   101  
   102  func errorexit() {
   103  	obj.Bflush(&bstdout)
   104  	if outfile != "" {
   105  		os.Remove(outfile)
   106  	}
   107  	os.Exit(2)
   108  }
   109  
   110  func pushio() {
   111  	i := iostack
   112  	if i == nil {
   113  		Yyerror("botch in pushio")
   114  		errorexit()
   115  	}
   116  
   117  	i.P = fi.P
   118  }
   119  
   120  func newio() {
   121  	var pushdepth int = 0
   122  
   123  	i := iofree
   124  	if i == nil {
   125  		pushdepth++
   126  		if pushdepth > 1000 {
   127  			Yyerror("macro/io expansion too deep")
   128  			errorexit()
   129  		}
   130  		i = new(Io)
   131  	} else {
   132  		iofree = i.Link
   133  	}
   134  	i.F = nil
   135  	i.P = nil
   136  	ionext = i
   137  }
   138  
   139  func newfile(s string, f *os.File) {
   140  	i := ionext
   141  	i.Link = iostack
   142  	iostack = i
   143  	i.F = f
   144  	if f == nil {
   145  		var err error
   146  		i.F, err = os.Open(s)
   147  		if err != nil {
   148  			Yyerror("%ca: %v", Thechar, err)
   149  			errorexit()
   150  		}
   151  	}
   152  
   153  	fi.P = nil
   154  	obj.Linklinehist(Ctxt, int(Lineno), s, 0)
   155  }
   156  
   157  var thetext *obj.LSym
   158  
   159  func Settext(s *obj.LSym) {
   160  	thetext = s
   161  }
   162  
   163  func LabelLookup(s *Sym) *Sym {
   164  	if thetext == nil {
   165  		s.Labelname = s.Name
   166  		return s
   167  	}
   168  
   169  	p := string(fmt.Sprintf("%s.%s", thetext.Name, s.Name))
   170  	lab := Lookup(p)
   171  
   172  	lab.Labelname = s.Name
   173  	return lab
   174  }
   175  
   176  func Lookup(symb string) *Sym {
   177  	// turn leading · into ""·
   178  	if strings.HasPrefix(symb, "·") {
   179  		symb = `""` + symb
   180  	}
   181  
   182  	// turn · (U+00B7) into .
   183  	// turn ∕ (U+2215) into /
   184  	symb = strings.Replace(symb, "·", ".", -1)
   185  	symb = strings.Replace(symb, "∕", "/", -1)
   186  
   187  	s := hash[symb]
   188  	if s != nil {
   189  		return s
   190  	}
   191  
   192  	s = new(Sym)
   193  	s.Name = symb
   194  	syminit(s)
   195  	hash[symb] = s
   196  	return s
   197  }
   198  
   199  func isalnum(c int) bool {
   200  	return isalpha(c) || isdigit(c)
   201  }
   202  
   203  func isalpha(c int) bool {
   204  	return 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z'
   205  }
   206  
   207  func isspace(c int) bool {
   208  	return c == ' ' || c == '\t' || c == '\r' || c == '\n'
   209  }
   210  
   211  func ISALPHA(c int) bool {
   212  	if isalpha(c) {
   213  		return true
   214  	}
   215  	if c >= utf8.RuneSelf {
   216  		return true
   217  	}
   218  	return false
   219  }
   220  
   221  var yybuf bytes.Buffer
   222  
   223  func (yyImpl) Error(s string) {
   224  	Yyerror("%s", s)
   225  }
   226  
   227  type Yylval struct {
   228  	Sym  *Sym
   229  	Lval int64
   230  	Sval string
   231  	Dval float64
   232  }
   233  
   234  func Yylex(yylval *Yylval) int {
   235  	var c1 int
   236  	var s *Sym
   237  
   238  	c := peekc
   239  	if c != IGN {
   240  		peekc = IGN
   241  		goto l1
   242  	}
   243  
   244  l0:
   245  	c = GETC()
   246  
   247  l1:
   248  	if c == EOF {
   249  		peekc = EOF
   250  		return -1
   251  	}
   252  
   253  	if isspace(c) {
   254  		if c == '\n' {
   255  			Lineno++
   256  			return ';'
   257  		}
   258  
   259  		goto l0
   260  	}
   261  
   262  	if ISALPHA(c) {
   263  		yybuf.Reset()
   264  		goto aloop
   265  	}
   266  	if isdigit(c) {
   267  		yybuf.Reset()
   268  		if c != '0' {
   269  			goto dc
   270  		}
   271  		yybuf.WriteByte(byte(c))
   272  		c = GETC()
   273  		c1 = 3
   274  		if c == 'x' || c == 'X' {
   275  			c1 = 4
   276  			c = GETC()
   277  		} else if c < '0' || c > '7' {
   278  			goto dc
   279  		}
   280  		yylval.Lval = 0
   281  		for {
   282  			if c >= '0' && c <= '9' {
   283  				if c > '7' && c1 == 3 {
   284  					break
   285  				}
   286  				yylval.Lval = int64(uint64(yylval.Lval) << uint(c1))
   287  				yylval.Lval += int64(c) - '0'
   288  				c = GETC()
   289  				continue
   290  			}
   291  
   292  			if c1 == 3 {
   293  				break
   294  			}
   295  			if c >= 'A' && c <= 'F' {
   296  				c += 'a' - 'A'
   297  			}
   298  			if c >= 'a' && c <= 'f' {
   299  				yylval.Lval = int64(uint64(yylval.Lval) << uint(c1))
   300  				yylval.Lval += int64(c) - 'a' + 10
   301  				c = GETC()
   302  				continue
   303  			}
   304  
   305  			break
   306  		}
   307  
   308  		goto ncu
   309  	}
   310  	switch c {
   311  	case '\n':
   312  		Lineno++
   313  		return ';'
   314  
   315  	case '#':
   316  		domacro()
   317  		goto l0
   318  
   319  	case '.':
   320  		c = GETC()
   321  		if ISALPHA(c) {
   322  			yybuf.Reset()
   323  			yybuf.WriteByte('.')
   324  			goto aloop
   325  		}
   326  
   327  		if isdigit(c) {
   328  			yybuf.Reset()
   329  			yybuf.WriteByte('.')
   330  			goto casedot
   331  		}
   332  
   333  		peekc = c
   334  		return '.'
   335  
   336  	case '_',
   337  		'@':
   338  		yybuf.Reset()
   339  		goto aloop
   340  
   341  	case '"':
   342  		var buf bytes.Buffer
   343  		c1 = 0
   344  		for {
   345  			c = escchar('"')
   346  			if c == EOF {
   347  				break
   348  			}
   349  			buf.WriteByte(byte(c))
   350  		}
   351  		yylval.Sval = buf.String()
   352  		return LSCONST
   353  
   354  	case '\'':
   355  		c = escchar('\'')
   356  		if c == EOF {
   357  			c = '\''
   358  		}
   359  		if escchar('\'') != EOF {
   360  			Yyerror("missing '")
   361  		}
   362  		yylval.Lval = int64(c)
   363  		return LCONST
   364  
   365  	case '/':
   366  		c1 = GETC()
   367  		if c1 == '/' {
   368  			for {
   369  				c = GETC()
   370  				if c == '\n' {
   371  					goto l1
   372  				}
   373  				if c == EOF {
   374  					Yyerror("eof in comment")
   375  					errorexit()
   376  				}
   377  			}
   378  		}
   379  
   380  		if c1 == '*' {
   381  			for {
   382  				c = GETC()
   383  				for c == '*' {
   384  					c = GETC()
   385  					if c == '/' {
   386  						goto l0
   387  					}
   388  				}
   389  
   390  				if c == EOF {
   391  					Yyerror("eof in comment")
   392  					errorexit()
   393  				}
   394  
   395  				if c == '\n' {
   396  					Lineno++
   397  				}
   398  			}
   399  		}
   400  
   401  	default:
   402  		return int(c)
   403  	}
   404  
   405  	peekc = c1
   406  	return int(c)
   407  
   408  casedot:
   409  	for {
   410  		yybuf.WriteByte(byte(c))
   411  		c = GETC()
   412  		if !(isdigit(c)) {
   413  			break
   414  		}
   415  	}
   416  
   417  	if c == 'e' || c == 'E' {
   418  		goto casee
   419  	}
   420  	goto caseout
   421  
   422  casee:
   423  	yybuf.WriteByte('e')
   424  	c = GETC()
   425  	if c == '+' || c == '-' {
   426  		yybuf.WriteByte(byte(c))
   427  		c = GETC()
   428  	}
   429  
   430  	for isdigit(c) {
   431  		yybuf.WriteByte(byte(c))
   432  		c = GETC()
   433  	}
   434  
   435  caseout:
   436  	peekc = c
   437  	if FPCHIP != 0 /*TypeKind(100016)*/ {
   438  		last = yybuf.String()
   439  		yylval.Dval = atof(last)
   440  		return LFCONST
   441  	}
   442  
   443  	Yyerror("assembler cannot interpret fp constants")
   444  	yylval.Lval = 1
   445  	return LCONST
   446  
   447  aloop:
   448  	yybuf.WriteByte(byte(c))
   449  	c = GETC()
   450  	if ISALPHA(c) || isdigit(c) || c == '_' || c == '$' {
   451  		goto aloop
   452  	}
   453  	peekc = c
   454  	last = yybuf.String()
   455  	s = Lookup(last)
   456  	if s.Macro != nil {
   457  		newio()
   458  		ionext.P = macexpand(s)
   459  		pushio()
   460  		ionext.Link = iostack
   461  		iostack = ionext
   462  		fi.P = ionext.P
   463  		if peekc != IGN {
   464  			fi.P = append(fi.P, byte(peekc))
   465  			peekc = IGN
   466  		}
   467  
   468  		goto l0
   469  	}
   470  
   471  	if s.Type == 0 {
   472  		s.Type = LNAME
   473  	}
   474  	if s.Type == LNAME || s.Type == LVAR || s.Type == LLAB {
   475  		yylval.Sym = s
   476  		yylval.Sval = last
   477  		return int(s.Type)
   478  	}
   479  
   480  	yylval.Lval = s.Value
   481  	yylval.Sval = last
   482  	return int(s.Type)
   483  
   484  dc:
   485  	for {
   486  		if !(isdigit(c)) {
   487  			break
   488  		}
   489  		yybuf.WriteByte(byte(c))
   490  		c = GETC()
   491  	}
   492  
   493  	if c == '.' {
   494  		goto casedot
   495  	}
   496  	if c == 'e' || c == 'E' {
   497  		goto casee
   498  	}
   499  	last = yybuf.String()
   500  	yylval.Lval = strtoll(last, nil, 10)
   501  
   502  ncu:
   503  	for c == 'U' || c == 'u' || c == 'l' || c == 'L' {
   504  		c = GETC()
   505  	}
   506  	peekc = c
   507  	return LCONST
   508  }
   509  
   510  func getc() int {
   511  	c := peekc
   512  	if c != IGN {
   513  		peekc = IGN
   514  		if c == '\n' {
   515  			Lineno++
   516  		}
   517  		return c
   518  	}
   519  
   520  	c = GETC()
   521  	if c == '\n' {
   522  		Lineno++
   523  	}
   524  	if c == EOF {
   525  		Yyerror("End of file")
   526  		errorexit()
   527  	}
   528  
   529  	return c
   530  }
   531  
   532  func getnsc() int {
   533  	var c int
   534  
   535  	for {
   536  		c = getc()
   537  		if !isspace(c) || c == '\n' {
   538  			return c
   539  		}
   540  	}
   541  }
   542  
   543  func unget(c int) {
   544  	peekc = c
   545  	if c == '\n' {
   546  		Lineno--
   547  	}
   548  }
   549  
   550  func escchar(e int) int {
   551  	var l int
   552  
   553  loop:
   554  	c := getc()
   555  	if c == '\n' {
   556  		Yyerror("newline in string")
   557  		return EOF
   558  	}
   559  
   560  	if c != '\\' {
   561  		if c == e {
   562  			return EOF
   563  		}
   564  		return c
   565  	}
   566  
   567  	c = getc()
   568  	if c >= '0' && c <= '7' {
   569  		l = c - '0'
   570  		c = getc()
   571  		if c >= '0' && c <= '7' {
   572  			l = l*8 + c - '0'
   573  			c = getc()
   574  			if c >= '0' && c <= '7' {
   575  				l = l*8 + c - '0'
   576  				return l
   577  			}
   578  		}
   579  
   580  		peekc = c
   581  		unget(c)
   582  		return l
   583  	}
   584  
   585  	switch c {
   586  	case '\n':
   587  		goto loop
   588  	case 'n':
   589  		return '\n'
   590  	case 't':
   591  		return '\t'
   592  	case 'b':
   593  		return '\b'
   594  	case 'r':
   595  		return '\r'
   596  	case 'f':
   597  		return '\f'
   598  	case 'a':
   599  		return 0x07
   600  	case 'v':
   601  		return 0x0b
   602  	case 'z':
   603  		return 0x00
   604  	}
   605  
   606  	return c
   607  }
   608  
   609  func pinit(f string) {
   610  	Lineno = 1
   611  	newio()
   612  	newfile(f, nil)
   613  	PC = 0
   614  	peekc = IGN
   615  	sym = 1
   616  	for _, s := range hash {
   617  		s.Macro = nil
   618  	}
   619  }
   620  
   621  func filbuf() int {
   622  	var n int
   623  
   624  loop:
   625  	i := iostack
   626  	if i == nil {
   627  		return EOF
   628  	}
   629  	if i.F == nil {
   630  		goto pop
   631  	}
   632  	n, _ = i.F.Read(i.B[:])
   633  	if n == 0 {
   634  		i.F.Close()
   635  		obj.Linklinehist(Ctxt, int(Lineno), "<pop>", 0)
   636  		goto pop
   637  	}
   638  	fi.P = i.B[1:n]
   639  	return int(i.B[0]) & 0xff
   640  
   641  pop:
   642  	iostack = i.Link
   643  	i.Link = iofree
   644  	iofree = i
   645  	i = iostack
   646  	if i == nil {
   647  		return EOF
   648  	}
   649  	fi.P = i.P
   650  	if len(fi.P) == 0 {
   651  		goto loop
   652  	}
   653  	tmp8 := fi.P
   654  	fi.P = fi.P[1:]
   655  	return int(tmp8[0]) & 0xff
   656  }
   657  
   658  var last string
   659  
   660  func Yyerror(a string, args ...interface{}) {
   661  	/*
   662  	 * hack to intercept message from yaccpar
   663  	 */
   664  	if a == "syntax error" || len(args) == 1 && a == "%s" && args[0] == "syntax error" {
   665  		Yyerror("syntax error, last name: %s", last)
   666  		return
   667  	}
   668  
   669  	prfile(Lineno)
   670  	fmt.Printf("%s\n", fmt.Sprintf(a, args...))
   671  	nerrors++
   672  	if nerrors > 10 {
   673  		fmt.Printf("too many errors\n")
   674  		errorexit()
   675  	}
   676  }
   677  
   678  func prfile(l int32) {
   679  	obj.Linkprfile(Ctxt, int(l))
   680  }
   681  
   682  func GETC() int {
   683  	if len(fi.P) == 0 {
   684  		return filbuf()
   685  	}
   686  	c := int(fi.P[0])
   687  	fi.P = fi.P[1:]
   688  	return c
   689  }
   690  
   691  func isdigit(c int) bool {
   692  	return '0' <= c && c <= '9'
   693  }
   694  
   695  func strtoll(s string, p *byte, base int) int64 {
   696  	if p != nil {
   697  		panic("strtoll")
   698  	}
   699  	n, err := strconv.ParseInt(s, base, 64)
   700  	if err != nil {
   701  		return 0
   702  	}
   703  	return n
   704  }
   705  
   706  func atof(s string) float64 {
   707  	f, err := strconv.ParseFloat(s, 64)
   708  	if err != nil {
   709  		return 0
   710  	}
   711  	return f
   712  }