339
|
1 /*
|
|
2 pass1.c
|
|
3 Copyright © 2008 William Astle
|
|
4
|
|
5 This file is part of LWASM.
|
|
6
|
|
7 LWASM is free software: you can redistribute it and/or modify it under the
|
|
8 terms of the GNU General Public License as published by the Free Software
|
|
9 Foundation, either version 3 of the License, or (at your option) any later
|
|
10 version.
|
|
11
|
|
12 This program is distributed in the hope that it will be useful, but WITHOUT
|
|
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
15 more details.
|
|
16
|
|
17 You should have received a copy of the GNU General Public License along with
|
|
18 this program. If not, see <http://www.gnu.org/licenses/>.
|
|
19
|
|
20
|
|
21 Handles first pass of assembly
|
|
22
|
|
23 First pass involves the following:
|
|
24
|
|
25 1. read all lines from the main source file, following all "include"
|
|
26 directives as appropriate
|
|
27 2. each operand is evaluated for syntax and futher for value if there are
|
|
28 multiple addressing sizes available; any undefined or not fully resolved
|
|
29 value will default to the largest addressing size available (16 bit)
|
|
30 3. addresses are assigned to every symbol defined in the assembly
|
|
31 4. macros are defined and expanded at this pass
|
|
32
|
|
33 * note: the lines are re-evaluated on the second pass
|
|
34
|
|
35 All source lines are read into memory with a record of the file name and
|
|
36 line number within the files.
|
|
37
|
|
38 Lines are one of the following formats:
|
|
39
|
|
40 <symbol> <opcode> <operand> <comment>
|
|
41 <symbol> <opcode> <comment>
|
|
42 <opcode> <operand> <comment>
|
|
43 <opcode> <comment>
|
|
44
|
|
45 A "*" or ";" appearing anywhere on the line that is not otherwise interpreted
|
|
46 as part of an operation code or operand introduces a comment.
|
|
47
|
|
48 Certain lwasm specific operations are prefixed with a "*" to aid in source
|
|
49 code portability (like *pragma).
|
|
50 */
|
|
51
|
|
52 #include <config.h>
|
|
53
|
|
54 #include <errno.h>
|
|
55 #include <stdio.h>
|
|
56 #include <stdlib.h>
|
|
57
|
|
58 #include "lwasm.h"
|
|
59 #include "util.h"
|
|
60
|
|
61
|
|
62 extern int lwasm_parse_line(asmstate_t *as, lwasm_line_t *l);
|
|
63
|
|
64 // we can't use standard line inputting functions here because we have to
|
|
65 // handle non-standard line terminations (CR, LF, CRLF, or LFCR)
|
|
66 int lwasm_read_file(asmstate_t *as, const char *filename)
|
|
67 {
|
|
68 FILE *f;
|
|
69 int c, c2;
|
|
70 lwasm_line_t *nl;
|
|
71 int lineno = 1;
|
|
72 char *fnref;
|
|
73
|
|
74 // ought to be long enough...we truncate longer lines
|
|
75 char linebuff[2049];
|
|
76 int lbloc = 0;
|
|
77 int eol = 0;
|
|
78
|
|
79 // add filename to list
|
|
80 as -> filelist = lwasm_realloc(as -> filelist, sizeof(char *) * (as -> filelistlen + 1));
|
|
81 fnref = as -> filelist[as -> filelistlen] = lwasm_strdup(filename);
|
|
82 as -> filelistlen += 1;
|
|
83
|
|
84 f = fopen(filename, "rb");
|
|
85 if (!f)
|
|
86 return -1;
|
|
87
|
|
88 for (;;)
|
|
89 {
|
|
90 c = fgetc(f);
|
|
91 if (c == EOF)
|
|
92 {
|
|
93 linebuff[lbloc] = '\0';
|
|
94 eol = 1;
|
|
95 }
|
|
96 else if (c == '\r')
|
|
97 {
|
|
98 linebuff[lbloc] = '\0';
|
|
99 eol = 1;
|
|
100 // check for '\n':
|
|
101 c2 = fgetc(f);
|
|
102 if (c2 == EOF)
|
|
103 c = EOF;
|
|
104 else if (c2 != '\n')
|
|
105 ungetc(c2, f);
|
|
106 }
|
|
107 else if (c == '\n')
|
|
108 {
|
|
109 linebuff[lbloc] = '\0';
|
|
110 eol = 1;
|
|
111 // check for '\r':
|
|
112 c2 = fgetc(f);
|
|
113 if (c2 == EOF)
|
|
114 c = EOF;
|
|
115 else if (c2 != '\r')
|
|
116 ungetc(c2, f);
|
|
117 }
|
|
118 else
|
|
119 {
|
|
120 // silently ignore characters past 2K on a line... FIXME
|
|
121 if (lbloc < 2048)
|
|
122 linebuff[lbloc++] = c;
|
|
123 }
|
|
124 if (eol)
|
|
125 {
|
|
126 eol = 0;
|
|
127 lbloc = 0;
|
|
128 nl = lwasm_alloc(sizeof(lwasm_line_t));
|
|
129 nl -> text = lwasm_strdup(linebuff);
|
|
130 nl -> lineno = lineno++;
|
|
131 nl -> filename = fnref;
|
|
132 nl -> next = NULL;
|
|
133 nl -> prev = as -> linestail;
|
|
134 nl -> err = NULL;
|
|
135 nl -> fsize = 0;
|
|
136 nl -> sym = NULL;
|
|
137 nl -> bytes = NULL;
|
|
138 nl -> codelen = 0;
|
|
139 nl -> codesize = 0;
|
|
140 nl -> nocodelen = 0;
|
|
141 nl -> addrset = 0;
|
|
142 nl -> symaddr = -1;
|
|
143 nl -> badop = 0;
|
|
144 nl -> relocoff = -1;
|
|
145 if (as -> linestail)
|
|
146 as -> linestail -> next = nl;
|
|
147 as -> linestail = nl;
|
|
148 if (!(as -> lineshead))
|
|
149 as -> lineshead = nl;
|
|
150 lwasm_parse_line(as, nl);
|
|
151 if (as -> endseen)
|
|
152 break;
|
|
153 }
|
|
154 if (c == EOF)
|
|
155 break;
|
|
156 }
|
|
157
|
|
158 fclose(f);
|
|
159 return 0;
|
|
160 }
|
|
161
|
|
162 void lwasm_pass1(asmstate_t *as)
|
|
163 {
|
|
164 as -> passnum = 1;
|
|
165 as -> addr = 0;
|
|
166 as -> nextcontext = 1;
|
|
167
|
|
168 as -> inmod = 0;
|
|
169
|
|
170 debug_message(1, "Entering pass 1");
|
|
171 if (lwasm_read_file(as, as -> infile) < 0)
|
|
172 {
|
|
173 fprintf(stderr, "Error reading input file '%s'", as -> infile);
|
|
174 perror("");
|
|
175 exit(1);
|
|
176 }
|
|
177
|
|
178 }
|