OBJ_PROCESS_STAB (seg, what, string + stroff, type, other, desc);
OBJ_PROCESS_STAB (seg, what, string, type, other, desc);
s_stab_generic (what, stab_secname, stabstr_secname)     int what;     char *stab_secname;     char *stabstr_secname;{  long longint;  char *string;  int type;  int other;  int desc;  /* The general format is:     .stabs "STRING",TYPE,OTHER,DESC,VALUE     .stabn TYPE,OTHER,DESC,VALUE     .stabd TYPE,OTHER,DESC     At this point input_line_pointer points after the pseudo-op and     any trailing whitespace.  The argument what is one of 's', 'n' or     'd' indicating which type of .stab this is.  */  if (what != 's')    string = "";  else    {      int length;      string = demand_copy_C_string (&length);      SKIP_WHITESPACE ();      if (*input_line_pointer == ',')	input_line_pointer++;      else	{	  as_warn (".stabs: Missing comma");	  ignore_rest_of_line ();	  return;	}    }  if (get_absolute_expression_and_terminator (&longint) != ',')    {      as_warn (".stab%c: Missing comma", what);      ignore_rest_of_line ();      return;    }  type = longint;  if (get_absolute_expression_and_terminator (&longint) != ',')    {      as_warn (".stab%c: Missing comma", what);      ignore_rest_of_line ();      return;    }  other = longint;  desc = get_absolute_expression ();  if (what == 's' || what == 'n')    {      if (*input_line_pointer != ',')	{	  as_warn (".stab%c: Missing comma", what);	  ignore_rest_of_line ();	  return;	}      input_line_pointer++;      SKIP_WHITESPACE ();    }  /* We have now gathered the type, other, and desc information.  For     .stabs or .stabn, input_line_pointer is now pointing at the     value.  */  if (SEPARATE_STAB_SECTIONS)    /* Output the stab information in a separate section.  This is used       at least for COFF and ELF.  */    {      segT saved_seg = now_seg;      subsegT saved_subseg = now_subseg;      fragS *saved_frag = frag_now;      valueT dot;      segT seg;      unsigned int stroff;      char *p;      static segT cached_sec;      static char *cached_secname;      dot = frag_now_fix ();      if (cached_secname && !strcmp (cached_secname, stab_secname))	{	  seg = cached_sec;	  subseg_set (seg, 0);	}      else	{	  seg = subseg_new (stab_secname, 0);	  if (cached_secname)	    free (cached_secname);	  cached_secname = strdup (stab_secname);	  if (cached_secname)	    cached_sec = seg;	}      if (! seg_info (seg)->hadone)	{#ifdef BFD_ASSEMBLER	  bfd_set_section_flags (stdoutput, seg,				 SEC_READONLY | SEC_RELOC | SEC_DEBUGGING);#endif#ifdef INIT_STAB_SECTION	  INIT_STAB_SECTION (seg);#endif	  seg_info (seg)->hadone = 1;	}      stroff = get_stab_string_offset (string, stabstr_secname);      /* At least for now, stabs in a special stab section are always	 output as 12 byte blocks of information.  */      p = frag_more (8);      md_number_to_chars (p, (valueT) stroff, 4);      md_number_to_chars (p + 4, (valueT) type, 1);      md_number_to_chars (p + 5, (valueT) other, 1);      md_number_to_chars (p + 6, (valueT) desc, 2);      if (what == 's' || what == 'n')	{	  /* Pick up the value from the input line.  */	  cons (4);	  input_line_pointer--;	}      else	{	  const char *fake;	  symbolS *symbol;	  expressionS exp;	  /* Arrange for a value representing the current location.  */	  fake = FAKE_LABEL_NAME;	  symbol = symbol_new (fake, saved_seg, dot, saved_frag);	  exp.X_op = O_symbol;	  exp.X_add_symbol = symbol;	  exp.X_add_number = 0;	  emit_expr (&exp, 4);	}#ifdef OBJ_PROCESS_STAB      OBJ_PROCESS_STAB (seg, what, string + stroff, type, other, desc);#endif      subseg_set (saved_seg, saved_subseg);    }  else    {#ifdef OBJ_PROCESS_STAB      OBJ_PROCESS_STAB (0, what, string, type, other, desc);#else      abort ();#endif    }#ifndef NO_LISTING  if (listing)    {      switch (type)	{	case N_SLINE:	  listing_source_line ((unsigned int) desc);	  break;	case N_SO:	case N_SOL:	  listing_source_file (string);	  break;	}    }#endif /* ! NO_LISTING */  demand_empty_rest_of_line ();}