OLD | NEW |
1 /* -*- mode: c; c-file-style: "bsd" -*- */ | 1 /* -*- mode: c; c-file-style: "bsd" -*- */ |
2 /* preproc.c macro preprocessor for the Netwide Assembler | 2 /* preproc.c macro preprocessor for the Netwide Assembler |
3 * | 3 * |
4 * The Netwide Assembler is copyright (C) 1996 Simon Tatham and | 4 * The Netwide Assembler is copyright (C) 1996 Simon Tatham and |
5 * Julian Hall. All rights reserved. The software is | 5 * Julian Hall. All rights reserved. The software is |
6 * redistributable under the licence given in the file "Licence" | 6 * redistributable under the licence given in the file "Licence" |
7 * distributed in the NASM archive. | 7 * distributed in the NASM archive. |
8 * | 8 * |
9 * initial version 18/iii/97 by Simon Tatham | 9 * initial version 18/iii/97 by Simon Tatham |
10 */ | 10 */ |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
56 typedef struct Include Include; | 56 typedef struct Include Include; |
57 typedef struct Cond Cond; | 57 typedef struct Cond Cond; |
58 | 58 |
59 /* | 59 /* |
60 * Store the definition of a single-line macro. | 60 * Store the definition of a single-line macro. |
61 */ | 61 */ |
62 struct SMacro | 62 struct SMacro |
63 { | 63 { |
64 SMacro *next; | 64 SMacro *next; |
65 char *name; | 65 char *name; |
| 66 int level; |
66 int casesense; | 67 int casesense; |
67 int nparam; | 68 int nparam; |
68 int in_progress; | 69 int in_progress; |
69 Token *expansion; | 70 Token *expansion; |
70 }; | 71 }; |
71 | 72 |
72 /* | 73 /* |
73 * Store the definition of a multi-line macro. This is also used to | 74 * Store the definition of a multi-line macro. This is also used to |
74 * store the interiors of `%rep...%endrep' blocks, which are | 75 * store the interiors of `%rep...%endrep' blocks, which are |
75 * effectively self-re-invoking multi-line macros which simply | 76 * effectively self-re-invoking multi-line macros which simply |
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
269 | 270 |
270 /* | 271 /* |
271 * Directive names. | 272 * Directive names. |
272 */ | 273 */ |
273 static const char *directives[] = { | 274 static const char *directives[] = { |
274 "%arg", | 275 "%arg", |
275 "%assign", "%clear", "%define", "%elif", "%elifctx", "%elifdef", | 276 "%assign", "%clear", "%define", "%elif", "%elifctx", "%elifdef", |
276 "%elifid", "%elifidn", "%elifidni", "%elifmacro", "%elifnctx", "%elifndef", | 277 "%elifid", "%elifidn", "%elifidni", "%elifmacro", "%elifnctx", "%elifndef", |
277 "%elifnid", "%elifnidn", "%elifnidni", "%elifnmacro", "%elifnnum", "%elifnst
r", | 278 "%elifnid", "%elifnidn", "%elifnidni", "%elifnmacro", "%elifnnum", "%elifnst
r", |
278 "%elifnum", "%elifstr", "%else", "%endif", "%endm", "%endmacro", | 279 "%elifnum", "%elifstr", "%else", "%endif", "%endm", "%endmacro", |
279 "%endrep", "%error", "%exitrep", "%iassign", "%idefine", "%if", | 280 "%endrep", "%endscope", "%error", "%exitrep", "%iassign", "%idefine", "%if", |
280 "%ifctx", "%ifdef", "%ifid", "%ifidn", "%ifidni", "%ifmacro", "%ifnctx", | 281 "%ifctx", "%ifdef", "%ifid", "%ifidn", "%ifidni", "%ifmacro", "%ifnctx", |
281 "%ifndef", "%ifnid", "%ifnidn", "%ifnidni", "%ifnmacro", "%ifnnum", | 282 "%ifndef", "%ifnid", "%ifnidn", "%ifnidni", "%ifnmacro", "%ifnnum", |
282 "%ifnstr", "%ifnum", "%ifstr", "%imacro", "%include", | 283 "%ifnstr", "%ifnum", "%ifstr", "%imacro", "%include", |
283 "%ixdefine", "%line", | 284 "%ixdefine", "%line", |
284 "%local", | 285 "%local", |
285 "%macro", "%pop", "%push", "%rep", "%repl", "%rotate", | 286 "%macro", "%pop", "%push", "%rep", "%repl", "%rotate", |
286 "%stacksize", | 287 "%scope", "%stacksize", |
287 "%strlen", "%substr", "%undef", "%xdefine" | 288 "%strlen", "%substr", "%undef", "%xdefine" |
288 }; | 289 }; |
289 enum | 290 enum |
290 { | 291 { |
291 PP_ARG, | 292 PP_ARG, |
292 PP_ASSIGN, PP_CLEAR, PP_DEFINE, PP_ELIF, PP_ELIFCTX, PP_ELIFDEF, | 293 PP_ASSIGN, PP_CLEAR, PP_DEFINE, PP_ELIF, PP_ELIFCTX, PP_ELIFDEF, |
293 PP_ELIFID, PP_ELIFIDN, PP_ELIFIDNI, PP_ELIFMACRO, PP_ELIFNCTX, PP_ELIFNDEF, | 294 PP_ELIFID, PP_ELIFIDN, PP_ELIFIDNI, PP_ELIFMACRO, PP_ELIFNCTX, PP_ELIFNDEF, |
294 PP_ELIFNID, PP_ELIFNIDN, PP_ELIFNIDNI, PP_ELIFNMACRO, PP_ELIFNNUM, PP_ELIFNS
TR, | 295 PP_ELIFNID, PP_ELIFNIDN, PP_ELIFNIDNI, PP_ELIFNMACRO, PP_ELIFNNUM, PP_ELIFNS
TR, |
295 PP_ELIFNUM, PP_ELIFSTR, PP_ELSE, PP_ENDIF, PP_ENDM, PP_ENDMACRO, | 296 PP_ELIFNUM, PP_ELIFSTR, PP_ELSE, PP_ENDIF, PP_ENDM, PP_ENDMACRO, |
296 PP_ENDREP, PP_ERROR, PP_EXITREP, PP_IASSIGN, PP_IDEFINE, PP_IF, | 297 PP_ENDREP, PP_ENDSCOPE, PP_ERROR, PP_EXITREP, PP_IASSIGN, PP_IDEFINE, PP_IF, |
297 PP_IFCTX, PP_IFDEF, PP_IFID, PP_IFIDN, PP_IFIDNI, PP_IFMACRO, PP_IFNCTX, | 298 PP_IFCTX, PP_IFDEF, PP_IFID, PP_IFIDN, PP_IFIDNI, PP_IFMACRO, PP_IFNCTX, |
298 PP_IFNDEF, PP_IFNID, PP_IFNIDN, PP_IFNIDNI, PP_IFNMACRO, PP_IFNNUM, | 299 PP_IFNDEF, PP_IFNID, PP_IFNIDN, PP_IFNIDNI, PP_IFNMACRO, PP_IFNNUM, |
299 PP_IFNSTR, PP_IFNUM, PP_IFSTR, PP_IMACRO, PP_INCLUDE, | 300 PP_IFNSTR, PP_IFNUM, PP_IFSTR, PP_IMACRO, PP_INCLUDE, |
300 PP_IXDEFINE, PP_LINE, | 301 PP_IXDEFINE, PP_LINE, |
301 PP_LOCAL, | 302 PP_LOCAL, |
302 PP_MACRO, PP_POP, PP_PUSH, PP_REP, PP_REPL, PP_ROTATE, | 303 PP_MACRO, PP_POP, PP_PUSH, PP_REP, PP_REPL, PP_ROTATE, |
303 PP_STACKSIZE, | 304 PP_SCOPE, PP_STACKSIZE, |
304 PP_STRLEN, PP_SUBSTR, PP_UNDEF, PP_XDEFINE | 305 PP_STRLEN, PP_SUBSTR, PP_UNDEF, PP_XDEFINE |
305 }; | 306 }; |
306 | 307 |
307 /* If this is a an IF, ELIF, ELSE or ENDIF keyword */ | 308 /* If this is a an IF, ELIF, ELSE or ENDIF keyword */ |
308 static int is_condition(int arg) | 309 static int is_condition(int arg) |
309 { | 310 { |
310 return ((arg >= PP_ELIF) && (arg <= PP_ENDIF)) || | 311 return ((arg >= PP_ELIF) && (arg <= PP_ENDIF)) || |
311 ((arg >= PP_IF) && (arg <= PP_IFSTR)); | 312 ((arg >= PP_IF) && (arg <= PP_IFSTR)); |
312 } | 313 } |
313 | 314 |
(...skipping 17 matching lines...) Expand all Loading... |
331 | 332 |
332 static const char *tasm_directives[] = { | 333 static const char *tasm_directives[] = { |
333 "arg", "elif", "else", "endif", "if", "ifdef", "ifdifi", | 334 "arg", "elif", "else", "endif", "if", "ifdef", "ifdifi", |
334 "ifndef", "include", "local" | 335 "ifndef", "include", "local" |
335 }; | 336 }; |
336 | 337 |
337 static int StackSize = 4; | 338 static int StackSize = 4; |
338 static const char *StackPointer = "ebp"; | 339 static const char *StackPointer = "ebp"; |
339 static int ArgOffset = 8; | 340 static int ArgOffset = 8; |
340 static int LocalOffset = 4; | 341 static int LocalOffset = 4; |
| 342 static int Level = 0; |
341 | 343 |
342 | 344 |
343 static Context *cstk; | 345 static Context *cstk; |
344 static Include *istk; | 346 static Include *istk; |
345 | 347 |
346 static FILE *first_fp = NULL; | 348 static FILE *first_fp = NULL; |
347 | 349 |
348 static efunc _error; /* Pointer to client-provided error reporting fu
nction */ | 350 static efunc _error; /* Pointer to client-provided error reporting fu
nction */ |
349 static evalfunc evaluate; | 351 static evalfunc evaluate; |
350 | 352 |
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
531 } | 533 } |
532 | 534 |
533 static char * | 535 static char * |
534 check_tasm_directive(char *line) | 536 check_tasm_directive(char *line) |
535 { | 537 { |
536 int i, j, k, m; | 538 int i, j, k, m; |
537 size_t len, len2; | 539 size_t len, len2; |
538 char *p, *oldline, oldchar, *q, oldchar2; | 540 char *p, *oldline, oldchar, *q, oldchar2; |
539 TMEndItem *end; | 541 TMEndItem *end; |
540 | 542 |
541 if ((p = strchr(line, ';'))) | |
542 *p = '\0'; | |
543 | |
544 p = line; | 543 p = line; |
545 | 544 |
546 /* Skip whitespace */ | 545 /* Skip whitespace */ |
547 while (isspace(*p) && *p != 0) | 546 while (isspace(*p) && *p != 0 && *p != ';') |
548 p++; | 547 p++; |
549 | 548 |
550 /* Ignore nasm directives */ | 549 /* Ignore nasm directives */ |
551 if (*p == '%') | 550 if (*p == '%') |
552 return line; | 551 return line; |
553 | 552 |
554 /* Binary search for the directive name */ | 553 /* Binary search for the directive name */ |
555 len = 0; | 554 len = 0; |
556 while (!isspace(p[len]) && p[len] != 0) | 555 while (!isspace(p[len]) && p[len] != 0 && p[len] != ';') |
557 len++; | 556 len++; |
558 if (!len) | 557 if (!len) |
559 return line; | 558 return line; |
560 | 559 |
561 oldchar = p[len]; | 560 oldchar = p[len]; |
562 p[len] = 0; | 561 p[len] = 0; |
563 i = -1; | 562 i = -1; |
564 j = elements(tasm_directives); | 563 j = elements(tasm_directives); |
565 while (j - i > 1) | 564 while (j - i > 1) |
566 { | 565 { |
(...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
864 /* handle ASSUME */ | 863 /* handle ASSUME */ |
865 if (!TAssumes) { | 864 if (!TAssumes) { |
866 TAssumes = nasm_malloc(sizeof(*TAssumes)); | 865 TAssumes = nasm_malloc(sizeof(*TAssumes)); |
867 TAssumes[0].segreg = NULL; | 866 TAssumes[0].segreg = NULL; |
868 } | 867 } |
869 i = 0; | 868 i = 0; |
870 q[len2] = oldchar2; | 869 q[len2] = oldchar2; |
871 /* Skip whitespaces */ | 870 /* Skip whitespaces */ |
872 while (isspace(*q) && *q) | 871 while (isspace(*q) && *q) |
873 q++; | 872 q++; |
874 while (*q) { | 873 while (*q && *q != ';') { |
875 p = q; | 874 p = q; |
876 for (; *q && *q != ':' && !isspace(*q); q++); | 875 for (; *q && *q != ';' && *q != ':' && !isspace(*q); q++); |
877 if (!*q) | 876 if (!*q || *q == ';') |
878 break; | 877 break; |
879 /* segment register name */ | 878 /* segment register name */ |
880 for (assume = TAssumes; assume->segreg; assume++) | 879 for (assume = TAssumes; assume->segreg; assume++) |
881 if (strlen(assume->segreg) == (size_t)(q-p) && | 880 if (strlen(assume->segreg) == (size_t)(q-p) && |
882 !yasm__strncasecmp(assume->segreg, p, q-p)) | 881 !yasm__strncasecmp(assume->segreg, p, q-p)) |
883 break; | 882 break; |
884 if (!assume->segreg) { | 883 if (!assume->segreg) { |
885 i = assume - TAssumes + 1; | 884 i = assume - TAssumes + 1; |
886 TAssumes = nasm_realloc(TAssumes, (i+1)*sizeof(*TAssumes)); | 885 TAssumes = nasm_realloc(TAssumes, (i+1)*sizeof(*TAssumes)); |
887 assume = TAssumes + i - 1; | 886 assume = TAssumes + i - 1; |
888 assume->segreg = nasm_strndup(p, q-p); | 887 assume->segreg = nasm_strndup(p, q-p); |
889 assume[1].segreg = NULL; | 888 assume[1].segreg = NULL; |
890 } | 889 } |
891 for (; *q && *q != ':' && isspace(*q); q++); | 890 for (; *q && *q != ';' && *q != ':' && isspace(*q); q++); |
892 if (*q != ':') | 891 if (*q != ':') |
893 error(ERR_FATAL, "expected `:' instead of `%c'", *q); | 892 error(ERR_FATAL, "expected `:' instead of `%c'", *q); |
894 for (q++; *q && isspace(*q); q++); | 893 for (q++; *q && isspace(*q); q++); |
895 | 894 |
896 /* segment name */ | 895 /* segment name */ |
897 p = q; | 896 p = q; |
898 for (; *q && *q != ',' && !isspace(*q); q++); | 897 for (; *q && *q != ';' && *q != ',' && !isspace(*q); q++); |
899 assume->segment = nasm_strndup(p, q-p); | 898 assume->segment = nasm_strndup(p, q-p); |
900 for (; *q && isspace(*q); q++); | 899 for (; *q && isspace(*q); q++); |
901 if (*q && *q != ',') | 900 if (*q && *q != ';' && *q != ',') |
902 error(ERR_FATAL, "expected `,' instead of `%c'", *q); | 901 error(ERR_FATAL, "expected `,' instead of `%c'", *q); |
903 | 902 |
904 for (q++; *q && isspace(*q); q++); | 903 if (*q && *q != ';') |
| 904 q++; |
| 905 for (; *q && isspace(*q); q++); |
905 } | 906 } |
906 TAssumes[i].segreg = NULL; | 907 TAssumes[i].segreg = NULL; |
907 TAssumes = nasm_realloc(TAssumes, (i+1)*sizeof(*TAssumes)); | 908 TAssumes = nasm_realloc(TAssumes, (i+1)*sizeof(*TAssumes)); |
908 nasm_free(line); | 909 nasm_free(line); |
909 return nasm_strdup(""); | 910 return nasm_strdup(""); |
910 } else if (inTstruc) { | 911 } else if (inTstruc) { |
911 struct TStrucField *field; | 912 struct TStrucField *field; |
912 /* TODO: handle unnamed data */ | 913 /* TODO: handle unnamed data */ |
913 field = nasm_malloc(sizeof(*field)); | 914 field = nasm_malloc(sizeof(*field)); |
914 field->name = nasm_strdup(p); | 915 field->name = nasm_strdup(p); |
(...skipping 972 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1887 * If you already know which context macro belongs to, you can pass | 1888 * If you already know which context macro belongs to, you can pass |
1888 * the context pointer as first parameter; if you won't but name begins | 1889 * the context pointer as first parameter; if you won't but name begins |
1889 * with %$ the context will be automatically computed. If all_contexts | 1890 * with %$ the context will be automatically computed. If all_contexts |
1890 * is true, macro will be searched in outer contexts as well. | 1891 * is true, macro will be searched in outer contexts as well. |
1891 */ | 1892 */ |
1892 static int | 1893 static int |
1893 smacro_defined(Context * ctx, char *name, int nparam, SMacro ** defn, | 1894 smacro_defined(Context * ctx, char *name, int nparam, SMacro ** defn, |
1894 int nocase) | 1895 int nocase) |
1895 { | 1896 { |
1896 SMacro *m; | 1897 SMacro *m; |
| 1898 int highest_level = -1; |
1897 | 1899 |
1898 if (ctx) | 1900 if (ctx) |
1899 m = ctx->localmac; | 1901 m = ctx->localmac; |
1900 else if (name[0] == '%' && name[1] == '$') | 1902 else if (name[0] == '%' && name[1] == '$') |
1901 { | 1903 { |
1902 if (cstk) | 1904 if (cstk) |
1903 ctx = get_ctx(name, FALSE); | 1905 ctx = get_ctx(name, FALSE); |
1904 if (!ctx) | 1906 if (!ctx) |
1905 return FALSE; /* got to return _something_ */ | 1907 return FALSE; /* got to return _something_ */ |
1906 m = ctx->localmac; | 1908 m = ctx->localmac; |
1907 } | 1909 } |
1908 else | 1910 else |
1909 m = smacros[hash(name)]; | 1911 m = smacros[hash(name)]; |
1910 | 1912 |
1911 while (m) | 1913 while (m) |
1912 { | 1914 { |
1913 if (!mstrcmp(m->name, name, m->casesense && nocase) && | 1915 if (!mstrcmp(m->name, name, m->casesense && nocase) && |
1914 (nparam <= 0 || m->nparam == 0 || nparam == m->nparam)) | 1916 (nparam <= 0 || m->nparam == 0 || nparam == m->nparam) && (highe
st_level < 0 || m->level > highest_level)) |
1915 { | 1917 { |
| 1918 highest_level = m->level; |
1916 if (defn) | 1919 if (defn) |
1917 { | 1920 { |
1918 if (nparam == m->nparam || nparam == -1) | 1921 if (nparam == m->nparam || nparam == -1) |
1919 *defn = m; | 1922 *defn = m; |
1920 else | 1923 else |
1921 *defn = NULL; | 1924 *defn = NULL; |
1922 } | 1925 } |
1923 return TRUE; | |
1924 } | 1926 } |
1925 m = m->next; | 1927 m = m->next; |
1926 } | 1928 } |
1927 | 1929 |
1928 return FALSE; | 1930 return highest_level >= 0; |
1929 } | 1931 } |
1930 | 1932 |
1931 /* | 1933 /* |
1932 * Count and mark off the parameters in a multi-line macro call. | 1934 * Count and mark off the parameters in a multi-line macro call. |
1933 * This is called both from within the multi-line macro expansion | 1935 * This is called both from within the multi-line macro expansion |
1934 * code, and also to mark off the default parameters when provided | 1936 * code, and also to mark off the default parameters when provided |
1935 * in a %macro definition line. | 1937 * in a %macro definition line. |
1936 */ | 1938 */ |
1937 static void | 1939 static void |
1938 count_mmac_params(Token * t, int *nparam, Token *** params) | 1940 count_mmac_params(Token * t, int *nparam, Token *** params) |
(...skipping 845 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2784 if (tline->next) | 2786 if (tline->next) |
2785 error(ERR_WARNING, "trailing garbage after `%%pop' ignored"); | 2787 error(ERR_WARNING, "trailing garbage after `%%pop' ignored"); |
2786 if (!cstk) | 2788 if (!cstk) |
2787 error(ERR_NONFATAL, | 2789 error(ERR_NONFATAL, |
2788 "`%%pop': context stack is already empty"); | 2790 "`%%pop': context stack is already empty"); |
2789 else | 2791 else |
2790 ctx_pop(); | 2792 ctx_pop(); |
2791 free_tlist(origline); | 2793 free_tlist(origline); |
2792 break; | 2794 break; |
2793 | 2795 |
| 2796 case PP_SCOPE: |
| 2797 if (tline->next) |
| 2798 error(ERR_WARNING, "trailing garbage after `%%scope' ignored"); |
| 2799 Level++; |
| 2800 free_tlist(origline); |
| 2801 break; |
| 2802 |
| 2803 case PP_ENDSCOPE: |
| 2804 if (tline->next) |
| 2805 error(ERR_WARNING, "trailing garbage after `%%endscope' ignored"
); |
| 2806 if (!Level) |
| 2807 error(ERR_NONFATAL, |
| 2808 "`%%endscope': already popped all levels"); |
| 2809 else |
| 2810 { |
| 2811 for (k = 0; k < NHASH; k++) |
| 2812 { |
| 2813 SMacro **smlast = &smacros[k]; |
| 2814 smac = smacros[k]; |
| 2815 while (smac) |
| 2816 { |
| 2817 if (smac->level < Level) |
| 2818 { |
| 2819 smlast = &smac->next; |
| 2820 smac = smac->next; |
| 2821 } |
| 2822 else |
| 2823 { |
| 2824 *smlast = smac->next; |
| 2825 nasm_free(smac->name); |
| 2826 free_tlist(smac->expansion); |
| 2827 nasm_free(smac); |
| 2828 smac = *smlast; |
| 2829 } |
| 2830 } |
| 2831 } |
| 2832 for (ctx = cstk; ctx; ctx = ctx->next) |
| 2833 { |
| 2834 SMacro **smlast = &ctx->localmac; |
| 2835 smac = ctx->localmac; |
| 2836 while (smac) |
| 2837 { |
| 2838 if (smac->level < Level) |
| 2839 { |
| 2840 smlast = &smac->next; |
| 2841 smac = smac->next; |
| 2842 } |
| 2843 else |
| 2844 { |
| 2845 *smlast = smac->next; |
| 2846 nasm_free(smac->name); |
| 2847 free_tlist(smac->expansion); |
| 2848 nasm_free(smac); |
| 2849 smac = *smlast; |
| 2850 } |
| 2851 } |
| 2852 } |
| 2853 Level--; |
| 2854 } |
| 2855 free_tlist(origline); |
| 2856 break; |
| 2857 |
2794 case PP_ERROR: | 2858 case PP_ERROR: |
2795 tline->next = expand_smacro(tline->next); | 2859 tline->next = expand_smacro(tline->next); |
2796 tline = tline->next; | 2860 tline = tline->next; |
2797 skip_white_(tline); | 2861 skip_white_(tline); |
2798 if (tok_type_(tline, TOK_STRING)) | 2862 if (tok_type_(tline, TOK_STRING)) |
2799 { | 2863 { |
2800 p = tline->text + 1; /* point past the quote to the name */ | 2864 p = tline->text + 1; /* point past the quote to the name */ |
2801 p[strlen(p) - 1] = '\0'; /* remove the trailing quote */ | 2865 p[strlen(p) - 1] = '\0'; /* remove the trailing quote */ |
2802 expand_macros_in_string(&p); | 2866 expand_macros_in_string(&p); |
2803 error(ERR_NONFATAL, "%s", p); | 2867 error(ERR_NONFATAL, "%s", p); |
(...skipping 504 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3308 { | 3372 { |
3309 if (!smac) | 3373 if (!smac) |
3310 { | 3374 { |
3311 error(ERR_WARNING, | 3375 error(ERR_WARNING, |
3312 "single-line macro `%s' defined both with and" | 3376 "single-line macro `%s' defined both with and" |
3313 " without parameters", mname); | 3377 " without parameters", mname); |
3314 free_tlist(origline); | 3378 free_tlist(origline); |
3315 free_tlist(macro_start); | 3379 free_tlist(macro_start); |
3316 return DIRECTIVE_FOUND; | 3380 return DIRECTIVE_FOUND; |
3317 } | 3381 } |
3318 else | 3382 else if (smac->level == Level) |
3319 { | 3383 { |
3320 /* | 3384 /* |
3321 * We're redefining, so we have to take over an | 3385 * We're redefining in the same level, so we have to |
3322 * existing SMacro structure. This means freeing | 3386 * take over an existing SMacro structure. This means |
3323 * what was already in it. | 3387 * freeing what was already in it. |
3324 */ | 3388 */ |
3325 nasm_free(smac->name); | 3389 nasm_free(smac->name); |
3326 free_tlist(smac->expansion); | 3390 free_tlist(smac->expansion); |
3327 } | 3391 } |
| 3392 else |
| 3393 { |
| 3394 smac = nasm_malloc(sizeof(SMacro)); |
| 3395 smac->next = *smhead; |
| 3396 *smhead = smac; |
| 3397 } |
3328 } | 3398 } |
3329 else | 3399 else |
3330 { | 3400 { |
3331 smac = nasm_malloc(sizeof(SMacro)); | 3401 smac = nasm_malloc(sizeof(SMacro)); |
3332 smac->next = *smhead; | 3402 smac->next = *smhead; |
3333 *smhead = smac; | 3403 *smhead = smac; |
3334 } | 3404 } |
3335 smac->name = nasm_strdup(mname); | 3405 smac->name = nasm_strdup(mname); |
3336 smac->casesense = ((i == PP_DEFINE) || (i == PP_XDEFINE)); | 3406 smac->casesense = ((i == PP_DEFINE) || (i == PP_XDEFINE)); |
3337 smac->nparam = nparam; | 3407 smac->nparam = nparam; |
| 3408 smac->level = Level; |
3338 smac->expansion = macro_start; | 3409 smac->expansion = macro_start; |
3339 smac->in_progress = FALSE; | 3410 smac->in_progress = FALSE; |
3340 free_tlist(origline); | 3411 free_tlist(origline); |
3341 return DIRECTIVE_FOUND; | 3412 return DIRECTIVE_FOUND; |
3342 | 3413 |
3343 case PP_UNDEF: | 3414 case PP_UNDEF: |
3344 tline = tline->next; | 3415 tline = tline->next; |
3345 skip_white_(tline); | 3416 skip_white_(tline); |
3346 tline = expand_id(tline); | 3417 tline = expand_id(tline); |
3347 if (!tline || (tline->type != TOK_ID && | 3418 if (!tline || (tline->type != TOK_ID && |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3452 } | 3523 } |
3453 else | 3524 else |
3454 { | 3525 { |
3455 smac = nasm_malloc(sizeof(SMacro)); | 3526 smac = nasm_malloc(sizeof(SMacro)); |
3456 smac->next = *smhead; | 3527 smac->next = *smhead; |
3457 *smhead = smac; | 3528 *smhead = smac; |
3458 } | 3529 } |
3459 smac->name = nasm_strdup(mname); | 3530 smac->name = nasm_strdup(mname); |
3460 smac->casesense = (i == PP_STRLEN); | 3531 smac->casesense = (i == PP_STRLEN); |
3461 smac->nparam = 0; | 3532 smac->nparam = 0; |
| 3533 smac->level = 0; |
3462 smac->expansion = macro_start; | 3534 smac->expansion = macro_start; |
3463 smac->in_progress = FALSE; | 3535 smac->in_progress = FALSE; |
3464 free_tlist(tline); | 3536 free_tlist(tline); |
3465 free_tlist(origline); | 3537 free_tlist(origline); |
3466 return DIRECTIVE_FOUND; | 3538 return DIRECTIVE_FOUND; |
3467 | 3539 |
3468 case PP_SUBSTR: | 3540 case PP_SUBSTR: |
3469 tline = tline->next; | 3541 tline = tline->next; |
3470 skip_white_(tline); | 3542 skip_white_(tline); |
3471 tline = expand_id(tline); | 3543 tline = expand_id(tline); |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3562 } | 3634 } |
3563 else | 3635 else |
3564 { | 3636 { |
3565 smac = nasm_malloc(sizeof(SMacro)); | 3637 smac = nasm_malloc(sizeof(SMacro)); |
3566 smac->next = *smhead; | 3638 smac->next = *smhead; |
3567 *smhead = smac; | 3639 *smhead = smac; |
3568 } | 3640 } |
3569 smac->name = nasm_strdup(mname); | 3641 smac->name = nasm_strdup(mname); |
3570 smac->casesense = (i == PP_SUBSTR); | 3642 smac->casesense = (i == PP_SUBSTR); |
3571 smac->nparam = 0; | 3643 smac->nparam = 0; |
| 3644 smac->level = 0; |
3572 smac->expansion = macro_start; | 3645 smac->expansion = macro_start; |
3573 smac->in_progress = FALSE; | 3646 smac->in_progress = FALSE; |
3574 free_tlist(tline); | 3647 free_tlist(tline); |
3575 free_tlist(origline); | 3648 free_tlist(origline); |
3576 return DIRECTIVE_FOUND; | 3649 return DIRECTIVE_FOUND; |
3577 | 3650 |
3578 | 3651 |
3579 case PP_ASSIGN: | 3652 case PP_ASSIGN: |
3580 case PP_IASSIGN: | 3653 case PP_IASSIGN: |
3581 tline = tline->next; | 3654 tline = tline->next; |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3657 } | 3730 } |
3658 else | 3731 else |
3659 { | 3732 { |
3660 smac = nasm_malloc(sizeof(SMacro)); | 3733 smac = nasm_malloc(sizeof(SMacro)); |
3661 smac->next = *smhead; | 3734 smac->next = *smhead; |
3662 *smhead = smac; | 3735 *smhead = smac; |
3663 } | 3736 } |
3664 smac->name = nasm_strdup(mname); | 3737 smac->name = nasm_strdup(mname); |
3665 smac->casesense = (i == PP_ASSIGN); | 3738 smac->casesense = (i == PP_ASSIGN); |
3666 smac->nparam = 0; | 3739 smac->nparam = 0; |
| 3740 smac->level = 0; |
3667 smac->expansion = macro_start; | 3741 smac->expansion = macro_start; |
3668 smac->in_progress = FALSE; | 3742 smac->in_progress = FALSE; |
3669 free_tlist(origline); | 3743 free_tlist(origline); |
3670 return DIRECTIVE_FOUND; | 3744 return DIRECTIVE_FOUND; |
3671 | 3745 |
3672 case PP_LINE: | 3746 case PP_LINE: |
3673 /* | 3747 /* |
3674 * Syntax is `%line nnn[+mmm] [filename]' | 3748 * Syntax is `%line nnn[+mmm] [filename]' |
3675 */ | 3749 */ |
3676 tline = tline->next; | 3750 tline = tline->next; |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3777 while (tline) | 3851 while (tline) |
3778 { | 3852 { |
3779 if (tline->type == TOK_PREPROC_ID && | 3853 if (tline->type == TOK_PREPROC_ID && |
3780 (((tline->text[1] == '+' || tline->text[1] == '-') | 3854 (((tline->text[1] == '+' || tline->text[1] == '-') |
3781 && tline->text[2]) || tline->text[1] == '%' | 3855 && tline->text[2]) || tline->text[1] == '%' |
3782 || (tline->text[1] >= '0' && tline->text[1] <= '9'))) | 3856 || (tline->text[1] >= '0' && tline->text[1] <= '9'))) |
3783 { | 3857 { |
3784 char *text = NULL; | 3858 char *text = NULL; |
3785 int type = 0, cc; /* type = 0 to placate optimisers */ | 3859 int type = 0, cc; /* type = 0 to placate optimisers */ |
3786 char tmpbuf[30]; | 3860 char tmpbuf[30]; |
| 3861 char *second_text = NULL; |
3787 int n, i; | 3862 int n, i; |
3788 MMacro *mac; | 3863 MMacro *mac; |
3789 | 3864 |
3790 t = tline; | 3865 t = tline; |
3791 tline = tline->next; | 3866 tline = tline->next; |
3792 | 3867 |
| 3868 second_text = strchr(t->text, ':'); |
| 3869 |
3793 mac = istk->mstk; | 3870 mac = istk->mstk; |
3794 while (mac && !mac->name) /* avoid mistaking %reps for macros */ | 3871 while (mac && !mac->name) /* avoid mistaking %reps for macros */ |
3795 mac = mac->next_active; | 3872 mac = mac->next_active; |
3796 if (!mac) | 3873 if (!mac) |
3797 error(ERR_NONFATAL, "`%s': not in a macro call", t->text); | 3874 error(ERR_NONFATAL, "`%s': not in a macro call", t->text); |
3798 else | 3875 else |
3799 switch (t->text[1]) | 3876 { |
| 3877 if (second_text) |
3800 { | 3878 { |
3801 /* | 3879 int end = atoi(second_text+1)-1; |
3802 * We have to make a substitution of one of the | 3880 int is_fst = 1; |
3803 * forms %1, %-1, %+1, %%foo, %0. | 3881 int k; |
3804 */ | 3882 n = atoi(t->text + 1)-1; |
3805 case '0': | 3883 if (end < 0) |
3806 type = TOK_NUMBER; | 3884 end += mac->nparam; |
3807 sprintf(tmpbuf, "%ld", mac->nparam); | 3885 |
3808 text = nasm_strdup(tmpbuf); | 3886 for (k = n; k <= end; k++) |
3809 break; | 3887 { |
3810 case '%': | 3888 if (k >= mac->nparam) |
3811 type = TOK_ID; | |
3812 sprintf(tmpbuf, "..@%lu.", mac->unique); | |
3813 text = nasm_strcat(tmpbuf, t->text + 2); | |
3814 break; | |
3815 case '-': | |
3816 n = atoi(t->text + 2) - 1; | |
3817 if (n >= mac->nparam) | |
3818 tt = NULL; | 3889 tt = NULL; |
3819 else | 3890 else |
3820 { | 3891 { |
3821 if (mac->nparam > 1) | 3892 if (mac->nparam > 1) |
3822 n = (n + mac->rotate) % mac->nparam; | 3893 k = (k + mac->rotate) % mac->nparam; |
3823 tt = mac->params[n]; | 3894 tt = mac->params[k]; |
3824 } | |
3825 cc = find_cc(tt); | |
3826 if (cc == -1) | |
3827 { | |
3828 error(ERR_NONFATAL, | |
3829 "macro parameter %d is not a condition code"
, | |
3830 n + 1); | |
3831 text = NULL; | |
3832 } | |
3833 else | |
3834 { | |
3835 type = TOK_ID; | |
3836 if (inverse_ccs[cc] == -1) | |
3837 { | |
3838 error(ERR_NONFATAL, | |
3839 "condition code `%s' is not invertible", | |
3840 conditions[cc]); | |
3841 text = NULL; | |
3842 } | |
3843 else | |
3844 text = | |
3845 nasm_strdup(conditions[inverse_ccs | |
3846 [cc]]); | |
3847 } | |
3848 break; | |
3849 case '+': | |
3850 n = atoi(t->text + 2) - 1; | |
3851 if (n >= mac->nparam) | |
3852 tt = NULL; | |
3853 else | |
3854 { | |
3855 if (mac->nparam > 1) | |
3856 n = (n + mac->rotate) % mac->nparam; | |
3857 tt = mac->params[n]; | |
3858 } | |
3859 cc = find_cc(tt); | |
3860 if (cc == -1) | |
3861 { | |
3862 error(ERR_NONFATAL, | |
3863 "macro parameter %d is not a condition code"
, | |
3864 n + 1); | |
3865 text = NULL; | |
3866 } | |
3867 else | |
3868 { | |
3869 type = TOK_ID; | |
3870 text = nasm_strdup(conditions[cc]); | |
3871 } | |
3872 break; | |
3873 default: | |
3874 n = atoi(t->text + 1) - 1; | |
3875 if (n >= mac->nparam) | |
3876 tt = NULL; | |
3877 else | |
3878 { | |
3879 if (mac->nparam > 1) | |
3880 n = (n + mac->rotate) % mac->nparam; | |
3881 tt = mac->params[n]; | |
3882 } | 3895 } |
3883 if (tt) | 3896 if (tt) |
3884 { | 3897 { |
3885 for (i = 0; i < mac->paramlen[n]; i++) | 3898 if (!is_fst && mac->paramlen[k]) |
| 3899 { |
| 3900 *tail = new_Token(NULL, TOK_OTHER, ",", 0); |
| 3901 tail = &(*tail)->next; |
| 3902 } |
| 3903 if (mac->paramlen[k]) |
| 3904 is_fst = 0; |
| 3905 for (i = 0; i < mac->paramlen[k]; i++) |
3886 { | 3906 { |
3887 *tail = | 3907 *tail = |
3888 new_Token(NULL, tt->type, tt->text, | 3908 new_Token(NULL, tt->type, tt->text, |
3889 0); | 3909 0); |
3890 tail = &(*tail)->next; | 3910 tail = &(*tail)->next; |
3891 tt = tt->next; | 3911 tt = tt->next; |
3892 } | 3912 } |
3893 } | 3913 } |
3894 text = NULL; /* we've done it here */ | 3914 text = NULL; /* we've done it here */ |
3895 break; | 3915 } |
3896 } | 3916 } |
| 3917 else |
| 3918 { |
| 3919 switch (t->text[1]) |
| 3920 { |
| 3921 /* |
| 3922 * We have to make a substitution of one of the |
| 3923 * forms %1, %-1, %+1, %%foo, %0. |
| 3924 */ |
| 3925 case '0': |
| 3926 type = TOK_NUMBER; |
| 3927 sprintf(tmpbuf, "%ld", mac->nparam); |
| 3928 text = nasm_strdup(tmpbuf); |
| 3929 break; |
| 3930 case '%': |
| 3931 type = TOK_ID; |
| 3932 sprintf(tmpbuf, "..@%lu.", mac->unique); |
| 3933 text = nasm_strcat(tmpbuf, t->text + 2); |
| 3934 break; |
| 3935 case '-': |
| 3936 n = atoi(t->text + 2) - 1; |
| 3937 if (n >= mac->nparam) |
| 3938 tt = NULL; |
| 3939 else |
| 3940 { |
| 3941 if (mac->nparam > 1) |
| 3942 n = (n + mac->rotate) % mac->nparam; |
| 3943 tt = mac->params[n]; |
| 3944 } |
| 3945 cc = find_cc(tt); |
| 3946 if (cc == -1) |
| 3947 { |
| 3948 error(ERR_NONFATAL, |
| 3949 "macro parameter %d is not a condition c
ode", |
| 3950 n + 1); |
| 3951 text = NULL; |
| 3952 } |
| 3953 else |
| 3954 { |
| 3955 type = TOK_ID; |
| 3956 if (inverse_ccs[cc] == -1) |
| 3957 { |
| 3958 error(ERR_NONFATAL, |
| 3959 "condition code `%s' is not invertib
le", |
| 3960 conditions[cc]); |
| 3961 text = NULL; |
| 3962 } |
| 3963 else |
| 3964 text = |
| 3965 nasm_strdup(conditions[inverse_ccs |
| 3966 [cc]]); |
| 3967 } |
| 3968 break; |
| 3969 case '+': |
| 3970 n = atoi(t->text + 2) - 1; |
| 3971 if (n >= mac->nparam) |
| 3972 tt = NULL; |
| 3973 else |
| 3974 { |
| 3975 if (mac->nparam > 1) |
| 3976 n = (n + mac->rotate) % mac->nparam; |
| 3977 tt = mac->params[n]; |
| 3978 } |
| 3979 cc = find_cc(tt); |
| 3980 if (cc == -1) |
| 3981 { |
| 3982 error(ERR_NONFATAL, |
| 3983 "macro parameter %d is not a condition c
ode", |
| 3984 n + 1); |
| 3985 text = NULL; |
| 3986 } |
| 3987 else |
| 3988 { |
| 3989 type = TOK_ID; |
| 3990 text = nasm_strdup(conditions[cc]); |
| 3991 } |
| 3992 break; |
| 3993 default: |
| 3994 n = atoi(t->text + 1) - 1; |
| 3995 if (n >= mac->nparam) |
| 3996 tt = NULL; |
| 3997 else |
| 3998 { |
| 3999 if (mac->nparam > 1) |
| 4000 n = (n + mac->rotate) % mac->nparam; |
| 4001 tt = mac->params[n]; |
| 4002 } |
| 4003 if (tt) |
| 4004 { |
| 4005 for (i = 0; i < mac->paramlen[n]; i++) |
| 4006 { |
| 4007 *tail = |
| 4008 new_Token(NULL, tt->type, tt->text, |
| 4009 0); |
| 4010 tail = &(*tail)->next; |
| 4011 tt = tt->next; |
| 4012 } |
| 4013 } |
| 4014 text = NULL; /* we've done it here */ |
| 4015 break; |
| 4016 } |
| 4017 } |
| 4018 } |
| 4019 |
3897 if (!text) | 4020 if (!text) |
3898 { | 4021 { |
3899 delete_Token(t); | 4022 delete_Token(t); |
3900 } | 4023 } |
3901 else | 4024 else |
3902 { | 4025 { |
3903 *tail = t; | 4026 *tail = t; |
3904 tail = &t->next; | 4027 tail = &t->next; |
3905 t->type = type; | 4028 t->type = type; |
3906 nasm_free(t->text); | 4029 nasm_free(t->text); |
(...skipping 760 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4667 } | 4790 } |
4668 } | 4791 } |
4669 } | 4792 } |
4670 | 4793 |
4671 list->uplevel(m->nolist ? LIST_MACRO_NOLIST : LIST_MACRO); | 4794 list->uplevel(m->nolist ? LIST_MACRO_NOLIST : LIST_MACRO); |
4672 | 4795 |
4673 return 1; | 4796 return 1; |
4674 } | 4797 } |
4675 | 4798 |
4676 /* | 4799 /* |
4677 * Since preprocessor always operate only on the line that didn't | 4800 * Since preprocessor always operates only on the line that didn't |
4678 * arrived yet, we should always use ERR_OFFBY1. Also since user | 4801 * arrive yet, we should always use ERR_OFFBY1. Also since user |
4679 * won't want to see same error twice (preprocessing is done once | 4802 * won't want to see same error twice (preprocessing is done once |
4680 * per pass) we will want to show errors only during pass one. | 4803 * per pass) we will want to show errors only during pass one. |
4681 */ | 4804 */ |
4682 static void | 4805 static void |
4683 error(int severity, const char *fmt, ...) | 4806 error(int severity, const char *fmt, ...) |
4684 { | 4807 { |
4685 va_list arg; | 4808 va_list arg; |
4686 char buff[1024]; | 4809 char buff[1024]; |
4687 | 4810 |
4688 /* If we're in a dead branch of IF or something like it, ignore the error */ | 4811 /* If we're in a dead branch of IF or something like it, ignore the error */ |
4689 if (istk && istk->conds && !emitting(istk->conds->state)) | 4812 if (istk && istk->conds && !emitting(istk->conds->state)) |
4690 return; | 4813 return; |
4691 | 4814 |
4692 va_start(arg, fmt); | 4815 va_start(arg, fmt); |
| 4816 #ifdef HAVE_VSNPRINTF |
| 4817 vsnprintf(buff, sizeof(buff), fmt, arg); |
| 4818 #else |
4693 vsprintf(buff, fmt, arg); | 4819 vsprintf(buff, fmt, arg); |
| 4820 #endif |
4694 va_end(arg); | 4821 va_end(arg); |
4695 | 4822 |
4696 if (istk && istk->mstk && istk->mstk->name) | 4823 if (istk && istk->mstk && istk->mstk->name) |
4697 _error(severity | ERR_PASS1, "(%s:%d) %s", istk->mstk->name, | 4824 _error(severity | ERR_PASS1, "(%s:%d) %s", istk->mstk->name, |
4698 istk->mstk->lineno, buff); | 4825 istk->mstk->lineno, buff); |
4699 else | 4826 else |
4700 _error(severity | ERR_PASS1, "%s", buff); | 4827 _error(severity | ERR_PASS1, "%s", buff); |
4701 } | 4828 } |
4702 | 4829 |
4703 static void | 4830 static void |
(...skipping 351 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5055 nasm_free(i->fname); | 5182 nasm_free(i->fname); |
5056 nasm_free(i); | 5183 nasm_free(i); |
5057 } | 5184 } |
5058 while (cstk) | 5185 while (cstk) |
5059 ctx_pop(); | 5186 ctx_pop(); |
5060 if (pass_ == 0) | 5187 if (pass_ == 0) |
5061 { | 5188 { |
5062 free_llist(builtindef); | 5189 free_llist(builtindef); |
5063 free_llist(stddef); | 5190 free_llist(stddef); |
5064 free_llist(predef); | 5191 free_llist(predef); |
| 5192 builtindef = NULL; |
| 5193 stddef = NULL; |
| 5194 predef = NULL; |
| 5195 freeTokens = NULL; |
5065 delete_Blocks(); | 5196 delete_Blocks(); |
| 5197 blocks.next = NULL; |
| 5198 blocks.chunk = NULL; |
5066 } | 5199 } |
5067 } | 5200 } |
5068 | 5201 |
5069 void | 5202 void |
5070 pp_pre_include(const char *fname) | 5203 pp_pre_include(const char *fname) |
5071 { | 5204 { |
5072 Token *inc, *space, *name; | 5205 Token *inc, *space, *name; |
5073 Line *l; | 5206 Line *l; |
5074 | 5207 |
5075 name = new_Token(NULL, TOK_INTERNAL_STRING, fname, 0); | 5208 name = new_Token(NULL, TOK_INTERNAL_STRING, fname, 0); |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5174 { | 5307 { |
5175 tok->text = yasm_intnum_get_str(val); | 5308 tok->text = yasm_intnum_get_str(val); |
5176 tok->type = TOK_NUMBER; | 5309 tok->type = TOK_NUMBER; |
5177 } | 5310 } |
5178 | 5311 |
5179 Preproc nasmpp = { | 5312 Preproc nasmpp = { |
5180 pp_reset, | 5313 pp_reset, |
5181 pp_getline, | 5314 pp_getline, |
5182 pp_cleanup | 5315 pp_cleanup |
5183 }; | 5316 }; |
OLD | NEW |