Overview
Comment: | Implement a {make} macro for making synthetic tokens. |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
6a9faa4fb1b2b335a0c92930aa1ace55 |
User & Date: | user on 2021-05-13 00:17:52 |
Other Links: | manifest | tags |
Context
2021-05-14
| ||
22:57 | Implement F7 (copy) and F12 (SQL) in the main menu of the picture editor. check-in: d90f0ae800 user: user tags: trunk | |
2021-05-13
| ||
00:17 | Implement a {make} macro for making synthetic tokens. check-in: 6a9faa4fb1 user: user tags: trunk | |
2021-05-12
| ||
06:24 | Make so that numbers out of range 0 to 31 are ignored for the {bit} macro check-in: 75e286812e user: user tags: trunk | |
Changes
Modified class.c from [04c44003dc] to [390a2adac5].
︙ | ︙ | |||
134 135 136 137 138 139 140 141 142 143 144 145 146 147 | #define MAC_MOD 0xFFC4 #define MAC_BAND 0xFFC5 #define MAC_BOR 0xFFC6 #define MAC_BXOR 0xFFC7 #define MAC_BNOT 0xFFC8 #define MAC_CAT 0xFFC9 #define MAC_BIT 0xFFCA #define MAC_VERSION 0xFFE0 #define MAC_DEFINE 0xFFE1 #define MAC_INCLUDE 0xFFE2 #define MAC_CALL 0xFFE3 #define MAC_APPEND 0xFFE4 #define MAC_UNDEFINED 0xFFFF | > | 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 | #define MAC_MOD 0xFFC4 #define MAC_BAND 0xFFC5 #define MAC_BOR 0xFFC6 #define MAC_BXOR 0xFFC7 #define MAC_BNOT 0xFFC8 #define MAC_CAT 0xFFC9 #define MAC_BIT 0xFFCA #define MAC_MAKE 0xFFCB #define MAC_VERSION 0xFFE0 #define MAC_DEFINE 0xFFE1 #define MAC_INCLUDE 0xFFE2 #define MAC_CALL 0xFFE3 #define MAC_APPEND 0xFFE4 #define MAC_UNDEFINED 0xFFFF |
︙ | ︙ | |||
349 350 351 352 353 354 355 | int c,i,fl,n,pr; magain: if(macstack) { TokenList*tl=0; pr=0; tokent=macstack->tok->t; if(tokent&TF_EOF) ParseError("Unexpected end of file in macro expansion\n"); tokenv=macstack->tok->v; | | | 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 | int c,i,fl,n,pr; magain: if(macstack) { TokenList*tl=0; pr=0; tokent=macstack->tok->t; if(tokent&TF_EOF) ParseError("Unexpected end of file in macro expansion\n"); tokenv=macstack->tok->v; if(tokent!=(TF_MACRO|TF_CLOSE)) *tokenstr=0; if(macstack->tok->str) strcpy(tokenstr,macstack->tok->str); if(main_options['M']) { printf("M* Macro %04X %08X \"",tokent,tokenv); for(i=0;tokenstr[i];i++) { if(tokenstr[i]<32 || tokenstr[i]>126) printf("<%02X>",tokenstr[i]&255); else putchar(tokenstr[i]); } |
︙ | ︙ | |||
832 833 834 835 836 837 838 839 840 841 842 843 844 845 | nxttok(); if(tokent==TF_MACRO+TF_CLOSE) break; if(tokent!=TF_INT) ParseError("Number expected\n"); if(tokenv<32) n|=1<<tokenv; } tokent=TF_INT; tokenv=n; break; case MAC_VERSION: nxttok1(); if(tokent!=TF_INT) ParseError("Number expected\n"); if(tokenv<MIN_VERSION || tokenv>MAX_VERSION) ParseError("Version number out of range\n"); nxttok1(); if(tokent!=TF_MACRO+TF_CLOSE) ParseError("Too many macro arguments\n"); | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 | nxttok(); if(tokent==TF_MACRO+TF_CLOSE) break; if(tokent!=TF_INT) ParseError("Number expected\n"); if(tokenv<32) n|=1<<tokenv; } tokent=TF_INT; tokenv=n; break; case MAC_MAKE: nxttok(); if(!(tokent&TF_NAME) || tokenv!=OP_STRING) ParseError("String literal expected\n"); s=tokenstr; n=0; while(*s) switch(*s++) { case '=': n|=0x0001; break; case ',': n|=0x0002; break; case ':': n|=0x0004; break; case '@': n|=0x0008; break; case '%': n|=0x0010; break; case '#': n|=0x0020; break; case '$': n|=0x0040; break; case '&': n|=0x0080; break; case '^': n|=0x0100; break; case '\'': n|=0x0400; break; case 'D': n|=0x0800; break; case '+': n|=0x1000; break; case 'C': n|=0x2000; break; case 'A': n|=0x4000; break; case '!': n|=0x8000; break; default: ParseError("Incorrect mode of {make}\n"); } nxttok(); if(tokent==TF_INT || ((tokent&TF_NAME) && !(tokenv&~255))) { n|=0x10000; snprintf(tokenstr,32,"%llu",(long long)tokenv); } else if(!(tokent&TF_NAME) || tokenv!=OP_STRING) { ParseError("Numeric or string literal expected\n"); } s=strdup(tokenstr); if(!s) fatal("Allocation failed\n"); nxttok(); strcpy(tokenstr,s); free(s); if(tokent!=TF_MACRO+TF_CLOSE) ParseError("Too many macro arguments\n"); if(n&0x10000) { n&=0xFFFF; tokent=TF_INT; tokenv=strtol(tokenstr,0,10); } switch(n) { case 0x0004: // : ReturnToken(TF_NAME|TF_ABNORMAL,OP_LABEL); case 0x0005: // =: ReturnToken(TF_NAME|TF_ABNORMAL|TF_EQUAL,OP_LABEL); case 0x0006: // ,: ReturnToken(TF_NAME|TF_ABNORMAL|TF_COMMA,OP_LABEL); case 0x0008: // @ tokent=TF_NAME; tokenv=look_hash(glohash,HASH_SIZE,0x2800,0x2FFF,num_globals+0x2800,"user global variables")?:(num_globals++)+0x2800; return; case 0x0009: // =@ tokent=TF_NAME|TF_EQUAL; tokenv=look_hash(glohash,HASH_SIZE,0x2800,0x2FFF,num_globals+0x2800,"user global variables")?:(num_globals++)+0x2800; return; case 0x0010: // % ReturnToken(TF_NAME|TF_ABNORMAL,OP_LOCAL); case 0x0011: // =% ReturnToken(TF_NAME|TF_ABNORMAL|TF_EQUAL,OP_LOCAL); case 0x0020: // # tokent=TF_NAME; tokenv=look_message_name()+0xC000; return; case 0x0040: // $ tokent=TF_NAME; tokenv=look_class_name()+0x4000; return; case 0x0080: // & tokent=TF_FUNCTION|TF_ABNORMAL; tokenv=look_hash(glohash,HASH_SIZE,0x8000,0xBFFF,num_functions+0x8000,"user functions")?:(num_functions++)+0x8000; return; case 0x0100: // ^ ReturnToken(TF_NAME|TF_ABNORMAL,OP_USERFLAG); case 0x0101: // =^ ReturnToken(TF_NAME|TF_ABNORMAL|TF_EQUAL,OP_USERFLAG); case 0x0102: // ,^ ReturnToken(TF_NAME|TF_ABNORMAL|TF_COMMA,OP_USERFLAG); case 0x0103: // =,^ ReturnToken(TF_NAME|TF_ABNORMAL|TF_EQUAL|TF_COMMA,OP_USERFLAG); case 0x0400: // ' if(tokent==TF_INT) { n=tokenv; } else { for(n=8;n<256;n++) if(heromesh_key_names[n] && !strcmp(heromesh_key_names[n],tokenstr)) break; } if(!heromesh_key_names[n&=255]) ParseError("Invalid key token (%d)\n",n); ReturnToken(TF_NAME|TF_KEY,n); case 0x0800: // D if(tokent==TF_INT) ReturnToken(TF_NAME|TF_DIR,tokenv&15); else ReturnToken(TF_NAME|TF_DIR,strtol(tokenstr,0,10)&15); case 0x1000: // + ReturnToken(TF_INT,strtol(tokenstr,0,10)); case 0x1001: // =+ ReturnToken(TF_INT,strtol(tokenstr,0,2)); case 0x1002: // ,+ ReturnToken(TF_INT,strtol(tokenstr,0,16)); case 0x1003: // =,+ ReturnToken(TF_INT,strtol(tokenstr,0,8)); case 0x2000: // C if(tokent!=TF_INT) tokenv=strtol(tokenstr,0,10); *tokenstr=n=tokenv&255; if(n<32) tokenstr[0]=31,tokenstr[1]=n,tokenstr[2]=0; else tokenstr[1]=0; ReturnToken(TF_NAME|TF_ABNORMAL,OP_STRING); case 0x2002: // ,C if(tokent!=TF_INT) tokenv=strtol(tokenstr,0,10); if(n<32) { *tokenstr=0; } else { tokenstr[0]=16; tokenstr[1]=n; tokenstr[2]=0; } ReturnToken(TF_NAME|TF_ABNORMAL,OP_STRING); case 0x4000: // A ReturnToken(TF_INT,*tokenstr&255); default: ParseError("Incorrect mode of {make}\n"); } break; case MAC_VERSION: nxttok1(); if(tokent!=TF_INT) ParseError("Number expected\n"); if(tokenv<MIN_VERSION || tokenv>MAX_VERSION) ParseError("Version number out of range\n"); nxttok1(); if(tokent!=TF_MACRO+TF_CLOSE) ParseError("Too many macro arguments\n"); |
︙ | ︙ | |||
1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 | strcpy(tokenstr,"mod"); glohash[look_hash_mac()].id=MAC_MOD; strcpy(tokenstr,"band"); glohash[look_hash_mac()].id=MAC_BAND; strcpy(tokenstr,"bor"); glohash[look_hash_mac()].id=MAC_BOR; strcpy(tokenstr,"bxor"); glohash[look_hash_mac()].id=MAC_BXOR; strcpy(tokenstr,"bnot"); glohash[look_hash_mac()].id=MAC_BNOT; strcpy(tokenstr,"cat"); glohash[look_hash_mac()].id=MAC_CAT; strcpy(tokenstr,"bit"); glohash[look_hash_mac()].id=MAC_BIT; strcpy(tokenstr,"version"); glohash[look_hash_mac()].id=MAC_VERSION; strcpy(tokenstr,"define"); glohash[look_hash_mac()].id=MAC_DEFINE; strcpy(tokenstr,"include"); glohash[look_hash_mac()].id=MAC_INCLUDE; strcpy(tokenstr,"call"); glohash[look_hash_mac()].id=MAC_CALL; strcpy(tokenstr,"append"); glohash[look_hash_mac()].id=MAC_APPEND; if(main_options['L']) { for(;;) { | > | 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 | strcpy(tokenstr,"mod"); glohash[look_hash_mac()].id=MAC_MOD; strcpy(tokenstr,"band"); glohash[look_hash_mac()].id=MAC_BAND; strcpy(tokenstr,"bor"); glohash[look_hash_mac()].id=MAC_BOR; strcpy(tokenstr,"bxor"); glohash[look_hash_mac()].id=MAC_BXOR; strcpy(tokenstr,"bnot"); glohash[look_hash_mac()].id=MAC_BNOT; strcpy(tokenstr,"cat"); glohash[look_hash_mac()].id=MAC_CAT; strcpy(tokenstr,"bit"); glohash[look_hash_mac()].id=MAC_BIT; strcpy(tokenstr,"make"); glohash[look_hash_mac()].id=MAC_MAKE; strcpy(tokenstr,"version"); glohash[look_hash_mac()].id=MAC_VERSION; strcpy(tokenstr,"define"); glohash[look_hash_mac()].id=MAC_DEFINE; strcpy(tokenstr,"include"); glohash[look_hash_mac()].id=MAC_INCLUDE; strcpy(tokenstr,"call"); glohash[look_hash_mac()].id=MAC_CALL; strcpy(tokenstr,"append"); glohash[look_hash_mac()].id=MAC_APPEND; if(main_options['L']) { for(;;) { |
︙ | ︙ |
Modified class.doc from [d38896fcbc] to [ca75a1769b].
︙ | ︙ | |||
170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 | with multiple tokens becomes the token with one less backslash. It is permitted to redefine existing macros as well as new ones. {include <string>} Include text from another file into this one. You cannot use {include} inside of another macro or in a macro argument. {mod <number> <number>} Modulo. {version <number>} Expands into nothing. The number must be zero, otherwise it is an error. Future versions of Free Hero Mesh may change this. It is possible to implement a tag system in this preprocessor, which makes it Turing complete. For example: {define "skip" {call \2}} {define "1" {skip \1|"3"|"3"|"2"|"1"|"H"}} {define "2" {skip \1|"3"|"3"|"1"}} {define "3" {skip \1|"3"|"3"}} {define "H" \1} {call "2"|"1"|"1"} Note: Macro names are entirely independent from token names. === Global definitions === These are the global definitions in the class definition file. (Animate <limit>) Set the limit for logical animations, from 1 to 255. The default is 32. | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 | with multiple tokens becomes the token with one less backslash. It is permitted to redefine existing macros as well as new ones. {include <string>} Include text from another file into this one. You cannot use {include} inside of another macro or in a macro argument. {make <mode> <arg>} Make a synthetic token; see the below section about synthetic tokens for details. The second argument can be a number, or a direction or key name which is treated as a number, or a string. In most cases, a number will be converted to a string with its unsigned decimal representation. {mod <number> <number>} Modulo. {version <number>} Expands into nothing. The number must be zero, otherwise it is an error. Future versions of Free Hero Mesh may change this. It is possible to implement a tag system in this preprocessor, which makes it Turing complete. For example: {define "skip" {call \2}} {define "1" {skip \1|"3"|"3"|"2"|"1"|"H"}} {define "2" {skip \1|"3"|"3"|"1"}} {define "3" {skip \1|"3"|"3"}} {define "H" \1} {call "2"|"1"|"1"} Note: Macro names are entirely independent from token names. === Synthetic tokens === The possible modes of synthetic tokens are: ":" A label with the specified name. "=:" Go to a label with a specified name. ",:" Subroutine call a label with a specified name. "@" A global variable. "=@" Write a global variable. "%" A local variable. "=%" Write a local variable. "#" A user-defined message. "$" A class. "&" A user-defined function. "^" A user flag (read self, or definition). "=^" A user flag (write self). ",^" A user flag (read object). "=,^" A user flag (write object). "'" A key token; either by number or by name. "D" A direction; only the low 4-bits are used. "+" A number interpreted as decimal. "=+" A number interpreted as binary. ",+" A number interpreted as hexadecimal. "=,+" A number interpreted as octal. "C" A string with a single character of the specified code. ",C" A string with a quiz button of the character with the code. "A" The ASCII code of the first character of the string. Note that as the argument, you can use {cat} to convert other tokens to strings if needed. === Global definitions === These are the global definitions in the class definition file. (Animate <limit>) Set the limit for logical animations, from 1 to 255. The default is 32. |
︙ | ︙ |