Mercurial > hg-old > index.cgi
view lwasm/pass1.c @ 340:1a6fc6ebb31c
Checkpoint
author | lost |
---|---|
date | Fri, 19 Mar 2010 02:54:43 +0000 |
parents | 04c80c51b16a |
children | 7b4123dce741 |
line wrap: on
line source
/* pass1.c Copyright © 2010 William Astle This file is part of LWTOOLS. LWTOOLS is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include <config.h> #include <stdio.h> #include <lw_alloc.h> #include "lwasm.h" #include "input.h" /* pass 1: parse the lines line format: [<symbol>] <opcode> <operand>[ <comment>] If <symbol> is followed by a :, whitespace may precede the symbol A line may optionally start with a number which must not be preceded by white space and must be followed by a single whitespace character. After that whitespace character, the line is parsed as if it had no line number. */ void do_pass1(asmstate_t *as) { char *line; line_t *cl; char *p1; int stpace; char *tok, *sym; int opnum; for (;;) { sym = NULL; line = input_readline(as); if (!line) break; printf("%s\n", line); cl = lw_alloc(sizeof(line_t)); cl -> next = NULL; cl -> prev = as -> line_tail; cl -> len = -1; cl -> insn = -1; if (!as -> line_tail) { as -> line_head = cl; cl -> addr = lw_expr_build(lw_expr_type_int, 0); } else { lw_expr_t te; as -> line_tail -> next = cl; te = lw_expr_build(lw_expr_type_special, lwasm_expr_linelen, cl -> prev); cl -> addr = lw_expr_build(lw_expr_type_oper, lw_expr_oper_plus, cl -> prev -> addr, te); lw_expr_destroy(te); lw_expr_simplify(cl -> addr); } as -> line_tail = cl; // blank lines don't count for anything if (!*line) { goto nextline; } // skip comments if (*line == '*' || *line == ';' || *line == '#') goto nextline; p1 = line; if (isdigit(*p1)) { // skip line number while (*p1 && isdigit(*p1)) p1++; if (!*p1 && !isspace(*p1)) p1 = line; else if (*p1 && isspace(*p1)) p1++; } if (!*p1) goto nextline; if (*p1 == '*' || *p1 == ';' || *p1 == '#') goto nextline; if (isspace(*p1)) { for (; *p1 && isspace(*p1); p1++) /* do nothing */ ; stspace = 1; } else stspace = 0; if (*p1 == '*' || *p1 == ';' || *p1 == '#' || !*p1) goto nextline; for (tok = p1; *p1 && !isspace(*p1) && *p1 != ':'; p1++) /* do nothing */ ; if (*p1 == ':' || stspace == 0) { // have a symbol here sym = lw_strndup(tok, p1 - tok); if (*p1 == ':') p1++; for (; *p1 && isspace(*p1); p1++) /* do nothing */ ; for (tok = p1; *p1 && !isspace(*p1); p1++) /* do nothing */ ; } cl -> sym = sym; cl -> symset = 0; // tok points to the opcode for the line or NUL if none if (*tok) { // look up operation code sym = lw_strndup(tok, p1 - tok); for (; *p1 && isspace(p1); p1++) /* do nothing */ ; for (opnum = 0; instab[opnum].opcode; opnum++) { if (!strcasecmp(instab[opnum].opcode, sym)) break; } lw_free(sym); // p1 points to the start of the operand if (instab[opnum].opcode == NULL) { cl -> insn = -1; if (*tok != ';' && *tok != '*') { // bad opcode; check for macro here } } else { cl -> insn = opnum; // call parse function if (*p1 && !isspace(*p1)) { // flag bad operand error } } } if (cl -> sym && cl -> symset == 0) { // register symbol at line address } lw_expr_print(cl -> addr); printf("\n"); // now parse the line nextline: lw_free(line); } }