home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / binutils-2.7-src.tgz / tar.out / fsf / binutils / gas / cond.c < prev    next >
C/C++ Source or Header  |  1996-09-28  |  9KB  |  365 lines

  1. /* cond.c - conditional assembly pseudo-ops, and .include
  2.    Copyright (C) 1990, 91, 92, 93, 95, 1996 Free Software Foundation, Inc.
  3.  
  4.    This file is part of GAS, the GNU Assembler.
  5.  
  6.    GAS is free software; you can redistribute it and/or modify
  7.    it under the terms of the GNU General Public License as published by
  8.    the Free Software Foundation; either version 2, or (at your option)
  9.    any later version.
  10.  
  11.    GAS is distributed in the hope that it will be useful,
  12.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.    GNU General Public License for more details.
  15.  
  16.    You should have received a copy of the GNU General Public License
  17.    along with GAS; see the file COPYING.  If not, write to
  18.    the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
  19.  
  20. #include "as.h"
  21.  
  22. #include "obstack.h"
  23.  
  24. /* This is allocated to grow and shrink as .ifdef/.endif pairs are scanned. */
  25. struct obstack cond_obstack;
  26.  
  27. struct file_line
  28. {
  29.   char *file;
  30.   unsigned int line;
  31. };                /* file_line */
  32.  
  33. /* This is what we push and pop. */
  34. struct conditional_frame
  35.   {
  36.     struct file_line if_file_line;    /* the source file & line number of the "if" */
  37.     struct file_line else_file_line;    /* the source file & line of the "else" */
  38.     struct conditional_frame *previous_cframe;
  39.     int else_seen;        /* have we seen an else yet? */
  40.     int ignoring;        /* if we are currently ignoring input. */
  41.     int dead_tree;        /* if a conditional at a higher level is ignoring input. */
  42.   };                /* conditional_frame */
  43.  
  44. static void initialize_cframe PARAMS ((struct conditional_frame *cframe));
  45. static char *get_mri_string PARAMS ((int, int *));
  46.  
  47. static struct conditional_frame *current_cframe = NULL;
  48.  
  49. void 
  50. s_ifdef (arg)
  51.      int arg;
  52. {
  53.   register char *name;        /* points to name of symbol */
  54.   register struct symbol *symbolP;    /* Points to symbol */
  55.   struct conditional_frame cframe;
  56.  
  57.   SKIP_WHITESPACE ();        /* Leading whitespace is part of operand. */
  58.   name = input_line_pointer;
  59.  
  60.   if (!is_name_beginner (*name))
  61.     {
  62.       as_bad ("invalid identifier for \".ifdef\"");
  63.       obstack_1grow (&cond_obstack, 0);
  64.       ignore_rest_of_line ();
  65.     }
  66.   else
  67.     {
  68.       char c;
  69.  
  70.       c = get_symbol_end ();
  71.       symbolP = symbol_find (name);
  72.       *input_line_pointer = c;
  73.  
  74.       initialize_cframe (&cframe);
  75.       cframe.ignoring = cframe.dead_tree || !((symbolP != 0) ^ arg);
  76.       current_cframe = ((struct conditional_frame *)
  77.             obstack_copy (&cond_obstack, &cframe,
  78.                       sizeof (cframe)));
  79.       demand_empty_rest_of_line ();
  80.     }                /* if a valid identifyer name */
  81. }                /* s_ifdef() */
  82.  
  83. void 
  84. s_if (arg)
  85.      int arg;
  86. {
  87.   expressionS operand;
  88.   struct conditional_frame cframe;
  89.   int t;
  90.   char *stop = NULL;
  91.   char stopc;
  92.  
  93.   if (flag_mri)
  94.     stop = mri_comment_field (&stopc);
  95.  
  96.   SKIP_WHITESPACE ();        /* Leading whitespace is part of operand. */
  97.  
  98.   if (current_cframe != NULL && current_cframe->ignoring)
  99.     {
  100.       operand.X_add_number = 0;
  101.       while (! is_end_of_line[(unsigned char) *input_line_pointer])
  102.     ++input_line_pointer;
  103.     }
  104.   else
  105.     {
  106.       expression (&operand);
  107.       if (operand.X_op != O_constant)
  108.     as_bad ("non-constant expression in \".if\" statement");
  109.     }
  110.  
  111.   switch ((operatorT) arg)
  112.     {
  113.     case O_eq: t = operand.X_add_number == 0; break;
  114.     case O_ne: t = operand.X_add_number != 0; break;
  115.     case O_lt: t = operand.X_add_number < 0; break;
  116.     case O_le: t = operand.X_add_number <= 0; break;
  117.     case O_ge: t = operand.X_add_number >= 0; break;
  118.     case O_gt: t = operand.X_add_number > 0; break;
  119.     default:
  120.       abort ();
  121.     }
  122.  
  123.   /* If the above error is signaled, this will dispatch
  124.      using an undefined result.  No big deal.  */
  125.   initialize_cframe (&cframe);
  126.   cframe.ignoring = cframe.dead_tree || ! t;
  127.   current_cframe = ((struct conditional_frame *)
  128.             obstack_copy (&cond_obstack, &cframe, sizeof (cframe)));
  129.  
  130.   if (flag_mri)
  131.     mri_comment_end (stop, stopc);
  132.  
  133.   demand_empty_rest_of_line ();
  134. }                /* s_if() */
  135.  
  136. /* Get a string for the MRI IFC or IFNC pseudo-ops.  */
  137.  
  138. static char *
  139. get_mri_string (terminator, len)
  140.      int terminator;
  141.      int *len;
  142. {
  143.   char *ret;
  144.   char *s;
  145.  
  146.   SKIP_WHITESPACE ();
  147.   s = ret = input_line_pointer;
  148.   if (*input_line_pointer == '\'')
  149.     {
  150.       ++s;
  151.       ++input_line_pointer;
  152.       while (! is_end_of_line[(unsigned char) *input_line_pointer])
  153.     {
  154.       *s++ = *input_line_pointer++;
  155.       if (s[-1] == '\'')
  156.         {
  157.           if (*input_line_pointer != '\'')
  158.         break;
  159.           ++input_line_pointer;
  160.         }
  161.     }
  162.       SKIP_WHITESPACE ();
  163.     }
  164.   else
  165.     {
  166.       while (*input_line_pointer != terminator
  167.          && ! is_end_of_line[(unsigned char) *input_line_pointer])
  168.     ++input_line_pointer;
  169.       s = input_line_pointer;
  170.       while (s > ret && (s[-1] == ' ' || s[-1] == '\t'))
  171.     --s;
  172.     }
  173.  
  174.   *len = s - ret;
  175.   return ret;
  176. }
  177.  
  178. /* The MRI IFC and IFNC pseudo-ops.  */
  179.  
  180. void
  181. s_ifc (arg)
  182.      int arg;
  183. {
  184.   char *s1, *s2;
  185.   int len1, len2;
  186.   int res;
  187.   struct conditional_frame cframe;
  188.  
  189.   s1 = get_mri_string (',', &len1);
  190.  
  191.   if (*input_line_pointer != ',')
  192.     as_bad ("bad format for ifc or ifnc");
  193.   else
  194.     ++input_line_pointer;
  195.  
  196.   s2 = get_mri_string (';', &len2);
  197.  
  198.   res = len1 == len2 && strncmp (s1, s2, len1) == 0;
  199.  
  200.   initialize_cframe (&cframe);
  201.   cframe.ignoring = cframe.dead_tree || ! (res ^ arg);
  202.   current_cframe = ((struct conditional_frame *)
  203.             obstack_copy (&cond_obstack, &cframe, sizeof (cframe)));
  204. }
  205.  
  206. void 
  207. s_endif (arg)
  208.      int arg;
  209. {
  210.   struct conditional_frame *hold;
  211.  
  212.   if (current_cframe == NULL)
  213.     {
  214.       as_bad ("\".endif\" without \".if\"");
  215.     }
  216.   else
  217.     {
  218.       hold = current_cframe;
  219.       current_cframe = current_cframe->previous_cframe;
  220.       obstack_free (&cond_obstack, hold);
  221.     }                /* if one pop too many */
  222.  
  223.   if (flag_mri)
  224.     {
  225.       while (! is_end_of_line[(unsigned char) *input_line_pointer])
  226.     ++input_line_pointer;
  227.     }
  228.  
  229.   demand_empty_rest_of_line ();
  230. }                /* s_endif() */
  231.  
  232. void 
  233. s_else (arg)
  234.      int arg;
  235. {
  236.   if (current_cframe == NULL)
  237.     {
  238.       as_bad (".else without matching .if - ignored");
  239.  
  240.     }
  241.   else if (current_cframe->else_seen)
  242.     {
  243.       as_bad ("duplicate \"else\" - ignored");
  244.       as_bad_where (current_cframe->else_file_line.file,
  245.             current_cframe->else_file_line.line,
  246.             "here is the previous \"else\"");
  247.       as_bad_where (current_cframe->if_file_line.file,
  248.             current_cframe->if_file_line.line,
  249.             "here is the previous \"if\"");
  250.     }
  251.   else
  252.     {
  253.       as_where (¤t_cframe->else_file_line.file,
  254.         ¤t_cframe->else_file_line.line);
  255.  
  256.       if (!current_cframe->dead_tree)
  257.     {
  258.       current_cframe->ignoring = !current_cframe->ignoring;
  259.     }            /* if not a dead tree */
  260.  
  261.       current_cframe->else_seen = 1;
  262.     }                /* if error else do it */
  263.  
  264.   if (flag_mri)
  265.     {
  266.       while (! is_end_of_line[(unsigned char) *input_line_pointer])
  267.     ++input_line_pointer;
  268.     }
  269.  
  270.   demand_empty_rest_of_line ();
  271. }                /* s_else() */
  272.  
  273. void 
  274. s_ifeqs (arg)
  275.      int arg;
  276. {
  277.   char *s1, *s2;
  278.   int len1, len2;
  279.   int res;
  280.   struct conditional_frame cframe;
  281.  
  282.   s1 = demand_copy_C_string (&len1);
  283.  
  284.   SKIP_WHITESPACE ();
  285.   if (*input_line_pointer != ',')
  286.     {
  287.       as_bad (".ifeqs syntax error");
  288.       ignore_rest_of_line ();
  289.       return;
  290.     }
  291.  
  292.   ++input_line_pointer;
  293.  
  294.   s2 = demand_copy_C_string (&len2);
  295.  
  296.   res = len1 == len2 && strncmp (s1, s2, len1) == 0;
  297.  
  298.   initialize_cframe (&cframe);
  299.   cframe.ignoring = cframe.dead_tree || ! (res ^ arg);
  300.   current_cframe = ((struct conditional_frame *)
  301.             obstack_copy (&cond_obstack, &cframe, sizeof (cframe)));
  302.  
  303.   demand_empty_rest_of_line ();
  304. }                /* s_ifeqs() */
  305.  
  306. int 
  307. ignore_input ()
  308. {
  309.   char *s;
  310.  
  311.   s = input_line_pointer;
  312.  
  313.   if (flag_m68k_mri
  314. #ifdef NO_PSEUDO_DOT
  315.       || 1
  316. #endif
  317.       )
  318.     {
  319.       if (s[-1] != '.')
  320.     --s;
  321.     }
  322.   else
  323.     {
  324.       if (s[-1] != '.')
  325.     return (current_cframe != NULL) && (current_cframe->ignoring);
  326.     }
  327.  
  328.   /* We cannot ignore certain pseudo ops.  */
  329.   if (((s[0] == 'i'
  330.     || s[0] == 'I')
  331.        && (!strncasecmp (s, "if", 2)
  332.        || !strncasecmp (s, "ifdef", 5)
  333.        || !strncasecmp (s, "ifndef", 6)))
  334.       || ((s[0] == 'e'
  335.        || s[0] == 'E')
  336.       && (!strncasecmp (s, "else", 4)
  337.           || !strncasecmp (s, "endif", 5)
  338.           || !strncasecmp (s, "endc", 4))))
  339.     return 0;
  340.  
  341.   return (current_cframe != NULL) && (current_cframe->ignoring);
  342. }                /* ignore_input() */
  343.  
  344. static void 
  345. initialize_cframe (cframe)
  346.      struct conditional_frame *cframe;
  347. {
  348.   memset (cframe, 0, sizeof (*cframe));
  349.   as_where (&cframe->if_file_line.file,
  350.         &cframe->if_file_line.line);
  351.   cframe->previous_cframe = current_cframe;
  352.   cframe->dead_tree = current_cframe != NULL && current_cframe->ignoring;
  353.  
  354.   return;
  355. }                /* initialize_cframe() */
  356.  
  357. /*
  358.  * Local Variables:
  359.  * fill-column: 131
  360.  * comment-column: 0
  361.  * End:
  362.  */
  363.  
  364. /* end of cond.c */
  365.