comparison lwcc/preproc.c @ 301:6f7fe78bb868 ccdev

Add string -> number conversion for preproc expression evaluator Q&D conversion from string to signed number. It should be noted that this really should be done during tokenization and the type of number be set by the tokenizer, including parsing floating point values. Then the preprocessor can decide what to do with non-integer numbers.
author William Astle <lost@l-w.ca>
date Sun, 15 Sep 2013 14:22:10 -0600
parents 8d6c47395653
children d85d173ba120
comparison
equal deleted inserted replaced
300:8d6c47395653 301:6f7fe78bb868
703 skip_eol(pp); 703 skip_eol(pp);
704 preproc_unget_token(pp, pp -> curtok); 704 preproc_unget_token(pp, pp -> curtok);
705 } 705 }
706 706
707 static long eval_expr_real(struct preproc_info *, int); 707 static long eval_expr_real(struct preproc_info *, int);
708 static long preproc_numval(struct token *); 708 static long preproc_numval(struct preproc_info *, struct token *);
709 709
710 static long eval_term_real(struct preproc_info *pp) 710 static long eval_term_real(struct preproc_info *pp)
711 { 711 {
712 long tval = 0; 712 long tval = 0;
713 struct token *ct; 713 struct token *ct;
781 /* unknown identifier - it's zero */ 781 /* unknown identifier - it's zero */
782 return 0; 782 return 0;
783 783
784 /* numbers */ 784 /* numbers */
785 case TOK_NUMBER: 785 case TOK_NUMBER:
786 return preproc_numval(ct); 786 return preproc_numval(pp, ct);
787 787
788 default: 788 default:
789 preproc_throw_error(pp, "Bad expression"); 789 preproc_throw_error(pp, "Bad expression");
790 skip_eoe(pp); 790 skip_eoe(pp);
791 return 0; 791 return 0;
928 skip_eol(pp); 928 skip_eol(pp);
929 } 929 }
930 return rv; 930 return rv;
931 } 931 }
932 932
933 static int eval_escape(char **t)
934 {
935 int c;
936 int c2;
937
938 if (**t == 0)
939 return 0;
940 c = *(*t)++;
941 int rv = 0;
942
943 switch (c)
944 {
945 case 'n':
946 return 10;
947 case 'r':
948 return 13;
949 case 'b':
950 return 8;
951 case 'e':
952 return 27;
953 case 'f':
954 return 12;
955 case 't':
956 return 9;
957 case 'v':
958 return 11;
959 case 'a':
960 return 7;
961 case '0': case '1': case '2': case '3': case '4':
962 case '5': case '6': case '7':
963 // octal constant
964 rv = c - '0';
965 c2 = 1;
966 for (; c2 < 3; c2++)
967 {
968 c = *(*t)++;
969 if (c < '0' || c > '7')
970 break;
971 rv = (rv << 3) | (c - '0');
972 }
973 return rv;
974 case 'x':
975 // hex constant
976 for (;;)
977 {
978 c = *(*t)++;
979 if (c < '0' || (c > '9' && c < 'A') || (c > 'F' && c < 'a') || c > 'f')
980 break;
981 c = c - '0';
982 if (c > 9)
983 c -= 7;
984 if (c > 15)
985 c -= 32;
986 rv = (rv << 4) | c;
987 }
988 return rv & 0xff;
989 default:
990 return c;
991 }
992 }
993
933 /* convert a numeric string to a number */ 994 /* convert a numeric string to a number */
934 long preproc_numval(struct token *t) 995 long preproc_numval(struct preproc_info *pp, struct token *t)
935 { 996 {
936 return 0; 997 unsigned long long rv = 0;
998 unsigned long long rv2 = 0;
999 char *tstr = t -> strval;
1000 int radix = 10;
1001 int c;
1002 int ovf = 0;
1003 union { long sv; unsigned long uv; } tv;
1004
1005 if (t -> ttype == TOK_CHR_LIT)
1006 {
1007 tstr++;
1008 while (*tstr && *tstr != '\'')
1009 {
1010 if (*tstr == '\\')
1011 {
1012 tstr++;
1013 c = eval_escape(&tstr);
1014 }
1015 else
1016 c = *tstr++;
1017 rv = (rv << 8) | c;
1018 if (rv / radix < rv2)
1019 ovf = 1;
1020 rv2 = rv;
1021
1022 }
1023 goto done;
1024 }
1025
1026
1027 if (*tstr == '0')
1028 {
1029 radix = 8;
1030 tstr++;
1031 if (*tstr == 'x')
1032 {
1033 radix = 16;
1034 tstr++;
1035 }
1036 }
1037 while (*tstr)
1038 {
1039 c = *tstr++;
1040 if (c < '0' || (c > '9' && c < 'A') || (c > 'F' && c < 'a') || c > 'f')
1041 break;
1042 c -= '0';
1043 if (c > 9)
1044 c -= 7;
1045 if (c > 15)
1046 c -= 32;
1047 if (c >= radix)
1048 break;
1049 rv = rv * radix + c;
1050 if (rv / radix < rv2)
1051 ovf = 1;
1052 rv2 = rv;
1053 }
1054 tstr--;
1055 while (*tstr == 'l' || *tstr == 'L')
1056 tstr++;
1057 tv.uv = rv;
1058 if (tv.sv < 0 && radix == 10)
1059 ovf = 1;
1060 done:
1061 if (ovf)
1062 preproc_throw_error(pp, "Constant out of range: %s", t -> strval);
1063 return rv;
937 } 1064 }
938 1065
939 /* 1066 /*
940 Below here is the logic for expanding a macro 1067 Below here is the logic for expanding a macro
941 */ 1068 */