/* * asm language mode for QEmacs. * * Copyright (c) 2000-2024 Charlie Gordon. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "qe.h" /*---------------- x86 Assembly language coloring ----------------*/ static char const asm_prepkeywords1[] = { "|align|arg|assume|codeseg|const|dataseg|display|dosseg" "|else|elseif|elseif1|elseif2|elseifb|elseifdef|elseifdif" "|elseifdifi|elseife|elseifidn|elseifidni|elseifnb|elseifndef" "|emul|end|endif|endm|endp|err|errif|errif1|errif2" "|errifb|errifdef|errifdif|errifdifi|errife|errifidn" "|errifidni|errifnb|errifndef|even|evendata|exitm|fardata" "|ideal|if|if1|if2|ifb|ifdef|ifdif|ifdifi|ife|ifidn" "|ifidni|ifnb|ifndef|include|includelib|irp|irpc" "|jumps|largestack|local|locals|macro|masm|masm51|model|multerrs" "|noemul|nojumps|nolocals|nomasm51|nomulterrs|nosmart|nowarn" "|proc|purge|quirks|radix|record|rept" "|smart|smallstack|stack|startupcode|subttl|title" "|version|warn|while" "|" }; static char const asm_prepkeywords2[] = { "|catstr|endp|ends|enum|equ|group" "|label|macro|proc|record|segment|struc" "|" }; /* colstate is used to store the comment character */ enum { ASM_STYLE_TEXT = QE_STYLE_DEFAULT, ASM_STYLE_PREPROCESS = QE_STYLE_PREPROCESS, ASM_STYLE_COMMENT = QE_STYLE_COMMENT, ASM_STYLE_STRING = QE_STYLE_STRING, ASM_STYLE_NUMBER = QE_STYLE_NUMBER, ASM_STYLE_IDENTIFIER = QE_STYLE_VARIABLE, }; static void asm_colorize_line(QEColorizeContext *cp, const char32_t *str, int n, QETermStyle *sbuf, ModeDef *syn) { char keyword[16]; int i = 0, start = 0, style = 0, len, wn = 0; /* word number on line */ int colstate = cp->colorize_state; char32_t c; if (colstate) goto in_comment; i = cp_skip_blanks(str, i, n); while (i < n) { start = i; c = str[i++]; switch (c) { case '\\': if (str[i] == '}' || str[i] == '{') goto prep; break; case '}': prep: /* scan for comment */ for (; i < n; i++) { if (str[i] == ';') break; } style = ASM_STYLE_PREPROCESS; break; case ';': i = n; style = ASM_STYLE_COMMENT; break; case '\'': case '\"': /* parse string const */ while (i < n && str[i++] != c) continue; style = ASM_STYLE_STRING; break; default: /* parse numbers */ if (qe_isdigit(c)) { for (; qe_isalnum(str[i]); i++) continue; style = ASM_STYLE_NUMBER; break; } /* parse identifiers and keywords */ if (qe_isalpha_(c) || qe_findchar("@.$%?", c)) { len = 0; keyword[len++] = qe_tolower(c); for (; qe_isalnum_(str[i]) || qe_findchar("@$%?", str[i]); i++) { if (len < countof(keyword) - 1) keyword[len++] = qe_tolower(str[i]); } keyword[len] = '\0'; if (++wn == 1) { if (strequal(keyword, "comment") && n > i) { SET_STYLE(sbuf, start, i, ASM_STYLE_PREPROCESS); i = cp_skip_blanks(str, i, n); start = i; colstate = str[i++]; /* end of comment character */ /* skip characters upto and including separator */ in_comment: while (i < n) { if ((char)str[i++] == (char)colstate) { colstate = 0; break; } } style = ASM_STYLE_COMMENT; break; } if (strfind(asm_prepkeywords1, keyword)) goto prep; } else if (wn == 2) { if (strfind(asm_prepkeywords2, keyword)) { style = ASM_STYLE_PREPROCESS; break; } } //SET_STYLE(sbuf, start, i, ASM_STYLE_IDENTIFIER); continue; } continue; } if (style) { SET_STYLE(sbuf, start, i, style); style = 0; } } cp->colorize_state = colstate; } static ModeDef asm_mode = { .name = "asm", .extensions = "asm|asi|cod", .colorize_func = asm_colorize_line, }; static int asm_init(QEmacsState *qs) { qe_register_mode(qs, &asm_mode, MODEF_SYNTAX); return 0; } qe_module_init(asm_init);