]> Cypherpunks.ru repositories - gostls13.git/blob - src/cmd/internal/asm/lexbody.go
d835e7b1172fcfd3dafa749f07495bd1225c363f
[gostls13.git] / src / cmd / internal / asm / lexbody.go
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 package asm
32
33 /*
34  * common code for all the assemblers
35  */
36 func pragpack() {
37
38         for getnsc() != '\n' {
39
40         }
41 }
42
43 func pragvararg() {
44         for getnsc() != '\n' {
45
46         }
47 }
48
49 func pragcgo(name string) {
50         for getnsc() != '\n' {
51
52         }
53 }
54
55 func pragfpround() {
56         for getnsc() != '\n' {
57
58         }
59 }
60
61 func pragtextflag() {
62         for getnsc() != '\n' {
63
64         }
65 }
66
67 func pragdataflag() {
68         for getnsc() != '\n' {
69
70         }
71 }
72
73 func pragprofile() {
74         for getnsc() != '\n' {
75
76         }
77 }
78
79 func pragincomplete() {
80         for getnsc() != '\n' {
81
82         }
83 }
84
85 func Alloc(n int32) interface{} {
86         var p interface{}
87
88         p = make([]byte, n)
89         if p == nil {
90                 fmt.Printf("alloc out of mem\n")
91                 main.Exits("alloc: out of mem")
92         }
93
94         main.Memset(p, 0, n)
95         return p
96 }
97
98 func Allocn(p interface{}, n int32, d int32) interface{} {
99         if p == nil {
100                 return Alloc(n + d)
101         }
102         p = main.Realloc(p, int(n+d))
103         if p == nil {
104                 fmt.Printf("allocn out of mem\n")
105                 main.Exits("allocn: out of mem")
106         }
107
108         if d > 0 {
109                 main.Memset(p.(string)[n:], 0, d)
110         }
111         return p
112 }
113
114 func Ensuresymb(n int32) {
115         if new5a.Symb == nil {
116                 new5a.Symb = Alloc(new5a.NSYMB + 1).(string)
117                 new5a.Nsymb = new5a.NSYMB
118         }
119
120         if n > new5a.Nsymb {
121                 new5a.Symb = Allocn(new5a.Symb, new5a.Nsymb, n+1-new5a.Nsymb).(string)
122                 new5a.Nsymb = n
123         }
124 }
125
126 func Setinclude(p string) {
127         var i int
128
129         if p == "" {
130                 return
131         }
132         for i = 1; i < new5a.Ninclude; i++ {
133                 if p == new5a.Include[i] {
134                         return
135                 }
136         }
137
138         if new5a.Ninclude%8 == 0 {
139                 new5a.Include = Allocn(new5a.Include, new5a.Ninclude*sizeof(string), 8*sizeof(string)).(*string)
140         }
141         new5a.Include[new5a.Ninclude] = p
142         new5a.Ninclude++
143 }
144
145 func Errorexit() {
146         obj.Bflush(&new5a.Bstdout)
147         if new5a.Outfile != "" {
148                 main.Remove(new5a.Outfile)
149         }
150         main.Exits("error")
151 }
152
153 func pushio() {
154         var i *new5a.Io
155
156         i = new5a.Iostack
157         if i == nil {
158                 Yyerror("botch in pushio")
159                 Errorexit()
160         }
161
162         i.P = new5a.Fi.p
163         i.C = int16(new5a.Fi.c)
164 }
165
166 func newio() {
167         var i *new5a.Io
168         var pushdepth int = 0
169
170         i = new5a.Iofree
171         if i == nil {
172                 pushdepth++
173                 if pushdepth > 1000 {
174                         Yyerror("macro/io expansion too deep")
175                         Errorexit()
176                 }
177
178                 i = Alloc(sizeof(*i)).(*new5a.Io)
179         } else {
180
181                 new5a.Iofree = i.Link
182         }
183         i.C = 0
184         i.F = -1
185         new5a.Ionext = i
186 }
187
188 func newfile(s string, f int) {
189         var i *new5a.Io
190
191         i = new5a.Ionext
192         i.Link = new5a.Iostack
193         new5a.Iostack = i
194         i.F = int16(f)
195         if f < 0 {
196                 i.F = int16(main.Open(s, 0))
197         }
198         if i.F < 0 {
199                 Yyerror("%ca: %r: %s", new5a.Thechar, s)
200                 Errorexit()
201         }
202
203         new5a.Fi.c = 0
204         obj.Linklinehist(new5a.Ctxt, int(new5a.Lineno), s, 0)
205 }
206
207 func Slookup(s string) *new5a.Sym {
208         Ensuresymb(int32(len(s)))
209         new5a.Symb = s
210         return lookup()
211 }
212
213 var thetext *obj.LSym
214
215 func settext(s *obj.LSym) {
216         thetext = s
217 }
218
219 func labellookup(s *new5a.Sym) *new5a.Sym {
220         var p string
221         var lab *new5a.Sym
222
223         if thetext == nil {
224                 s.Labelname = s.Name
225                 return s
226         }
227
228         p = string(fmt.Sprintf("%s.%s", thetext.Name, s.Name))
229         lab = Slookup(p)
230
231         lab.Labelname = s.Name
232         return lab
233 }
234
235 func lookup() *new5a.Sym {
236         var s *new5a.Sym
237         var h uint32
238         var p string
239         var c int
240         var l int
241         var r string
242         var w string
243
244         if uint8(new5a.Symb[0]) == 0xc2 && uint8(new5a.Symb[1]) == 0xb7 {
245                 // turn leading · into ""·
246                 h = uint32(len(new5a.Symb))
247
248                 Ensuresymb(int32(h + 2))
249                 main.Memmove(new5a.Symb[2:], new5a.Symb, h+1)
250                 new5a.Symb[0] = '"'
251                 new5a.Symb[1] = '"'
252         }
253
254         w = new5a.Symb
255         for r = w; r[0] != 0; r = r[1:] {
256                 // turn · (U+00B7) into .
257                 // turn ∕ (U+2215) into /
258                 if uint8(r[0]) == 0xc2 && uint8((r[1:])[0]) == 0xb7 {
259
260                         w[0] = '.'
261                         w = w[1:]
262                         r = r[1:]
263                 } else if uint8(r[0]) == 0xe2 && uint8((r[1:])[0]) == 0x88 && uint8((r[2:])[0]) == 0x95 {
264                         w[0] = '/'
265                         w = w[1:]
266                         r = r[1:]
267                         r = r[1:]
268                 } else {
269
270                         w[0] = r[0]
271                         w = w[1:]
272                 }
273         }
274
275         w[0] = '\x00'
276
277         h = 0
278         for p = new5a.Symb; ; p = p[1:] {
279                 c = int(p[0])
280                 if !(c != 0) {
281                         break
282                 }
283                 h = h + h + h + uint32(c)
284         }
285         l = (-cap(p) + cap(new5a.Symb)) + 1
286         h &= 0xffffff
287         h %= new5a.NHASH
288         c = int(new5a.Symb[0])
289         for s = new5a.Hash[h]; s != nil; s = s.Link {
290                 if int(s.Name[0]) != c {
291                         continue
292                 }
293                 if s.Name == new5a.Symb {
294                         return s
295                 }
296         }
297
298         s = Alloc(sizeof(*s)).(*new5a.Sym)
299         s.Name = Alloc(int32(l)).(string)
300         main.Memmove(s.Name, new5a.Symb, l)
301
302         s.Link = new5a.Hash[h]
303         new5a.Hash[h] = s
304         new5a.Syminit(s)
305         return s
306 }
307
308 func ISALPHA(c int) int {
309         if main.Isalpha(c) != 0 {
310                 return 1
311         }
312         if c >= main.Runeself {
313                 return 1
314         }
315         return 0
316 }
317
318 func yylex() int32 {
319         var c int
320         var c1 int
321         var cp string
322         var s *new5a.Sym
323
324         c = new5a.Peekc
325         if c != new5a.IGN {
326                 new5a.Peekc = new5a.IGN
327                 goto l1
328         }
329
330 l0:
331         c = new5a.GETC()
332
333 l1:
334         if c == new5a.EOF {
335                 new5a.Peekc = new5a.EOF
336                 return -1
337         }
338
339         if main.Isspace(c) != 0 {
340                 if c == '\n' {
341                         new5a.Lineno++
342                         return ';'
343                 }
344
345                 goto l0
346         }
347
348         if ISALPHA(c) != 0 {
349                 goto talph
350         }
351         if main.Isdigit(c) != 0 {
352                 goto tnum
353         }
354         switch c {
355         case '\n':
356                 new5a.Lineno++
357                 return ';'
358
359         case '#':
360                 domacro()
361                 goto l0
362
363         case '.':
364                 c = new5a.GETC()
365                 if ISALPHA(c) != 0 {
366                         cp = new5a.Symb
367                         cp[0] = '.'
368                         cp = cp[1:]
369                         goto aloop
370                 }
371
372                 if main.Isdigit(c) != 0 {
373                         cp = new5a.Symb
374                         cp[0] = '.'
375                         cp = cp[1:]
376                         goto casedot
377                 }
378
379                 new5a.Peekc = c
380                 return '.'
381
382         case '_',
383                 '@':
384         talph:
385                 cp = new5a.Symb
386
387         aloop:
388                 cp[0] = byte(c)
389                 cp = cp[1:]
390                 c = new5a.GETC()
391                 if ISALPHA(c) != 0 || main.Isdigit(c) != 0 || c == '_' || c == '$' {
392                         goto aloop
393                 }
394                 cp = ""
395                 new5a.Peekc = c
396                 s = lookup()
397                 if s.Macro != "" {
398                         newio()
399                         cp = new5a.Ionext.B
400                         macexpand(s, cp)
401                         pushio()
402                         new5a.Ionext.Link = new5a.Iostack
403                         new5a.Iostack = new5a.Ionext
404                         new5a.Fi.p = cp
405                         new5a.Fi.c = len(cp)
406                         if new5a.Peekc != new5a.IGN {
407                                 cp[new5a.Fi.c] = byte(new5a.Peekc)
408                                 new5a.Fi.c++
409                                 cp[new5a.Fi.c] = 0
410                                 new5a.Peekc = new5a.IGN
411                         }
412
413                         goto l0
414                 }
415
416                 if s.Type_ == 0 {
417                         s.Type_ = new5a.LNAME
418                 }
419                 if s.Type_ == new5a.LNAME || s.Type_ == new5a.LVAR || s.Type_ == new5a.LLAB {
420                         new5a.Yylval.sym = s
421                         return int32(s.Type_)
422                 }
423
424                 new5a.Yylval.lval = s.Value
425                 return int32(s.Type_)
426
427         tnum:
428                 cp = new5a.Symb
429                 if c != '0' {
430                         goto dc
431                 }
432                 cp[0] = byte(c)
433                 cp = cp[1:]
434                 c = new5a.GETC()
435                 c1 = 3
436                 if c == 'x' || c == 'X' {
437                         c1 = 4
438                         c = new5a.GETC()
439                 } else if c < '0' || c > '7' {
440                         goto dc
441                 }
442                 new5a.Yylval.lval = 0
443                 for {
444                         if c >= '0' && c <= '9' {
445                                 if c > '7' && c1 == 3 {
446                                         break
447                                 }
448                                 new5a.Yylval.lval = int32(uint64(new5a.Yylval.lval) << uint(c1))
449                                 new5a.Yylval.lval += int32(c) - '0'
450                                 c = new5a.GETC()
451                                 continue
452                         }
453
454                         if c1 == 3 {
455                                 break
456                         }
457                         if c >= 'A' && c <= 'F' {
458                                 c += 'a' - 'A'
459                         }
460                         if c >= 'a' && c <= 'f' {
461                                 new5a.Yylval.lval = int32(uint64(new5a.Yylval.lval) << uint(c1))
462                                 new5a.Yylval.lval += int32(c) - 'a' + 10
463                                 c = new5a.GETC()
464                                 continue
465                         }
466
467                         break
468                 }
469
470                 goto ncu
471
472         dc:
473                 for {
474                         if !(main.Isdigit(c) != 0) {
475                                 break
476                         }
477                         cp[0] = byte(c)
478                         cp = cp[1:]
479                         c = new5a.GETC()
480                 }
481
482                 if c == '.' {
483                         goto casedot
484                 }
485                 if c == 'e' || c == 'E' {
486                         goto casee
487                 }
488                 cp = ""
489                 if sizeof(new5a.Yylval.lval) == sizeof(int64) {
490                         new5a.Yylval.lval = int32(main.Strtoll(new5a.Symb, nil, 10))
491                 } else {
492
493                         new5a.Yylval.lval = int32(main.Strtol(new5a.Symb, nil, 10))
494                 }
495
496         ncu:
497                 for c == 'U' || c == 'u' || c == 'l' || c == 'L' {
498                         c = new5a.GETC()
499                 }
500                 new5a.Peekc = c
501                 return new5a.LCONST
502
503         casedot:
504                 for {
505                         cp[0] = byte(c)
506                         cp = cp[1:]
507                         c = new5a.GETC()
508                         if !(main.Isdigit(c) != 0) {
509                                 break
510                         }
511                 }
512
513                 if c == 'e' || c == 'E' {
514                         goto casee
515                 }
516                 goto caseout
517
518         casee:
519                 cp[0] = 'e'
520                 cp = cp[1:]
521                 c = new5a.GETC()
522                 if c == '+' || c == '-' {
523                         cp[0] = byte(c)
524                         cp = cp[1:]
525                         c = new5a.GETC()
526                 }
527
528                 for main.Isdigit(c) != 0 {
529                         cp[0] = byte(c)
530                         cp = cp[1:]
531                         c = new5a.GETC()
532                 }
533
534         caseout:
535                 cp = ""
536                 new5a.Peekc = c
537                 if new5a.FPCHIP != 0 /*TypeKind(100016)*/ {
538                         new5a.Yylval.dval = main.Atof(new5a.Symb)
539                         return new5a.LFCONST
540                 }
541
542                 Yyerror("assembler cannot interpret fp constants")
543                 new5a.Yylval.lval = 1
544                 return new5a.LCONST
545
546         case '"':
547                 main.Memmove(new5a.Yylval.sval, new5a.Nullgen.U.Sval, sizeof(new5a.Yylval.sval))
548                 cp = new5a.Yylval.sval
549                 c1 = 0
550                 for {
551                         c = escchar('"')
552                         if c == new5a.EOF {
553                                 break
554                         }
555                         if c1 < sizeof(new5a.Yylval.sval) {
556                                 cp[0] = byte(c)
557                                 cp = cp[1:]
558                         }
559                         c1++
560                 }
561
562                 if c1 > sizeof(new5a.Yylval.sval) {
563                         Yyerror("string constant too long")
564                 }
565                 return new5a.LSCONST
566
567         case '\'':
568                 c = escchar('\'')
569                 if c == new5a.EOF {
570                         c = '\''
571                 }
572                 if escchar('\'') != new5a.EOF {
573                         Yyerror("missing '")
574                 }
575                 new5a.Yylval.lval = int32(c)
576                 return new5a.LCONST
577
578         case '/':
579                 c1 = new5a.GETC()
580                 if c1 == '/' {
581                         for {
582                                 c = new5a.GETC()
583                                 if c == '\n' {
584                                         goto l1
585                                 }
586                                 if c == new5a.EOF {
587                                         Yyerror("eof in comment")
588                                         Errorexit()
589                                 }
590                         }
591                 }
592
593                 if c1 == '*' {
594                         for {
595                                 c = new5a.GETC()
596                                 for c == '*' {
597                                         c = new5a.GETC()
598                                         if c == '/' {
599                                                 goto l0
600                                         }
601                                 }
602
603                                 if c == new5a.EOF {
604                                         Yyerror("eof in comment")
605                                         Errorexit()
606                                 }
607
608                                 if c == '\n' {
609                                         new5a.Lineno++
610                                 }
611                         }
612                 }
613
614         default:
615                 return int32(c)
616         }
617
618         new5a.Peekc = c1
619         return int32(c)
620 }
621
622 func getc() int {
623         var c int
624
625         c = new5a.Peekc
626         if c != new5a.IGN {
627                 new5a.Peekc = new5a.IGN
628                 return c
629         }
630
631         c = new5a.GETC()
632         if c == '\n' {
633                 new5a.Lineno++
634         }
635         if c == new5a.EOF {
636                 Yyerror("End of file")
637                 Errorexit()
638         }
639
640         return c
641 }
642
643 func getnsc() int {
644         var c int
645
646         for {
647                 c = getc()
648                 if !(main.Isspace(c) != 0) || c == '\n' {
649                         return c
650                 }
651         }
652 }
653
654 func unget(c int) {
655         new5a.Peekc = c
656         if c == '\n' {
657                 new5a.Lineno--
658         }
659 }
660
661 func escchar(e int) int {
662         var c int
663         var l int
664
665 loop:
666         c = getc()
667         if c == '\n' {
668                 Yyerror("newline in string")
669                 return new5a.EOF
670         }
671
672         if c != '\\' {
673                 if c == e {
674                         return new5a.EOF
675                 }
676                 return c
677         }
678
679         c = getc()
680         if c >= '0' && c <= '7' {
681                 l = c - '0'
682                 c = getc()
683                 if c >= '0' && c <= '7' {
684                         l = l*8 + c - '0'
685                         c = getc()
686                         if c >= '0' && c <= '7' {
687                                 l = l*8 + c - '0'
688                                 return l
689                         }
690                 }
691
692                 new5a.Peekc = c
693                 return l
694         }
695
696         switch c {
697         case '\n':
698                 goto loop
699         case 'n':
700                 return '\n'
701         case 't':
702                 return '\t'
703         case 'b':
704                 return '\b'
705         case 'r':
706                 return '\r'
707         case 'f':
708                 return '\f'
709         case 'a':
710                 return 0x07
711         case 'v':
712                 return 0x0b
713         case 'z':
714                 return 0x00
715         }
716
717         return c
718 }
719
720 func Pinit(f string) {
721         var i int
722         var s *new5a.Sym
723
724         new5a.Lineno = 1
725         newio()
726         newfile(f, -1)
727         new5a.Pc = 0
728         new5a.Peekc = new5a.IGN
729         new5a.Sym = 1
730         for i = 0; i < new5a.NHASH; i++ {
731                 for s = new5a.Hash[i]; s != nil; s = s.Link {
732                         s.Macro = ""
733                 }
734         }
735 }
736
737 func filbuf() int {
738         var i *new5a.Io
739
740 loop:
741         i = new5a.Iostack
742         if i == nil {
743                 return new5a.EOF
744         }
745         if i.F < 0 {
746                 goto pop
747         }
748         new5a.Fi.c = main.Read(int(i.F), i.B, new5a.BUFSIZ) - 1
749         if new5a.Fi.c < 0 {
750                 main.Close(int(i.F))
751                 obj.Linklinehist(new5a.Ctxt, int(new5a.Lineno), "", 0)
752                 goto pop
753         }
754
755         new5a.Fi.p = i.B[1:]
756         return int(i.B[0]) & 0xff
757
758 pop:
759         new5a.Iostack = i.Link
760         i.Link = new5a.Iofree
761         new5a.Iofree = i
762         i = new5a.Iostack
763         if i == nil {
764                 return new5a.EOF
765         }
766         new5a.Fi.p = i.P
767         new5a.Fi.c = int(i.C)
768         new5a.Fi.c--
769         if new5a.Fi.c < 0 {
770                 goto loop
771         }
772         tmp8 := new5a.Fi.p
773         new5a.Fi.p = new5a.Fi.p[1:]
774         return int(tmp8[0]) & 0xff
775 }
776
777 func Yyerror(a string, args ...interface{}) {
778         var buf string
779         var arg []interface{}
780
781         /*
782          * hack to intercept message from yaccpar
783          */
784         if a == "syntax error" {
785
786                 Yyerror("syntax error, last name: %s", new5a.Symb)
787                 return
788         }
789
790         prfile(new5a.Lineno)
791         main.Va_start(arg, a)
792         obj.Vseprint(buf, buf[sizeof(buf):], a, arg)
793         main.Va_end(arg)
794         fmt.Printf("%s\n", buf)
795         new5a.Nerrors++
796         if new5a.Nerrors > 10 {
797                 fmt.Printf("too many errors\n")
798                 Errorexit()
799         }
800 }
801
802 func prfile(l int32) {
803         obj.Linkprfile(new5a.Ctxt, l)
804 }