]> Cypherpunks.ru repositories - gostls13.git/blob - src/cmd/internal/asm/macbody.go
[dev.cc] cmd/new5a etc, cmd/internal/asm: edit to produce working Go code
[gostls13.git] / src / cmd / internal / asm / macbody.go
1 // Inferno utils/cc/macbody
2 // http://code.Google.Com/p/inferno-os/source/browse/utils/cc/macbody
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 import (
34         "bytes"
35         "cmd/internal/obj"
36         "fmt"
37         "os"
38         "strings"
39 )
40
41 const (
42         VARMAC = 0x80
43 )
44
45 func getnsn() int32 {
46         var n int32
47         var c int
48
49         c = getnsc()
50         if c < '0' || c > '9' {
51                 return -1
52         }
53         n = 0
54         for c >= '0' && c <= '9' {
55                 n = n*10 + int32(c) - '0'
56                 c = getc()
57         }
58
59         unget(c)
60         return n
61 }
62
63 func getsym() *Sym {
64         var c int
65
66         c = getnsc()
67         if !isalpha(c) && c != '_' && c < 0x80 {
68                 unget(c)
69                 return nil
70         }
71
72         var buf bytes.Buffer
73         for {
74                 buf.WriteByte(byte(c))
75                 c = getc()
76                 if isalnum(c) || c == '_' || c >= 0x80 {
77                         continue
78                 }
79                 unget(c)
80                 break
81         }
82         last = buf.String()
83         return Lookup(last)
84 }
85
86 func getsymdots(dots *int) *Sym {
87         var c int
88         var s *Sym
89
90         s = getsym()
91         if s != nil {
92                 return s
93         }
94
95         c = getnsc()
96         if c != '.' {
97                 unget(c)
98                 return nil
99         }
100
101         if getc() != '.' || getc() != '.' {
102                 Yyerror("bad dots in macro")
103         }
104         *dots = 1
105         return Lookup("__VA_ARGS__")
106 }
107
108 func getcom() int {
109         var c int
110
111         for {
112                 c = getnsc()
113                 if c != '/' {
114                         break
115                 }
116                 c = getc()
117                 if c == '/' {
118                         for c != '\n' {
119                                 c = getc()
120                         }
121                         break
122                 }
123
124                 if c != '*' {
125                         break
126                 }
127                 c = getc()
128                 for {
129                         if c == '*' {
130                                 c = getc()
131                                 if c != '/' {
132                                         continue
133                                 }
134                                 c = getc()
135                                 break
136                         }
137
138                         if c == '\n' {
139                                 Yyerror("comment across newline")
140                                 break
141                         }
142
143                         c = getc()
144                 }
145
146                 if c == '\n' {
147                         break
148                 }
149         }
150
151         return c
152 }
153
154 func dodefine(cp string) {
155         var s *Sym
156         var p string
157
158         if i := strings.Index(cp, "="); i >= 0 {
159                 p = cp[i+1:]
160                 cp = cp[:i]
161                 s = Lookup(cp)
162                 s.Macro = &Macro{Text: p}
163         } else {
164                 s = Lookup(cp)
165                 s.Macro = &Macro{Text: "1"}
166         }
167
168         if debug['m'] != 0 {
169                 fmt.Printf("#define (-D) %s %s\n", s.Name, s.Macro.Text)
170         }
171 }
172
173 var mactab = []struct {
174         Macname string
175         Macf    func()
176 }{
177         {"ifdef", nil},  /* macif(0) */
178         {"ifndef", nil}, /* macif(1) */
179         {"else", nil},   /* macif(2) */
180         {"line", maclin},
181         {"define", macdef},
182         {"include", macinc},
183         {"undef", macund},
184         {"pragma", macprag},
185         {"endif", macend},
186 }
187
188 func domacro() {
189         var i int
190         var s *Sym
191
192         s = getsym()
193         if s == nil {
194                 s = Lookup("endif")
195         }
196         for i = 0; i < len(mactab); i++ {
197                 if s.Name == mactab[i].Macname {
198                         if mactab[i].Macf != nil {
199                                 mactab[i].Macf()
200                         } else {
201                                 macif(i)
202                         }
203                         return
204                 }
205         }
206
207         Yyerror("unknown #: %s", s.Name)
208         macend()
209 }
210
211 func macund() {
212         var s *Sym
213
214         s = getsym()
215         macend()
216         if s == nil {
217                 Yyerror("syntax in #undef")
218                 return
219         }
220
221         s.Macro = nil
222 }
223
224 const (
225         NARG = 25
226 )
227
228 func macdef() {
229         var s *Sym
230         var a *Sym
231         var args [NARG]string
232         var n int
233         var i int
234         var c int
235         var dots int
236         var ischr int
237         var base bytes.Buffer
238
239         s = getsym()
240         if s == nil {
241                 goto bad
242         }
243         if s.Macro != nil {
244                 Yyerror("macro redefined: %s", s.Name)
245         }
246         c = getc()
247         n = -1
248         dots = 0
249         if c == '(' {
250                 n++
251                 c = getnsc()
252                 if c != ')' {
253                         unget(c)
254                         for {
255                                 a = getsymdots(&dots)
256                                 if a == nil {
257                                         goto bad
258                                 }
259                                 if n >= NARG {
260                                         Yyerror("too many arguments in #define: %s", s.Name)
261                                         goto bad
262                                 }
263
264                                 args[n] = a.Name
265                                 n++
266                                 c = getnsc()
267                                 if c == ')' {
268                                         break
269                                 }
270                                 if c != ',' || dots != 0 {
271                                         goto bad
272                                 }
273                         }
274                 }
275
276                 c = getc()
277         }
278
279         if isspace(c) {
280                 if c != '\n' {
281                         c = getnsc()
282                 }
283         }
284         ischr = 0
285         for {
286                 if isalpha(c) || c == '_' {
287                         var buf bytes.Buffer
288                         buf.WriteByte(byte(c))
289                         c = getc()
290                         for isalnum(c) || c == '_' {
291                                 buf.WriteByte(byte(c))
292                                 c = getc()
293                         }
294
295                         symb := buf.String()
296                         for i = 0; i < n; i++ {
297                                 if symb == args[i] {
298                                         break
299                                 }
300                         }
301                         if i >= n {
302                                 base.WriteString(symb)
303                                 continue
304                         }
305
306                         base.WriteByte('#')
307                         base.WriteByte(byte('a' + i))
308                         continue
309                 }
310
311                 if ischr != 0 {
312                         if c == '\\' {
313                                 base.WriteByte(byte(c))
314                                 c = getc()
315                         } else if c == ischr {
316                                 ischr = 0
317                         }
318                 } else {
319
320                         if c == '"' || c == '\'' {
321                                 base.WriteByte(byte(c))
322                                 ischr = c
323                                 c = getc()
324                                 continue
325                         }
326
327                         if c == '/' {
328                                 c = getc()
329                                 if c == '/' {
330                                         c = getc()
331                                         for {
332                                                 if c == '\n' {
333                                                         break
334                                                 }
335                                                 c = getc()
336                                         }
337
338                                         continue
339                                 }
340
341                                 if c == '*' {
342                                         c = getc()
343                                         for {
344                                                 if c == '*' {
345                                                         c = getc()
346                                                         if c != '/' {
347                                                                 continue
348                                                         }
349                                                         c = getc()
350                                                         break
351                                                 }
352
353                                                 if c == '\n' {
354                                                         Yyerror("comment and newline in define: %s", s.Name)
355                                                         break
356                                                 }
357
358                                                 c = getc()
359                                         }
360
361                                         continue
362                                 }
363
364                                 base.WriteByte('/')
365                                 continue
366                         }
367                 }
368
369                 if c == '\\' {
370                         c = getc()
371                         if c == '\n' {
372                                 c = getc()
373                                 continue
374                         } else if c == '\r' {
375                                 c = getc()
376                                 if c == '\n' {
377                                         c = getc()
378                                         continue
379                                 }
380                         }
381
382                         base.WriteByte('\\')
383                         continue
384                 }
385
386                 if c == '\n' {
387                         break
388                 }
389                 if c == '#' {
390                         if n > 0 {
391                                 base.WriteByte(byte(c))
392                         }
393                 }
394
395                 base.WriteByte(byte(c))
396                 c = GETC()
397                 if c == '\n' {
398                         Lineno++
399                 }
400                 if c == -1 {
401                         Yyerror("eof in a macro: %s", s.Name)
402                         break
403                 }
404         }
405
406         s.Macro = &Macro{
407                 Text: base.String(),
408                 Narg: n + 1,
409                 Dots: dots != 0,
410         }
411         if debug['m'] != 0 {
412                 fmt.Printf("#define %s %s\n", s.Name, s.Macro.Text)
413         }
414         return
415
416 bad:
417         if s == nil {
418                 Yyerror("syntax in #define")
419         } else {
420
421                 Yyerror("syntax in #define: %s", s.Name)
422         }
423         macend()
424 }
425
426 func macexpand(s *Sym) []byte {
427         var l int
428         var c int
429         var arg []string
430         var out bytes.Buffer
431         var buf bytes.Buffer
432         var cp string
433
434         if s.Macro.Narg == 0 {
435                 if debug['m'] != 0 {
436                         fmt.Printf("#expand %s %s\n", s.Name, s.Macro.Text)
437                 }
438                 return []byte(s.Macro.Text)
439         }
440
441         nargs := s.Macro.Narg - 1
442         dots := s.Macro.Dots
443
444         c = getnsc()
445         if c != '(' {
446                 goto bad
447         }
448         c = getc()
449         if c != ')' {
450                 unget(c)
451                 l = 0
452                 for {
453                         c = getc()
454                         if c == '"' {
455                                 for {
456                                         buf.WriteByte(byte(c))
457                                         c = getc()
458                                         if c == '\\' {
459                                                 buf.WriteByte(byte(c))
460                                                 c = getc()
461                                                 continue
462                                         }
463
464                                         if c == '\n' {
465                                                 goto bad
466                                         }
467                                         if c == '"' {
468                                                 break
469                                         }
470                                 }
471                         }
472
473                         if c == '\'' {
474                                 for {
475                                         buf.WriteByte(byte(c))
476                                         c = getc()
477                                         if c == '\\' {
478                                                 buf.WriteByte(byte(c))
479                                                 c = getc()
480                                                 continue
481                                         }
482
483                                         if c == '\n' {
484                                                 goto bad
485                                         }
486                                         if c == '\'' {
487                                                 break
488                                         }
489                                 }
490                         }
491
492                         if c == '/' {
493                                 c = getc()
494                                 switch c {
495                                 case '*':
496                                         for {
497                                                 c = getc()
498                                                 if c == '*' {
499                                                         c = getc()
500                                                         if c == '/' {
501                                                                 break
502                                                         }
503                                                 }
504                                         }
505
506                                         buf.WriteByte(' ')
507                                         continue
508
509                                 case '/':
510                                         for {
511                                                 c = getc()
512                                                 if !(c != '\n') {
513                                                         break
514                                                 }
515                                         }
516
517                                 default:
518                                         unget(c)
519                                         c = '/'
520                                 }
521                         }
522
523                         if l == 0 {
524                                 if c == ',' {
525                                         if len(arg) == nargs-1 && dots {
526                                                 buf.WriteByte(',')
527                                                 continue
528                                         }
529
530                                         arg = append(arg, buf.String())
531                                         buf.Reset()
532                                         continue
533                                 }
534
535                                 if c == ')' {
536                                         arg = append(arg, buf.String())
537                                         break
538                                 }
539                         }
540
541                         if c == '\n' {
542                                 c = ' '
543                         }
544                         buf.WriteByte(byte(c))
545                         if c == '(' {
546                                 l++
547                         }
548                         if c == ')' {
549                                 l--
550                         }
551                 }
552         }
553
554         if len(arg) != nargs {
555                 Yyerror("argument mismatch expanding: %s", s.Name)
556                 return nil
557         }
558
559         cp = s.Macro.Text
560         for i := 0; i < len(cp); i++ {
561                 c = int(cp[i])
562                 if c == '\n' {
563                         c = ' '
564                 }
565                 if c != '#' {
566                         out.WriteByte(byte(c))
567                         continue
568                 }
569
570                 i++
571                 if i >= len(cp) {
572                         goto bad
573                 }
574                 c = int(cp[i])
575                 if c == '#' {
576                         out.WriteByte(byte(c))
577                         continue
578                 }
579
580                 c -= 'a'
581                 if c < 0 || c >= len(arg) {
582                         continue
583                 }
584                 out.WriteString(arg[c])
585         }
586
587         if debug['m'] != 0 {
588                 fmt.Printf("#expand %s %s\n", s.Name, out.String())
589         }
590         return out.Bytes()
591
592 bad:
593         Yyerror("syntax in macro expansion: %s", s.Name)
594         return nil
595 }
596
597 func macinc() {
598         var c0 int
599         var c int
600         var i int
601         var buf bytes.Buffer
602         var f *os.File
603         var hp string
604         var str string
605         var symb string
606
607         c0 = getnsc()
608         if c0 != '"' {
609                 c = c0
610                 if c0 != '<' {
611                         goto bad
612                 }
613                 c0 = '>'
614         }
615
616         for {
617                 c = getc()
618                 if c == c0 {
619                         break
620                 }
621                 if c == '\n' {
622                         goto bad
623                 }
624                 buf.WriteByte(byte(c))
625         }
626         str = buf.String()
627
628         c = getcom()
629         if c != '\n' {
630                 goto bad
631         }
632
633         for i = 0; i < len(include); i++ {
634                 if i == 0 && c0 == '>' {
635                         continue
636                 }
637                 symb = include[i]
638                 symb += "/"
639                 if symb == "./" {
640                         symb = ""
641                 }
642                 symb += str
643                 var err error
644                 f, err = os.Open(symb)
645                 if err == nil {
646                         break
647                 }
648         }
649
650         if f == nil {
651                 symb = str
652         }
653         hp = symb
654         newio()
655         pushio()
656         newfile(hp, f)
657         return
658
659 bad:
660         unget(c)
661         Yyerror("syntax in #include")
662         macend()
663 }
664
665 func maclin() {
666         var c int
667         var n int32
668         var buf bytes.Buffer
669         var symb string
670
671         n = getnsn()
672         c = getc()
673         if n < 0 {
674                 goto bad
675         }
676         for {
677                 if c == ' ' || c == '\t' {
678                         c = getc()
679                         continue
680                 }
681
682                 if c == '"' {
683                         break
684                 }
685                 if c == '\n' {
686                         symb = "<noname>"
687                         goto nn
688                 }
689
690                 goto bad
691         }
692
693         for {
694                 c = getc()
695                 if c == '"' {
696                         break
697                 }
698                 buf.WriteByte(byte(c))
699         }
700         symb = buf.String()
701
702         c = getcom()
703         if c != '\n' {
704                 goto bad
705         }
706
707 nn:
708         obj.Linklinehist(Ctxt, int(Lineno), symb, int(n))
709         return
710
711 bad:
712         unget(c)
713         Yyerror("syntax in #line")
714         macend()
715 }
716
717 func macif(f int) {
718         var c int
719         var l int
720         var bol int
721         var s *Sym
722
723         if f == 2 {
724                 goto skip
725         }
726         s = getsym()
727         if s == nil {
728                 goto bad
729         }
730         if getcom() != '\n' {
731                 goto bad
732         }
733         if (s.Macro != nil) != (f != 0) {
734                 return
735         }
736
737 skip:
738         bol = 1
739         l = 0
740         for {
741                 c = getc()
742                 if c != '#' {
743                         if !isspace(c) {
744                                 bol = 0
745                         }
746                         if c == '\n' {
747                                 bol = 1
748                         }
749                         continue
750                 }
751
752                 if !(bol != 0) {
753                         continue
754                 }
755                 s = getsym()
756                 if s == nil {
757                         continue
758                 }
759                 if s.Name == "endif" {
760                         if l != 0 {
761                                 l--
762                                 continue
763                         }
764
765                         macend()
766                         return
767                 }
768
769                 if s.Name == "ifdef" || s.Name == "ifndef" {
770                         l++
771                         continue
772                 }
773
774                 if l == 0 && f != 2 && s.Name == "else" {
775                         macend()
776                         return
777                 }
778         }
779
780 bad:
781         Yyerror("syntax in #if(n)def")
782         macend()
783 }
784
785 func macprag() {
786         var s *Sym
787         var c0 int
788         var c int
789         var buf bytes.Buffer
790         var symb string
791
792         s = getsym()
793
794         if s != nil && s.Name == "lib" {
795                 goto praglib
796         }
797         if s != nil && s.Name == "pack" {
798                 pragpack()
799                 return
800         }
801
802         if s != nil && s.Name == "fpround" {
803                 pragfpround()
804                 return
805         }
806
807         if s != nil && s.Name == "textflag" {
808                 pragtextflag()
809                 return
810         }
811
812         if s != nil && s.Name == "dataflag" {
813                 pragdataflag()
814                 return
815         }
816
817         if s != nil && s.Name == "varargck" {
818                 pragvararg()
819                 return
820         }
821
822         if s != nil && s.Name == "incomplete" {
823                 pragincomplete()
824                 return
825         }
826
827         if s != nil && (strings.HasPrefix(s.Name, "cgo_") || strings.HasPrefix(s.Name, "dyn")) {
828                 pragcgo(s.Name)
829                 return
830         }
831
832         for getnsc() != '\n' {
833
834         }
835         return
836
837 praglib:
838         c0 = getnsc()
839         if c0 != '"' {
840                 c = c0
841                 if c0 != '<' {
842                         goto bad
843                 }
844                 c0 = '>'
845         }
846
847         for {
848                 c = getc()
849                 if c == c0 {
850                         break
851                 }
852                 if c == '\n' {
853                         goto bad
854                 }
855                 buf.WriteByte(byte(c))
856         }
857         symb = buf.String()
858
859         c = getcom()
860         if c != '\n' {
861                 goto bad
862         }
863
864         /*
865          * put pragma-line in as a funny history
866          */
867         obj.Linklinehist(Ctxt, int(Lineno), symb, -1)
868         return
869
870 bad:
871         unget(c)
872         Yyerror("syntax in #pragma lib")
873         macend()
874 }
875
876 func macend() {
877         var c int
878
879         for {
880                 c = getnsc()
881                 if c < 0 || c == '\n' {
882                         return
883                 }
884         }
885 }