1 // Inferno utils/cc/macbody
2 // http://code.Google.Com/p/inferno-os/source/browse/utils/cc/macbody
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.
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:
20 // The above copyright notice and this permission notice shall be included in
21 // all copies or substantial portions of the Software.
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
50 if c < '0' || c > '9' {
54 for c >= '0' && c <= '9' {
55 n = n*10 + int32(c) - '0'
67 if !isalpha(c) && c != '_' && c < 0x80 {
74 buf.WriteByte(byte(c))
76 if isalnum(c) || c == '_' || c >= 0x80 {
86 func getsymdots(dots *int) *Sym {
101 if getc() != '.' || getc() != '.' {
102 Yyerror("bad dots in macro")
105 return Lookup("__VA_ARGS__")
139 Yyerror("comment across newline")
154 func dodefine(cp string) {
158 if i := strings.Index(cp, "="); i >= 0 {
162 s.Macro = &Macro{Text: p}
165 s.Macro = &Macro{Text: "1"}
169 fmt.Printf("#define (-D) %s %s\n", s.Name, s.Macro.Text)
173 var mactab = []struct {
177 {"ifdef", nil}, /* macif(0) */
178 {"ifndef", nil}, /* macif(1) */
179 {"else", nil}, /* macif(2) */
196 for i = 0; i < len(mactab); i++ {
197 if s.Name == mactab[i].Macname {
198 if mactab[i].Macf != nil {
207 Yyerror("unknown #: %s", s.Name)
217 Yyerror("syntax in #undef")
231 var args [NARG]string
237 var base bytes.Buffer
244 Yyerror("macro redefined: %s", s.Name)
255 a = getsymdots(&dots)
260 Yyerror("too many arguments in #define: %s", s.Name)
270 if c != ',' || dots != 0 {
286 if isalpha(c) || c == '_' {
288 buf.WriteByte(byte(c))
290 for isalnum(c) || c == '_' {
291 buf.WriteByte(byte(c))
296 for i = 0; i < n; i++ {
302 base.WriteString(symb)
307 base.WriteByte(byte('a' + i))
313 base.WriteByte(byte(c))
315 } else if c == ischr {
320 if c == '"' || c == '\'' {
321 base.WriteByte(byte(c))
354 Yyerror("comment and newline in define: %s", s.Name)
374 } else if c == '\r' {
391 base.WriteByte(byte(c))
395 base.WriteByte(byte(c))
401 Yyerror("eof in a macro: %s", s.Name)
412 fmt.Printf("#define %s %s\n", s.Name, s.Macro.Text)
418 Yyerror("syntax in #define")
421 Yyerror("syntax in #define: %s", s.Name)
426 func macexpand(s *Sym) []byte {
434 if s.Macro.Narg == 0 {
436 fmt.Printf("#expand %s %s\n", s.Name, s.Macro.Text)
438 return []byte(s.Macro.Text)
441 nargs := s.Macro.Narg - 1
456 buf.WriteByte(byte(c))
459 buf.WriteByte(byte(c))
475 buf.WriteByte(byte(c))
478 buf.WriteByte(byte(c))
525 if len(arg) == nargs-1 && dots {
530 arg = append(arg, buf.String())
536 arg = append(arg, buf.String())
544 buf.WriteByte(byte(c))
554 if len(arg) != nargs {
555 Yyerror("argument mismatch expanding: %s", s.Name)
560 for i := 0; i < len(cp); i++ {
566 out.WriteByte(byte(c))
576 out.WriteByte(byte(c))
581 if c < 0 || c >= len(arg) {
584 out.WriteString(arg[c])
588 fmt.Printf("#expand %s %s\n", s.Name, out.String())
593 Yyerror("syntax in macro expansion: %s", s.Name)
624 buf.WriteByte(byte(c))
633 for i = 0; i < len(include); i++ {
634 if i == 0 && c0 == '>' {
644 f, err = os.Open(symb)
661 Yyerror("syntax in #include")
677 if c == ' ' || c == '\t' {
698 buf.WriteByte(byte(c))
708 obj.Linklinehist(Ctxt, int(Lineno), symb, int(n))
713 Yyerror("syntax in #line")
730 if getcom() != '\n' {
733 if (s.Macro != nil) != (f != 0) {
759 if s.Name == "endif" {
769 if s.Name == "ifdef" || s.Name == "ifndef" {
774 if l == 0 && f != 2 && s.Name == "else" {
781 Yyerror("syntax in #if(n)def")
794 if s != nil && s.Name == "lib" {
797 if s != nil && s.Name == "pack" {
802 if s != nil && s.Name == "fpround" {
807 if s != nil && s.Name == "textflag" {
812 if s != nil && s.Name == "dataflag" {
817 if s != nil && s.Name == "varargck" {
822 if s != nil && s.Name == "incomplete" {
827 if s != nil && (strings.HasPrefix(s.Name, "cgo_") || strings.HasPrefix(s.Name, "dyn")) {
832 for getnsc() != '\n' {
855 buf.WriteByte(byte(c))
865 * put pragma-line in as a funny history
867 obj.Linklinehist(Ctxt, int(Lineno), symb, -1)
872 Yyerror("syntax in #pragma lib")
881 if c < 0 || c == '\n' {