github.com/ader1990/go@v0.0.0-20140630135419-8c24447fa791/src/cmd/cc/dpchk.c (about)

     1  // Inferno utils/cc/dpchk.c
     2  // http://code.google.com/p/inferno-os/source/browse/utils/cc/dpchk.c
     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  #include	<u.h>
    32  #include	"cc.h"
    33  #include	"y.tab.h"
    34  
    35  enum
    36  {
    37  	Fnone	= 0,
    38  	Fl,
    39  	Fvl,
    40  	Fignor,
    41  	Fstar,
    42  	Fadj,
    43  
    44  	Fverb	= 10,
    45  };
    46  
    47  typedef	struct	Tprot	Tprot;
    48  struct	Tprot
    49  {
    50  	Type*	type;
    51  	Bits	flag;
    52  	Tprot*	link;
    53  };
    54  
    55  typedef	struct	Tname	Tname;
    56  struct	Tname
    57  {
    58  	char*	name;
    59  	int	param;
    60  	int	count;
    61  	Tname*	link;
    62  	Tprot*	prot;
    63  };
    64  
    65  static	Type*	indchar;
    66  static	uchar	flagbits[512];
    67  static	char*	lastfmt;
    68  static	int	lastadj;
    69  static	int	lastverb;
    70  static	int	nstar;
    71  static	Tprot*	tprot;
    72  static	Tname*	tname;
    73  
    74  void
    75  argflag(int c, int v)
    76  {
    77  
    78  	switch(v) {
    79  	case Fignor:
    80  	case Fstar:
    81  	case Fl:
    82  	case Fvl:
    83  		flagbits[c] = v;
    84  		break;
    85  	case Fverb:
    86  		flagbits[c] = lastverb;
    87  /*print("flag-v %c %d\n", c, lastadj);*/
    88  		lastverb++;
    89  		break;
    90  	case Fadj:
    91  		flagbits[c] = lastadj;
    92  /*print("flag-l %c %d\n", c, lastadj);*/
    93  		lastadj++;
    94  		break;
    95  	}
    96  }
    97  
    98  Bits
    99  getflag(char *s)
   100  {
   101  	Bits flag;
   102  	int f;
   103  	Fmt fmt;
   104  	Rune c;
   105  
   106  	flag = zbits;
   107  	nstar = 0;
   108  	fmtstrinit(&fmt);
   109  	for(;;) {
   110  		s += chartorune(&c, s);
   111  		if(c == 0 || c >= nelem(flagbits))
   112  			break;
   113  		fmtrune(&fmt, c);
   114  		f = flagbits[c];
   115  		switch(f) {
   116  		case Fnone:
   117  			argflag(c, Fverb);
   118  			f = flagbits[c];
   119  			break;
   120  		case Fstar:
   121  			nstar++;
   122  		case Fignor:
   123  			continue;
   124  		case Fl:
   125  			if(bset(flag, Fl))
   126  				flag = bor(flag, blsh(Fvl));
   127  		}
   128  		flag = bor(flag, blsh(f));
   129  		if(f >= Fverb)
   130  			break;
   131  	}
   132  	free(lastfmt);
   133  	lastfmt = fmtstrflush(&fmt);
   134  	return flag;
   135  }
   136  
   137  static void
   138  newprot(Sym *m, Type *t, char *s, Tprot **prot)
   139  {
   140  	Bits flag;
   141  	Tprot *l;
   142  
   143  	if(t == T) {
   144  		warn(Z, "%s: newprot: type not defined", m->name);
   145  		return;
   146  	}
   147  	flag = getflag(s);
   148  	for(l=*prot; l; l=l->link)
   149  		if(beq(flag, l->flag) && sametype(t, l->type))
   150  			return;
   151  	l = alloc(sizeof(*l));
   152  	l->type = t;
   153  	l->flag = flag;
   154  	l->link = *prot;
   155  	*prot = l;
   156  }
   157  
   158  static Tname*
   159  newname(char *s, int p, int count)
   160  {
   161  	Tname *l;
   162  
   163  	for(l=tname; l; l=l->link)
   164  		if(strcmp(l->name, s) == 0) {
   165  			if(p >= 0 && l->param != p)
   166  				yyerror("vargck %s already defined\n", s);
   167  			return l;
   168  		}
   169  	if(p < 0)
   170  		return nil;
   171  
   172  	l = alloc(sizeof(*l));
   173  	l->name = s;
   174  	l->param = p;
   175  	l->link = tname;
   176  	l->count = count;
   177  	tname = l;
   178  	return l;
   179  }
   180  
   181  void
   182  arginit(void)
   183  {
   184  	int i;
   185  
   186  /* debug['F'] = 1;*/
   187  /* debug['w'] = 1;*/
   188  
   189  	lastadj = Fadj;
   190  	lastverb = Fverb;
   191  	indchar = typ(TIND, types[TCHAR]);
   192  
   193  	memset(flagbits, Fnone, sizeof(flagbits));
   194  
   195  	for(i='0'; i<='9'; i++)
   196  		argflag(i, Fignor);
   197  	argflag('.', Fignor);
   198  	argflag('#', Fignor);
   199  	argflag('u', Fignor);
   200  	argflag('h', Fignor);
   201  	argflag('+', Fignor);
   202  	argflag('-', Fignor);
   203  
   204  	argflag('*', Fstar);
   205  	argflag('l', Fl);
   206  
   207  	argflag('o', Fverb);
   208  	flagbits['x'] = flagbits['o'];
   209  	flagbits['X'] = flagbits['o'];
   210  }
   211  
   212  static char*
   213  getquoted(void)
   214  {
   215  	int c;
   216  	Rune r;
   217  	Fmt fmt;
   218  
   219  	c = getnsc();
   220  	if(c != '"')
   221  		return nil;
   222  	fmtstrinit(&fmt);
   223  	for(;;) {
   224  		r = getr();
   225  		if(r == '\n') {
   226  			free(fmtstrflush(&fmt));
   227  			return nil;
   228  		}
   229  		if(r == '"')
   230  			break;
   231  		fmtrune(&fmt, r);
   232  	}
   233  	free(lastfmt);
   234  	lastfmt = fmtstrflush(&fmt);
   235  	return strdup(lastfmt);
   236  }
   237  
   238  void
   239  pragvararg(void)
   240  {
   241  	Sym *s;
   242  	int n, c;
   243  	char *t;
   244  	Type *ty;
   245  	Tname *l;
   246  
   247  	if(!debug['F'])
   248  		goto out;
   249  	s = getsym();
   250  	if(s && strcmp(s->name, "argpos") == 0)
   251  		goto ckpos;
   252  	if(s && strcmp(s->name, "type") == 0)
   253  		goto cktype;
   254  	if(s && strcmp(s->name, "flag") == 0)
   255  		goto ckflag;
   256  	if(s && strcmp(s->name, "countpos") == 0)
   257  		goto ckcount;
   258  	yyerror("syntax in #pragma varargck");
   259  	goto out;
   260  
   261  ckpos:
   262  /*#pragma	varargck	argpos	warn	2*/
   263  	s = getsym();
   264  	if(s == S)
   265  		goto bad;
   266  	n = getnsn();
   267  	if(n < 0)
   268  		goto bad;
   269  	newname(s->name, n, 0);
   270  	goto out;
   271  
   272  ckcount:
   273  /*#pragma	varargck	countpos	name 2*/
   274  	s = getsym();
   275  	if(s == S)
   276  		goto bad;
   277  	n = getnsn();
   278  	if(n < 0)
   279  		goto bad;
   280  	newname(s->name, 0, n);
   281  	goto out;
   282  
   283  ckflag:
   284  /*#pragma	varargck	flag	'c'*/
   285  	c = getnsc();
   286  	if(c != '\'')
   287  		goto bad;
   288  	c = getr();
   289  	if(c == '\\')
   290  		c = getr();
   291  	else if(c == '\'')
   292  		goto bad;
   293  	if(c == '\n')
   294  		goto bad;
   295  	if(getc() != '\'')
   296  		goto bad;
   297  	argflag(c, Fignor);
   298  	goto out;
   299  
   300  cktype:
   301  	c = getnsc();
   302  	unget(c);
   303  	if(c != '"') {
   304  /*#pragma	varargck	type	name	int*/
   305  		s = getsym();
   306  		if(s == S)
   307  			goto bad;
   308  		l = newname(s->name, -1, -1);
   309  		s = getsym();
   310  		if(s == S)
   311  			goto bad;
   312  		ty = s->type;
   313  		while((c = getnsc()) == '*')
   314  			ty = typ(TIND, ty);
   315  		unget(c);
   316  		newprot(s, ty, "a", &l->prot);
   317  		goto out;
   318  	}
   319  
   320  /*#pragma	varargck	type	O	int*/
   321  	t = getquoted();
   322  	if(t == nil)
   323  		goto bad;
   324  	s = getsym();
   325  	if(s == S)
   326  		goto bad;
   327  	ty = s->type;
   328  	while((c = getnsc()) == '*')
   329  		ty = typ(TIND, ty);
   330  	unget(c);
   331  	newprot(s, ty, t, &tprot);
   332  	goto out;
   333  
   334  bad:
   335  	yyerror("syntax in #pragma varargck");
   336  
   337  out:
   338  	while(getnsc() != '\n')
   339  		;
   340  }
   341  
   342  Node*
   343  nextarg(Node *n, Node **a)
   344  {
   345  	if(n == Z) {
   346  		*a = Z;
   347  		return Z;
   348  	}
   349  	if(n->op == OLIST) {
   350  		*a = n->left;
   351  		return n->right;
   352  	}
   353  	*a = n;
   354  	return Z;
   355  }
   356  
   357  void
   358  checkargs(Node *nn, char *s, int pos)
   359  {
   360  	Node *a, *n;
   361  	Bits flag;
   362  	Tprot *l;
   363  
   364  	if(!debug['F'])
   365  		return;
   366  	n = nn;
   367  	for(;;) {
   368  		s = strchr(s, '%');
   369  		if(s == 0) {
   370  			nextarg(n, &a);
   371  			if(a != Z)
   372  				warn(nn, "more arguments than format %T",
   373  					a->type);
   374  			return;
   375  		}
   376  		s++;
   377  		flag = getflag(s);
   378  		while(nstar > 0) {
   379  			n = nextarg(n, &a);
   380  			pos++;
   381  			nstar--;
   382  			if(a == Z) {
   383  				warn(nn, "more format than arguments %s",
   384  					lastfmt);
   385  				return;
   386  			}
   387  			if(a->type == T)
   388  				continue;
   389  			if(!sametype(types[TINT], a->type) &&
   390  			   !sametype(types[TUINT], a->type))
   391  				warn(nn, "format mismatch '*' in %s %T, arg %d",
   392  					lastfmt, a->type, pos);
   393  		}
   394  		for(l=tprot; l; l=l->link)
   395  			if(sametype(types[TVOID], l->type)) {
   396  				if(beq(flag, l->flag)) {
   397  					s++;
   398  					goto loop;
   399  				}
   400  			}
   401  
   402  		n = nextarg(n, &a);
   403  		pos++;
   404  		if(a == Z) {
   405  			warn(nn, "more format than arguments %s",
   406  				lastfmt);
   407  			return;
   408  		}
   409  		if(a->type == 0)
   410  			continue;
   411  		for(l=tprot; l; l=l->link)
   412  			if(sametype(a->type, l->type)) {
   413  /*print("checking %T/%ux %T/%ux\n", a->type, flag.b[0], l->type, l->flag.b[0]);*/
   414  				if(beq(flag, l->flag))
   415  					goto loop;
   416  			}
   417  		warn(nn, "format mismatch %s %T, arg %d", lastfmt, a->type, pos);
   418  	loop:;
   419  	}
   420  }
   421  
   422  void
   423  dpcheck(Node *n)
   424  {
   425  	char *s;
   426  	Node *a, *b;
   427  	Tname *l;
   428  	Tprot *tl;
   429  	int i, j;
   430  
   431  	if(n == Z)
   432  		return;
   433  	b = n->left;
   434  	if(b == Z || b->op != ONAME)
   435  		return;
   436  	s = b->sym->name;
   437  	for(l=tname; l; l=l->link)
   438  		if(strcmp(s, l->name) == 0)
   439  			break;
   440  	if(l == 0)
   441  		return;
   442  
   443  	if(l->count > 0) {
   444  		// fetch count, then check remaining length
   445  		i = l->count;
   446  		a = nil;
   447  		b = n->right;
   448  		while(i > 0) {
   449  			b = nextarg(b, &a);
   450  			i--;
   451  		}
   452  		if(a == Z) {
   453  			diag(n, "can't find count arg");
   454  			return;
   455  		}
   456  		if(a->op != OCONST || !typechl[a->type->etype]) {
   457  			diag(n, "count is invalid constant");
   458  			return;
   459  		}
   460  		j = a->vconst;
   461  		i = 0;
   462  		while(b != Z) {
   463  			b = nextarg(b, &a);
   464  			i++;
   465  		}
   466  		if(i != j)
   467  			diag(n, "found %d argument%s after count %d", i, i == 1 ? "" : "s", j);
   468  	}
   469  
   470  	if(l->prot != nil) {
   471  		// check that all arguments after param or count
   472  		// are listed in type list.
   473  		i = l->count;
   474  		if(i == 0)
   475  			i = l->param;
   476  		if(i == 0)
   477  			return;
   478  		a = nil;
   479  		b = n->right;
   480  		while(i > 0) {
   481  			b = nextarg(b, &a);
   482  			i--;
   483  		}
   484  		if(a == Z) {
   485  			diag(n, "can't find count/param arg");
   486  			return;
   487  		}
   488  		while(b != Z) {
   489  			b = nextarg(b, &a);
   490  			for(tl=l->prot; tl; tl=tl->link)
   491  				if(sametype(a->type, tl->type))
   492  					break;
   493  			if(tl == nil)
   494  				diag(a, "invalid type %T in call to %s", a->type, s);
   495  		}
   496  	}
   497  
   498  	if(l->param <= 0)
   499  		return;
   500  	i = l->param;
   501  	a = nil;
   502  	b = n->right;
   503  	while(i > 0) {
   504  		b = nextarg(b, &a);
   505  		i--;
   506  	}
   507  	if(a == Z) {
   508  		diag(n, "can't find format arg");
   509  		return;
   510  	}
   511  	if(!sametype(indchar, a->type)) {
   512  		diag(n, "format arg type %T", a->type);
   513  		return;
   514  	}
   515  	if(a->op != OADDR || a->left->op != ONAME || a->left->sym != symstring) {
   516  /*		warn(n, "format arg not constant string");*/
   517  		return;
   518  	}
   519  	s = a->left->cstring;
   520  	checkargs(b, s, l->param);
   521  }
   522  
   523  void
   524  pragpack(void)
   525  {
   526  	Sym *s;
   527  
   528  	packflg = 0;
   529  	s = getsym();
   530  	if(s) {
   531  		packflg = atoi(s->name+1);
   532  		if(strcmp(s->name, "on") == 0 ||
   533  		   strcmp(s->name, "yes") == 0)
   534  			packflg = 1;
   535  	}
   536  	while(getnsc() != '\n')
   537  		;
   538  	if(debug['f'])
   539  		if(packflg)
   540  			print("%4d: pack %d\n", lineno, packflg);
   541  		else
   542  			print("%4d: pack off\n", lineno);
   543  }
   544  
   545  void
   546  pragfpround(void)
   547  {
   548  	Sym *s;
   549  
   550  	fproundflg = 0;
   551  	s = getsym();
   552  	if(s) {
   553  		fproundflg = atoi(s->name+1);
   554  		if(strcmp(s->name, "on") == 0 ||
   555  		   strcmp(s->name, "yes") == 0)
   556  			fproundflg = 1;
   557  	}
   558  	while(getnsc() != '\n')
   559  		;
   560  	if(debug['f'])
   561  		if(fproundflg)
   562  			print("%4d: fproundflg %d\n", lineno, fproundflg);
   563  		else
   564  			print("%4d: fproundflg off\n", lineno);
   565  }
   566  
   567  void
   568  pragtextflag(void)
   569  {
   570  	Sym *s;
   571  
   572  	s = getsym();
   573  	if(s == S) {
   574  		textflag = getnsn();
   575  	} else {
   576  		if(s->macro) {
   577  			macexpand(s, symb);
   578  		}
   579  		if(symb[0] < '0' || symb[0] > '9')
   580  			yyerror("pragma textflag not an integer");
   581  		textflag = atoi(symb);
   582  	}
   583  	while(getnsc() != '\n')
   584  		;
   585  	if(debug['f'])
   586  		print("%4d: textflag %d\n", lineno, textflag);
   587  }
   588  
   589  void
   590  pragdataflag(void)
   591  {
   592  	Sym *s;
   593  
   594  	s = getsym();
   595  	if(s == S) {
   596  		dataflag = getnsn();
   597  	} else {
   598  		if(s->macro) {
   599  			macexpand(s, symb);
   600  		}
   601  		if(symb[0] < '0' || symb[0] > '9')
   602  			yyerror("pragma dataflag not an integer");
   603  		dataflag = atoi(symb);
   604  	}
   605  	while(getnsc() != '\n')
   606  		;
   607  	if(debug['f'])
   608  		print("%4d: dataflag %d\n", lineno, dataflag);
   609  }
   610  
   611  void
   612  pragincomplete(void)
   613  {
   614  	Sym *s;
   615  	Type *t;
   616  	int istag, w, et;
   617  
   618  	istag = 0;
   619  	s = getsym();
   620  	if(s == nil)
   621  		goto out;
   622  	et = 0;
   623  	w = s->lexical;
   624  	if(w == LSTRUCT)
   625  		et = TSTRUCT;
   626  	else if(w == LUNION)
   627  		et = TUNION;
   628  	if(et != 0){
   629  		s = getsym();
   630  		if(s == nil){
   631  			yyerror("missing struct/union tag in pragma incomplete");
   632  			goto out;
   633  		}
   634  		if(s->lexical != LNAME && s->lexical != LTYPE){
   635  			yyerror("invalid struct/union tag: %s", s->name);
   636  			goto out;
   637  		}
   638  		dotag(s, et, 0);
   639  		istag = 1;
   640  	}else if(strcmp(s->name, "_off_") == 0){
   641  		debug['T'] = 0;
   642  		goto out;
   643  	}else if(strcmp(s->name, "_on_") == 0){
   644  		debug['T'] = 1;
   645  		goto out;
   646  	}
   647  	t = s->type;
   648  	if(istag)
   649  		t = s->suetag;
   650  	if(t == T)
   651  		yyerror("unknown type %s in pragma incomplete", s->name);
   652  	else if(!typesu[t->etype])
   653  		yyerror("not struct/union type in pragma incomplete: %s", s->name);
   654  	else
   655  		t->garb |= GINCOMPLETE;
   656  out:
   657  	while(getnsc() != '\n')
   658  		;
   659  	if(debug['f'])
   660  		print("%s incomplete\n", s->name);
   661  }
   662  
   663  Sym*
   664  getimpsym(void)
   665  {
   666  	int c;
   667  	char *cp;
   668  
   669  	c = getnsc();
   670  	if(isspace(c) || c == '"') {
   671  		unget(c);
   672  		return S;
   673  	}
   674  	for(cp = symb;;) {
   675  		if(cp <= symb+NSYMB-4)
   676  			*cp++ = c;
   677  		c = getc();
   678  		if(c > 0 && !isspace(c) && c != '"')
   679  			continue;
   680  		unget(c);
   681  		break;
   682  	}
   683  	*cp = 0;
   684  	if(cp > symb+NSYMB-4)
   685  		yyerror("symbol too large: %s", symb);
   686  	return lookup();
   687  }
   688  
   689  static int
   690  more(void)
   691  {
   692  	int c;
   693  	
   694  	do
   695  		c = getnsc();
   696  	while(c == ' ' || c == '\t');
   697  	unget(c);
   698  	return c != '\n';
   699  }
   700  
   701  void
   702  pragcgo(char *verb)
   703  {
   704  	Sym *local, *remote;
   705  	char *p;
   706  
   707  	if(strcmp(verb, "cgo_dynamic_linker") == 0 || strcmp(verb, "dynlinker") == 0) {
   708  		p = getquoted();
   709  		if(p == nil)
   710  			goto err1;
   711  		fmtprint(&pragcgobuf, "cgo_dynamic_linker %q\n", p);
   712  		goto out;
   713  	
   714  	err1:
   715  		yyerror("usage: #pragma cgo_dynamic_linker \"path\"");
   716  		goto out;
   717  	}	
   718  	
   719  	if(strcmp(verb, "dynexport") == 0)
   720  		verb = "cgo_export_dynamic";
   721  	if(strcmp(verb, "cgo_export_static") == 0 || strcmp(verb, "cgo_export_dynamic") == 0) {
   722  		local = getimpsym();
   723  		if(local == nil)
   724  			goto err2;
   725  		if(!more()) {
   726  			fmtprint(&pragcgobuf, "%s %q\n", verb, local->name);
   727  			goto out;
   728  		}
   729  		remote = getimpsym();
   730  		if(remote == nil)
   731  			goto err2;
   732  		fmtprint(&pragcgobuf, "%s %q %q\n", verb, local->name, remote->name);
   733  		goto out;
   734  	
   735  	err2:
   736  		yyerror("usage: #pragma %s local [remote]", verb);
   737  		goto out;
   738  	}
   739  	
   740  	if(strcmp(verb, "cgo_import_dynamic") == 0 || strcmp(verb, "dynimport") == 0) {
   741  		local = getimpsym();
   742  		if(local == nil)
   743  			goto err3;
   744  		if(!more()) {
   745  			fmtprint(&pragcgobuf, "cgo_import_dynamic %q\n", local->name);
   746  			goto out;
   747  		}
   748  		remote = getimpsym();
   749  		if(remote == nil)
   750  			goto err3;
   751  		if(!more()) {
   752  			fmtprint(&pragcgobuf, "cgo_import_dynamic %q %q\n", local->name, remote->name);
   753  			goto out;
   754  		}
   755  		p = getquoted();
   756  		if(p == nil)	
   757  			goto err3;
   758  		fmtprint(&pragcgobuf, "cgo_import_dynamic %q %q %q\n", local->name, remote->name, p);
   759  		goto out;
   760  	
   761  	err3:
   762  		yyerror("usage: #pragma cgo_import_dynamic local [remote [\"library\"]]");
   763  		goto out;
   764  	}
   765  	
   766  	if(strcmp(verb, "cgo_import_static") == 0) {
   767  		local = getimpsym();
   768  		if(local == nil)
   769  			goto err4;
   770  		fmtprint(&pragcgobuf, "cgo_import_static %q\n", local->name);
   771  		goto out;
   772  
   773  	err4:
   774  		yyerror("usage: #pragma cgo_import_static local [remote]");
   775  		goto out;
   776  	}
   777  	
   778  	if(strcmp(verb, "cgo_ldflag") == 0) {
   779  		p = getquoted();
   780  		if(p == nil)
   781  			goto err5;
   782  		fmtprint(&pragcgobuf, "cgo_ldflag %q\n", p);
   783  		goto out;
   784  
   785  	err5:
   786  		yyerror("usage: #pragma cgo_ldflag \"arg\"");
   787  		goto out;
   788  	}
   789  	
   790  out:
   791  	while(getnsc() != '\n')
   792  		;
   793  }