Rev 5222 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 5222 | Rev 6324 | ||
---|---|---|---|
Line 1... | Line 1... | ||
1 | /* expr.c -operands, expressions- |
1 | /* expr.c -operands, expressions- |
2 | Copyright 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, |
- | |
3 | 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2009, 2010, 2011, |
- | |
4 | 2012 Free Software Foundation, Inc. |
2 | Copyright (C) 1987-2015 Free Software Foundation, Inc. |
Line 5... | Line 3... | ||
5 | 3 | ||
Line 6... | Line 4... | ||
6 | This file is part of GAS, the GNU Assembler. |
4 | This file is part of GAS, the GNU Assembler. |
7 | 5 | ||
Line 27... | Line 25... | ||
27 | 25 | ||
Line 28... | Line 26... | ||
28 | #define min(a, b) ((a) < (b) ? (a) : (b)) |
26 | #define min(a, b) ((a) < (b) ? (a) : (b)) |
29 | 27 | ||
30 | #include "as.h" |
- | |
Line 31... | Line 28... | ||
31 | #include "safe-ctype.h" |
28 | #include "as.h" |
32 | #include "obstack.h" |
29 | #include "safe-ctype.h" |
33 | 30 | ||
34 | #ifdef HAVE_LIMITS_H |
31 | #ifdef HAVE_LIMITS_H |
Line 125... | Line 122... | ||
125 | the symbol. */ |
122 | the symbol. */ |
Line 126... | Line 123... | ||
126 | 123 | ||
127 | int |
124 | int |
128 | expr_symbol_where (symbolS *sym, char **pfile, unsigned int *pline) |
125 | expr_symbol_where (symbolS *sym, char **pfile, unsigned int *pline) |
129 | { |
126 | { |
Line 130... | Line 127... | ||
130 | register struct expr_symbol_line *l; |
127 | struct expr_symbol_line *l; |
131 | 128 | ||
132 | for (l = expr_symbol_lines; l != NULL; l = l->next) |
129 | for (l = expr_symbol_lines; l != NULL; l = l->next) |
133 | { |
130 | { |
Line 286... | Line 283... | ||
286 | #define valuesize 64 |
283 | #define valuesize 64 |
287 | #else /* includes non-bfd case, mostly */ |
284 | #else /* includes non-bfd case, mostly */ |
288 | #define valuesize 32 |
285 | #define valuesize 32 |
289 | #endif |
286 | #endif |
Line -... | Line 287... | ||
- | 287 | ||
- | 288 | if (is_end_of_line[(unsigned char) *input_line_pointer]) |
|
- | 289 | { |
|
- | 290 | expressionP->X_op = O_absent; |
|
- | 291 | return; |
|
- | 292 | } |
|
290 | 293 | ||
291 | if ((NUMBERS_WITH_SUFFIX || flag_m68k_mri) && radix == 0) |
294 | if ((NUMBERS_WITH_SUFFIX || flag_m68k_mri) && radix == 0) |
292 | { |
295 | { |
Line 293... | Line 296... | ||
293 | int flt = 0; |
296 | int flt = 0; |
Line 833... | Line 836... | ||
833 | input_line_pointer++; |
836 | input_line_pointer++; |
834 | integer_constant (16, expressionP); |
837 | integer_constant (16, expressionP); |
835 | break; |
838 | break; |
Line 836... | Line 839... | ||
836 | 839 | ||
837 | case 'b': |
840 | case 'b': |
838 | if (LOCAL_LABELS_FB && ! (flag_m68k_mri || NUMBERS_WITH_SUFFIX)) |
- | |
839 | { |
- | |
840 | /* This code used to check for '+' and '-' here, and, in |
- | |
841 | some conditions, fall through to call |
- | |
842 | integer_constant. However, that didn't make sense, |
- | |
843 | as integer_constant only accepts digits. */ |
- | |
844 | /* Some of our code elsewhere does permit digits greater |
- | |
845 | than the expected base; for consistency, do the same |
- | |
846 | here. */ |
841 | if (LOCAL_LABELS_FB && !flag_m68k_mri |
847 | if (input_line_pointer[1] < '0' |
842 | && input_line_pointer[1] != '0' |
848 | || input_line_pointer[1] > '9') |
843 | && input_line_pointer[1] != '1') |
849 | { |
844 | { |
850 | /* Parse this as a back reference to label 0. */ |
845 | /* Parse this as a back reference to label 0. */ |
851 | input_line_pointer--; |
846 | input_line_pointer--; |
852 | integer_constant (10, expressionP); |
847 | integer_constant (10, expressionP); |
853 | break; |
848 | break; |
854 | } |
849 | } |
855 | /* Otherwise, parse this as a binary number. */ |
- | |
856 | } |
850 | /* Otherwise, parse this as a binary number. */ |
857 | /* Fall through. */ |
851 | /* Fall through. */ |
- | 852 | case 'B': |
|
- | 853 | if (input_line_pointer[1] == '0' |
|
- | 854 | || input_line_pointer[1] == '1') |
|
858 | case 'B': |
855 | { |
859 | input_line_pointer++; |
- | |
860 | if (flag_m68k_mri || NUMBERS_WITH_SUFFIX) |
- | |
861 | goto default_case; |
856 | input_line_pointer++; |
862 | integer_constant (2, expressionP); |
857 | integer_constant (2, expressionP); |
- | 858 | break; |
|
- | 859 | } |
|
- | 860 | if (flag_m68k_mri || NUMBERS_WITH_SUFFIX) |
|
- | 861 | input_line_pointer++; |
|
Line 863... | Line 862... | ||
863 | break; |
862 | goto default_case; |
864 | 863 | ||
865 | case '0': |
864 | case '0': |
866 | case '1': |
865 | case '1': |
Line 876... | Line 875... | ||
876 | break; |
875 | break; |
Line 877... | Line 876... | ||
877 | 876 | ||
878 | case 'f': |
877 | case 'f': |
879 | if (LOCAL_LABELS_FB) |
878 | if (LOCAL_LABELS_FB) |
- | 879 | { |
|
- | 880 | int is_label = 1; |
|
880 | { |
881 | |
881 | /* If it says "0f" and it could possibly be a floating point |
882 | /* If it says "0f" and it could possibly be a floating point |
882 | number, make it one. Otherwise, make it a local label, |
883 | number, make it one. Otherwise, make it a local label, |
883 | and try to deal with parsing the rest later. */ |
- | |
884 | if (!input_line_pointer[1] |
884 | and try to deal with parsing the rest later. */ |
885 | || (is_end_of_line[0xff & input_line_pointer[1]]) |
885 | if (!is_end_of_line[(unsigned char) input_line_pointer[1]] |
886 | || strchr (FLT_CHARS, 'f') == NULL) |
- | |
887 | goto is_0f_label; |
886 | && strchr (FLT_CHARS, 'f') != NULL) |
888 | { |
887 | { |
- | 888 | char *cp = input_line_pointer + 1; |
|
889 | char *cp = input_line_pointer + 1; |
889 | |
890 | int r = atof_generic (&cp, ".", EXP_CHARS, |
890 | atof_generic (&cp, ".", EXP_CHARS, |
891 | &generic_floating_point_number); |
- | |
892 | switch (r) |
- | |
893 | { |
- | |
894 | case 0: |
- | |
895 | case ERROR_EXPONENT_OVERFLOW: |
- | |
896 | if (*cp == 'f' || *cp == 'b') |
- | |
897 | /* Looks like a difference expression. */ |
- | |
898 | goto is_0f_label; |
- | |
899 | else if (cp == input_line_pointer + 1) |
- | |
900 | /* No characters has been accepted -- looks like |
- | |
901 | end of operand. */ |
- | |
902 | goto is_0f_label; |
- | |
903 | else |
- | |
904 | goto is_0f_float; |
- | |
905 | default: |
- | |
906 | as_fatal (_("expr.c(operand): bad atof_generic return val %d"), |
- | |
907 | r); |
- | |
908 | } |
- | |
Line 909... | Line 891... | ||
909 | } |
891 | &generic_floating_point_number); |
- | 892 | ||
910 | 893 | /* Was nothing parsed, or does it look like an |
|
- | 894 | expression? */ |
|
- | 895 | is_label = (cp == input_line_pointer + 1 |
|
911 | /* Okay, now we've sorted it out. We resume at one of these |
896 | || (cp == input_line_pointer + 2 |
- | 897 | && (cp[-1] == '-' || cp[-1] == '+')) |
|
- | 898 | || *cp == 'f' |
|
912 | two labels, depending on what we've decided we're probably |
899 | || *cp == 'b'); |
- | 900 | } |
|
913 | looking at. */ |
901 | if (is_label) |
914 | is_0f_label: |
902 | { |
915 | input_line_pointer--; |
903 | input_line_pointer--; |
916 | integer_constant (10, expressionP); |
- | |
917 | break; |
- | |
918 | - | ||
919 | is_0f_float: |
- | |
920 | /* Fall through. */ |
904 | integer_constant (10, expressionP); |
- | 905 | break; |
|
- | 906 | } |
|
Line 921... | Line 907... | ||
921 | ; |
907 | } |
922 | } |
908 | /* Fall through. */ |
923 | 909 | ||
924 | case 'd': |
910 | case 'd': |
Line 1022... | Line 1008... | ||
1022 | if (expressionP->X_op == O_constant) |
1008 | if (expressionP->X_op == O_constant) |
1023 | { |
1009 | { |
1024 | /* input_line_pointer -> char after operand. */ |
1010 | /* input_line_pointer -> char after operand. */ |
1025 | if (c == '-') |
1011 | if (c == '-') |
1026 | { |
1012 | { |
- | 1013 | expressionP->X_add_number |
|
1027 | expressionP->X_add_number = - expressionP->X_add_number; |
1014 | = - (addressT) expressionP->X_add_number; |
1028 | /* Notice: '-' may overflow: no warning is given. |
1015 | /* Notice: '-' may overflow: no warning is given. |
1029 | This is compatible with other people's |
1016 | This is compatible with other people's |
1030 | assemblers. Sigh. */ |
1017 | assemblers. Sigh. */ |
1031 | expressionP->X_unsigned = 0; |
1018 | expressionP->X_unsigned = 0; |
1032 | if (expressionP->X_add_number) |
1019 | if (expressionP->X_add_number) |
Line 1153... | Line 1140... | ||
1153 | { |
1140 | { |
1154 | char *buf; |
1141 | char *buf; |
Line 1155... | Line 1142... | ||
1155 | 1142 | ||
1156 | ++input_line_pointer; |
1143 | ++input_line_pointer; |
1157 | SKIP_WHITESPACE (); |
- | |
1158 | name = input_line_pointer; |
1144 | SKIP_WHITESPACE (); |
Line 1159... | Line 1145... | ||
1159 | c = get_symbol_end (); |
1145 | c = get_symbol_name (& name); |
1160 | 1146 | ||
1161 | buf = (char *) xmalloc (strlen (name) + 10); |
1147 | buf = (char *) xmalloc (strlen (name) + 10); |
1162 | if (start) |
1148 | if (start) |
Line 1169... | Line 1155... | ||
1169 | expressionP->X_op = O_symbol; |
1155 | expressionP->X_op = O_symbol; |
1170 | expressionP->X_add_symbol = symbolP; |
1156 | expressionP->X_add_symbol = symbolP; |
1171 | expressionP->X_add_number = 0; |
1157 | expressionP->X_add_number = 0; |
Line 1172... | Line 1158... | ||
1172 | 1158 | ||
1173 | *input_line_pointer = c; |
1159 | *input_line_pointer = c; |
1174 | SKIP_WHITESPACE (); |
1160 | SKIP_WHITESPACE_AFTER_NAME (); |
1175 | if (*input_line_pointer != ')') |
1161 | if (*input_line_pointer != ')') |
1176 | as_bad (_("syntax error in .startof. or .sizeof.")); |
1162 | as_bad (_("syntax error in .startof. or .sizeof.")); |
1177 | else |
1163 | else |
1178 | ++input_line_pointer; |
1164 | ++input_line_pointer; |
Line 1225... | Line 1211... | ||
1225 | 1211 | ||
1226 | default: |
1212 | default: |
1227 | #if defined(md_need_index_operator) || defined(TC_M68K) |
1213 | #if defined(md_need_index_operator) || defined(TC_M68K) |
1228 | de_fault: |
1214 | de_fault: |
1229 | #endif |
1215 | #endif |
1230 | if (is_name_beginner (c)) /* Here if did not begin with a digit. */ |
1216 | if (is_name_beginner (c) || c == '"') /* Here if did not begin with a digit. */ |
1231 | { |
1217 | { |
1232 | /* Identifier begins here. |
1218 | /* Identifier begins here. |
1233 | This is kludged for speed, so code is repeated. */ |
1219 | This is kludged for speed, so code is repeated. */ |
1234 | isname: |
1220 | isname: |
1235 | name = --input_line_pointer; |
1221 | -- input_line_pointer; |
Line 1236... | Line 1222... | ||
1236 | c = get_symbol_end (); |
1222 | c = get_symbol_name (&name); |
1237 | 1223 | ||
1238 | #ifdef md_operator |
1224 | #ifdef md_operator |
Line 1239... | Line 1225... | ||
1239 | { |
1225 | { |
1240 | operatorT op = md_operator (name, 1, &c); |
1226 | operatorT op = md_operator (name, 1, &c); |
1241 | 1227 | ||
1242 | switch (op) |
1228 | switch (op) |
1243 | { |
1229 | { |
1244 | case O_uminus: |
1230 | case O_uminus: |
1245 | *input_line_pointer = c; |
1231 | restore_line_pointer (c); |
1246 | c = '-'; |
1232 | c = '-'; |
1247 | goto unary; |
1233 | goto unary; |
1248 | case O_bit_not: |
1234 | case O_bit_not: |
1249 | *input_line_pointer = c; |
1235 | restore_line_pointer (c); |
1250 | c = '~'; |
1236 | c = '~'; |
1251 | goto unary; |
1237 | goto unary; |
1252 | case O_logical_not: |
1238 | case O_logical_not: |
1253 | *input_line_pointer = c; |
1239 | restore_line_pointer (c); |
1254 | c = '!'; |
1240 | c = '!'; |
1255 | goto unary; |
1241 | goto unary; |
1256 | case O_illegal: |
1242 | case O_illegal: |
1257 | as_bad (_("invalid use of operator \"%s\""), name); |
1243 | as_bad (_("invalid use of operator \"%s\""), name); |
1258 | break; |
1244 | break; |
- | 1245 | default: |
|
1259 | default: |
1246 | break; |
1260 | break; |
1247 | } |
1261 | } |
1248 | |
1262 | if (op != O_absent && op != O_illegal) |
1249 | if (op != O_absent && op != O_illegal) |
1263 | { |
1250 | { |
1264 | *input_line_pointer = c; |
1251 | restore_line_pointer (c); |
1265 | expr (9, expressionP, mode); |
1252 | expr (9, expressionP, mode); |
1266 | expressionP->X_add_symbol = make_expr_symbol (expressionP); |
1253 | expressionP->X_add_symbol = make_expr_symbol (expressionP); |
Line 1277... | Line 1264... | ||
1277 | specially in certain contexts. If a name always has a |
1264 | specially in certain contexts. If a name always has a |
1278 | specific value, it can often be handled by simply |
1265 | specific value, it can often be handled by simply |
1279 | entering it in the symbol table. */ |
1266 | entering it in the symbol table. */ |
1280 | if (md_parse_name (name, expressionP, mode, &c)) |
1267 | if (md_parse_name (name, expressionP, mode, &c)) |
1281 | { |
1268 | { |
1282 | *input_line_pointer = c; |
1269 | restore_line_pointer (c); |
1283 | break; |
1270 | break; |
1284 | } |
1271 | } |
1285 | #endif |
1272 | #endif |
Line 1286... | Line 1273... | ||
1286 | 1273 | ||
Line 1297... | Line 1284... | ||
1297 | 1284 | ||
1298 | start = (name[1] == 't' |
1285 | start = (name[1] == 't' |
Line 1299... | Line 1286... | ||
1299 | || name[1] == 'T'); |
1286 | || name[1] == 'T'); |
1300 | 1287 | ||
Line 1301... | Line -... | ||
1301 | *input_line_pointer = c; |
- | |
1302 | SKIP_WHITESPACE (); |
1288 | *input_line_pointer = c; |
Line 1303... | Line 1289... | ||
1303 | 1289 | SKIP_WHITESPACE_AFTER_NAME (); |
|
1304 | name = input_line_pointer; |
1290 | |
1305 | c = get_symbol_end (); |
1291 | c = get_symbol_name (& name); |
1306 | 1292 | ||
Line 1315... | Line 1301... | ||
1315 | expressionP->X_op = O_symbol; |
1301 | expressionP->X_op = O_symbol; |
1316 | expressionP->X_add_symbol = symbolP; |
1302 | expressionP->X_add_symbol = symbolP; |
1317 | expressionP->X_add_number = 0; |
1303 | expressionP->X_add_number = 0; |
Line 1318... | Line 1304... | ||
1318 | 1304 | ||
1319 | *input_line_pointer = c; |
1305 | *input_line_pointer = c; |
1320 | SKIP_WHITESPACE (); |
- | |
1321 | 1306 | SKIP_WHITESPACE_AFTER_NAME (); |
|
1322 | break; |
1307 | break; |
1323 | } |
1308 | } |
Line 1324... | Line 1309... | ||
1324 | #endif |
1309 | #endif |
Line 1344... | Line 1329... | ||
1344 | { |
1329 | { |
1345 | expressionP->X_op = O_symbol; |
1330 | expressionP->X_op = O_symbol; |
1346 | expressionP->X_add_symbol = symbolP; |
1331 | expressionP->X_add_symbol = symbolP; |
1347 | expressionP->X_add_number = 0; |
1332 | expressionP->X_add_number = 0; |
1348 | } |
1333 | } |
- | 1334 | ||
1349 | *input_line_pointer = c; |
1335 | restore_line_pointer (c); |
1350 | } |
1336 | } |
1351 | else |
1337 | else |
1352 | { |
1338 | { |
1353 | /* Let the target try to parse it. Success is indicated by changing |
1339 | /* Let the target try to parse it. Success is indicated by changing |
1354 | the X_op field to something other than O_absent and pointing |
1340 | the X_op field to something other than O_absent and pointing |
Line 1600... | Line 1586... | ||
1600 | return O_illegal; |
1586 | return O_illegal; |
Line 1601... | Line 1587... | ||
1601 | 1587 | ||
1602 | #ifdef md_operator |
1588 | #ifdef md_operator |
1603 | if (is_name_beginner (c)) |
1589 | if (is_name_beginner (c)) |
1604 | { |
1590 | { |
1605 | char *name = input_line_pointer; |
1591 | char *name; |
Line 1606... | Line 1592... | ||
1606 | char ec = get_symbol_end (); |
1592 | char ec = get_symbol_name (& name); |
1607 | 1593 | ||
1608 | ret = md_operator (name, 2, &ec); |
1594 | ret = md_operator (name, 2, &ec); |
1609 | switch (ret) |
1595 | switch (ret) |
Line 2329... | Line 2315... | ||
2329 | 2315 | ||
2330 | /* This lives here because it belongs equally in expr.c & read.c. |
2316 | /* This lives here because it belongs equally in expr.c & read.c. |
2331 | expr.c is just a branch office read.c anyway, and putting it |
2317 | expr.c is just a branch office read.c anyway, and putting it |
2332 | here lessens the crowd at read.c. |
2318 | here lessens the crowd at read.c. |
Line 2333... | Line 2319... | ||
2333 | 2319 | ||
- | 2320 | Assume input_line_pointer is at start of symbol name, or the |
|
2334 | Assume input_line_pointer is at start of symbol name. |
2321 | start of a double quote enclosed symbol name. |
2335 | Advance input_line_pointer past symbol name. |
2322 | Advance input_line_pointer past symbol name. |
- | 2323 | Turn that character into a '\0', returning its former value, |
|
2336 | Turn that character into a '\0', returning its former value. |
2324 | which may be the closing double quote. |
2337 | This allows a string compare (RMS wants symbol names to be strings) |
2325 | This allows a string compare (RMS wants symbol names to be strings) |
2338 | of the symbol name. |
2326 | of the symbol name. |
2339 | There will always be a char following symbol name, because all good |
2327 | There will always be a char following symbol name, because all good |
Line 2340... | Line 2328... | ||
2340 | lines end in end-of-line. */ |
2328 | lines end in end-of-line. */ |
2341 | 2329 | ||
2342 | char |
2330 | char |
2343 | get_symbol_end (void) |
2331 | get_symbol_name (char ** ilp_return) |
Line -... | Line 2332... | ||
- | 2332 | { |
|
2344 | { |
2333 | char c; |
2345 | char c; |
2334 | |
2346 | 2335 | * ilp_return = input_line_pointer; |
|
2347 | /* We accept \001 in a name in case this is being called with a |
2336 | /* We accept \001 in a name in case this is being called with a |
2348 | constructed string. */ |
2337 | constructed string. */ |
2349 | if (is_name_beginner (c = *input_line_pointer++) || c == '\001') |
2338 | if (is_name_beginner (c = *input_line_pointer++) || c == '\001') |
2350 | { |
2339 | { |
2351 | while (is_part_of_name (c = *input_line_pointer++) |
2340 | while (is_part_of_name (c = *input_line_pointer++) |
2352 | || c == '\001') |
2341 | || c == '\001') |
2353 | ; |
2342 | ; |
- | 2343 | if (is_name_ender (c)) |
|
- | 2344 | c = *input_line_pointer++; |
|
- | 2345 | } |
|
- | 2346 | else if (c == '"') |
|
- | 2347 | { |
|
- | 2348 | bfd_boolean backslash_seen; |
|
- | 2349 | ||
- | 2350 | * ilp_return = input_line_pointer; |
|
- | 2351 | do |
|
- | 2352 | { |
|
- | 2353 | backslash_seen = c == '\\'; |
|
- | 2354 | c = * input_line_pointer ++; |
|
- | 2355 | } |
|
- | 2356 | while (c != 0 && (c != '"' || backslash_seen)); |
|
- | 2357 | ||
2354 | if (is_name_ender (c)) |
2358 | if (c == 0) |
2355 | c = *input_line_pointer++; |
2359 | as_warn (_("missing closing '\"'")); |
- | 2360 | } |
|
- | 2361 | *--input_line_pointer = 0; |
|
- | 2362 | return c; |
|
- | 2363 | } |
|
- | 2364 | ||
- | 2365 | /* Replace the NUL character pointed to by input_line_pointer |
|
- | 2366 | with C. If C is \" then advance past it. Return the character |
|
- | 2367 | now pointed to by input_line_pointer. */ |
|
- | 2368 | ||
- | 2369 | char |
|
- | 2370 | restore_line_pointer (char c) |
|
- | 2371 | { |
|
- | 2372 | * input_line_pointer = c; |
|
2356 | } |
2373 | if (c == '"') |
Line 2357... | Line 2374... | ||
2357 | *--input_line_pointer = 0; |
2374 | c = * ++ input_line_pointer; |
2358 | return (c); |
2375 | return c; |
2359 | } |
2376 | } |