├── .gitignore
├── C-Documentation.pdf
├── LICENSE
├── README.md
├── examples
├── Makefile
├── bin
│ └── stub
└── src
│ ├── ex1.c
│ ├── ex2.c
│ ├── ex3.c
│ ├── ex4.c
│ ├── ex5.c
│ ├── ex6.c
│ └── ex7.c
└── src
├── .deps
├── error.Po
├── main.Po
├── parser.Po
├── preprocessor.Po
├── scanner.Po
├── symbol.Po
└── utils.Po
├── Makefile
├── compiler
├── Makefile
├── drivers
│ ├── error
│ │ └── make_err.c
│ ├── parser
│ │ └── get_token.c
│ ├── preprocessor
│ │ ├── fseek_test.c
│ │ ├── get_inc_fname.c
│ │ └── get_next_word.c
│ ├── scanner
│ │ ├── extract_token.c
│ │ ├── get_lexeme.c
│ │ ├── get_token.c
│ │ ├── is_valid_id.c
│ │ ├── return_string.c
│ │ └── write_token.c
│ ├── semantic
│ │ └── stub
│ ├── symbol
│ │ └── is_keyword.c
│ └── utils
│ │ ├── bsearch.c
│ │ ├── fcpeek.c
│ │ ├── get_column.c
│ │ ├── get_files_from_argv.c
│ │ ├── get_filesize.c
│ │ ├── getword.c
│ │ ├── scan_for_o.c
│ │ └── strip_whitesp.c
├── error.c
├── error.h
├── main.c
├── main.h
├── parser.c
├── parser.h
├── preprocessor.c
├── preprocessor.h
├── scanner.c
├── scanner.h
├── symbol.c
├── symbol.h
├── utils.c
└── utils.h
└── cvm
├── Makefile
├── cvm.c
├── cvm.h
└── drivers
└── main.c
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 |
3 | docs/*
4 | docs/html/*
5 | docs/latex/*
6 |
--------------------------------------------------------------------------------
/C-Documentation.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eudisd/c-compiler/9aa5e08fe4217accd4935b8120178e4e0377e0a0/C-Documentation.pdf
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 | Preamble
9 |
10 | The GNU General Public License is a free, copyleft license for
11 | software and other kinds of works.
12 |
13 | The licenses for most software and other practical works are designed
14 | to take away your freedom to share and change the works. By contrast,
15 | the GNU General Public License is intended to guarantee your freedom to
16 | share and change all versions of a program--to make sure it remains free
17 | software for all its users. We, the Free Software Foundation, use the
18 | GNU General Public License for most of our software; it applies also to
19 | any other work released this way by its authors. You can apply it to
20 | your programs, too.
21 |
22 | When we speak of free software, we are referring to freedom, not
23 | price. Our General Public Licenses are designed to make sure that you
24 | have the freedom to distribute copies of free software (and charge for
25 | them if you wish), that you receive source code or can get it if you
26 | want it, that you can change the software or use pieces of it in new
27 | free programs, and that you know you can do these things.
28 |
29 | To protect your rights, we need to prevent others from denying you
30 | these rights or asking you to surrender the rights. Therefore, you have
31 | certain responsibilities if you distribute copies of the software, or if
32 | you modify it: responsibilities to respect the freedom of others.
33 |
34 | For example, if you distribute copies of such a program, whether
35 | gratis or for a fee, you must pass on to the recipients the same
36 | freedoms that you received. You must make sure that they, too, receive
37 | or can get the source code. And you must show them these terms so they
38 | know their rights.
39 |
40 | Developers that use the GNU GPL protect your rights with two steps:
41 | (1) assert copyright on the software, and (2) offer you this License
42 | giving you legal permission to copy, distribute and/or modify it.
43 |
44 | For the developers' and authors' protection, the GPL clearly explains
45 | that there is no warranty for this free software. For both users' and
46 | authors' sake, the GPL requires that modified versions be marked as
47 | changed, so that their problems will not be attributed erroneously to
48 | authors of previous versions.
49 |
50 | Some devices are designed to deny users access to install or run
51 | modified versions of the software inside them, although the manufacturer
52 | can do so. This is fundamentally incompatible with the aim of
53 | protecting users' freedom to change the software. The systematic
54 | pattern of such abuse occurs in the area of products for individuals to
55 | use, which is precisely where it is most unacceptable. Therefore, we
56 | have designed this version of the GPL to prohibit the practice for those
57 | products. If such problems arise substantially in other domains, we
58 | stand ready to extend this provision to those domains in future versions
59 | of the GPL, as needed to protect the freedom of users.
60 |
61 | Finally, every program is threatened constantly by software patents.
62 | States should not allow patents to restrict development and use of
63 | software on general-purpose computers, but in those that do, we wish to
64 | avoid the special danger that patents applied to a free program could
65 | make it effectively proprietary. To prevent this, the GPL assures that
66 | patents cannot be used to render the program non-free.
67 |
68 | The precise terms and conditions for copying, distribution and
69 | modification follow.
70 |
71 | TERMS AND CONDITIONS
72 |
73 | 0. Definitions.
74 |
75 | "This License" refers to version 3 of the GNU General Public License.
76 |
77 | "Copyright" also means copyright-like laws that apply to other kinds of
78 | works, such as semiconductor masks.
79 |
80 | "The Program" refers to any copyrightable work licensed under this
81 | License. Each licensee is addressed as "you". "Licensees" and
82 | "recipients" may be individuals or organizations.
83 |
84 | To "modify" a work means to copy from or adapt all or part of the work
85 | in a fashion requiring copyright permission, other than the making of an
86 | exact copy. The resulting work is called a "modified version" of the
87 | earlier work or a work "based on" the earlier work.
88 |
89 | A "covered work" means either the unmodified Program or a work based
90 | on the Program.
91 |
92 | To "propagate" a work means to do anything with it that, without
93 | permission, would make you directly or secondarily liable for
94 | infringement under applicable copyright law, except executing it on a
95 | computer or modifying a private copy. Propagation includes copying,
96 | distribution (with or without modification), making available to the
97 | public, and in some countries other activities as well.
98 |
99 | To "convey" a work means any kind of propagation that enables other
100 | parties to make or receive copies. Mere interaction with a user through
101 | a computer network, with no transfer of a copy, is not conveying.
102 |
103 | An interactive user interface displays "Appropriate Legal Notices"
104 | to the extent that it includes a convenient and prominently visible
105 | feature that (1) displays an appropriate copyright notice, and (2)
106 | tells the user that there is no warranty for the work (except to the
107 | extent that warranties are provided), that licensees may convey the
108 | work under this License, and how to view a copy of this License. If
109 | the interface presents a list of user commands or options, such as a
110 | menu, a prominent item in the list meets this criterion.
111 |
112 | 1. Source Code.
113 |
114 | The "source code" for a work means the preferred form of the work
115 | for making modifications to it. "Object code" means any non-source
116 | form of a work.
117 |
118 | A "Standard Interface" means an interface that either is an official
119 | standard defined by a recognized standards body, or, in the case of
120 | interfaces specified for a particular programming language, one that
121 | is widely used among developers working in that language.
122 |
123 | The "System Libraries" of an executable work include anything, other
124 | than the work as a whole, that (a) is included in the normal form of
125 | packaging a Major Component, but which is not part of that Major
126 | Component, and (b) serves only to enable use of the work with that
127 | Major Component, or to implement a Standard Interface for which an
128 | implementation is available to the public in source code form. A
129 | "Major Component", in this context, means a major essential component
130 | (kernel, window system, and so on) of the specific operating system
131 | (if any) on which the executable work runs, or a compiler used to
132 | produce the work, or an object code interpreter used to run it.
133 |
134 | The "Corresponding Source" for a work in object code form means all
135 | the source code needed to generate, install, and (for an executable
136 | work) run the object code and to modify the work, including scripts to
137 | control those activities. However, it does not include the work's
138 | System Libraries, or general-purpose tools or generally available free
139 | programs which are used unmodified in performing those activities but
140 | which are not part of the work. For example, Corresponding Source
141 | includes interface definition files associated with source files for
142 | the work, and the source code for shared libraries and dynamically
143 | linked subprograms that the work is specifically designed to require,
144 | such as by intimate data communication or control flow between those
145 | subprograms and other parts of the work.
146 |
147 | The Corresponding Source need not include anything that users
148 | can regenerate automatically from other parts of the Corresponding
149 | Source.
150 |
151 | The Corresponding Source for a work in source code form is that
152 | same work.
153 |
154 | 2. Basic Permissions.
155 |
156 | All rights granted under this License are granted for the term of
157 | copyright on the Program, and are irrevocable provided the stated
158 | conditions are met. This License explicitly affirms your unlimited
159 | permission to run the unmodified Program. The output from running a
160 | covered work is covered by this License only if the output, given its
161 | content, constitutes a covered work. This License acknowledges your
162 | rights of fair use or other equivalent, as provided by copyright law.
163 |
164 | You may make, run and propagate covered works that you do not
165 | convey, without conditions so long as your license otherwise remains
166 | in force. You may convey covered works to others for the sole purpose
167 | of having them make modifications exclusively for you, or provide you
168 | with facilities for running those works, provided that you comply with
169 | the terms of this License in conveying all material for which you do
170 | not control copyright. Those thus making or running the covered works
171 | for you must do so exclusively on your behalf, under your direction
172 | and control, on terms that prohibit them from making any copies of
173 | your copyrighted material outside their relationship with you.
174 |
175 | Conveying under any other circumstances is permitted solely under
176 | the conditions stated below. Sublicensing is not allowed; section 10
177 | makes it unnecessary.
178 |
179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
180 |
181 | No covered work shall be deemed part of an effective technological
182 | measure under any applicable law fulfilling obligations under article
183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or
184 | similar laws prohibiting or restricting circumvention of such
185 | measures.
186 |
187 | When you convey a covered work, you waive any legal power to forbid
188 | circumvention of technological measures to the extent such circumvention
189 | is effected by exercising rights under this License with respect to
190 | the covered work, and you disclaim any intention to limit operation or
191 | modification of the work as a means of enforcing, against the work's
192 | users, your or third parties' legal rights to forbid circumvention of
193 | technological measures.
194 |
195 | 4. Conveying Verbatim Copies.
196 |
197 | You may convey verbatim copies of the Program's source code as you
198 | receive it, in any medium, provided that you conspicuously and
199 | appropriately publish on each copy an appropriate copyright notice;
200 | keep intact all notices stating that this License and any
201 | non-permissive terms added in accord with section 7 apply to the code;
202 | keep intact all notices of the absence of any warranty; and give all
203 | recipients a copy of this License along with the Program.
204 |
205 | You may charge any price or no price for each copy that you convey,
206 | and you may offer support or warranty protection for a fee.
207 |
208 | 5. Conveying Modified Source Versions.
209 |
210 | You may convey a work based on the Program, or the modifications to
211 | produce it from the Program, in the form of source code under the
212 | terms of section 4, provided that you also meet all of these conditions:
213 |
214 | a) The work must carry prominent notices stating that you modified
215 | it, and giving a relevant date.
216 |
217 | b) The work must carry prominent notices stating that it is
218 | released under this License and any conditions added under section
219 | 7. This requirement modifies the requirement in section 4 to
220 | "keep intact all notices".
221 |
222 | c) You must license the entire work, as a whole, under this
223 | License to anyone who comes into possession of a copy. This
224 | License will therefore apply, along with any applicable section 7
225 | additional terms, to the whole of the work, and all its parts,
226 | regardless of how they are packaged. This License gives no
227 | permission to license the work in any other way, but it does not
228 | invalidate such permission if you have separately received it.
229 |
230 | d) If the work has interactive user interfaces, each must display
231 | Appropriate Legal Notices; however, if the Program has interactive
232 | interfaces that do not display Appropriate Legal Notices, your
233 | work need not make them do so.
234 |
235 | A compilation of a covered work with other separate and independent
236 | works, which are not by their nature extensions of the covered work,
237 | and which are not combined with it such as to form a larger program,
238 | in or on a volume of a storage or distribution medium, is called an
239 | "aggregate" if the compilation and its resulting copyright are not
240 | used to limit the access or legal rights of the compilation's users
241 | beyond what the individual works permit. Inclusion of a covered work
242 | in an aggregate does not cause this License to apply to the other
243 | parts of the aggregate.
244 |
245 | 6. Conveying Non-Source Forms.
246 |
247 | You may convey a covered work in object code form under the terms
248 | of sections 4 and 5, provided that you also convey the
249 | machine-readable Corresponding Source under the terms of this License,
250 | in one of these ways:
251 |
252 | a) Convey the object code in, or embodied in, a physical product
253 | (including a physical distribution medium), accompanied by the
254 | Corresponding Source fixed on a durable physical medium
255 | customarily used for software interchange.
256 |
257 | b) Convey the object code in, or embodied in, a physical product
258 | (including a physical distribution medium), accompanied by a
259 | written offer, valid for at least three years and valid for as
260 | long as you offer spare parts or customer support for that product
261 | model, to give anyone who possesses the object code either (1) a
262 | copy of the Corresponding Source for all the software in the
263 | product that is covered by this License, on a durable physical
264 | medium customarily used for software interchange, for a price no
265 | more than your reasonable cost of physically performing this
266 | conveying of source, or (2) access to copy the
267 | Corresponding Source from a network server at no charge.
268 |
269 | c) Convey individual copies of the object code with a copy of the
270 | written offer to provide the Corresponding Source. This
271 | alternative is allowed only occasionally and noncommercially, and
272 | only if you received the object code with such an offer, in accord
273 | with subsection 6b.
274 |
275 | d) Convey the object code by offering access from a designated
276 | place (gratis or for a charge), and offer equivalent access to the
277 | Corresponding Source in the same way through the same place at no
278 | further charge. You need not require recipients to copy the
279 | Corresponding Source along with the object code. If the place to
280 | copy the object code is a network server, the Corresponding Source
281 | may be on a different server (operated by you or a third party)
282 | that supports equivalent copying facilities, provided you maintain
283 | clear directions next to the object code saying where to find the
284 | Corresponding Source. Regardless of what server hosts the
285 | Corresponding Source, you remain obligated to ensure that it is
286 | available for as long as needed to satisfy these requirements.
287 |
288 | e) Convey the object code using peer-to-peer transmission, provided
289 | you inform other peers where the object code and Corresponding
290 | Source of the work are being offered to the general public at no
291 | charge under subsection 6d.
292 |
293 | A separable portion of the object code, whose source code is excluded
294 | from the Corresponding Source as a System Library, need not be
295 | included in conveying the object code work.
296 |
297 | A "User Product" is either (1) a "consumer product", which means any
298 | tangible personal property which is normally used for personal, family,
299 | or household purposes, or (2) anything designed or sold for incorporation
300 | into a dwelling. In determining whether a product is a consumer product,
301 | doubtful cases shall be resolved in favor of coverage. For a particular
302 | product received by a particular user, "normally used" refers to a
303 | typical or common use of that class of product, regardless of the status
304 | of the particular user or of the way in which the particular user
305 | actually uses, or expects or is expected to use, the product. A product
306 | is a consumer product regardless of whether the product has substantial
307 | commercial, industrial or non-consumer uses, unless such uses represent
308 | the only significant mode of use of the product.
309 |
310 | "Installation Information" for a User Product means any methods,
311 | procedures, authorization keys, or other information required to install
312 | and execute modified versions of a covered work in that User Product from
313 | a modified version of its Corresponding Source. The information must
314 | suffice to ensure that the continued functioning of the modified object
315 | code is in no case prevented or interfered with solely because
316 | modification has been made.
317 |
318 | If you convey an object code work under this section in, or with, or
319 | specifically for use in, a User Product, and the conveying occurs as
320 | part of a transaction in which the right of possession and use of the
321 | User Product is transferred to the recipient in perpetuity or for a
322 | fixed term (regardless of how the transaction is characterized), the
323 | Corresponding Source conveyed under this section must be accompanied
324 | by the Installation Information. But this requirement does not apply
325 | if neither you nor any third party retains the ability to install
326 | modified object code on the User Product (for example, the work has
327 | been installed in ROM).
328 |
329 | The requirement to provide Installation Information does not include a
330 | requirement to continue to provide support service, warranty, or updates
331 | for a work that has been modified or installed by the recipient, or for
332 | the User Product in which it has been modified or installed. Access to a
333 | network may be denied when the modification itself materially and
334 | adversely affects the operation of the network or violates the rules and
335 | protocols for communication across the network.
336 |
337 | Corresponding Source conveyed, and Installation Information provided,
338 | in accord with this section must be in a format that is publicly
339 | documented (and with an implementation available to the public in
340 | source code form), and must require no special password or key for
341 | unpacking, reading or copying.
342 |
343 | 7. Additional Terms.
344 |
345 | "Additional permissions" are terms that supplement the terms of this
346 | License by making exceptions from one or more of its conditions.
347 | Additional permissions that are applicable to the entire Program shall
348 | be treated as though they were included in this License, to the extent
349 | that they are valid under applicable law. If additional permissions
350 | apply only to part of the Program, that part may be used separately
351 | under those permissions, but the entire Program remains governed by
352 | this License without regard to the additional permissions.
353 |
354 | When you convey a copy of a covered work, you may at your option
355 | remove any additional permissions from that copy, or from any part of
356 | it. (Additional permissions may be written to require their own
357 | removal in certain cases when you modify the work.) You may place
358 | additional permissions on material, added by you to a covered work,
359 | for which you have or can give appropriate copyright permission.
360 |
361 | Notwithstanding any other provision of this License, for material you
362 | add to a covered work, you may (if authorized by the copyright holders of
363 | that material) supplement the terms of this License with terms:
364 |
365 | a) Disclaiming warranty or limiting liability differently from the
366 | terms of sections 15 and 16 of this License; or
367 |
368 | b) Requiring preservation of specified reasonable legal notices or
369 | author attributions in that material or in the Appropriate Legal
370 | Notices displayed by works containing it; or
371 |
372 | c) Prohibiting misrepresentation of the origin of that material, or
373 | requiring that modified versions of such material be marked in
374 | reasonable ways as different from the original version; or
375 |
376 | d) Limiting the use for publicity purposes of names of licensors or
377 | authors of the material; or
378 |
379 | e) Declining to grant rights under trademark law for use of some
380 | trade names, trademarks, or service marks; or
381 |
382 | f) Requiring indemnification of licensors and authors of that
383 | material by anyone who conveys the material (or modified versions of
384 | it) with contractual assumptions of liability to the recipient, for
385 | any liability that these contractual assumptions directly impose on
386 | those licensors and authors.
387 |
388 | All other non-permissive additional terms are considered "further
389 | restrictions" within the meaning of section 10. If the Program as you
390 | received it, or any part of it, contains a notice stating that it is
391 | governed by this License along with a term that is a further
392 | restriction, you may remove that term. If a license document contains
393 | a further restriction but permits relicensing or conveying under this
394 | License, you may add to a covered work material governed by the terms
395 | of that license document, provided that the further restriction does
396 | not survive such relicensing or conveying.
397 |
398 | If you add terms to a covered work in accord with this section, you
399 | must place, in the relevant source files, a statement of the
400 | additional terms that apply to those files, or a notice indicating
401 | where to find the applicable terms.
402 |
403 | Additional terms, permissive or non-permissive, may be stated in the
404 | form of a separately written license, or stated as exceptions;
405 | the above requirements apply either way.
406 |
407 | 8. Termination.
408 |
409 | You may not propagate or modify a covered work except as expressly
410 | provided under this License. Any attempt otherwise to propagate or
411 | modify it is void, and will automatically terminate your rights under
412 | this License (including any patent licenses granted under the third
413 | paragraph of section 11).
414 |
415 | However, if you cease all violation of this License, then your
416 | license from a particular copyright holder is reinstated (a)
417 | provisionally, unless and until the copyright holder explicitly and
418 | finally terminates your license, and (b) permanently, if the copyright
419 | holder fails to notify you of the violation by some reasonable means
420 | prior to 60 days after the cessation.
421 |
422 | Moreover, your license from a particular copyright holder is
423 | reinstated permanently if the copyright holder notifies you of the
424 | violation by some reasonable means, this is the first time you have
425 | received notice of violation of this License (for any work) from that
426 | copyright holder, and you cure the violation prior to 30 days after
427 | your receipt of the notice.
428 |
429 | Termination of your rights under this section does not terminate the
430 | licenses of parties who have received copies or rights from you under
431 | this License. If your rights have been terminated and not permanently
432 | reinstated, you do not qualify to receive new licenses for the same
433 | material under section 10.
434 |
435 | 9. Acceptance Not Required for Having Copies.
436 |
437 | You are not required to accept this License in order to receive or
438 | run a copy of the Program. Ancillary propagation of a covered work
439 | occurring solely as a consequence of using peer-to-peer transmission
440 | to receive a copy likewise does not require acceptance. However,
441 | nothing other than this License grants you permission to propagate or
442 | modify any covered work. These actions infringe copyright if you do
443 | not accept this License. Therefore, by modifying or propagating a
444 | covered work, you indicate your acceptance of this License to do so.
445 |
446 | 10. Automatic Licensing of Downstream Recipients.
447 |
448 | Each time you convey a covered work, the recipient automatically
449 | receives a license from the original licensors, to run, modify and
450 | propagate that work, subject to this License. You are not responsible
451 | for enforcing compliance by third parties with this License.
452 |
453 | An "entity transaction" is a transaction transferring control of an
454 | organization, or substantially all assets of one, or subdividing an
455 | organization, or merging organizations. If propagation of a covered
456 | work results from an entity transaction, each party to that
457 | transaction who receives a copy of the work also receives whatever
458 | licenses to the work the party's predecessor in interest had or could
459 | give under the previous paragraph, plus a right to possession of the
460 | Corresponding Source of the work from the predecessor in interest, if
461 | the predecessor has it or can get it with reasonable efforts.
462 |
463 | You may not impose any further restrictions on the exercise of the
464 | rights granted or affirmed under this License. For example, you may
465 | not impose a license fee, royalty, or other charge for exercise of
466 | rights granted under this License, and you may not initiate litigation
467 | (including a cross-claim or counterclaim in a lawsuit) alleging that
468 | any patent claim is infringed by making, using, selling, offering for
469 | sale, or importing the Program or any portion of it.
470 |
471 | 11. Patents.
472 |
473 | A "contributor" is a copyright holder who authorizes use under this
474 | License of the Program or a work on which the Program is based. The
475 | work thus licensed is called the contributor's "contributor version".
476 |
477 | A contributor's "essential patent claims" are all patent claims
478 | owned or controlled by the contributor, whether already acquired or
479 | hereafter acquired, that would be infringed by some manner, permitted
480 | by this License, of making, using, or selling its contributor version,
481 | but do not include claims that would be infringed only as a
482 | consequence of further modification of the contributor version. For
483 | purposes of this definition, "control" includes the right to grant
484 | patent sublicenses in a manner consistent with the requirements of
485 | this License.
486 |
487 | Each contributor grants you a non-exclusive, worldwide, royalty-free
488 | patent license under the contributor's essential patent claims, to
489 | make, use, sell, offer for sale, import and otherwise run, modify and
490 | propagate the contents of its contributor version.
491 |
492 | In the following three paragraphs, a "patent license" is any express
493 | agreement or commitment, however denominated, not to enforce a patent
494 | (such as an express permission to practice a patent or covenant not to
495 | sue for patent infringement). To "grant" such a patent license to a
496 | party means to make such an agreement or commitment not to enforce a
497 | patent against the party.
498 |
499 | If you convey a covered work, knowingly relying on a patent license,
500 | and the Corresponding Source of the work is not available for anyone
501 | to copy, free of charge and under the terms of this License, through a
502 | publicly available network server or other readily accessible means,
503 | then you must either (1) cause the Corresponding Source to be so
504 | available, or (2) arrange to deprive yourself of the benefit of the
505 | patent license for this particular work, or (3) arrange, in a manner
506 | consistent with the requirements of this License, to extend the patent
507 | license to downstream recipients. "Knowingly relying" means you have
508 | actual knowledge that, but for the patent license, your conveying the
509 | covered work in a country, or your recipient's use of the covered work
510 | in a country, would infringe one or more identifiable patents in that
511 | country that you have reason to believe are valid.
512 |
513 | If, pursuant to or in connection with a single transaction or
514 | arrangement, you convey, or propagate by procuring conveyance of, a
515 | covered work, and grant a patent license to some of the parties
516 | receiving the covered work authorizing them to use, propagate, modify
517 | or convey a specific copy of the covered work, then the patent license
518 | you grant is automatically extended to all recipients of the covered
519 | work and works based on it.
520 |
521 | A patent license is "discriminatory" if it does not include within
522 | the scope of its coverage, prohibits the exercise of, or is
523 | conditioned on the non-exercise of one or more of the rights that are
524 | specifically granted under this License. You may not convey a covered
525 | work if you are a party to an arrangement with a third party that is
526 | in the business of distributing software, under which you make payment
527 | to the third party based on the extent of your activity of conveying
528 | the work, and under which the third party grants, to any of the
529 | parties who would receive the covered work from you, a discriminatory
530 | patent license (a) in connection with copies of the covered work
531 | conveyed by you (or copies made from those copies), or (b) primarily
532 | for and in connection with specific products or compilations that
533 | contain the covered work, unless you entered into that arrangement,
534 | or that patent license was granted, prior to 28 March 2007.
535 |
536 | Nothing in this License shall be construed as excluding or limiting
537 | any implied license or other defenses to infringement that may
538 | otherwise be available to you under applicable patent law.
539 |
540 | 12. No Surrender of Others' Freedom.
541 |
542 | If conditions are imposed on you (whether by court order, agreement or
543 | otherwise) that contradict the conditions of this License, they do not
544 | excuse you from the conditions of this License. If you cannot convey a
545 | covered work so as to satisfy simultaneously your obligations under this
546 | License and any other pertinent obligations, then as a consequence you may
547 | not convey it at all. For example, if you agree to terms that obligate you
548 | to collect a royalty for further conveying from those to whom you convey
549 | the Program, the only way you could satisfy both those terms and this
550 | License would be to refrain entirely from conveying the Program.
551 |
552 | 13. Use with the GNU Affero General Public License.
553 |
554 | Notwithstanding any other provision of this License, you have
555 | permission to link or combine any covered work with a work licensed
556 | under version 3 of the GNU Affero General Public License into a single
557 | combined work, and to convey the resulting work. The terms of this
558 | License will continue to apply to the part which is the covered work,
559 | but the special requirements of the GNU Affero General Public License,
560 | section 13, concerning interaction through a network will apply to the
561 | combination as such.
562 |
563 | 14. Revised Versions of this License.
564 |
565 | The Free Software Foundation may publish revised and/or new versions of
566 | the GNU General Public License from time to time. Such new versions will
567 | be similar in spirit to the present version, but may differ in detail to
568 | address new problems or concerns.
569 |
570 | Each version is given a distinguishing version number. If the
571 | Program specifies that a certain numbered version of the GNU General
572 | Public License "or any later version" applies to it, you have the
573 | option of following the terms and conditions either of that numbered
574 | version or of any later version published by the Free Software
575 | Foundation. If the Program does not specify a version number of the
576 | GNU General Public License, you may choose any version ever published
577 | by the Free Software Foundation.
578 |
579 | If the Program specifies that a proxy can decide which future
580 | versions of the GNU General Public License can be used, that proxy's
581 | public statement of acceptance of a version permanently authorizes you
582 | to choose that version for the Program.
583 |
584 | Later license versions may give you additional or different
585 | permissions. However, no additional obligations are imposed on any
586 | author or copyright holder as a result of your choosing to follow a
587 | later version.
588 |
589 | 15. Disclaimer of Warranty.
590 |
591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
599 |
600 | 16. Limitation of Liability.
601 |
602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
610 | SUCH DAMAGES.
611 |
612 | 17. Interpretation of Sections 15 and 16.
613 |
614 | If the disclaimer of warranty and limitation of liability provided
615 | above cannot be given local legal effect according to their terms,
616 | reviewing courts shall apply local law that most closely approximates
617 | an absolute waiver of all civil liability in connection with the
618 | Program, unless a warranty or assumption of liability accompanies a
619 | copy of the Program in return for a fee.
620 |
621 | END OF TERMS AND CONDITIONS
622 |
623 | How to Apply These Terms to Your New Programs
624 |
625 | If you develop a new program, and you want it to be of the greatest
626 | possible use to the public, the best way to achieve this is to make it
627 | free software which everyone can redistribute and change under these terms.
628 |
629 | To do so, attach the following notices to the program. It is safest
630 | to attach them to the start of each source file to most effectively
631 | state the exclusion of warranty; and each file should have at least
632 | the "copyright" line and a pointer to where the full notice is found.
633 |
634 |
635 | Copyright (C)
636 |
637 | This program is free software: you can redistribute it and/or modify
638 | it under the terms of the GNU General Public License as published by
639 | the Free Software Foundation, either version 3 of the License, or
640 | (at your option) any later version.
641 |
642 | This program is distributed in the hope that it will be useful,
643 | but WITHOUT ANY WARRANTY; without even the implied warranty of
644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
645 | GNU General Public License for more details.
646 |
647 | You should have received a copy of the GNU General Public License
648 | along with this program. If not, see .
649 |
650 | Also add information on how to contact you by electronic and paper mail.
651 |
652 | If the program does terminal interaction, make it output a short
653 | notice like this when it starts in an interactive mode:
654 |
655 | Copyright (C)
656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
657 | This is free software, and you are welcome to redistribute it
658 | under certain conditions; type `show c' for details.
659 |
660 | The hypothetical commands `show w' and `show c' should show the appropriate
661 | parts of the General Public License. Of course, your program's commands
662 | might be different; for a GUI interface, you would use an "about box".
663 |
664 | You should also get your employer (if you work as a programmer) or school,
665 | if any, to sign a "copyright disclaimer" for the program, if necessary.
666 | For more information on this, and how to apply and follow the GNU GPL, see
667 | .
668 |
669 | The GNU General Public License does not permit incorporating your program
670 | into proprietary programs. If your program is a subroutine library, you
671 | may consider it more useful to permit linking proprietary applications with
672 | the library. If this is what you want to do, use the GNU Lesser General
673 | Public License instead of this License. But first, please read
674 | .
675 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | C Compiler
2 | ==========
3 | By Eudis Duran
4 | --------------
5 |
6 | ## Compiling
7 |
8 | ### Linux:
9 |
10 | You can build the source with a single command.
11 | Make sure you are in the root src directory, and
12 | type: "make all" This will build both the compiler
13 | and virtual machine. The resulting executables will
14 | be placed in the root binary folder for the project.
15 | The programs are named "c" for the compiler, and "cvm" for
16 | the virtual machine.
17 |
18 | ### Example Programs/Tests
19 | Once you have built the compiler and virtual machine, both
20 | executables are also copied to the bin folder under 'examples.'
21 | The example programs can be built in a similar fasion.
22 | Change directory to examples/ and execute a "make"
23 | call. That will build all the examples for execution.
24 | In this case however, the Makefile will use my C compiler
25 | to build the examples, and will produce VM executables
26 | in the bin folder under the examples folders.
27 |
28 | ### Windows:
29 | Not tested.
30 |
31 |
32 | ## Usage:
33 | To compile a source file, first make sure that it adheres
34 | to the small C subset that is specified in the Documentation
35 | file, as not all of C is implemented yet.
36 |
37 | Once you have checked that off, locate the compiler and VM
38 | executable in the bin directory and change to that directory
39 | through the command line. Assuming you have a test
40 | file, say test.c, you could type in the following to compile
41 | the file:
42 |
43 | ```bash
44 | $ ./c test.c -o test.vm
45 | ```
46 |
47 | That would compile the c source and produce a virtual machine
48 | bytecode executable. To run that exectuable, type in the
49 | following:
50 |
51 | ```bash
52 | $ ./cvm test.vm
53 | ```
54 |
55 | That would execute the program.
56 |
57 | You can display a help screen by typing in --help in either of the
58 | program's command line arguments, like so:
59 |
60 | ```bash
61 | $ ./c --help
62 | ```
63 |
64 | or
65 |
66 | ```bash
67 | $ ./cvm --help
68 | ```
69 |
--------------------------------------------------------------------------------
/examples/Makefile:
--------------------------------------------------------------------------------
1 | # Makefile to build all the examples/tests using my c compiler
2 | # By Eudis Duran
3 |
4 |
5 | EXECS = bin/ex1.vm bin/ex2.vm bin/ex3.vm bin/ex4.vm bin/ex5.vm bin/ex6.vm bin/ex7.vm
6 |
7 | $(EXECS) : $(EXECS)
8 |
9 | bin/ex1.vm: src/ex1.c
10 | bin/c src/ex1.c -o bin/ex1.vm
11 |
12 | bin/ex2.vm: src/ex2.c
13 | bin/c src/ex2.c -o bin/ex2.vm
14 |
15 | bin/ex3.vm: src/ex3.c
16 | bin/c src/ex3.c -o bin/ex3.vm
17 |
18 | bin/ex4.vm: src/ex4.c
19 | bin/c src/ex4.c -o bin/ex4.vm
20 |
21 | bin/ex5.vm: src/ex5.c
22 | bin/c src/ex5.c -o bin/ex5.vm
23 |
24 | bin/ex6.vm: src/ex6.c
25 | bin/c src/ex6.c -o bin/ex6.vm
26 |
27 | bin/ex7.vm: src/ex7.c
28 | bin/c src/ex7.c -o bin/ex7.vm
29 |
30 |
31 |
--------------------------------------------------------------------------------
/examples/bin/stub:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eudisd/c-compiler/9aa5e08fe4217accd4935b8120178e4e0377e0a0/examples/bin/stub
--------------------------------------------------------------------------------
/examples/src/ex1.c:
--------------------------------------------------------------------------------
1 | /*--------------------------------------*/
2 | /* This is a simple hello world program */
3 | /*--------------------------------------*/
4 |
5 | /*
6 | * By: Eudis Duran
7 | * Spring 2011
8 | */
9 |
10 | int main()
11 | {
12 | printf("Hello World!");
13 | }
14 |
--------------------------------------------------------------------------------
/examples/src/ex2.c:
--------------------------------------------------------------------------------
1 | /*--------------------------------------------------------*/
2 | /* This test demonstrates declaration of variables.
3 | * So far, only three are available. int, char, and float.
4 | *
5 | * It also demonstrates assignment, and printing.
6 | */
7 | /*--------------------------------------------------------*/
8 |
9 | /*
10 | * By: Eudis Duran
11 | * Spring 2011
12 | */
13 |
14 | int x, y;
15 | float z, w;
16 | char a, b, c;
17 |
18 | int main()
19 | {
20 | x = 1;
21 | printf ("The value of X is: ");
22 | printf(x);
23 | }
24 |
--------------------------------------------------------------------------------
/examples/src/ex3.c:
--------------------------------------------------------------------------------
1 | /*--------------------------------------------------------*/
2 | /* This test demonstrates declaration of variables in different
3 | * scopes. In other words, lexical scoping is presented.
4 | * It also shows the conditional if else construct.
5 | */
6 | /*--------------------------------------------------------*/
7 |
8 | /*
9 | * By: Eudis Duran
10 | * Spring 2011
11 | */
12 |
13 | int main()
14 | {
15 | int x;
16 | x = 1;
17 | printf (x); /* This x is different from the one below */
18 |
19 | if( x == 1 ){
20 | int x;
21 | x = 2;
22 | printf ("This should execute!");
23 | printf (x);
24 | }
25 | else {
26 | printf ("This should not!");
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/examples/src/ex4.c:
--------------------------------------------------------------------------------
1 | /*--------------------------------------------------------*/
2 | /* Here, I demonstrate while and do-while looping constructs.
3 | * I do so, by presenting the iterative fibonacci algorithm,
4 | * and the GCD algorithm for a very small set of numbers.
5 | */
6 | /*--------------------------------------------------------*/
7 |
8 | /*
9 | * By: Eudis Duran
10 | * Spring 2011
11 | */
12 |
13 |
14 |
15 | int main()
16 | {
17 | int fib_total;
18 |
19 | fib_total = 20;
20 |
21 | int i, j, fib;
22 |
23 | i = 0;
24 | j = 1;
25 |
26 | /* f(n) = f(n - 1) + f(n - 2) */
27 | printf ("Fibonacci Sequence");
28 | while( fib < fib_total ){
29 | fib = i + j;
30 | j = i;
31 | i = fib;
32 | printf (fib);
33 | }
34 |
35 | int a, b, c, d;
36 |
37 | a = 6;
38 | b = 6;
39 |
40 | printf ("Greatest Commond Divisisor");
41 | do {
42 | c = a % b;
43 | a = b;
44 | b = c;
45 | }while( b > 0 );
46 |
47 | printf ("The GCD is: ");
48 | printf(a);
49 |
50 | }
51 |
--------------------------------------------------------------------------------
/examples/src/ex5.c:
--------------------------------------------------------------------------------
1 | /*--------------------------------------------------------*/
2 | /* This source file demonstrates gotos/labels. Branching accross
3 | * scopes is not supported. */
4 | /*--------------------------------------------------------*/
5 |
6 | /*
7 | * By: Eudis Duran
8 | * Spring 2011
9 | */
10 |
11 |
12 | int main()
13 | {
14 | int x;
15 | x = 10;
16 |
17 | /* Goto First, Label Second */
18 | goto label2;
19 |
20 | printf ("Do not print this");
21 |
22 | label2:
23 |
24 | x = 5;
25 | printf("Print this: ");
26 | printf(x);
27 |
28 |
29 | /* Label First, Goto Second */
30 |
31 | int counter;
32 | counter = 0;
33 |
34 | label1:
35 |
36 | printf ("This always gets printed!");
37 |
38 | if( counter < 10 ){
39 | counter = counter + 1;
40 | goto label1;
41 | }
42 |
43 | /* Here the loop ends */
44 |
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/examples/src/ex6.c:
--------------------------------------------------------------------------------
1 | /*--------------------------------------------------------*/
2 | /* This source file demonstrates integer array declaration and
3 | use. */
4 | /*--------------------------------------------------------*/
5 |
6 | /*
7 | * By: Eudis Duran
8 | * Spring 2011
9 | */
10 |
11 | int main()
12 | {
13 | int x, sorted;
14 | x = 20;
15 |
16 | int a[5];
17 | a[0] = 10;
18 |
19 | /* First we print the original x */
20 |
21 | printf(x);
22 |
23 | /* Next, we print the newly assigned x */
24 |
25 | x = a[0];
26 | printf (x);
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/examples/src/ex7.c:
--------------------------------------------------------------------------------
1 | int main()
2 | {
3 | printf("Hello World!");
4 | }
5 |
--------------------------------------------------------------------------------
/src/.deps/error.Po:
--------------------------------------------------------------------------------
1 | error.o: error.c error.h /usr/include/stdio.h /usr/include/features.h \
2 | /usr/include/bits/predefs.h /usr/include/sys/cdefs.h \
3 | /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h \
4 | /usr/include/gnu/stubs-32.h \
5 | /usr/lib/gcc/i686-linux-gnu/4.4.5/include/stddef.h \
6 | /usr/include/bits/types.h /usr/include/bits/typesizes.h \
7 | /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
8 | /usr/lib/gcc/i686-linux-gnu/4.4.5/include/stdarg.h \
9 | /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
10 | /usr/include/bits/stdio.h /usr/include/bits/stdio2.h \
11 | /usr/include/stdlib.h /usr/include/bits/waitflags.h \
12 | /usr/include/bits/waitstatus.h /usr/include/endian.h \
13 | /usr/include/bits/endian.h /usr/include/bits/byteswap.h \
14 | /usr/include/sys/types.h /usr/include/time.h /usr/include/sys/select.h \
15 | /usr/include/bits/select.h /usr/include/bits/sigset.h \
16 | /usr/include/bits/time.h /usr/include/sys/sysmacros.h \
17 | /usr/include/bits/pthreadtypes.h /usr/include/alloca.h \
18 | /usr/include/bits/stdlib.h
19 |
20 | error.h:
21 |
22 | /usr/include/stdio.h:
23 |
24 | /usr/include/features.h:
25 |
26 | /usr/include/bits/predefs.h:
27 |
28 | /usr/include/sys/cdefs.h:
29 |
30 | /usr/include/bits/wordsize.h:
31 |
32 | /usr/include/gnu/stubs.h:
33 |
34 | /usr/include/gnu/stubs-32.h:
35 |
36 | /usr/lib/gcc/i686-linux-gnu/4.4.5/include/stddef.h:
37 |
38 | /usr/include/bits/types.h:
39 |
40 | /usr/include/bits/typesizes.h:
41 |
42 | /usr/include/libio.h:
43 |
44 | /usr/include/_G_config.h:
45 |
46 | /usr/include/wchar.h:
47 |
48 | /usr/lib/gcc/i686-linux-gnu/4.4.5/include/stdarg.h:
49 |
50 | /usr/include/bits/stdio_lim.h:
51 |
52 | /usr/include/bits/sys_errlist.h:
53 |
54 | /usr/include/bits/stdio.h:
55 |
56 | /usr/include/bits/stdio2.h:
57 |
58 | /usr/include/stdlib.h:
59 |
60 | /usr/include/bits/waitflags.h:
61 |
62 | /usr/include/bits/waitstatus.h:
63 |
64 | /usr/include/endian.h:
65 |
66 | /usr/include/bits/endian.h:
67 |
68 | /usr/include/bits/byteswap.h:
69 |
70 | /usr/include/sys/types.h:
71 |
72 | /usr/include/time.h:
73 |
74 | /usr/include/sys/select.h:
75 |
76 | /usr/include/bits/select.h:
77 |
78 | /usr/include/bits/sigset.h:
79 |
80 | /usr/include/bits/time.h:
81 |
82 | /usr/include/sys/sysmacros.h:
83 |
84 | /usr/include/bits/pthreadtypes.h:
85 |
86 | /usr/include/alloca.h:
87 |
88 | /usr/include/bits/stdlib.h:
89 |
--------------------------------------------------------------------------------
/src/.deps/main.Po:
--------------------------------------------------------------------------------
1 | main.o: main.c main.h /usr/include/stdlib.h /usr/include/features.h \
2 | /usr/include/bits/predefs.h /usr/include/sys/cdefs.h \
3 | /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h \
4 | /usr/include/gnu/stubs-32.h \
5 | /usr/lib/gcc/i686-linux-gnu/4.4.5/include/stddef.h \
6 | /usr/include/bits/waitflags.h /usr/include/bits/waitstatus.h \
7 | /usr/include/endian.h /usr/include/bits/endian.h \
8 | /usr/include/bits/byteswap.h /usr/include/sys/types.h \
9 | /usr/include/bits/types.h /usr/include/bits/typesizes.h \
10 | /usr/include/time.h /usr/include/sys/select.h /usr/include/bits/select.h \
11 | /usr/include/bits/sigset.h /usr/include/bits/time.h \
12 | /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
13 | /usr/include/alloca.h /usr/include/bits/stdlib.h /usr/include/stdio.h \
14 | /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
15 | /usr/lib/gcc/i686-linux-gnu/4.4.5/include/stdarg.h \
16 | /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
17 | /usr/include/bits/stdio.h /usr/include/bits/stdio2.h \
18 | /usr/include/string.h /usr/include/xlocale.h /usr/include/bits/string.h \
19 | /usr/include/bits/string2.h /usr/include/bits/string3.h \
20 | /usr/include/malloc.h utils.h
21 |
22 | main.h:
23 |
24 | /usr/include/stdlib.h:
25 |
26 | /usr/include/features.h:
27 |
28 | /usr/include/bits/predefs.h:
29 |
30 | /usr/include/sys/cdefs.h:
31 |
32 | /usr/include/bits/wordsize.h:
33 |
34 | /usr/include/gnu/stubs.h:
35 |
36 | /usr/include/gnu/stubs-32.h:
37 |
38 | /usr/lib/gcc/i686-linux-gnu/4.4.5/include/stddef.h:
39 |
40 | /usr/include/bits/waitflags.h:
41 |
42 | /usr/include/bits/waitstatus.h:
43 |
44 | /usr/include/endian.h:
45 |
46 | /usr/include/bits/endian.h:
47 |
48 | /usr/include/bits/byteswap.h:
49 |
50 | /usr/include/sys/types.h:
51 |
52 | /usr/include/bits/types.h:
53 |
54 | /usr/include/bits/typesizes.h:
55 |
56 | /usr/include/time.h:
57 |
58 | /usr/include/sys/select.h:
59 |
60 | /usr/include/bits/select.h:
61 |
62 | /usr/include/bits/sigset.h:
63 |
64 | /usr/include/bits/time.h:
65 |
66 | /usr/include/sys/sysmacros.h:
67 |
68 | /usr/include/bits/pthreadtypes.h:
69 |
70 | /usr/include/alloca.h:
71 |
72 | /usr/include/bits/stdlib.h:
73 |
74 | /usr/include/stdio.h:
75 |
76 | /usr/include/libio.h:
77 |
78 | /usr/include/_G_config.h:
79 |
80 | /usr/include/wchar.h:
81 |
82 | /usr/lib/gcc/i686-linux-gnu/4.4.5/include/stdarg.h:
83 |
84 | /usr/include/bits/stdio_lim.h:
85 |
86 | /usr/include/bits/sys_errlist.h:
87 |
88 | /usr/include/bits/stdio.h:
89 |
90 | /usr/include/bits/stdio2.h:
91 |
92 | /usr/include/string.h:
93 |
94 | /usr/include/xlocale.h:
95 |
96 | /usr/include/bits/string.h:
97 |
98 | /usr/include/bits/string2.h:
99 |
100 | /usr/include/bits/string3.h:
101 |
102 | /usr/include/malloc.h:
103 |
104 | utils.h:
105 |
--------------------------------------------------------------------------------
/src/.deps/parser.Po:
--------------------------------------------------------------------------------
1 | parser.o: parser.c parser.h
2 |
3 | parser.h:
4 |
--------------------------------------------------------------------------------
/src/.deps/preprocessor.Po:
--------------------------------------------------------------------------------
1 | preprocessor.o: preprocessor.c preprocessor.h
2 |
3 | preprocessor.h:
4 |
--------------------------------------------------------------------------------
/src/.deps/scanner.Po:
--------------------------------------------------------------------------------
1 | scanner.o: scanner.c scanner.h
2 |
3 | scanner.h:
4 |
--------------------------------------------------------------------------------
/src/.deps/symbol.Po:
--------------------------------------------------------------------------------
1 | symbol.o: symbol.c symbol.h
2 |
3 | symbol.h:
4 |
--------------------------------------------------------------------------------
/src/.deps/utils.Po:
--------------------------------------------------------------------------------
1 | utils.o: utils.c utils.h /usr/include/stdio.h /usr/include/features.h \
2 | /usr/include/bits/predefs.h /usr/include/sys/cdefs.h \
3 | /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h \
4 | /usr/include/gnu/stubs-32.h \
5 | /usr/lib/gcc/i686-linux-gnu/4.4.5/include/stddef.h \
6 | /usr/include/bits/types.h /usr/include/bits/typesizes.h \
7 | /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
8 | /usr/lib/gcc/i686-linux-gnu/4.4.5/include/stdarg.h \
9 | /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
10 | /usr/include/bits/stdio.h /usr/include/bits/stdio2.h \
11 | /usr/include/stdlib.h /usr/include/bits/waitflags.h \
12 | /usr/include/bits/waitstatus.h /usr/include/endian.h \
13 | /usr/include/bits/endian.h /usr/include/bits/byteswap.h \
14 | /usr/include/sys/types.h /usr/include/time.h /usr/include/sys/select.h \
15 | /usr/include/bits/select.h /usr/include/bits/sigset.h \
16 | /usr/include/bits/time.h /usr/include/sys/sysmacros.h \
17 | /usr/include/bits/pthreadtypes.h /usr/include/alloca.h \
18 | /usr/include/bits/stdlib.h /usr/include/xlocale.h /usr/include/malloc.h
19 |
20 | utils.h:
21 |
22 | /usr/include/stdio.h:
23 |
24 | /usr/include/features.h:
25 |
26 | /usr/include/bits/predefs.h:
27 |
28 | /usr/include/sys/cdefs.h:
29 |
30 | /usr/include/bits/wordsize.h:
31 |
32 | /usr/include/gnu/stubs.h:
33 |
34 | /usr/include/gnu/stubs-32.h:
35 |
36 | /usr/lib/gcc/i686-linux-gnu/4.4.5/include/stddef.h:
37 |
38 | /usr/include/bits/types.h:
39 |
40 | /usr/include/bits/typesizes.h:
41 |
42 | /usr/include/libio.h:
43 |
44 | /usr/include/_G_config.h:
45 |
46 | /usr/include/wchar.h:
47 |
48 | /usr/lib/gcc/i686-linux-gnu/4.4.5/include/stdarg.h:
49 |
50 | /usr/include/bits/stdio_lim.h:
51 |
52 | /usr/include/bits/sys_errlist.h:
53 |
54 | /usr/include/bits/stdio.h:
55 |
56 | /usr/include/bits/stdio2.h:
57 |
58 | /usr/include/stdlib.h:
59 |
60 | /usr/include/bits/waitflags.h:
61 |
62 | /usr/include/bits/waitstatus.h:
63 |
64 | /usr/include/endian.h:
65 |
66 | /usr/include/bits/endian.h:
67 |
68 | /usr/include/bits/byteswap.h:
69 |
70 | /usr/include/sys/types.h:
71 |
72 | /usr/include/time.h:
73 |
74 | /usr/include/sys/select.h:
75 |
76 | /usr/include/bits/select.h:
77 |
78 | /usr/include/bits/sigset.h:
79 |
80 | /usr/include/bits/time.h:
81 |
82 | /usr/include/sys/sysmacros.h:
83 |
84 | /usr/include/bits/pthreadtypes.h:
85 |
86 | /usr/include/alloca.h:
87 |
88 | /usr/include/bits/stdlib.h:
89 |
90 | /usr/include/xlocale.h:
91 |
92 | /usr/include/malloc.h:
93 |
--------------------------------------------------------------------------------
/src/Makefile:
--------------------------------------------------------------------------------
1 | # General Makefile
2 |
3 | # By Eudis Duran
4 |
5 | .SILENT:
6 | .IGNORE:
7 |
8 |
9 | .PHONY: c cvm all
10 |
11 | c:
12 | make -C "compiler"
13 |
14 | cvm:
15 | make -C "cvm"
16 |
17 | all:
18 | make -C "compiler"
19 | make -C "cvm"
20 |
--------------------------------------------------------------------------------
/src/compiler/Makefile:
--------------------------------------------------------------------------------
1 | # C - Compiler Makefile
2 |
3 | CC := gcc
4 | LIBS := -lm
5 | FLAGS := -Wall -O2 -g
6 |
7 | OBJS := main.o error.o parser.o scanner.o symbol.o preprocessor.o utils.o
8 |
9 | TARGET:=c
10 |
11 | $(TARGET) : $(OBJS)
12 | $(CC) $(FLAGS) $(OBJS) -o $(TARGET) $(LIBS)
13 | @echo
14 | @echo "Done Building C Compiler."
15 | @-rm *.o
16 | @-cp ./$(TARGET) ../../bin
17 | @-cp ./$(TARGET) ../../examples/bin
18 | @echo
19 |
20 | main.o : main.c main.h
21 | @echo "(Modified) Compiling Translation Unit: main.c + main.h"
22 | $(CC) -c main.c -o main.o
23 |
24 | error.o : error.c error.h
25 | @echo "(Modified) Compiling Translation Unit: error.c + error.h"
26 | $(CC) -c error.c -o error.o
27 |
28 | parser.o : parser.c parser.h
29 | @echo "(Modified) Compiling Translation Unit: parser.c + parser.h"
30 | $(CC) -c parser.c -o parser.o
31 |
32 | scanner.o : scanner.c scanner.h
33 | @echo "(Modified) Compiling Translation Unit: scanner.c + scanner.h"
34 | $(CC) -c scanner.c -o scanner.o
35 |
36 | symbol.o : symbol.c symbol.h
37 | @echo "(Modified) Compiling Translation Unit: symbol.c + symbol.h"
38 | $(CC) -c symbol.c -o symbol.o
39 |
40 | preprocessor.o : preprocessor.c preprocessor.h
41 | @echo "(Modified) Compiling Translation Unit: preprocessor.c + preprocessor.h"
42 | $(CC) -c preprocessor.c -o preprocessor.o
43 |
44 | utils.o : utils.c utils.h
45 | @echo "(Modified) Compiling Translation Unit: utils.c + utils.h"
46 | $(CC) -c utils.c -o utils.o
47 |
48 |
49 |
--------------------------------------------------------------------------------
/src/compiler/drivers/error/make_err.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | int main()
5 | {
6 | adfs;
7 | return 0;
8 | }
9 |
--------------------------------------------------------------------------------
/src/compiler/drivers/parser/get_token.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 |
5 |
6 | char *get_lexeme(FILE *i);
7 | int get_token_name(char *lexeme);
8 | char *get_token_value(char *lexeme);
9 |
10 | int main()
11 | {
12 | char *tk_stream = "<10,20><30,40><50,60>";
13 | FILE *in = fopen("test.c", "rb");
14 |
15 | char *token = get_lexeme(in);
16 |
17 | printf("\n\nGet Token: '%s', token_name: %d, token_value: %d\n\n", token, get_token_name(token), get_token_value(token) );
18 | token = get_lexeme(in);
19 |
20 | printf("\n\nGet Token: '%s', token_name: %d, token_value: %d\n\n", token, get_token_name(token), get_token_value(token) );
21 | free(token);
22 |
23 | token = get_lexeme(in);
24 |
25 | printf("\n\nGet Token: '%s', token_name: %d, token_value: %d\n\n", token, get_token_name(token), get_token_value(token) );
26 | token = get_lexeme(in);
27 |
28 | printf("\n\nGet Token: '%s', token_name: %d, token_value: %d\n\n", token, get_token_name(token), get_token_value(token) );
29 |
30 |
31 |
32 | return 0;
33 | }
34 |
35 | char *get_lexeme(FILE *in)
36 | {
37 | int i=0, j;
38 | char *token;
39 | int pos = ftell(in);
40 | char c = getc(in);
41 | if(c == '<' && c != EOF){
42 | while( (c = getc(in)) != EOF ){
43 | i++;
44 | if(c == '>')
45 | break;
46 |
47 | }
48 | }
49 | else {
50 | return NULL;
51 | }
52 |
53 | token = (char*)malloc(sizeof(char)*i + 1);
54 |
55 | fseek(in, pos, SEEK_SET);
56 |
57 | i = 0;
58 |
59 | while( (c = getc(in)) != EOF ){
60 | token[i] = c;
61 | i++;
62 | if(c == '>')
63 | break;
64 |
65 | }
66 |
67 | token[i] = '\0';
68 | return token;
69 | }
70 |
71 | char *get_token_value(char *lexeme)
72 | {
73 | if(lexeme == NULL){
74 | return -1;
75 | }
76 |
77 | int k = 0;
78 | while( lexeme[k] != ',' ){
79 | k++;
80 | }
81 |
82 | int start = k + 1;
83 |
84 | int end = 0;
85 |
86 | int i = 0;
87 | while(end < strlen(lexeme)){
88 | if( lexeme[end] == '>' ){
89 | break;
90 | }
91 | end++;
92 | }
93 |
94 | char *tmp = (char*)malloc(sizeof(char)*(end - start)+1);
95 | int j;
96 |
97 | for(j = 0; j < (end - start + 1); j ++){
98 | tmp[j] = lexeme[start + j];
99 | }
100 | tmp[(end - start)] = '\0';
101 |
102 | int x = atoi(tmp);
103 | free(tmp);
104 |
105 | return x;
106 | }
107 |
108 | int get_token_name(char *lexeme)
109 | {
110 | if(lexeme == NULL){
111 | return -1;
112 | }
113 |
114 | int start = 1;
115 |
116 | int end = 0;
117 |
118 | int i = 0;
119 | while(end < strlen(lexeme)){
120 | if( lexeme[end] == ',' ){
121 | break;
122 | }
123 | end++;
124 | }
125 |
126 | char *tmp = (char*)malloc(sizeof(char)*(end - start)+1);
127 | int j;
128 |
129 | for(j = 0; j < (end - start + 1); j ++){
130 | tmp[j] = lexeme[start + j];
131 | }
132 | tmp[(end - start)] = '\0';
133 |
134 | int x = atoi(tmp);
135 | free(tmp);
136 |
137 | return x;
138 | }
139 |
--------------------------------------------------------------------------------
/src/compiler/drivers/preprocessor/fseek_test.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | int main()
5 | {
6 | FILE *f;
7 | f = fopen("tmp.txt", "r");
8 |
9 | printf("\nI am at: %d\n", (int)ftell(f));
10 | getc(f);
11 | printf("\nNow I am at: %d\n", (int)ftell(f));
12 | fseek(f, 1, SEEK_CUR);
13 | printf("\nNow I am back at: %d\n", (int)ftell(f));
14 |
15 | return 0;
16 | }
17 |
--------------------------------------------------------------------------------
/src/compiler/drivers/preprocessor/get_inc_fname.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include "../../utils.h"
5 |
6 | char *get_inc_fname(FILE *i);
7 |
8 | int main()
9 | {
10 | char *name;
11 | FILE *f = fopen("tmp.txt", "r");
12 | name = get_inc_fname(f);
13 | printf("%s\n", name);
14 | return 0;
15 | }
16 |
17 |
18 | char *get_inc_fname(FILE *i)
19 | {
20 | int j = 0;
21 | char c;
22 | char *name;
23 |
24 | int size = 0;
25 | int pos; /**> Used to save the start position of the filestream.
26 | Will be reverted after size is calculated */
27 |
28 | pos = ftell(i);
29 | printf("Start file-p position: %d\n", (int)ftell(i));
30 |
31 | while( (c = getc(i)) != EOF ){ /* The 'c' here begins at position 0 of the filename string. */
32 |
33 | if( c == '<' ){
34 | c = getc(i); /* Do not count '<' as it's not part of the string
35 | name, so pop it off the stream */
36 | while( (c != EOF) && (c != '>') ){
37 | size++;
38 | c = getc(i);
39 | }
40 | break;
41 | }
42 | }
43 |
44 | printf("Size of filename string is: %d\n", size);
45 | printf("Current file-p position: %d\n", (int)ftell(i));
46 | fseek(i, -(ftell(i)-pos), SEEK_CUR);
47 | printf("Reset the file-p position to: %d\n", (int)ftell(i));
48 |
49 | name = (char*)malloc(sizeof(char)*size);
50 |
51 | while( (c = getc(i)) != EOF && (j < size) ){ /* The 'c' here begins at position 0 of the filename string. */
52 | if( c == '<' ){
53 | c = getc(i);
54 | while( (c != EOF) && (c != '>') ){
55 | name[j] = c;
56 | j++;
57 | c = getc(i);
58 | }
59 | break;
60 | }
61 | }
62 |
63 | return name;
64 | }
65 |
--------------------------------------------------------------------------------
/src/compiler/drivers/preprocessor/get_next_word.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 |
5 | char *get_next_word(FILE *f);
6 |
7 | int main()
8 | {
9 | FILE *f = fopen("tmp.txt", "r");
10 |
11 | //printf("%s", get_next_word(f));
12 | get_next_word(f);
13 | get_next_word(f);
14 | get_next_word(f);
15 | get_next_word(f);
16 | return 0;
17 | }
18 |
19 |
20 | char *get_next_word(FILE *f)
21 | {
22 | char *word;
23 | int get_out = 0;
24 | char c;
25 | int start_pos = ftell(f);
26 | int count = 0;
27 | int last_run = 0;
28 |
29 | while ( (c = getc(f)) != EOF ){
30 | if(c == ' ' || c == '\t' || c == '\n')
31 | continue;
32 | else {
33 | while(c != EOF){
34 | if(c != ' ' && c != '\t' && c != '\n'){
35 | (!last_run)? count++ : count;
36 | printf("%c", c);
37 | c = getc(f);
38 | }
39 | else {
40 | get_out = last_run = 1;
41 |
42 | break;
43 | }
44 | }
45 | if(get_out == 1) {
46 | fseek(f, -count, SEEK_CUR); // Offset by word length amount
47 | if(last_run == 1){
48 | word = (char*)malloc(sizeof(char)*count);
49 | printf(" :Word Length: %d\n", count);
50 | }
51 | break;
52 |
53 | }
54 | }
55 | }
56 | return "YO";
57 | }
58 |
59 |
60 |
--------------------------------------------------------------------------------
/src/compiler/drivers/scanner/extract_token.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 |
5 | #include "../../utils.h"
6 |
7 | int is_valid_id(char *word);
8 | char *extract_token(char *word);
9 | char *return_keyword(char *word);
10 |
11 | int main()
12 | {
13 | //char ar[] = "int;";
14 | //printf("%c\n", ar[3]);
15 | printf("keyword: '%s'\n\n", extract_token("(int"));
16 | return 0;
17 | }
18 |
19 | char *extract_token(char *word)
20 | {
21 | switch(word[0]){
22 | case '{':
23 | return "{";
24 | case '}':
25 | return "}";
26 | case '(':
27 | return "(";
28 | case ')':
29 | return ")";
30 | case ']':
31 | return "]";
32 | case '[':
33 | return "[";
34 | case '.':
35 | return ".";
36 | case '!':
37 | return "!";
38 | case '~':
39 | return "~";
40 | /* ~ */
41 | /* ~= */
42 | case '+':
43 | return "+";
44 | /* + */
45 | /* ++ */
46 | /* += */
47 | case '-':
48 | return "-";
49 | /* - */
50 | /* -- */
51 | /* -= */
52 | case '*':
53 | return "*";
54 | /* * */
55 | /* *= */
56 | case '&':
57 | return "&";
58 | /* & */
59 | /* && */
60 | /* &= */
61 | case '/':
62 | return "/";
63 | /* / */
64 | /* /= */
65 | case '%':
66 | return "%";
67 | /* % */
68 | /* %= */
69 | case '<':
70 | return "<";
71 | /* < */
72 | /* << */
73 | /* <= */
74 | /* <<= */
75 | case '>':
76 | return ">";
77 | /* > */
78 | /* >> */
79 | /* >= */
80 | /* >>= */
81 | case '=':
82 | return "=";
83 | /* = */
84 | /* == */
85 | case '|':
86 | return "|";
87 | /* | */
88 | /* || */
89 | /* |= */
90 | case '^':
91 | return "^";
92 | /* ^ */
93 | /* ^= */
94 | case '?':
95 | return "?";
96 | case ':':
97 | return ":";
98 | case ';':
99 | return ";";
100 | /* Constants */
101 |
102 | case '\'':
103 | return "'";
104 | /* String Literals */
105 | /* Questioning if this even belongs here?*/
106 | case '"':
107 | return "\"";
108 | break;
109 |
110 | default:
111 | return return_keyword(word);
112 | break;
113 |
114 |
115 | }
116 | return NULL;
117 | }
118 |
119 | char *return_keyword(char *word)
120 | {
121 |
122 | size_t size = strlen(word);
123 | int i;
124 | printf("\n");
125 | for(i = 0; i < size; i++){
126 | if( !isdigit(word[i]) && !isalpha(word[i]) && word[i] != '_'){
127 | break;
128 | }
129 | }
130 | /* 'i' is the size of the valid keyword or id */
131 | char *keyword = (char *)xmalloc(sizeof(char)* i + 1);
132 |
133 | strcpy(keyword, word);
134 | keyword[i] = '\0';
135 |
136 | return keyword;
137 |
138 | }
139 |
140 |
141 | int is_valid_id(char *word)
142 | {
143 | size_t size = strlen(word);
144 |
145 | int j;
146 | for(j = 0; j < size; j++){
147 | if( !isalpha(word[j]) && !isdigit(word[j]) && word[j] != '_' ){
148 |
149 | return 0;
150 | }
151 |
152 | }
153 |
154 |
155 | return size;
156 | }
157 |
158 |
--------------------------------------------------------------------------------
/src/compiler/drivers/scanner/get_lexeme.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 |
5 | char *get_lexeme(FILE *i);
6 |
7 | int main()
8 | {
9 | FILE *i = fopen("tmp.txt", "r");
10 |
11 | printf("%s\n\n", get_lexeme(i));
12 | return 0;
13 | }
14 |
15 | char *get_lexeme(FILE *i)
16 | {
17 | char c;
18 | while ( (c = fget(i)) != '>' ){}
19 | return NULL;
20 | }
21 |
--------------------------------------------------------------------------------
/src/compiler/drivers/scanner/get_token.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include "../../utils.h"
4 | #include "../../scanner.h"
5 | #include
6 |
7 | int parse_tokens();
8 |
9 | int main()
10 | {
11 | parse_tokens();
12 | return 0;
13 | }
14 |
15 |
16 |
--------------------------------------------------------------------------------
/src/compiler/drivers/scanner/is_valid_id.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 |
5 | #include "../../utils.h"
6 |
7 | int is_valid_id(char *word);
8 |
9 | int main()
10 | {
11 |
12 | printf("%d", is_valid_id("int;"));
13 | return 0;
14 | }
15 |
16 | //int is_valid_id(FILE *i)
17 | //{
18 | // printf("Current File Pos: %d\n", ftell(i));
19 | // int valid = 0;
20 | // size_t file_pos = ftell(i); /**> Save the current file p. */
21 | // char *word = getword(i);
22 | // //free(word);
23 | // //word = getword(i);
24 | //
25 | // printf("Current WORD: %s\n", word);
26 | //
27 | // size_t size = strlen(word);
28 | //
29 | //
30 | // printf("Is it valid? ");
31 | // int j;
32 | // for(j = 0; j < size; j++){
33 | // if( !isalpha(word[j]) && !isdigit(word[j]) && word[j] != '_' ){
34 | //
35 | // printf("No! (%d)\n", valid);
36 | // valid = 0;
37 | // return 0;
38 | // }
39 | // valid = 1;
40 | // }
41 | // if(valid == 1){
42 | // printf("YES! (%d)\n", valid);
43 | // //return size;
44 | // }
45 | //
46 | // fseek(i, -(ftell(i) - file_pos), SEEK_CUR);
47 | // free(word); /* Release the resource */
48 | // printf("Ending File Pos: %d\n", ftell(i));
49 | // return 0;
50 | //}
51 |
52 | int is_valid_id(char *word)
53 | {
54 | size_t size = strlen(word);
55 |
56 | int j;
57 | for(j = 0; j < size; j++){
58 | if( !isalpha(word[j]) && !isdigit(word[j]) && word[j] != '_' ){
59 |
60 | return 0;
61 | }
62 |
63 | }
64 |
65 |
66 | return size;
67 | }
68 |
69 |
70 |
--------------------------------------------------------------------------------
/src/compiler/drivers/scanner/return_string.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 |
5 | char *return_string(char *word);
6 |
7 |
8 | int main()
9 | {
10 | char *word = "\" \"";
11 | printf("%s\n", word);
12 | printf("String: %s\n", return_string(word));
13 | return 0;
14 | }
15 |
16 |
17 | char *return_string(char *word)
18 | {
19 | int i, j;
20 | size_t size = strlen(word);
21 | char *tmp;
22 | for(i = 1; i < size; i++){
23 | if( word[i] == '"' ){
24 | i++;
25 | break;
26 | }
27 | }
28 |
29 | tmp = (char*)malloc(sizeof(char)*i + 1);
30 |
31 | for(j = 0; j < i; j++){
32 | tmp[j] = word[j];
33 | }
34 |
35 | tmp[i] = '\0';
36 |
37 |
38 | return tmp;
39 | }
40 |
--------------------------------------------------------------------------------
/src/compiler/drivers/scanner/write_token.c:
--------------------------------------------------------------------------------
1 | void write_token(FILE *o, char *tk_name, char *tk_value)
2 | {
3 | size_t tk_name_size = strlen(tk_name);
4 | size_t tk_value_size = strlen(tk_value);
5 |
6 | putc('<', o);
7 | fwrite(tk_name, sizeof(char), tk_name_size, o);
8 | putc(',', o);
9 | fwrite(tk_value, sizeof(char), tk_value_size, o);
10 | putc('>', o);
11 | }
12 |
--------------------------------------------------------------------------------
/src/compiler/drivers/semantic/stub:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eudisd/c-compiler/9aa5e08fe4217accd4935b8120178e4e0377e0a0/src/compiler/drivers/semantic/stub
--------------------------------------------------------------------------------
/src/compiler/drivers/symbol/is_keyword.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | #define TRUE 1
5 | #define FALSE 0
6 | #define KEYWORD_TOTAL 30
7 |
8 | char *keywords[] = {
9 | "auto",
10 | "break",
11 | "case",
12 | "char",
13 | "const",
14 | "continue",
15 | "default",
16 | "do",
17 | "double",
18 | "else",
19 | "extern",
20 | "float",
21 | "goto",
22 | "int",
23 | "if",
24 | "long",
25 | "register",
26 | "return",
27 | "short",
28 | "signed",
29 | "sizeof",
30 | "static",
31 | "struct",
32 | "switch",
33 | "typedef",
34 | "union",
35 | "unsigned",
36 | "void",
37 | "volatile",
38 | "while"
39 | };
40 |
41 | int is_keyword(char *lexeme);
42 |
43 | int main(){
44 | /* Driver: Test All Cases Test Correctly */
45 | int i = 0;
46 |
47 |
48 | for(i = 0; i < KEYWORD_TOTAL; i++){
49 | /* These should all print '1' for Answer!*/
50 | printf("Is %s a keyword? Answer: %d\n", keywords[i], is_keyword(keywords[i]));
51 | }
52 | return 0;
53 | }
54 |
55 | int is_keyword(char *lexeme)
56 | {
57 | switch(lexeme[0]){
58 | case 'a':
59 | /* auto */
60 | if( !strcmp(lexeme, "auto") )
61 | return TRUE;
62 | return FALSE;
63 | case 'b':
64 | /* break */
65 | if( !strcmp(lexeme, "break") )
66 | return TRUE;
67 | return FALSE;
68 | case 'c':
69 | /* case */
70 | /* char */
71 | /* const */
72 | /* continue */
73 | if( !strcmp(lexeme, "case") ||
74 | !strcmp(lexeme, "char") ||
75 | !strcmp(lexeme, "const") ||
76 | !strcmp(lexeme, "continue")
77 | )
78 | return TRUE;
79 | return FALSE;
80 | case 'd':
81 | /* default */
82 | /* do */
83 | /* double */
84 | if( !strcmp(lexeme, "default")||
85 | !strcmp(lexeme, "do") ||
86 | !strcmp(lexeme, "double")
87 | )
88 | return TRUE;
89 | return FALSE;
90 | case 'e':
91 | /* else */
92 | /* enum */
93 | /* extern */
94 | if( !strcmp(lexeme, "else") ||
95 | !strcmp(lexeme, "enum") ||
96 | !strcmp(lexeme, "extern")
97 | )
98 | return TRUE;
99 | return FALSE;
100 | case 'f':
101 | /* float */
102 | /* for */
103 | if( !strcmp(lexeme, "float")||
104 | !strcmp(lexeme, "for")
105 | )
106 | return TRUE;
107 | return FALSE;
108 | case 'g':
109 | /* goto */
110 | if( !strcmp(lexeme, "goto") )
111 | return TRUE;
112 | return FALSE;
113 |
114 | case 'i':
115 | /* int */
116 | /* if */
117 | if( !strcmp(lexeme, "int") ||
118 | !strcmp(lexeme, "if")
119 | )
120 | return TRUE;
121 | return FALSE;
122 | case 'l':
123 | /* long */
124 | if( !strcmp(lexeme, "long") )
125 | return TRUE;
126 | return FALSE;
127 | case 'r':
128 | /* register */
129 | /* return */
130 | if( !strcmp(lexeme, "register")||
131 | !strcmp(lexeme, "return")
132 | )
133 | return TRUE;
134 | return FALSE;
135 | case 's':
136 | /* short */
137 | /* signed */
138 | /* sizeof */
139 | /* static */
140 | /* struct */
141 | /* switch */
142 | if( !strcmp(lexeme, "short") ||
143 | !strcmp(lexeme, "signed") ||
144 | !strcmp(lexeme, "sizeof") ||
145 | !strcmp(lexeme, "static") ||
146 | !strcmp(lexeme, "struct") ||
147 | !strcmp(lexeme, "switch")
148 | )
149 | return TRUE;
150 | return FALSE;
151 | case 't':
152 | /* typedef */
153 | if( !strcmp(lexeme, "typedef") )
154 | return TRUE;
155 | return FALSE;
156 | case 'u':
157 | /* union */
158 | /* unsigned */
159 | if( !strcmp(lexeme, "union") ||
160 | !strcmp(lexeme, "unsigned")
161 | )
162 | return TRUE;
163 | return FALSE;
164 | case 'v':
165 | /* void */
166 | /* volatile */
167 | if( !strcmp(lexeme, "void") ||
168 | !strcmp(lexeme, "volatile")
169 | )
170 | return TRUE;
171 | return FALSE;
172 | case 'w':
173 | /* while */
174 | if( !strcmp(lexeme, "while") )
175 | return TRUE;
176 | return FALSE;
177 | default:
178 | return FALSE;
179 | }
180 | }
181 |
--------------------------------------------------------------------------------
/src/compiler/drivers/utils/bsearch.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | int bint_comp(const void *a, const void *b);
5 |
6 | int bfloat_comp(const void *a, const void *b);
7 |
8 | int main()
9 | {
10 | int a[10] = {0,1,2,3,4,5,6,7,8,9};
11 | double b[10] = {0.1, 0.01, 0.2, 0.022, 0.101, 0.1, 12.3, 10.3, 11.3, 1.1};
12 | double key = 0.21;
13 | double *item = bsearch(&key, b, 10, sizeof(double), bfloat_comp);
14 | if(!item){
15 |
16 | }
17 | else {
18 | printf("%f\n", *item);
19 | }
20 | return 0;
21 | }
22 |
23 | int bint_comp(const void *a, const void *b)
24 | {
25 | if ( *(int*)a > *(int*)b ) return 1;
26 | if ( *(int*)a == *(int*)b ) return 0;
27 | if ( *(int*)a < *(int*)b ) return -1;
28 | }
29 |
30 | int bfloat_comp(const void *a, const void *b)
31 | {
32 | if ( *(double*)a > *(double*)b ) return 1;
33 | if ( *(double*)a == *(double*)b ) return 0;
34 | if ( *(double*)a < *(double*)b ) return -1;
35 | }
36 |
--------------------------------------------------------------------------------
/src/compiler/drivers/utils/fcpeek.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | char fcpeek(FILE *f);
5 |
6 | int main()
7 | {
8 | FILE *f = fopen("tmp.txt", "r");
9 | printf("Char: %c\n", fcpeek(f));
10 | printf("Current Pos: %d\n", (long int)ftell(f));
11 | return 0;
12 | }
13 |
14 | char fcpeek(FILE *f)
15 | {
16 | char c = getc(f);
17 | ungetc(c, f);
18 | return c;
19 | }
20 |
--------------------------------------------------------------------------------
/src/compiler/drivers/utils/get_column.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include "../../utils.h"
4 |
5 | int get_column(FILE *i);
6 |
7 | int main()
8 | {
9 | FILE *i = fopen("tmp.txt", "r");
10 | getc(i);
11 | getc(i);
12 | getc(i);
13 | getc(i);
14 | getc(i);
15 | getc(i);
16 | getc(i);
17 | getc(i);
18 | getc(i);
19 | getc(i);
20 | getc(i);
21 | getc(i);
22 | getc(i);
23 | getc(i);
24 | getc(i);
25 | getc(i);
26 | getc(i);
27 | getc(i);
28 | getc(i);
29 | getc(i);
30 | printf("Answer: %d\n", get_column(i));
31 | return 0;
32 | }
33 |
34 | int get_column(FILE *i){
35 | int cur_pos = ftell(i);
36 | int offset = 0;
37 | char c = fcpeek(i);
38 |
39 | while( c != '\n' && (ftell(i) > 0) && c != EOF){
40 | fseek(i, -1, SEEK_CUR);
41 | offset++;
42 | c = fcpeek(i);
43 | }
44 | fseek(i, cur_pos, SEEK_CUR);
45 | return offset;
46 | }
47 |
--------------------------------------------------------------------------------
/src/compiler/drivers/utils/get_files_from_argv.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 |
5 |
6 |
7 | char **get_files_from_argv(int argc, char *argv[]);
8 |
9 | int main(int argc, char *argv[])
10 | {
11 | int i;
12 | char **a = (char**)get_files_from_argv(argc, argv);
13 |
14 | for(i = 1; i < argc; i++){
15 | printf("%s\n", a[i]);
16 | }
17 | return 0;
18 | }
19 |
20 | char **get_files_from_argv(int argc, char *argv[])
21 | {
22 | char **files = (char**)malloc(sizeof(char*)*argc);
23 | int i;
24 | size_t size;
25 |
26 | for(i = 1; i < argc; i++){
27 | size = strlen(argv[i]);
28 | files[i] = (char*)malloc(sizeof(char)*size);
29 | strcpy(files[i], argv[i]);
30 | }
31 |
32 | return files;
33 | }
34 |
--------------------------------------------------------------------------------
/src/compiler/drivers/utils/get_filesize.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | int get_filesize(char *filename);
5 |
6 | int main()
7 | {
8 | printf("FILESIZE: %d-bytes\n", get_filesize("tmp.txt"));
9 | #if defined(__linux)
10 | system("wc -c tmp.txt");
11 | #endif
12 | return 0;
13 | }
14 |
15 | int get_filesize(char *filename)
16 | {
17 | FILE *f = fopen(filename, "r");
18 | fseek(f, 0, SEEK_END);
19 | return ftell(f);
20 | }
21 |
--------------------------------------------------------------------------------
/src/compiler/drivers/utils/getword.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 |
6 | char *getword(FILE *i);
7 | size_t total_newlines;
8 | int main()
9 | {
10 | char *name;
11 | FILE *f = fopen("tmp.txt", "r");
12 |
13 | printf("%s\n", getword(f));
14 | /*printf("%s\n", getword(f));
15 | printf("%s\n", getword(f));
16 | printf("%s\n", getword(f));
17 | printf("%s\n", getword(f));
18 | printf("%s\n", getword(f));
19 | printf("%s\n", getword(f));
20 | printf("%s\n", getword(f));
21 | printf("%s\n", getword(f));
22 | printf("%s\n", getword(f));
23 | printf("%s\n", getword(f));
24 | printf("%s\n", getword(f));
25 | printf("%s\n", getword(f));
26 | printf("%s\n", getword(f));
27 | printf("%s\n", getword(f));
28 | */
29 | fclose(f);
30 | return 0;
31 | }
32 |
33 |
34 | char *getword(FILE *i)
35 | {
36 |
37 | int j = 0;
38 | char c;
39 | char *word;
40 | int pos;
41 | size_t size = 0;
42 |
43 | if(fcpeek(i) == EOF){
44 | return NULL;
45 | }
46 |
47 | pos = ftell(i);
48 | c = getc(i);
49 | if( c == '\n' ){
50 | //total_newlines++;
51 | }
52 |
53 | /* We first calculate the size of the word */
54 | while ( (c != EOF) && !isspace(c) ){
55 | /* Read and count new lines and characters */
56 |
57 | /* This new section handles the string word input count*/
58 | if ( c == '\"' ){
59 | size++;
60 | c = getc(i);
61 | while( c != '\"' ){
62 |
63 | if( c == '\n' ){
64 | printf("String error!\n");
65 | exit(EXIT_FAILURE);
66 | }
67 |
68 | size++;
69 | c = getc(i);
70 |
71 | }
72 | }
73 | size++;
74 | c = getc(i);
75 | if( c == '\n' ){
76 | //total_newlines++;
77 | }
78 |
79 | }
80 | fseek(i, -(ftell(i) - pos), SEEK_CUR);
81 |
82 | word = (char*)xmalloc(sizeof(char)*size + 1);
83 |
84 | c = getc(i);
85 |
86 | /* Then we copy the word the to malloc'ed space */
87 | while ( ((c != EOF) && !isspace(c)) && (j < size) ){
88 | /* This new section handles the new string copy! */
89 | if ( c == '\"' ){
90 | word[j] = c;
91 | j++;
92 | c = getc(i);
93 | word[j] = c;
94 |
95 | while( c != '\"' && (j < size) ){
96 | word[j] = c;
97 | j++;
98 | c = getc(i);
99 | }
100 | }
101 | word[j] = c;
102 | j++;
103 | c = getc(i);
104 | }
105 | word[size] = '\0';
106 |
107 |
108 | return word;
109 | }
110 |
--------------------------------------------------------------------------------
/src/compiler/drivers/utils/scan_for_o.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 |
5 | char *scan_for_o(int argc, char *argv[])
6 | {
7 | int i;
8 | for(i = 0; i < argc; i++){
9 | if(strcmp(argv[i], "-o") == 0){
10 | return argv[i + 1];
11 | }
12 | }
13 | }
14 |
15 | int main()
16 | {
17 | char *argv[3] = {"program", "-o", "name"};
18 |
19 | printf("%s", scan_for_o(3, argv));
20 | return 0;
21 | }
22 |
23 |
--------------------------------------------------------------------------------
/src/compiler/drivers/utils/strip_whitesp.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | char *strip_whitesp(char *str);
5 |
6 | int main()
7 | {
8 | char s[] = " crap ";
9 | printf("Before:'%s'\n", s);
10 |
11 | printf("After:'%s'\n", strip_whitesp(s));
12 | return 0;
13 | }
14 |
15 | char *strip_whitesp(char *str)
16 | {
17 | return NULL;
18 | }
19 |
--------------------------------------------------------------------------------
/src/compiler/error.c:
--------------------------------------------------------------------------------
1 | /** \file error.c
2 | \brief
3 | */
4 |
5 | #include "error.h"
6 |
7 | void error(char* file, int line, int column, char *msg){
8 | printf("\n%s:%d:%d: error: %s\n", file, line, column, msg);
9 | exit(EXIT_FAILURE);
10 | }
11 |
12 | void warning(char* file, int line, int column, char *msg){
13 | printf("\n%s:%d:%d: warning: %s\n", file, line, column, msg);
14 | }
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/src/compiler/error.h:
--------------------------------------------------------------------------------
1 | /** \file error.h
2 | \brief Header file containing all of the error handling primatives for the compiler.
3 | These primatives are for error output in terms of the runtime compiler, not the
4 | development environment for this code.
5 | */
6 |
7 | #ifndef _ERROR_H_
8 | #define _ERROR_H_
9 |
10 | #include
11 | #include
12 |
13 | enum {
14 | TYPE_ERR,
15 | TOKEN_ERR,
16 | SYNTAX_ERR,
17 | TYPE_WARN,
18 | TOKEN_WARN,
19 | SYNTAX_WARN
20 | };
21 |
22 |
23 | size_t lines;
24 | size_t columns;
25 |
26 | /** Prints an error message in standard UNIX(GNU/GCC) format
27 | */
28 | inline void error(char* file, int line, int column, char *msg);
29 | /** Prints an warning message in standard UNIX(GNU/GCC) format
30 | */
31 | inline void warning(char* file, int line, int column, char *msg);
32 |
33 | /** Get the line number where the error occurred.
34 | */
35 | inline int get_line(FILE *i);
36 |
37 | /** Get the column number where the error occurred.
38 | */
39 | inline int get_column(FILE *i);
40 |
41 | #endif
42 |
--------------------------------------------------------------------------------
/src/compiler/main.c:
--------------------------------------------------------------------------------
1 | /** \file main.c
2 | \brief
3 | */
4 |
5 | #include "main.h"
6 |
7 | size_t total_newlines = 1;
8 |
9 | extern file_struct file;
10 |
11 | symbol_table *string_table;
12 | symbol_table *id_table;
13 |
14 | int so = 0;
15 |
16 | int main(int argc, char *argv[])
17 | {
18 | char *ofile; /**> Filename of the output file */
19 | char *infile; /**> Filename of the input file */
20 | size_t o_name_len; /**> Filesize of the name specifed by the -o flag */
21 |
22 | /* Initialize some file information */
23 | strcpy(file.calling_prog, argv[0]);
24 | strcpy(file.default_o, DEFAULT_OUTPUT);
25 | file.cur_line = 0;
26 | file.cur_column = 0;
27 |
28 | switch(argc){
29 | case 1:
30 | printf("%s: no input files.\n Try --help for more options.\n", file.calling_prog);
31 | break;
32 | case 2:
33 | if(strcmp(argv[1], "--help") == 0){
34 | usage();
35 | }
36 | else if(strcmp(argv[1], "--version") == 0){
37 | version();
38 | }
39 | else {
40 | /* Initialize File Contents */
41 | strcpy(file.filename, argv[1]);
42 |
43 | /* No output name specified, we default to unix elf name a.out */
44 | // run_preprocessor(&file);
45 |
46 | run_scanner(&file);
47 | run_parser(); /* Generates Stack Code */
48 | }
49 | break;
50 | case 3:
51 | fprintf(stderr, "File input error!\n");
52 | exit(EXIT_FAILURE);
53 | break;
54 | default:
55 | /* These next few lines handle the -o flag */
56 |
57 | if( strcmp(argv[1], "-So") == 0 ){
58 | printf("\n%s\n", argv[2]);
59 | }
60 | o_name_len = strlen((char*)scan_for_o(argc, argv));
61 |
62 | if(o_name_len > 0){
63 | ofile = (char*)xmalloc(sizeof(char)*o_name_len);
64 | strcpy(ofile, (char*)scan_for_o(argc, argv));
65 |
66 | strcpy(file.filename, argv[1]);
67 | strcpy(file.default_o, ofile);
68 |
69 |
70 | run_preprocessor(&file);
71 |
72 | run_scanner(&file); /* Outputs an interim file */
73 | run_parser(); /* Generates Stack Code */
74 |
75 | free(ofile);
76 | }
77 |
78 | break;
79 | }
80 |
81 | return EXIT_SUCCESS;
82 | }
83 |
84 |
--------------------------------------------------------------------------------
/src/compiler/main.h:
--------------------------------------------------------------------------------
1 | /** \file main.h
2 | \brief
3 | */
4 |
5 | #ifndef _MAIN_H_
6 | #define _MAIN_H_
7 |
8 | #include
9 | #include
10 | #include
11 | #include
12 |
13 | #include "symbol.h"
14 | #include "utils.h"
15 | #include "preprocessor.h"
16 | #include "scanner.h"
17 |
18 |
19 | /* Command Line Options (externals)*/
20 |
21 | extern int So;
22 |
23 |
24 | #endif
25 |
--------------------------------------------------------------------------------
/src/compiler/parser.h:
--------------------------------------------------------------------------------
1 | /** \file parser.h
2 | \brief
3 | */
4 |
5 | #ifndef _PARSER_H_
6 | #define _PARSER_H_
7 |
8 | #include
9 | #include
10 | #include
11 | #include "error.h"
12 | #include "utils.h"
13 | #include "symbol.h"
14 | #include "scanner.h"
15 |
16 | /* Opcodes */
17 |
18 | #define OP_PUSH 0
19 | #define OP_PUSHI 1
20 | #define OP_POP 2
21 | #define OP_EXCH 3
22 | #define OP_DUP 4
23 | #define OP_ADDF 5
24 | #define OP_ADD 6
25 | #define OP_SUBF 7
26 | #define OP_SUB 8
27 | #define OP_MULF 9
28 | #define OP_MUL 10
29 | #define OP_DIV 11
30 | #define OP_DIVF 12
31 | #define OP_AND 13
32 | #define OP_OR 14
33 | #define OP_EQL 15
34 | #define OP_NEG 16
35 | #define OP_NOT 17
36 | #define OP_LSS 18
37 | #define OP_GTR 19
38 | #define OP_LEQ 20
39 | #define OP_GEQ 21
40 | #define OP_CVI 22
41 | #define OP_CVR 23
42 | #define OP_JMP 24
43 | #define OP_JFALSE 25
44 | #define OP_JTRUE 26
45 | #define OP_HALT 27
46 | #define OP_WRITEINT 28
47 |
48 | #define OP_WRITEFLOAT 29
49 | #define OP_MOD 30
50 |
51 | #define OP_PUSHF 31
52 | #define OP_POPF 32
53 |
54 | #define OP_WRITEINTID 33
55 | #define OP_POPEMPTY 34
56 | #define OP_NOP 35
57 |
58 | #define OP_NEQ 36
59 | #define OP_EQU 37
60 | #define OP_NEGF 38
61 | #define OP_WRITESTRING 39
62 | #define OP_GET 40
63 | #define OP_PUT 41
64 |
65 | /* Type defs */
66 | typedef unsigned char uchar;
67 | typedef char TYPE;
68 |
69 | typedef union Operand_TAG {
70 | int i;
71 | float f;
72 | } Operand;
73 |
74 | typedef struct Instruction_TAG {
75 | char opcode; /* 8-bit */
76 | Operand operand; /* 32-bit */
77 | }Instruction;
78 |
79 | /* Globals */
80 | static char *cur_token;
81 | static int dp = 0;
82 |
83 |
84 | /* Externals */
85 | extern file_struct file;
86 | extern symbol_table *string_table;
87 | extern symbol_table *id_table;
88 |
89 | extern symbol_table *stab_stack[];
90 |
91 | /** Gets a lexeme. _MUST_ be freed after use.
92 | */
93 | char *get_lexeme(FILE *i);
94 |
95 | /** Given a lexeme, returns the NAME part. _MUST_ be freed after call.
96 | */
97 | int get_token_name(char *lexeme);
98 |
99 | /** Given a lexeme, returns the NAME part. _MUST_ be freed after call.
100 | */
101 | int get_token_value(char *lexeme);
102 |
103 | float get_token_value_f(char *lexeme);
104 |
105 | /**
106 | */
107 |
108 | char* get_token();
109 |
110 | /**
111 | */
112 | void match(char *token);
113 |
114 | /**
115 | */
116 | void matchi(int token);
117 |
118 | /**
119 | */
120 | char *peek_next_token();
121 |
122 |
123 | /**** PRODUCTIONS ******/
124 |
125 | TYPE CProgram();
126 |
127 | void Declarations();
128 | void Assignment();
129 | void MainEntry();
130 |
131 | int IntDec();
132 | int FloatDec();
133 | int CharDec();
134 |
135 | void Statements();
136 | void IfStatement();
137 | void DoWhile();
138 | void While();
139 | void Goto();
140 | void Label();
141 | void Switch();
142 | void Case();
143 |
144 | /* Expression Productions */
145 | /**
146 | */
147 | TYPE E();
148 |
149 | /**
150 | */
151 | TYPE EPrime();
152 |
153 | /**
154 | */
155 | TYPE T();
156 |
157 | /**
158 | */
159 | TYPE TPrime();
160 |
161 | /**
162 | */
163 | TYPE F();
164 |
165 |
166 | /**
167 | */
168 |
169 | TYPE L();
170 |
171 | /**
172 | */
173 | TYPE LPrime();
174 |
175 | #endif
176 |
--------------------------------------------------------------------------------
/src/compiler/preprocessor.c:
--------------------------------------------------------------------------------
1 | /** \file preprocessor.c
2 | \brief
3 | */
4 |
5 | #include "preprocessor.h"
6 |
7 | file_struct file;
8 |
9 | void run_preprocessor(file_struct *file)
10 | {
11 | /* Order of file processing ("data" is the name of the intermediary file"):
12 | **********************************************************************
13 | * ifilename(open the stream) --> include_headers("data") --> data -->
14 | * remove_comments("data") --> data --> handle_defines("data") -->
15 | * data
16 | */
17 |
18 | /* We need certain flags to be set here. If they are not set, then we simply use
19 | * the system defaults. These flags deal with the standard directories, among others things.
20 | */
21 |
22 | int dir_flag = FALSE;
23 | int lib_flag = FALSE;
24 |
25 |
26 | /* set_flags(dir_flag, lib_flag); */
27 |
28 | if( !dir_flag ){
29 | sys_inc_dir = (char*)xmalloc(sizeof(char)*strlen(DEFAULT_INC_DIR) + 1);
30 | strcpy(sys_inc_dir, DEFAULT_INC_DIR);
31 | }
32 | if( !lib_flag ){
33 | sys_lib_dir = (char*)xmalloc(sizeof(char)*strlen(DEFAULT_LIB_DIR) + 1);
34 | strcpy(sys_lib_dir, DEFAULT_LIB_DIR);
35 | }
36 |
37 |
38 | /********************************************************************
39 | * First we import all included header files into the current working c temp
40 | * file and output an intermediary object file.
41 | ********************************************************************/
42 |
43 | //include_headers(prog, ifilename, INTERIM_FILENAME);
44 |
45 | /* This same interim file is then used for all subsequent operations, including
46 | feeding it to the compiler (scanner, parser, etc etc).
47 | */
48 |
49 |
50 | /* After header files are included, we remove all C-Style comments from the tmp file*/
51 | remove_comments(file);
52 |
53 | /* At this point, we have to handle #defines. There are two types of cases here.
54 | One is a symbolic constant, the other is a macro. I will handle the constant case
55 | first, and leave stubs for macro, as I'm not sure if I'll implement it fully yet
56 | */
57 |
58 | //handle_defines((char*)prog, "tmp.txt");
59 |
60 | /* Memory Clean Up */
61 |
62 | if( !dir_flag ){
63 | free(sys_inc_dir);
64 | }
65 | if( !lib_flag ){
66 | free(sys_lib_dir);
67 | }
68 | }
69 |
70 | char *handle_defines(char* prog, char *filename)
71 | {
72 | char c;
73 | int j;
74 | char *def_keyword;
75 | char *def_name;
76 | char *def_value;
77 |
78 | char *def_name_tmp;
79 | int paren_flag = FALSE;
80 |
81 | /* create preprocessor symbol table here */
82 | symbol_table *defines_stab = create_stab("Preprocessor", MAX_SLOTS);
83 |
84 | FILE *i = fopen(filename, "r");
85 |
86 | /* This bit handles the defines */
87 | while( (c = getc(i)) != EOF ){
88 | if( c == '#' && (tolower(fcpeek(i)) == 'd') ) {
89 | def_keyword = getword(i);
90 | def_name = getword(i);
91 |
92 | /* does the first macro-word have '(' ? */
93 | /* If so then: */
94 | /*
95 | if(strchr(def_name, '(')){
96 | def_name_tmp = getword(i);
97 | while(!strchr(def_name_tmp, ')')){
98 | strcat(def_name, def_name_tmp);
99 | free(def_name_tmp);
100 | def_name_tmp = getword(i);
101 | }
102 | strcat(def_name, def_name_tmp);
103 | free(def_name_tmp);
104 | }*/
105 |
106 | def_value = getword(i);
107 |
108 | stab_insert(filename, get_record(def_name, def_value, 't', 0, "Global"), defines_stab );
109 |
110 | free(def_keyword);
111 | free(def_name);
112 | free(def_value);
113 | }
114 |
115 |
116 |
117 | }
118 |
119 | //print_stab(defines_stab);
120 | /* This bit handles the defines */
121 |
122 |
123 |
124 | return NULL;
125 | }
126 |
127 | void include_headers(const char *prog, const char *ifilename, const char *ofilename)
128 | {
129 | char c; /**> Top level character stream container. Holds the characters of ifilename. */
130 | char c_inc; /**> Nested character stream container. Holds the characters of the included files to write. */
131 | char *inc_fname; /**> This is the stripped include file name. */
132 | char *inc_keyword; /**> This is for debugging, holds the include keyword file read so far. */
133 | char *full_filename; /**> This represents the directory (is_it_system?) and filename concatenated. */
134 | char *fname;
135 | char *file_path; /**> Holds the full pathname.*/
136 |
137 | int is_it_system = FALSE; /**> (is it system files?) Just a flag to specify system vs. user files. */
138 |
139 | FILE *includes; /**> Input file stream for all include files to be inserted. */
140 |
141 |
142 |
143 | FILE *i = fopen(ifilename, "r");
144 | FILE *o = fopen(ofilename, "w");
145 |
146 | if(!i)
147 | file_error((char*)prog, "open", (char*)ifilename, "for inserting include headers", "No such file or directory");
148 | if(!o)
149 | file_error((char*)prog, "write", (char*)ofilename, "for inserting include headers(preproc intermediate file)\n", "Unknown reason.");
150 |
151 |
152 | /* Here we write out the included file to the intermediary preprocessor file */
153 | while( (c = getc(i)) != EOF ){
154 | if( c == '\n' ){
155 | total_newlines++;
156 | }
157 | if(c == '#' && (fcpeek(i) == 'i')){
158 |
159 | inc_keyword = getword(i);
160 | full_filename = getword(i);
161 |
162 | /* Here, we determine if the include file is a system file, or user defined */
163 | if(full_filename && full_filename[0] == '<')
164 | is_it_system = TRUE;
165 | else if (full_filename && full_filename[0] == '"')
166 | is_it_system = FALSE;
167 |
168 | inc_fname = (char*)get_inc_fname(full_filename);
169 | /*
170 | printf("%s :\n", inc_keyword);
171 | printf("'%s' :\n", inc_fname);
172 | printf("Is it system file? %s\n\n", ((is_it_system)? "Yes": "No"));
173 | */
174 | if(is_it_system){
175 | file_path = (char*)xmalloc(sizeof(char)* (strlen(sys_inc_dir) + strlen(inc_fname) + 1));
176 | strcpy(file_path, sys_inc_dir);
177 | strcat(file_path, inc_fname);
178 | strcat(file_path, "\0");
179 | }
180 | else if(!is_it_system){
181 | file_path = (char*)xmalloc(sizeof(char)* (strlen(sys_inc_dir) + 3));
182 | strcpy(file_path, "./");
183 | strcat(file_path, inc_fname);
184 | strcat(file_path, "\0");
185 | }
186 |
187 | /*
188 | printf("Full Path: %s\n", file_path);
189 | */
190 |
191 | includes = fopen(file_path, "r");
192 |
193 | if (!includes){
194 | file_error((char*)prog, "open", (char*)file_path, "While doing header inclusions", "No such file or directory");
195 | }
196 |
197 | while ( (c_inc = getc(includes)) != EOF ) {
198 | putc(c_inc, o);
199 | }
200 |
201 | fclose(includes);
202 |
203 |
204 | free(inc_keyword);
205 | free(inc_fname);
206 | //free(fname);
207 |
208 |
209 | c = getc(i); /* We need to pop this off c (since it's the '#' character) from the
210 | * if conditional above. Then it is safe to write out. */
211 | }
212 | putc(c, o);
213 | }
214 |
215 |
216 | fclose(i);
217 | fclose(o);
218 | }
219 |
220 | char *get_inc_fname(char *n)
221 | {
222 | int i;
223 | size_t size = strlen(n);
224 | char *new_word = (char*)xmalloc(sizeof(char)*(size-2)); /* + 1 for the '\0' terminator */
225 |
226 |
227 | for(i = 0; i < (size-2); i++){
228 | new_word[i] = n[i+1];
229 |
230 | }
231 |
232 | new_word[size-2] = '\0';
233 | free(n);
234 | return new_word;
235 | }
236 |
237 |
238 | void remove_comments(file_struct *file)
239 | {
240 |
241 | FILE *i = fopen(file->filename, "r");
242 | FILE *o = fopen(INTERIM_FILENAME, "w");
243 |
244 | if(!i)
245 | file_error((char*)file->calling_prog,
246 | "open",
247 | (char*)file->filename,
248 | "for removing comments", "No such file or directory.");
249 | if(!o)
250 | file_error((char*)file->calling_prog,
251 | "write",
252 | (char*)file->filename,
253 | "preproc intermediate file",
254 | "Unknown reason(possibly permissions");
255 |
256 | /* This code handles the multiline comments removal */
257 | char c, c_tmp;
258 |
259 | while ( (c = getc(i)) != EOF ){
260 |
261 | if( c == '\n' ){
262 | total_newlines++;
263 | }
264 |
265 | if(c == '/' && (fcpeek(i) == '*')){
266 |
267 | c = getc(i); /* Holds '*' */
268 | c = getc(i); /* Knock that starter '*' off the file discriptor. */
269 | while( c != EOF ){
270 | if( c == '\n' ){
271 | total_newlines++;
272 | }
273 | if( c == '/' && (fcpeek(i) == '*')){
274 | remove(INTERIM_FILENAME);
275 | error(file->filename, total_newlines, 0, "Cannot nest comments!\n");
276 | }
277 | if( c == '*' && fcpeek(i) == '/' )
278 | break;
279 |
280 | c = getc(i);
281 | }
282 |
283 | c = getc(i); /* Pop off the last '*' */
284 | c = getc(i); /* Pop off the last '/' */
285 |
286 | /* Why am I doing the below again? Crap, I show really comment my code...*/
287 | /*if (c == '\n'){
288 | c = getc(i);
289 |
290 | }*/
291 | }
292 | putc(c, o);
293 | }
294 |
295 | fclose(i);
296 | fclose(o);
297 |
298 | //remove(file->filename);
299 | //rename("data.tmp", file->filename);
300 | }
301 |
302 |
303 |
304 |
--------------------------------------------------------------------------------
/src/compiler/preprocessor.h:
--------------------------------------------------------------------------------
1 | /** \file preprocessor.h
2 | \brief Preprocessor defines all the operations necessary for the first pass in the compiler.
3 | */
4 |
5 | #ifndef _PREPROCESSOR_H_
6 | #define _PREPROCESSOR_H_
7 |
8 | #include
9 | #include
10 | #include
11 |
12 | #include "utils.h"
13 | #include "symbol.h"
14 |
15 | /* First Pass */
16 |
17 | #define MAX_PREPROC_IDENT 2
18 |
19 | #define PREPROC_DEFINE 0
20 | #define PREPROC_INCLUDE 1
21 |
22 | #define DEFAULT_INC_DIR "/usr/include/"
23 | #define DEFAULT_LIB_DIR "/usr/lib/"
24 |
25 |
26 | /*------------------------- Globals -------------------------*/
27 |
28 | char *sys_inc_dir;
29 | char *sys_lib_dir;
30 |
31 | extern size_t total_newlines;
32 | extern file_struct file;
33 |
34 |
35 |
36 |
37 |
38 |
39 | /*------------------- Function Prototypes -------------------*/
40 |
41 |
42 | /** Runs the preprocessor on the specified file.
43 | */
44 | void run_preporcessor(file_struct *file);
45 |
46 | /**
47 | */
48 | void include_headers(const char *prog, const char *ifilename, const char *ofilename);
49 |
50 |
51 | /** This gets the next include name from the #include preprocessor directive.
52 | * It is malloced internally. It _MUST_ be freed after each use.
53 | */
54 | char *get_inc_fname(char *n);
55 |
56 | /**
57 | */
58 | char *handle_defines(char *prog, char *filename);
59 |
60 | /** Removes all comments from the import source file, and outputs an intermediary file for
61 | * further processing. At the moment, only handles 1 nested level of inclusion.
62 | */
63 | void remove_comments(file_struct *file);
64 |
65 |
66 | #endif
67 |
--------------------------------------------------------------------------------
/src/compiler/scanner.c:
--------------------------------------------------------------------------------
1 | /** \file scanner.c
2 | \brief Contains all lexical analyzer operations.
3 | */
4 |
5 | #include "scanner.h"
6 |
7 | symbol_table *string_table;
8 | symbol_table *id_table;
9 |
10 | void run_scanner(file_struct *file)
11 | {
12 | char *word;
13 | int _u = 0;
14 |
15 | /* This is wasteful */
16 | string_table = create_stab("String Literals", MAX_SLOTS);
17 | id_table = create_stab("ID Symbol Table", MAX_SLOTS);
18 |
19 | /* Dispatcher. Suggested by professor Vulis to eliminate comparison overhead
20 | incurred by switch statement! Very nice.
21 | */
22 | void (*dispatcher[255])(FILE *o, char *word);
23 |
24 | /* Set everything on the dispatcher to the default job */
25 |
26 | for(_u = 0; _u < 256; _u++)
27 | dispatcher[_u] = &default_;
28 |
29 | dispatcher['a'] = &a;
30 | dispatcher['b'] = &b;
31 | dispatcher['c'] = &c;
32 | dispatcher['d'] = &d;
33 | dispatcher['e'] = &e;
34 | dispatcher['f'] = &f;
35 | dispatcher['g'] = &g;
36 | dispatcher['i'] = &i;
37 | dispatcher['l'] = &l;
38 | dispatcher['r'] = &r;
39 | dispatcher['s'] = &s;
40 | dispatcher['t'] = &t;
41 | dispatcher['u'] = &u;
42 | dispatcher['v'] = &v;
43 | dispatcher['w'] = &w;
44 | dispatcher['p'] = &p;
45 | dispatcher['{'] = &leftbracket;
46 | dispatcher['}'] = &rightbracket;
47 | dispatcher['('] = &leftparen;
48 | dispatcher[')'] = &rightparen;
49 | dispatcher['['] = &left_sqr_bracket;
50 | dispatcher[']'] = &right_sqr_bracket;
51 | dispatcher['.'] = ˙
52 | dispatcher[','] = ,
53 | dispatcher['!'] = &exclamation;
54 | dispatcher['~'] = &tilda;
55 | dispatcher['+'] = +
56 | dispatcher['-'] = −
57 | dispatcher['*'] = &unary_star;
58 | dispatcher['&'] = &ersand;
59 | dispatcher['/'] = &div_;
60 | dispatcher['%'] = &mod;
61 | dispatcher['<'] = &less;
62 | dispatcher['>'] = &greater;
63 | dispatcher['='] = &equal;
64 | dispatcher['|'] = ∨
65 | dispatcher['^'] = &xor;
66 | dispatcher['?'] = &question;
67 | dispatcher[':'] = :
68 | dispatcher[';'] = &semicolon;
69 |
70 | FILE *i = fopen(INTERIM_FILENAME, "r");
71 | FILE *o = fopen("tmp", "w");
72 |
73 | if( i == NULL ){
74 | error(file->filename, 0, 0, "Could not open file for processing! Exiting");
75 | }
76 |
77 | /* getword() returns a string, so a NULL signifies that
78 | * nothing useful was retrieved from the input stream
79 | */
80 |
81 | while( (word = getword(i)) != NULL ){
82 | dispatcher[word[0]](o, word);
83 | free(word);
84 | }
85 |
86 | fclose(i);
87 | fclose(o);
88 | remove(INTERIM_FILENAME);
89 | rename("tmp", INTERIM_FILENAME);
90 |
91 | }
92 |
93 | void put_lexeme(FILE *o, char *tk_name, char *tk_value)
94 | {
95 | size_t tk_name_size = strlen(tk_name);
96 | size_t tk_value_size = strlen(tk_value);
97 |
98 | putc('<', o);
99 | fwrite(tk_name, sizeof(char), tk_name_size, o);
100 | putc(',', o);
101 | fwrite(tk_value, sizeof(char), tk_value_size, o);
102 | putc('>', o);
103 | }
104 |
105 | void put_ulexeme(FILE *o, char *tk_name)
106 | {
107 | size_t tk_name_size = strlen(tk_name);
108 |
109 | putc('<', o);
110 | fwrite(tk_name, sizeof(char), tk_name_size, o);
111 | putc('>', o);
112 | }
113 |
114 |
115 | /* NOTE TO SELF: Still need to handle the multiple character
116 | * token extractions!! That is, say, '<<' as opposed to '<'
117 | */
118 |
119 | char *extract_token(char *word)
120 | {
121 |
122 | switch(word[0]){
123 | case '{':
124 | return copy_alloced("{");
125 | case '}':
126 | return copy_alloced("}");
127 | case '(':
128 | return copy_alloced("(");
129 | case ')':
130 | return copy_alloced(")");
131 | case ']':
132 | return copy_alloced("]");
133 | case '[':
134 | return copy_alloced("[");
135 | case '.':
136 | return copy_alloced(".");
137 | case ',':
138 | return copy_alloced(",");
139 | case '!':
140 | if (word[1] == '='){
141 | return copy_alloced("!=");
142 | }
143 | else
144 | return copy_alloced("!");
145 | case '~':
146 | if (word[1] == '=')
147 | return copy_alloced("~=");
148 | else
149 | return copy_alloced("~");
150 | case '+':
151 | if (word[1] == '+')
152 | return copy_alloced("++");
153 | else if (word[1] == '=')
154 | return copy_alloced("+=");
155 | else
156 | return copy_alloced("+");
157 | case '-':
158 | if (word[1] == '-')
159 | return copy_alloced("--");
160 | else if (word[1] == '=')
161 | return copy_alloced("-=");
162 | else
163 | return copy_alloced("-");
164 | case '*':
165 | if(word[1] == '=')
166 | return copy_alloced("*=");
167 | else
168 | return copy_alloced("*");
169 |
170 | case '&':
171 | if(word[1] == '&')
172 | return copy_alloced("&&");
173 | else if (word[1] == '=')
174 | return copy_alloced("&=");
175 | else
176 | return copy_alloced("&");
177 |
178 | case '/':
179 | if(word[0] == '=')
180 | return copy_alloced("/=");
181 | else
182 | return copy_alloced("/");
183 |
184 | case '%':
185 | if( word[1] == '=' )
186 | return copy_alloced("%=");
187 | else
188 | return copy_alloced("%");
189 |
190 | case '<':
191 | if( word[1] == '<' ){
192 | if (word[2] == '=')
193 | return copy_alloced("<<=");
194 | else
195 | return copy_alloced("<<");
196 | }
197 | else if (word[1] == '=')
198 | return copy_alloced("<=");
199 | else
200 | return copy_alloced("<");
201 |
202 | case '>':
203 | if( word[1] == '>' ){
204 | if (word[2] == '=')
205 | return copy_alloced(">>=");
206 | else
207 | return copy_alloced(">>");
208 | }
209 | else if (word[1] == '=')
210 | return copy_alloced(">=");
211 | else
212 | return copy_alloced(">");
213 |
214 | case '=':
215 | if( word[1] == '=' )
216 | return copy_alloced("==");
217 | else
218 | return copy_alloced("=");
219 | case '|':
220 | if (word[1] == '|')
221 | return copy_alloced("||");
222 | else if (word[1] == '=')
223 | return copy_alloced("|=");
224 | else
225 | return copy_alloced("|");
226 | case '^':
227 | if (word[1] == '=')
228 | return copy_alloced("^=");
229 | else
230 | return copy_alloced("^");
231 | case '?':
232 | return copy_alloced("?");
233 | case ':':
234 | return copy_alloced(":");
235 | case ';':
236 | return copy_alloced(";");
237 |
238 | /* Constants */
239 |
240 | case '\'':
241 | return return_char(word);
242 | /* String Literals */
243 | /* Questioning if this even belongs here?*/
244 | case '"':
245 | return return_string(word);
246 | break;
247 |
248 | default:
249 | if( isdigit(word[0]) ){
250 | return return_integral(word);
251 | }
252 | else {
253 | return return_keyword(word);
254 | }
255 | break;
256 | }
257 | return NULL;
258 | }
259 |
260 | char *return_char(char *word)
261 | {
262 | int i, j;
263 | size_t size = strlen(word);
264 | char *tmp;
265 | for(i = 1; i < size; i++){
266 | if( word[i] == '\'' ){
267 | i++;
268 | break;
269 | }
270 | }
271 |
272 | tmp = (char*)xmalloc(sizeof(char)*i + 1);
273 |
274 | for(j = 0; j < i; j++){
275 | tmp[j] = word[j];
276 | }
277 |
278 | tmp[i] = '\0';
279 | if(strlen(tmp) > 3){
280 | error("unknown-file", total_newlines, 0, "Bad character literal!\n");
281 | }
282 |
283 | return tmp;
284 | }
285 |
286 | char *return_integral(char *word)
287 | {
288 | int i, j;
289 | size_t size = strlen(word);
290 |
291 | for(i = 0; i < size; i++){
292 | if( !isdigit(word[i]) && word[i] != '.' ){
293 | break;
294 | }
295 | }
296 |
297 | char *integral = (char*)xmalloc(sizeof(char)* i + 1);
298 |
299 | for(j = 0; j < i; j++){
300 | integral[j] = word[j];
301 | }
302 | integral[i] = '\0';
303 | return integral;
304 | }
305 |
306 | char *return_string(char *word)
307 | {
308 | int i, j;
309 | size_t size = strlen(word);
310 | char *tmp;
311 |
312 | for(i = 1; i < size; i++){
313 | if( word[i] == '"' ){
314 | i++;
315 | break;
316 | }
317 | }
318 | tmp = (char*)xmalloc(sizeof(char)*i + 1);
319 |
320 | for(j = 0; j < i; j++){
321 | tmp[j] = word[j];
322 | }
323 | tmp[i] = '\0';
324 |
325 | return tmp;
326 | }
327 |
328 | char *return_keyword(char *word)
329 | {
330 | if (word == NULL){
331 | return NULL;
332 | }
333 |
334 | size_t size = strlen(word);
335 | int i;
336 | for(i = 0; i < size; i++){
337 | if( !isdigit(word[i]) && !isalpha(word[i]) && word[i] != '_'){
338 | break;
339 | }
340 | }
341 | /* 'i' is the size of the valid keyword or id */
342 | char *keyword = (char *)xmalloc(sizeof(char)* i + 1);
343 |
344 | strcpy(keyword, word);
345 | keyword[i] = '\0';
346 |
347 | return keyword;
348 |
349 | }
350 |
351 | int is_valid_id(char *word)
352 | {
353 | size_t size = strlen(word);
354 | int is_valid;
355 | int j;
356 | for(j = 0; j < size; j++){
357 | if( !isalpha(word[j]) && !isdigit(word[j]) && word[j] != '_' ){
358 | return FALSE;
359 | }
360 | }
361 | return TRUE;
362 | }
363 |
364 | int parse_tokens(FILE *o, char *word)
365 | {
366 | int index; /**> Used for the hash return value */
367 | size_t n, m;
368 | char *token = extract_token(word);
369 | char *tmp;
370 | size_t tk_size = strlen(token);
371 | size_t word_size = strlen(word);
372 | size_t diff = word_size - tk_size;
373 | size_t upto = tk_size;
374 |
375 | token_package tk;
376 |
377 | while(tk_size > 0){
378 | tmp = (char*)xmalloc(sizeof(char)*diff + 1);
379 |
380 | for(n = 0, m = upto; n < diff; n++, m++){
381 | tmp[n] = word[m];
382 | }
383 | tmp[diff] = '\n';
384 |
385 | tk = get_sval(token);
386 |
387 | if (tk.type == -1){
388 | sprintf(tk_buffer0, "%d", tk.val);
389 | put_ulexeme(o, tk_buffer0);
390 | }
391 | else if (tk.type == TK_KEYWORD) {
392 |
393 | // Switching from to only
394 | sprintf(tk_buffer0, "%d", tk.val);
395 |
396 | put_ulexeme(o, tk_buffer0);
397 | }
398 | else if (tk.type == TK_IDENTIFIER) {
399 |
400 | record *rec = (record*)get_record(token, "NULL", 'V', 0, "\0");
401 | rec->addr = -1;
402 |
403 | index = hash(token, id_table->size);
404 |
405 | if (id_table->table[index].slot != EMPTY_SLOT){
406 | free(rec);
407 | }
408 | else {
409 | stab_insert("symbol", rec, id_table);
410 | }
411 |
412 | sprintf(tk_buffer0, "%d", TK_IDENTIFIER);
413 | sprintf(tk_buffer1, "%d", index);
414 | put_lexeme(o, tk_buffer0, tk_buffer1);
415 | }
416 | else if (tk.type == TK_STRINGLIT) {
417 |
418 | record *rec = (record*)get_record(token, "NULL", 'S', 0, "\0");
419 | stab_insert("c-string-literal", rec, string_table);
420 | index = hash(rec->name, string_table->size);
421 | /* If there are any collisions, the we just ignore those. I
422 | * output the slot number of the hash, and the TK_STRINLIT token
423 | */
424 |
425 | sprintf(tk_buffer0, "%d", TK_STRINGLIT);
426 | sprintf(tk_buffer1, "%d", index);
427 |
428 | put_lexeme(o, tk_buffer0, tk_buffer1);
429 | }
430 |
431 | else if (tk.type == TK_INTLIT) {
432 | sprintf(tk_buffer0, "%d", TK_INTLIT);
433 | sprintf(tk_buffer1, "%d", tk.val);
434 | put_lexeme(o, tk_buffer0, tk_buffer1);
435 | }
436 | else if (tk.type == TK_FLOATLIT) {
437 | sprintf(tk_buffer0, "%d", TK_FLOATLIT);
438 | sprintf(tk_buffer1, "%f", tk.f_val);
439 | put_lexeme(o, tk_buffer0, tk_buffer1);
440 | }
441 |
442 | if(token != NULL){
443 | free(token);
444 | }
445 | token = extract_token(tmp);
446 | tk_size = strlen(token);
447 |
448 | upto += tk_size;
449 | diff = word_size - upto;
450 |
451 |
452 | /* HUGE BUG HERE, I cannot figure out why it keeps crashing on this free call
453 | I've solved the problem by introducing another bug. There is memory leaking here */
454 | /*
455 | if(tmp != NULL){
456 | printf("tmp_value: %x\n", tmp[0]);
457 |
458 | tmp = NULL;
459 | }*/
460 | free(tmp);
461 |
462 | }
463 | return 0;
464 |
465 | }
466 |
467 | token_package get_sval(char *s)
468 | {
469 | token_package tk;
470 |
471 | if( !strcmp(s, "{") ){
472 | tk.type = -1;
473 | tk.val = TK_LEFTBRACKET;
474 | }
475 | else if( !strcmp(s, "}") ){
476 | tk.type = -1;
477 | tk.val = TK_RIGHTBRACKET;
478 | }
479 | else if( !strcmp(s, "(") ){
480 | tk.type = -1;
481 | tk.val = TK_LEFTPAREN;
482 | }
483 | else if( !strcmp(s, ")") ){
484 | tk.type = -1;
485 | tk.val = TK_RIGHTPAREN;
486 | }
487 | else if( !strcmp(s, "[") ){
488 | tk.type = -1;
489 | tk.val = TK_LEFT_SQR_BRACKET;
490 | }
491 | else if( !strcmp(s, "]") ){
492 | tk.type = -1;
493 | tk.val = TK_RIGHT_SQR_BRACKET;
494 | }
495 | else if( !strcmp(s, ".") ){
496 | tk.type = -1;
497 | tk.val = TK_DOT;
498 | }
499 | else if( !strcmp(s, "!") ){
500 | tk.type = -1;
501 | tk.val = TK_UNARY_EXCLAMATION;
502 | }
503 | else if( !strcmp(s, "~") ){
504 | tk.type = -1;
505 | tk.val = TK_UNARY_TILDA;
506 | }
507 | else if( !strcmp(s, "++") ){
508 | tk.type = -1;
509 | tk.val = TK_UNARY_PLUSPLUS;
510 | }
511 | else if( !strcmp(s, "--") ){
512 | tk.type = -1;
513 | tk.val = TK_UNARY_MINUSMINUS;
514 | }
515 | else if( !strcmp(s, "+") ){
516 | tk.type = -1;
517 | tk.val = TK_PLUS;
518 | }
519 | else if( !strcmp(s, "-") ){
520 | tk.type = -1;
521 | tk.val = TK_MINUS;
522 | }
523 | else if( !strcmp(s, "*") ){
524 | tk.type = -1;
525 | tk.val = TK_MULT_STAR;
526 | }
527 | else if( !strcmp(s, "&") ){
528 | tk.type = -1;
529 | tk.val = TK_UNARY_AMPERSAND;
530 | }
531 | else if( !strcmp(s, "/") ){
532 | tk.type = -1;
533 | tk.val = TK_DIV;
534 | }
535 | else if( !strcmp(s, "%") ){
536 | tk.type = -1;
537 | tk.val = TK_MOD;
538 | }
539 | else if( !strcmp(s, "<<") ){
540 | tk.type = -1;
541 | tk.val = TK_LEFT_SHIFT;
542 | }
543 | else if( !strcmp(s, ">>") ){
544 | tk.type = -1;
545 | tk.val = TK_RIGHT_SHIFT;
546 | }
547 | else if( !strcmp(s, "<") ){
548 | tk.type = -1;
549 | tk.val = TK_LESS_LOGIC;
550 | }
551 | else if( !strcmp(s, ">") ){
552 | tk.type = -1;
553 | tk.val = TK_GREATER_LOGIC;
554 | }
555 | else if( !strcmp(s, ">=") ){
556 | tk.type = -1;
557 | tk.val = TK_GREATER_EQU_LOGIC;
558 | }
559 | else if( !strcmp(s, "<=") ){
560 | tk.type = -1;
561 | tk.val = TK_LESS_EQU_LOGIC;
562 | }
563 | else if( !strcmp(s, "==") ){
564 | tk.type = -1;
565 | tk.val = TK_EQU_EQU_LOGIC;
566 | }
567 | else if( !strcmp(s, "!=") ){
568 | tk.type = -1;
569 | tk.val = TK_NOT_EQU_LOGIC;
570 | }
571 | else if( !strcmp(s, "^") ){
572 | tk.type = -1;
573 | tk.val = TK_BIT_XOR;
574 | }
575 | else if( !strcmp(s, "|") ){
576 | tk.type = -1;
577 | tk.val = TK_BIT_OR;
578 | }
579 | else if( !strcmp(s, "&&") ){
580 | tk.type = -1;
581 | tk.val = TK_LOGIC_AND;
582 | }
583 | else if( !strcmp(s, "||") ){
584 | tk.type = -1;
585 | tk.val = TK_LOGIC_OR;
586 | }
587 | else if( !strcmp(s, "?") ){
588 | tk.type = -1;
589 | tk.val = TK_QUESTION;
590 | }
591 | else if( !strcmp(s, ":") ){
592 | tk.type = -1;
593 | tk.val = TK_COLON;
594 | }
595 | else if( !strcmp(s, ";") ){
596 | tk.type = -1;
597 | tk.val = TK_SEMICOLON;
598 | }
599 | else if( !strcmp(s, "=") ){
600 | tk.type = -1;
601 | tk.val = TK_EQU;
602 | }
603 | else if( !strcmp(s, "+=") ){
604 | tk.type = -1;
605 | tk.val = TK_PLUS_EQU;
606 | }
607 | else if( !strcmp(s, "-=") ){
608 | tk.type = -1;
609 | tk.val = TK_MINUS_EQU;
610 | }
611 | else if( !strcmp(s, "*=") ){
612 | tk.type = -1;
613 | tk.val = TK_STAR_EQU;
614 | }
615 | else if( !strcmp(s, "/=") ){
616 | tk.type = -1;
617 | tk.val = TK_DIV_EQU;
618 | }
619 | else if( !strcmp(s, "%=") ){
620 | tk.type = -1;
621 | tk.val = TK_MOD_EQU;
622 | }
623 | else if( !strcmp(s, "&=") ){
624 | tk.type = -1;
625 | tk.val = TK_AND_EQU;
626 | }
627 | else if( !strcmp(s, "^=") ){
628 | tk.type = -1;
629 | tk.val = TK_XOR_EQU;
630 | }
631 | else if( !strcmp(s, "|=") ){
632 | tk.type = -1;
633 | tk.val = TK_OR_EQU;
634 | }
635 | else if( !strcmp(s, "<=") ){
636 | tk.type = -1;
637 | tk.val = TK_LSHIFT_EQU;
638 | }
639 | else if( !strcmp(s, ">=") ){
640 | tk.type = -1;
641 | tk.val = TK_RSHIFT_EQU;
642 | }
643 | /*** NEW AND NOT COMPLETE ****/
644 | else if( !strcmp(s, "<<=") ){
645 | tk.type = -1;
646 | tk.val = TK_LSHIFT_EQU;
647 | }
648 | else if( !strcmp(s, ">>=") ){
649 | tk.type = -1;
650 | tk.val = TK_RSHIFT_EQU;
651 | }
652 |
653 | /*** NEW AND NOT COMPLETE END ***/
654 | else if( !strcmp(s, ",") ){
655 | tk.type = -1;
656 | tk.val = TK_COMMA;
657 | }
658 | else if( !strcmp(s, "") ){
659 | tk.type = -1;
660 | tk.val = TK_LEFTPAREN;
661 | }
662 | else if( !strcmp(s, ")") ){
663 | tk.type = -1;
664 | tk.val = TK_RIGHTPAREN;
665 | }
666 | else if( !strcmp(s, "auto") ){
667 | tk.type = TK_KEYWORD;
668 | tk.val = TK_AUTO;
669 | }
670 | else if( !strcmp(s, "break") ){
671 | tk.type = TK_KEYWORD;
672 | tk.val = TK_BREAK;
673 | }
674 | else if( !strcmp(s, "case") ){
675 | tk.type = TK_KEYWORD;
676 | tk.val = TK_CASE;
677 | }
678 | else if( !strcmp(s, "char") ){
679 | tk.type = TK_KEYWORD;
680 | tk.val = TK_CHAR;
681 | }
682 | else if( !strcmp(s, "const") ){
683 | tk.type = TK_KEYWORD;
684 | tk.val = TK_CONST;
685 | }
686 | else if( !strcmp(s, "continue") ){
687 | tk.type = TK_KEYWORD;
688 | tk.val = TK_CONTINUE;
689 | }
690 | else if( !strcmp(s, "default") ){
691 | tk.type = TK_KEYWORD;
692 | tk.val = TK_DEFAULT;
693 | }
694 | else if( !strcmp(s, "do") ){
695 | tk.type = TK_KEYWORD;
696 | tk.val = TK_DO;
697 | }
698 | else if( !strcmp(s, "double") ){
699 | tk.type = TK_KEYWORD;
700 | tk.val = TK_DOUBLE;
701 | }
702 | else if( !strcmp(s, "else") ){
703 | tk.type = TK_KEYWORD;
704 | tk.val = TK_ELSE;
705 | }
706 | else if( !strcmp(s, "enum") ){
707 | tk.type = TK_KEYWORD;
708 | tk.val = TK_ENUM;
709 | }
710 | else if( !strcmp(s, "extern") ){
711 | tk.type = TK_KEYWORD;
712 | tk.val = TK_EXTERN;
713 | }
714 | else if( !strcmp(s, "float") ){
715 | tk.type = TK_KEYWORD;
716 | tk.val = TK_FLOAT;
717 | }
718 | else if( !strcmp(s, "for") ){
719 | tk.type = TK_KEYWORD;
720 | tk.val = TK_FOR;
721 | }
722 | else if( !strcmp(s, "goto") ){
723 | tk.type = TK_KEYWORD;
724 | tk.val = TK_GOTO;
725 | }
726 | else if( !strcmp(s, "if") ){
727 | tk.type = TK_KEYWORD;
728 | tk.val = TK_IF;
729 | }
730 | else if( !strcmp(s, "int") ){
731 | tk.type = TK_KEYWORD;
732 | tk.val = TK_INT;
733 | }
734 | else if( !strcmp(s, "long") ){
735 | tk.type = TK_KEYWORD;
736 | tk.val = TK_LONG;
737 | }
738 | else if( !strcmp(s, "register") ){
739 | tk.type = TK_KEYWORD;
740 | tk.val = TK_REGISTER;
741 | }
742 | else if( !strcmp(s, "return") ){
743 | tk.type = TK_KEYWORD;
744 | tk.val = TK_RETURN;
745 | }
746 | else if( !strcmp(s, "short") ){
747 | tk.type = TK_KEYWORD;
748 | tk.val = TK_SHORT;
749 | }
750 | else if( !strcmp(s, "signed") ){
751 | tk.type = TK_KEYWORD;
752 | tk.val = TK_SIGNED;
753 | }
754 | else if( !strcmp(s, "sizeof") ){
755 | tk.type = TK_KEYWORD;
756 | tk.val = TK_SIZEOF;
757 | }
758 | else if( !strcmp(s, "static") ){
759 | tk.type = TK_KEYWORD;
760 | tk.val = TK_STATIC;
761 | }
762 | else if( !strcmp(s, "struct") ){
763 | tk.type = TK_KEYWORD;
764 | tk.val = TK_STRUCT;
765 | }
766 | else if( !strcmp(s, "switch") ){
767 | tk.type = TK_KEYWORD;
768 | tk.val = TK_SWITCH;
769 | }
770 | else if( !strcmp(s, "typedef") ){
771 | tk.type = TK_KEYWORD;
772 | tk.val = TK_TYPEDEF;
773 | }
774 | else if( !strcmp(s, "union" ) ){
775 | tk.type = TK_KEYWORD;
776 | tk.val = TK_UNION;
777 | }
778 | else if( !strcmp(s, "unsigned") ){
779 | tk.type = TK_KEYWORD;
780 | tk.val = TK_UNSIGNED;
781 | }
782 | else if( !strcmp(s, "void") ){
783 | tk.type = TK_KEYWORD;
784 | tk.val = TK_VOID;
785 | }
786 | else if( !strcmp(s, "volatile") ){
787 | tk.type = TK_KEYWORD;
788 | tk.val = TK_VOLATILE;
789 | }
790 | else if( !strcmp(s, "while") ){
791 | tk.type = TK_KEYWORD;
792 | tk.val = TK_WHILE;
793 | }
794 | else if( !strcmp(s, "printf") ){
795 | tk.type = TK_KEYWORD;
796 | tk.val = TK_PRINTF;
797 | }
798 |
799 | else {
800 | if( s[0] == '\"'){
801 | tk.type = TK_STRINGLIT;
802 | tk.val = 0;
803 | }
804 | else if( s[0] == '\''){
805 | tk.type = TK_INTLIT;
806 | tk.val = extract_char(s);
807 | }
808 | else if( isdigit(s[0]) ){
809 | int i;
810 | int dot = FALSE;
811 | size_t size = strlen(s);
812 |
813 | for (i = 0; i < size; i++){
814 | if(s[i] == '.')
815 | dot = TRUE;
816 | else if ( !isdigit(s[i]) ){
817 | printf("Bad number!!!! Has characters in it\n");
818 | return tk;
819 | }
820 | }
821 | if(dot == TRUE){
822 | tk.type = TK_FLOATLIT;
823 | tk.f_val = atof(s);
824 | }
825 | else {
826 | tk.type = TK_INTLIT;
827 | tk.val = atoi(s);
828 | }
829 | }
830 | else {
831 | // Last case, must be a valid id
832 | if( is_valid_id(s) == TRUE){
833 | tk.type = TK_IDENTIFIER;
834 | tk.val = 0; /* Hash slot */
835 | }
836 | }
837 | }
838 | return tk;
839 | }
840 |
841 | int extract_char(char *word)
842 | {
843 | /* This looks like it's going to break any minute! */
844 | size_t size = strlen(word);
845 | char tmp[4];
846 | sprintf(tmp, "%d", word[1]);
847 | tmp[3] = '\n';
848 | return atoi(tmp);
849 | }
850 |
851 | /************************* DISPATCH *****************************/
852 |
853 | void p(FILE *o, char *word)
854 | {
855 | /* printf */
856 | if( !strcmp(word, "printf") ) {
857 | sprintf(tk_buffer0, "%d", TK_PRINTF);
858 | put_ulexeme(o, tk_buffer0);
859 | }
860 | else {
861 | parse_tokens(o,word);
862 | }
863 | }
864 |
865 | void a(FILE *o, char *word)
866 | {
867 | /* auto */
868 | if ( !strcmp(word, "auto") ){
869 | sprintf(tk_buffer0, "%d", TK_AUTO);
870 | put_ulexeme(o, tk_buffer0);
871 | }
872 | else {
873 | parse_tokens(o,word);
874 | }
875 | }
876 |
877 | void b(FILE *o, char *word)
878 | {
879 | /* break */
880 | if ( !strcmp(word, "break") ){
881 | sprintf(tk_buffer0, "%d", TK_BREAK);
882 | put_ulexeme(o, tk_buffer0);
883 | }
884 | else {
885 | parse_tokens(o,word);
886 | }
887 | }
888 | void c(FILE *o, char *word)
889 | {
890 | /* case */
891 | /* char */
892 | /* const */
893 | /* continue */
894 | if( !strcmp(word, "case") ) {
895 | sprintf(tk_buffer0, "%d", TK_CASE);
896 | put_ulexeme(o, tk_buffer0);
897 | }
898 | else if ( !strcmp(word, "char") ){
899 | sprintf(tk_buffer0, "%d", TK_CHAR);
900 | put_ulexeme(o, tk_buffer0);
901 |
902 | }
903 | else if ( !strcmp(word, "const") ){
904 | sprintf(tk_buffer0, "%d", TK_CONST);
905 | put_ulexeme(o, tk_buffer0);
906 | }
907 | else if ( !strcmp(word, "continue") ){
908 | sprintf(tk_buffer0, "%d", TK_CONTINUE);
909 | put_ulexeme(o, tk_buffer0);
910 | }
911 | else {
912 | parse_tokens(o,word);
913 | }
914 | }
915 | void d(FILE *o, char *word)
916 | {
917 | /* default */
918 | /* do */
919 | /* double */
920 | if( !strcmp(word, "default") ) {
921 | sprintf(tk_buffer0, "%d", TK_DEFAULT);
922 | put_ulexeme(o, tk_buffer0);
923 | }
924 | else if ( !strcmp(word, "do") ){
925 | sprintf(tk_buffer0, "%d", TK_DO);
926 | put_ulexeme(o, tk_buffer0);
927 | }
928 | else if ( !strcmp(word, "double") ){
929 | sprintf(tk_buffer0, "%d", TK_DOUBLE);
930 | put_ulexeme(o, tk_buffer0);
931 | }
932 | else {
933 | parse_tokens(o,word);
934 | }
935 | }
936 | void e(FILE *o, char *word)
937 | {
938 | /* else */
939 | /* enum */
940 | /* extern */
941 | if( !strcmp(word, "else") ) {
942 | sprintf(tk_buffer0, "%d", TK_ELSE);
943 | put_ulexeme(o, tk_buffer0);
944 | }
945 | else if ( !strcmp(word, "enum") ){
946 | sprintf(tk_buffer0, "%d", TK_ENUM);
947 | put_ulexeme(o, tk_buffer0);
948 | }
949 | else if ( !strcmp(word, "extern") ){
950 | sprintf(tk_buffer0, "%d", TK_EXTERN);
951 | put_ulexeme(o, tk_buffer0);
952 | }
953 | else {
954 | parse_tokens(o,word);
955 | }
956 | }
957 |
958 | void f(FILE *o, char *word)
959 | {
960 | /* float */
961 | /* for */
962 | if( !strcmp(word, "float") ) {
963 | sprintf(tk_buffer0, "%d", TK_FLOAT);
964 | put_ulexeme(o, tk_buffer0);
965 | }
966 | else if ( !strcmp(word, "for") ){
967 | sprintf(tk_buffer0, "%d", TK_FOR);
968 | put_ulexeme(o, tk_buffer0);
969 | }
970 | else {
971 | parse_tokens(o,word);
972 | }
973 | }
974 |
975 | void g(FILE *o, char *word)
976 | {
977 | /* goto */
978 | if( !strcmp(word, "goto") ) {
979 | sprintf(tk_buffer0, "%d", TK_GOTO);
980 | put_ulexeme(o, tk_buffer0);
981 | }
982 | else {
983 | parse_tokens(o,word);
984 | }
985 | }
986 | void i(FILE *o, char *word)
987 | {
988 | /* int */
989 | /* if */
990 |
991 | if( !strcmp(word, "int") ) {
992 | sprintf(tk_buffer0, "%d", TK_INT);
993 | put_ulexeme(o, tk_buffer0);
994 | }
995 | else if ( !strcmp(word, "if") ){
996 | sprintf(tk_buffer0, "%d", TK_IF);
997 | put_ulexeme(o, tk_buffer0);
998 | }
999 | else {
1000 |
1001 | parse_tokens(o,word);
1002 | }
1003 | }
1004 | void l(FILE *o, char *word)
1005 | {
1006 |
1007 | /* long */
1008 | if( !strcmp(word, "long") ) {
1009 | sprintf(tk_buffer0, "%d", TK_LONG);
1010 | put_ulexeme(o, tk_buffer0);
1011 | }
1012 | else {
1013 | parse_tokens(o,word);
1014 | }
1015 | }
1016 | void r(FILE *o, char *word)
1017 | {
1018 | /* register */
1019 | /* return */
1020 | if( !strcmp(word, "register") ) {
1021 | sprintf(tk_buffer0, "%d", TK_REGISTER);
1022 | put_ulexeme(o, tk_buffer0);
1023 | }
1024 | else if ( !strcmp(word, "return") ){
1025 | sprintf(tk_buffer0, "%d", TK_RETURN);
1026 | put_ulexeme(o, tk_buffer0);
1027 | }
1028 | else {
1029 | parse_tokens(o,word);
1030 | }
1031 | }
1032 | void s(FILE *o, char *word)
1033 | {
1034 | /* short */
1035 | /* signed */
1036 | /* sizeof */
1037 | /* static */
1038 | /* struct */
1039 | /* switch */
1040 |
1041 | if( !strcmp(word, "short") ) {
1042 | sprintf(tk_buffer0, "%d", TK_SHORT);
1043 | put_ulexeme(o, tk_buffer0);
1044 | }
1045 | else if ( !strcmp(word, "signed") ){
1046 | sprintf(tk_buffer0, "%d", TK_SIGNED);
1047 | put_ulexeme(o, tk_buffer0);
1048 | }
1049 | else if ( !strcmp(word, "sizeof") ){
1050 | sprintf(tk_buffer0, "%d", TK_SIZEOF);
1051 | put_ulexeme(o, tk_buffer0);
1052 | }
1053 | else if ( !strcmp(word, "static") ){
1054 | sprintf(tk_buffer0, "%d", TK_STATIC);
1055 | put_ulexeme(o, tk_buffer0);
1056 | }
1057 | else if ( !strcmp(word, "struct") ){
1058 | sprintf(tk_buffer0, "%d", TK_STRUCT);
1059 | put_ulexeme(o, tk_buffer0);
1060 | }
1061 | else if ( !strcmp(word, "switch") ){
1062 | sprintf(tk_buffer0, "%d", TK_SWITCH);
1063 | put_ulexeme(o, tk_buffer0);
1064 | }
1065 | else {
1066 | parse_tokens(o,word);
1067 | }
1068 | }
1069 |
1070 | void t(FILE *o, char *word)
1071 | {
1072 | /* typedef */
1073 | if( !strcmp(word, "typedef") ) {
1074 | sprintf(tk_buffer0, "%d", TK_TYPEDEF);
1075 | put_ulexeme(o, tk_buffer0);
1076 | }
1077 | else {
1078 | parse_tokens(o,word);
1079 | }
1080 | }
1081 | void u(FILE *o, char *word)
1082 | {
1083 | /* union */
1084 | /* unsigned */
1085 | if( !strcmp(word, "union") ) {
1086 | sprintf(tk_buffer0, "%d", TK_UNION);
1087 | put_ulexeme(o, tk_buffer0);
1088 | }
1089 | else if ( !strcmp(word, "unsigned") ){
1090 | sprintf(tk_buffer0, "%d", TK_UNSIGNED);
1091 | put_ulexeme(o, tk_buffer0);
1092 | }
1093 | else {
1094 | parse_tokens(o,word);
1095 | }
1096 | }
1097 | void v(FILE *o, char *word)
1098 | {
1099 | /* void */
1100 | /* volatile */
1101 | if( !strcmp(word, "void") ) {
1102 | sprintf(tk_buffer0, "%d", TK_VOID);
1103 | put_ulexeme(o, tk_buffer0);
1104 | }
1105 | else if ( !strcmp(word, "volatile") ){
1106 | sprintf(tk_buffer0, "%d", TK_VOLATILE);
1107 | put_ulexeme(o, tk_buffer0);
1108 | }
1109 | else {
1110 | parse_tokens(o,word);
1111 | }
1112 | }
1113 | void w(FILE *o, char *word)
1114 | {
1115 | /* while */
1116 | if( !strcmp(word, "while") ) {
1117 | sprintf(tk_buffer0, "%d", TK_WHILE);
1118 | put_ulexeme(o, tk_buffer0);
1119 | }
1120 | else {
1121 | parse_tokens(o,word);
1122 | }
1123 |
1124 | }
1125 | void leftbracket(FILE *o, char *word)
1126 | {
1127 | if( !strcmp(word, "{") ) {
1128 | sprintf(tk_buffer0, "%d", TK_LEFTBRACKET);
1129 | put_ulexeme(o, tk_buffer0);
1130 | }
1131 | else {
1132 | parse_tokens(o,word);
1133 | }
1134 | }
1135 | void rightbracket(FILE *o, char *word)
1136 | {
1137 | if( !strcmp(word, "}") ) {
1138 | sprintf(tk_buffer0, "%d", TK_RIGHTBRACKET);
1139 | put_ulexeme(o, tk_buffer0);
1140 | }
1141 | else {
1142 | parse_tokens(o,word);
1143 | }
1144 | }
1145 |
1146 | void leftparen(FILE *o, char *word)
1147 | {
1148 | /* ( */
1149 | /* (casting) */
1150 | if( !strcmp(word, "(") ) {
1151 | sprintf(tk_buffer0, "%d", TK_LEFTPAREN);
1152 | put_ulexeme(o, tk_buffer0);
1153 | }
1154 | else {
1155 | parse_tokens(o,word);
1156 | }
1157 | }
1158 | void rightparen(FILE *o, char *word)
1159 | {
1160 | if( !strcmp(word, ")") ) {
1161 | sprintf(tk_buffer0, "%d", TK_RIGHTPAREN);
1162 | put_ulexeme(o, tk_buffer0);
1163 | }
1164 | else {
1165 | parse_tokens(o,word);
1166 | }
1167 | }
1168 | void left_sqr_bracket(FILE *o, char *word)
1169 | {
1170 | if( !strcmp(word, "]") ) {
1171 | sprintf(tk_buffer0, "%d", TK_RIGHT_SQR_BRACKET);
1172 | put_ulexeme(o, tk_buffer0);
1173 | }
1174 | else {
1175 | parse_tokens(o,word);
1176 | }
1177 | }
1178 | void right_sqr_bracket(FILE *o, char *word)
1179 | {
1180 | if( !strcmp(word, "[") ) {
1181 | sprintf(tk_buffer0, "%d", TK_LEFT_SQR_BRACKET);
1182 | put_ulexeme(o, tk_buffer0);
1183 | }
1184 | else {
1185 | parse_tokens(o,word);
1186 | }
1187 | }
1188 | void dot(FILE *o, char *word)
1189 | {
1190 | if( !strcmp(word, ".") ) {
1191 | sprintf(tk_buffer0, "%d", TK_DOT);
1192 | put_ulexeme(o, tk_buffer0);
1193 | }
1194 | else {
1195 | parse_tokens(o,word);
1196 | }
1197 | }
1198 | void comma(FILE *o, char *word)
1199 | {
1200 |
1201 | if( !strcmp(word, ",") ) {
1202 | sprintf(tk_buffer0, "%d", TK_COMMA);
1203 | put_ulexeme(o, tk_buffer0);
1204 | }
1205 | else {
1206 | parse_tokens(o,word);
1207 | }
1208 | }
1209 | void exclamation(FILE *o, char *word)
1210 | {
1211 |
1212 | if( !strcmp(word, "!") ) {
1213 | sprintf(tk_buffer0, "%d", TK_UNARY_EXCLAMATION);
1214 | put_ulexeme(o, tk_buffer0);
1215 | }
1216 | else {
1217 | parse_tokens(o,word);
1218 | }
1219 | }
1220 | void tilda(FILE *o, char *word)
1221 | {
1222 | /* ~ */
1223 | /* ~= */
1224 | if( !strcmp(word, "~") ) {
1225 | sprintf(tk_buffer0, "%d", TK_UNARY_TILDA);
1226 | put_ulexeme(o, tk_buffer0);
1227 | }
1228 | else {
1229 | parse_tokens(o,word);
1230 | }
1231 | }
1232 | void plus(FILE *o, char *word)
1233 | {
1234 | /* + */
1235 | /* ++ */
1236 | /* += */
1237 | if( !strcmp(word, "+") ) {
1238 | sprintf(tk_buffer0, "%d", TK_PLUS);
1239 | put_ulexeme(o, tk_buffer0);
1240 | }
1241 | else {
1242 | parse_tokens(o,word);
1243 | }
1244 | }
1245 | void minus(FILE *o, char *word)
1246 | {
1247 | /* - */
1248 | /* -- */
1249 | /* -= */
1250 | if( !strcmp(word, "-") ) {
1251 | sprintf(tk_buffer0, "%d", TK_MINUS);
1252 | put_ulexeme(o, tk_buffer0);
1253 | }
1254 | else {
1255 | parse_tokens(o,word);
1256 | }
1257 | }
1258 | void unary_star(FILE *o, char *word)
1259 | {
1260 | /* * */
1261 | /* Is it a mult? Is it a dereference? is it a pointer? Is it a santactic sugar?
1262 | these are all questions which must be answered here */
1263 | /* *= */
1264 | if( !strcmp(word, "*") ) {
1265 | sprintf(tk_buffer0, "%d", TK_MULT_STAR);
1266 | put_ulexeme(o, tk_buffer0);
1267 | }
1268 | else {
1269 | parse_tokens(o,word);
1270 | }
1271 | }
1272 | void ampersand(FILE *o, char *word)
1273 | {
1274 | /* & */
1275 | /* && */
1276 | /* &= */
1277 | if( !strcmp(word, "&") ) {
1278 | sprintf(tk_buffer0, "%d", TK_BIT_AMPERSAND);
1279 | put_ulexeme(o, tk_buffer0);
1280 | }
1281 | else {
1282 | parse_tokens(o,word);
1283 | }
1284 | }
1285 | void div_(FILE *o, char *word)
1286 | {
1287 | /* / */
1288 | /* /= */
1289 | if( !strcmp(word, "/") ) {
1290 | sprintf(tk_buffer0, "%d", TK_DIV);
1291 | put_ulexeme(o, tk_buffer0);
1292 | }
1293 | else {
1294 | parse_tokens(o,word);
1295 | }
1296 | }
1297 | void mod(FILE *o, char *word)
1298 | {
1299 | /* % */
1300 | /* %= */
1301 | if( !strcmp(word, "%") ) {
1302 | sprintf(tk_buffer0, "%d", TK_MOD);
1303 | put_ulexeme(o, tk_buffer0);
1304 | }
1305 | else {
1306 | parse_tokens(o,word);
1307 | }
1308 | }
1309 | void less(FILE *o, char *word)
1310 | {
1311 | /* < */
1312 | /* << */
1313 | /* <= */
1314 | /* <<= */
1315 | if( !strcmp(word, "<") ) {
1316 | sprintf(tk_buffer0, "%d", TK_LESS_LOGIC);
1317 | put_ulexeme(o, tk_buffer0);
1318 | }
1319 | else {
1320 | parse_tokens(o,word);
1321 | }
1322 | }
1323 | void greater(FILE *o, char *word)
1324 | {
1325 | /* > */
1326 | /* >> */
1327 | /* >= */
1328 | /* >>= */
1329 | if( !strcmp(word, ">") ) {
1330 | sprintf(tk_buffer0, "%d", TK_GREATER_LOGIC);
1331 | put_ulexeme(o, tk_buffer0);
1332 | }
1333 | else {
1334 | parse_tokens(o,word);
1335 | }
1336 | }
1337 | void equal(FILE *o, char *word)
1338 | {
1339 | /* = */
1340 | /* == */
1341 | if( !strcmp(word, "=") ) {
1342 | sprintf(tk_buffer0, "%d", TK_EQU);
1343 | put_ulexeme(o, tk_buffer0);
1344 | }
1345 | else {
1346 | parse_tokens(o,word);
1347 | }
1348 | }
1349 | void or(FILE *o, char *word)
1350 | {
1351 | /* | */
1352 | /* || */
1353 | /* |= */
1354 | if( !strcmp(word, "|") ) {
1355 | sprintf(tk_buffer0, "%d", TK_BIT_OR);
1356 | put_ulexeme(o, tk_buffer0);
1357 | }
1358 | else {
1359 | parse_tokens(o,word);
1360 | }
1361 | }
1362 | void xor(FILE *o, char *word)
1363 | {
1364 | /* ^ */
1365 | /* ^= */
1366 | if( !strcmp(word, "^") ) {
1367 | sprintf(tk_buffer0, "%d", TK_BIT_XOR);
1368 | put_ulexeme(o, tk_buffer0);
1369 | }
1370 | else {
1371 | parse_tokens(o,word);
1372 | }
1373 | }
1374 |
1375 |
1376 | void question(FILE *o, char *word)
1377 | {
1378 | if( !strcmp(word, "?") ) {
1379 | sprintf(tk_buffer0, "%d", TK_QUESTION);
1380 | put_ulexeme(o, tk_buffer0);
1381 | }
1382 | else {
1383 | parse_tokens(o,word);
1384 | }
1385 | }
1386 | void colon(FILE *o, char *word)
1387 | {
1388 | if( !strcmp(word, ":") ) {
1389 | sprintf(tk_buffer0, "%d", TK_COLON);
1390 | put_ulexeme(o, tk_buffer0);
1391 | }
1392 | else {
1393 | parse_tokens(o,word);
1394 | }
1395 | }
1396 | void semicolon(FILE *o, char *word)
1397 | {
1398 | if( !strcmp(word, ";") ) {
1399 | sprintf(tk_buffer0, "%d", TK_SEMICOLON);
1400 | put_ulexeme(o, tk_buffer0);
1401 | }
1402 | else {
1403 | parse_tokens(o,word);
1404 | }
1405 | }
1406 |
1407 | /* Constants */
1408 | void constant(FILE *o, char *word)
1409 | {
1410 | }
1411 |
1412 | /* String Literals */
1413 | void stringlit(FILE *o, char *word)
1414 | {
1415 | }
1416 |
1417 | void default_(FILE *o, char *word)
1418 | {
1419 | /* Try To See if it's a identifier, if not:
1420 | ERROR! Given token is not part of the lang def. */
1421 | parse_tokens(o, word);
1422 | }
1423 |
1424 |
1425 |
--------------------------------------------------------------------------------
/src/compiler/scanner.h:
--------------------------------------------------------------------------------
1 | /** \file scanner.h
2 | * \brief Lists the associativity and precedence of all tokens.
3 | *
4 | * This is done in order of precedence, with the defines at the top with the highest.
5 | *
6 | * The defines here are grouped in order of associativity, and listed
7 | * with descending precedence as we go down.
8 | *
9 | * The rest are token values for keywords and the like.
10 | *
11 | * Everything else normally in a header file comes after.
12 | */
13 |
14 | #ifndef _SCANNER_H_
15 | #define _SCANNER_H_
16 |
17 | #include
18 | #include
19 | #include
20 | #include
21 |
22 | #include "utils.h"
23 | #include "symbol.h"
24 |
25 | #define INTLIT_TABLE_MAX 1000
26 | #define FLOATLIT_TABLE_MAX 1000
27 | #define STRINGLIT_TABLE_MAX 1000
28 |
29 | /* Scope */
30 | #define TK_LEFTBRACKET 0
31 | #define TK_RIGHTBRACKET 1
32 |
33 | /* Left To Right Associativity */
34 | #define TK_LEFTPAREN 2
35 | #define TK_RIGHTPAREN 3
36 | #define TK_LEFT_SQR_BRACKET 4
37 | #define TK_RIGHT_SQR_BRACKET 5
38 | #define TK_DOT 6
39 |
40 | /* Right To Left Associativity */
41 | #define TK_UNARY_EXCLAMATION 7
42 | #define TK_UNARY_TILDA 8
43 | #define TK_UNARY_PLUSPLUS 9
44 | #define TK_UNARY_MINUSMINUS 10
45 | #define TK_UNARY_PLUS 11
46 | #define TK_UNARY_MINUS 12
47 | #define TK_UNARY_STAR 13
48 | #define TK_UNARY_AMPERSAND 14
49 | #define TK_UNARY_CASTING 15
50 | #define TK_UNARY_SIZEOF 16
51 |
52 | /* Left To Right Associativity */
53 | #define TK_MULT_STAR 17
54 | #define TK_DIV 18
55 | #define TK_MOD 19
56 |
57 | /* Left To Right Associativity */
58 | #define TK_PLUS 20
59 | #define TK_MINUS 21
60 |
61 | /* Left To Right Associativity */
62 | #define TK_LEFT_SHIFT 22
63 | #define TK_RIGHT_SHIFT 23
64 |
65 | /* Left To Right Associativity */
66 | #define TK_LESS_LOGIC 24
67 | #define TK_GREATER_LOGIC 25
68 | #define TK_GREATER_EQU_LOGIC 26
69 | #define TK_LESS_EQU_LOGIC 27
70 |
71 | /* Left To Right Associativity */
72 | #define TK_EQU_EQU_LOGIC 28
73 | #define TK_NOT_EQU_LOGIC 29
74 |
75 | /* Left To Right Associativity */
76 | #define TK_BIT_AMPERSAND 30
77 | #define TK_BIT_XOR 31
78 | #define TK_BIT_OR 32
79 |
80 | /* Left To Right Associativity */
81 | #define TK_LOGIC_AND 33
82 | #define TK_LOGIC_OR 34
83 |
84 | /* Left To Right Associativity */
85 | #define TK_QUESTION 35
86 | #define TK_COLON 36
87 |
88 | /* Right To Left Associativity */
89 | #define TK_EQU 37
90 | #define TK_PLUS_EQU 38
91 | #define TK_MINUS_EQU 39
92 | #define TK_STAR_EQU 40
93 | #define TK_DIV_EQU 41
94 | #define TK_MOD_EQU 42
95 | #define TK_AND_EQU 43
96 | #define TK_XOR_EQU 44
97 | #define TK_OR_EQU 45
98 | #define TK_LSHIFT_EQU 46
99 | #define TK_RSHIFT_EQU 47
100 |
101 | /* Left To Right Associativity */
102 | #define TK_COMMA 48
103 |
104 | /* Precedence and Associative Irrelavent */
105 |
106 | #define TK_KEYWORD 49
107 | #define TK_IDENTIFIER 50
108 | #define TK_CONSTANT 51
109 | #define TK_STRING 52
110 |
111 | /* ************************************* */
112 |
113 | /* Keywords/Reserved */
114 |
115 | #define TK_AUTO 53
116 | #define TK_BREAK 54
117 | #define TK_CASE 55
118 | #define TK_CHAR 56
119 | #define TK_CONST 57
120 | #define TK_CONTINUE 58
121 | #define TK_DEFAULT 59
122 | #define TK_DO 60
123 | #define TK_DOUBLE 61
124 | #define TK_ELSE 62
125 | #define TK_ENUM 63
126 | #define TK_EXTERN 64
127 | #define TK_FLOAT 65
128 | #define TK_FOR 66
129 | #define TK_GOTO 67
130 | #define TK_IF 68
131 | #define TK_INT 69
132 | #define TK_LONG 70
133 | #define TK_REGISTER 71
134 | #define TK_RETURN 72
135 | #define TK_SHORT 73
136 | #define TK_SIGNED 74
137 | #define TK_SIZEOF 75
138 | #define TK_STATIC 76
139 | #define TK_STRUCT 77
140 | #define TK_SWITCH 78
141 | #define TK_TYPEDEF 79
142 | #define TK_UNION 80
143 | #define TK_UNSIGNED 81
144 | #define TK_VOID 82
145 | #define TK_VOLATILE 83
146 | #define TK_WHILE 84
147 |
148 |
149 | #define TK_SEMICOLON 85
150 | #define TK_INTLIT 86 /**> need array for this */
151 | #define TK_STRINGLIT 87 /**> need a symbol table for this */
152 | #define TK_FLOATLIT 88 /**> need a symbol table for this too. This is for both float and double */
153 |
154 | #define TK_LABEL 89
155 | #define TK_FUNCTION_CALL 90
156 |
157 | #define TK_PRINTF 91
158 |
159 |
160 | /*-------------------------Typedefs -------------------------*/
161 | typedef struct token_package_Tag {
162 | int val;
163 | double f_val;
164 | int type;
165 | } token_package;
166 | /*------------------------- Globals -------------------------*/
167 |
168 |
169 | extern size_t total_newlines;
170 |
171 | static char tk_buffer0[5]; /**> Used to write the interger values of lexemes below as strings (easier). */
172 | static char tk_buffer1[5];
173 |
174 | static size_t intlit_t_counter;
175 | static size_t floatlit_t_counter;
176 | static int intlit_table[INTLIT_TABLE_MAX];
177 | static double floatlit_table[FLOATLIT_TABLE_MAX];
178 |
179 | extern symbol_table *string_table; /**> This holds all the string literals*/
180 | extern symbol_table *id_table; /**>This holds all of the identifier names */
181 |
182 | /* Token Defininitions */
183 |
184 | /*------------------------- Globals -------------------------*/
185 |
186 | size_t total_char; /**> Initialize total character count counter */
187 | size_t total_char_per_line;
188 | size_t total_newlines; /**> Initialize newlines, to ready counter */
189 |
190 | /*------------------- Function Prototoypes -------------------*/
191 |
192 | /** High level scanner encapsulator.
193 | */
194 | void run_scanner(file_struct *file);
195 |
196 | /** Writes a lexeme out to file, given a name-value pair.
197 | */
198 | void put_lexeme(FILE *o, char *tk_name, char *tk_value);
199 |
200 | /** Writes a unary lexeme out to file, given a name.
201 | */
202 | void put_ulexeme(FILE *o, char *tk_name);
203 |
204 | /** Tests if the given word is a valid C symbol, or identifier.
205 | * If false, returns 0, if true returns the size of the identifier.
206 | * This is useful because we can use the size to handle the function
207 | * case, in which an identifier can have '(' directly concatenated (no space)
208 | * with the identifier. (i.e. main() vs main () )
209 | *
210 | * This function also _RESETS_ the file pointer to where it was at
211 | * the beginning of the call.
212 | */
213 | int is_valid_id(char *word);
214 |
215 | /**
216 | */
217 | int parse_tokens(FILE *o, char *word);
218 |
219 | /**
220 | */
221 | char *extract_token(char *word);
222 | /** _MUST_ be freed.
223 | */
224 |
225 | char *return_char(char *word);
226 |
227 | /** _MUST_ be freed.
228 | */
229 | char *return_integral(char *word);
230 |
231 | /** _MUST_ be freed.
232 | */
233 |
234 | char *return_string(char *word);
235 |
236 | /** _MUST_ be freed.
237 | */
238 | char *return_keyword(char *word);
239 |
240 | /**
241 | */
242 | int extract_char(char *word);
243 |
244 | /**
245 | */
246 | token_package get_sval(char *s);
247 |
248 | /* Jobs prototypes */
249 |
250 | inline static void a(FILE *o, char *word);
251 | inline static void b(FILE *o, char *word);
252 | inline static void c(FILE *o, char *word);
253 | inline static void d(FILE *o, char *word);
254 | inline static void e(FILE *o, char *word);
255 | inline static void f(FILE *o, char *word);
256 | inline static void g(FILE *o, char *word);
257 | inline static void i(FILE *o, char *word);
258 | inline static void l(FILE *o, char *word);
259 | inline static void r(FILE *o, char *word);
260 | inline static void s(FILE *o, char *word);
261 | inline static void t(FILE *o, char *word);
262 | inline static void p(FILE *o, char *word);
263 | inline static void u(FILE *o, char *word);
264 | inline static void v(FILE *o, char *word);
265 | inline static void w(FILE *o, char *word);
266 | inline static void leftbracket(FILE *o, char *word);
267 | inline static void rightbracket(FILE *o, char *word);
268 | inline static void leftparen(FILE *o, char *word);
269 | inline static void rightparen(FILE *o, char *word);
270 | inline static void left_sqr_bracket(FILE *o, char *word);
271 | inline static void right_sqr_bracket(FILE *o, char *word);
272 | inline static void dot(FILE *o, char *word);
273 | inline static void comma(FILE *o, char *word);
274 | inline static void exclamation(FILE *o, char *word);
275 | inline static void tilda(FILE *o, char *word);
276 | inline static void plus(FILE *o, char *word);
277 | inline static void minus(FILE *o, char *word);
278 | inline static void unary_star(FILE *o, char *word);
279 | inline static void ampersand(FILE *o, char *word);
280 | inline static void div_(FILE *o, char *word);
281 | inline static void mod(FILE *o, char *word);
282 | inline static void less(FILE *o, char *word);
283 | inline static void greater(FILE *o, char *word);
284 | inline static void equal(FILE *o, char *word);
285 | inline static void or(FILE *o, char *word);
286 | inline static void xor(FILE *o, char *word);
287 | inline static void question(FILE *o, char *word);
288 | inline static void colon(FILE *o, char *word);
289 | inline static void semicolon(FILE *o, char *word);
290 | inline static void constant(FILE *o, char *word);
291 | inline static void stringlit(FILE *o, char *word);
292 | inline static void default_(FILE *o, char *word);
293 |
294 |
295 |
296 |
297 |
298 |
299 | #endif
300 |
--------------------------------------------------------------------------------
/src/compiler/symbol.c:
--------------------------------------------------------------------------------
1 | /** \file symbol.c
2 | \brief Defines all of the symbol table primitives.
3 | */
4 |
5 | #include "symbol.h"
6 |
7 | void print_stab(symbol_table *stab)
8 | {
9 | int i;
10 | printf("\n\nCurrent Symbol Table: '%s' \n - Status -\n"
11 | "Total Used: %4d\t Size: %4d\t Load Factor: %4.2f\n"
12 | "\n", stab->t_name, (int)stab->in_use, (int)stab->size, stab->load_factor);
13 | printf("-------\t----\t-----\t----\t-----\n"
14 | "Address\tName\tValue\tSlot\tType\tScope\tIsArray\tArray-Size\n");
15 | for(i = 0; i < stab->size; i++){
16 | if( stab->table[i].slot != EMPTY_SLOT ){
17 | printf("%4d\t%s\t%s\t%d\t%c\t%d\t%c\t%d\n",
18 | stab->table[i].addr, stab->table[i].name,
19 | stab->table[i].value, stab->table[i].slot,
20 | stab->table[i].type,
21 | stab->table[i].scope,
22 | stab->table[i].isarray,
23 | stab->table[i].arraysize);
24 | }
25 | }
26 | }
27 |
28 | size_t hash(char *key, size_t limit)
29 | {
30 | int hash_value = 0;
31 | int i = 0;
32 | size_t size = strlen(key);
33 |
34 | for(i = 0; i < size; i++){
35 | hash_value = 31*hash_value + key[i];
36 | }
37 | return (size_t)(hash_value%limit);
38 | }
39 |
40 | symbol_table *create_stab(char* t_name, size_t max)
41 | {
42 | int i;
43 | symbol_table *stab = (symbol_table*)xmalloc(sizeof(symbol_table)*1);
44 |
45 | stab->table = (record*)xmalloc(sizeof(record)*max);
46 | stab->in_use = 0;
47 | stab->load_factor = 0;
48 | stab->size = max;
49 | strcpy(stab->t_name, t_name);
50 |
51 | for(i = 0; i < max; i++){
52 | stab->table[i].addr = -1;
53 | stab->table[i].slot = EMPTY_SLOT;
54 | stab->table[i].seen = 0;
55 | }
56 |
57 | return stab;
58 | }
59 |
60 | void stab_insert(char* filename, record *rec, symbol_table *stab)
61 | {
62 | size_t index = hash(rec->name, stab->size);
63 | rec->slot = index;
64 |
65 | stab->table[index] = *rec;
66 | stab->in_use++;
67 | stab->load_factor = ((float)stab->in_use) / stab->size;
68 |
69 | }
70 |
71 | record *get_record(char *name, char*val, char type, int slot, char *scope)
72 | {
73 | record *rec = (record*)xmalloc(sizeof(record)*1);
74 |
75 | /* NOTE: I have to purge all these allocations in the freeing of the records! */
76 |
77 | rec->value = (char*)xmalloc(sizeof(char)*strlen(val));
78 |
79 | strcpy(rec->name, name);
80 | strcpy(rec->value, val);
81 | rec->type = type;
82 | rec->slot = slot;
83 | rec->scope = 0;
84 |
85 | return rec;
86 | }
87 |
88 | int return_value(symbol_table *stab, int target)
89 | {
90 | return 1;
91 | }
92 |
93 | void purge_record(record *rec)
94 | {
95 | }
96 |
97 | void destroy_stab(symbol_table *stab)
98 | {
99 | }
100 |
101 | int is_keyword(char *lexeme)
102 | {
103 | switch(lexeme[0]){
104 | case 'a':
105 | /* auto */
106 | if( !strcmp(lexeme, "auto") )
107 | return TRUE;
108 | return FALSE;
109 | case 'b':
110 | /* break */
111 | if( !strcmp(lexeme, "break") )
112 | return TRUE;
113 | return FALSE;
114 | case 'c':
115 | /* case */
116 | /* char */
117 | /* const */
118 | /* continue */
119 | if( !strcmp(lexeme, "case") ||
120 | !strcmp(lexeme, "char") ||
121 | !strcmp(lexeme, "const") ||
122 | !strcmp(lexeme, "continue")
123 | )
124 | return TRUE;
125 | return FALSE;
126 | case 'd':
127 | /* default */
128 | /* do */
129 | /* double */
130 | if( !strcmp(lexeme, "default")||
131 | !strcmp(lexeme, "do") ||
132 | !strcmp(lexeme, "double")
133 | )
134 | return TRUE;
135 | return FALSE;
136 | case 'e':
137 | /* else */
138 | /* enum */
139 | /* extern */
140 | if( !strcmp(lexeme, "else") ||
141 | !strcmp(lexeme, "enum") ||
142 | !strcmp(lexeme, "extern")
143 | )
144 | return TRUE;
145 | return FALSE;
146 | case 'f':
147 | /* float */
148 | /* for */
149 | if( !strcmp(lexeme, "float")||
150 | !strcmp(lexeme, "for")
151 | )
152 | return TRUE;
153 | return FALSE;
154 | case 'g':
155 | /* goto */
156 | if( !strcmp(lexeme, "goto") )
157 | return TRUE;
158 | return FALSE;
159 |
160 | case 'i':
161 | /* int */
162 | /* if */
163 | if( !strcmp(lexeme, "int") ||
164 | !strcmp(lexeme, "if")
165 | )
166 | return TRUE;
167 | return FALSE;
168 | case 'l':
169 | /* long */
170 | if( !strcmp(lexeme, "long") )
171 | return TRUE;
172 | return FALSE;
173 | case 'r':
174 | /* register */
175 | /* return */
176 | if( !strcmp(lexeme, "register")||
177 | !strcmp(lexeme, "return")
178 | )
179 | return TRUE;
180 | return FALSE;
181 | case 's':
182 | /* short */
183 | /* signed */
184 | /* sizeof */
185 | /* static */
186 | /* struct */
187 | /* switch */
188 | if( !strcmp(lexeme, "short") ||
189 | !strcmp(lexeme, "signed") ||
190 | !strcmp(lexeme, "sizeof") ||
191 | !strcmp(lexeme, "static") ||
192 | !strcmp(lexeme, "struct") ||
193 | !strcmp(lexeme, "switch")
194 | )
195 | return TRUE;
196 | return FALSE;
197 | case 't':
198 | /* typedef */
199 | if( !strcmp(lexeme, "typedef") )
200 | return TRUE;
201 | return FALSE;
202 | case 'u':
203 | /* union */
204 | /* unsigned */
205 | if( !strcmp(lexeme, "union") ||
206 | !strcmp(lexeme, "unsigned")
207 | )
208 | return TRUE;
209 | return FALSE;
210 | case 'v':
211 | /* void */
212 | /* volatile */
213 | if( !strcmp(lexeme, "void") ||
214 | !strcmp(lexeme, "volatile")
215 | )
216 | return TRUE;
217 | return FALSE;
218 | case 'w':
219 | /* while */
220 | if( !strcmp(lexeme, "while") )
221 | return TRUE;
222 | return FALSE;
223 | default:
224 | return FALSE;
225 | }
226 | }
227 |
228 |
229 |
--------------------------------------------------------------------------------
/src/compiler/symbol.h:
--------------------------------------------------------------------------------
1 | /** \file symbol.h
2 | \brief
3 | */
4 |
5 | #ifndef _SYMBOL_H_
6 | #define _SYMBOL_H_
7 |
8 | #include
9 | #include
10 | #include
11 | #include
12 |
13 | #include "utils.h" /* For TRUE and FALSE constants */
14 | #include "error.h" /* For reporting ID errors, among other things */
15 |
16 | #define MAX_SLOTS 10000 /**> Total number of identifiers possible in memory */
17 | #define EMPTY_SLOT -1 /**> This symbolic constant signifies empty slots in the hash map. */
18 |
19 | typedef struct record_TAG{
20 | int addr;
21 | char type;
22 | char name[64];
23 | char *value;
24 | int slot; /**> Either EMPTY_SLOT or NOT_EMPTY */
25 | char scope;
26 | int seen;
27 | char isarray;
28 | int arraysize;
29 | char *block_info;
30 | }record;
31 |
32 | typedef struct symbol_table_TAG {
33 | /* Public Fields */
34 | char t_name[32]; /**> Table identifier. */
35 | double load_factor; /**> Load factor. If it is > 0.5, it is bad. */
36 | size_t in_use; /**> How many slots are in use for this one symbol table */
37 | size_t size; /**> Total Size of the symbol talbe */
38 | record *table; /**> An array of all the records currently in use. */
39 |
40 | /* Public Methods */
41 | } symbol_table;
42 |
43 | /**
44 | */
45 | void print_stab(symbol_table *stab);
46 |
47 | /**
48 | */
49 | symbol_table *create_stab(char *t_name, size_t max);
50 |
51 | /**
52 | */
53 | void stab_insert(char* filename, record *rec, symbol_table *stab);
54 |
55 | /**
56 | */
57 | record *get_record(char *name, char *val, char type, int slot, char *scope);
58 |
59 | /**
60 | */
61 | void purge_record(record *rec);
62 |
63 | /**
64 | */
65 | size_t hash(char *key, size_t limit);
66 |
67 | /**
68 | */
69 | int is_keyword(char *lexeme);
70 |
71 | /**
72 | */
73 | int return_value(symbol_table *stab, int target);
74 |
75 | #endif
76 |
--------------------------------------------------------------------------------
/src/compiler/utils.c:
--------------------------------------------------------------------------------
1 | /** \file utils.c
2 | \brief
3 | */
4 |
5 | #include "utils.h"
6 |
7 | void usage( void )
8 | {
9 | printf("Usage: c [options] file...\n"
10 | "Options:\n"
11 | " --help\tPrint help screen description.\n"
12 | " --version\tPrint version number.\n"
13 | " --verbose\tPrint extra information.\n"
14 | " -o \tSpecify an output file name.\n"
15 | " -Sc \tSpecify the size of the Code Segment (Not Implemented Yet).\n"
16 | " -Sd \tSpecify the size of the Data Segment (Not Implemented Yet).\n"
17 | " -Ss \tSpecify String Symbol Table Hash (Not Implemented Yet).\n"
18 | " -Si \tSpecify ID Symbol Table Hash (Not Implemented Yet).\n"
19 | " -So \tPrint VM Assembly to stdout.\n"
20 | "\n"
21 | );
22 | }
23 |
24 | void version( void )
25 | {
26 | printf("c (C Compiler) %s %d (release) %d - Build: %d\n"
27 | "Copyright (c) 2011 Eudis Duran\n"
28 | "See LICENSE file for details.\n"
29 | ,VERSION, get_build_date(), RELEASE, BUILD_NUMBER);
30 |
31 | }
32 |
33 | char *scan_for_o(int argc, char *argv[])
34 | {
35 | int i;
36 | for(i = 0; i < argc; i++){
37 | if(strcmp(argv[i], "-o") == 0){
38 | return argv[i + 1];
39 | }
40 | }
41 | }
42 |
43 | char **get_files_from_argv(int argc, char *argv[])
44 | {
45 |
46 | }
47 |
48 | int get_filesize(char *filename)
49 | {
50 | FILE *f = fopen(filename, "r");
51 | fseek(f, 0, SEEK_END);
52 | return ftell(f);
53 | }
54 |
55 | void *xmalloc(int size)
56 | {
57 | register void *value = malloc(size);
58 | if (value == NULL){
59 | fprintf(stderr, "Virtual Memory Exhausted!\n");
60 | exit(1);
61 | }
62 | else {
63 | return value;
64 | }
65 | }
66 |
67 | char fcpeek(FILE *f)
68 | {
69 | char c = getc(f);
70 | ungetc(c, f);
71 | return c;
72 | }
73 |
74 | char *getword(FILE *i)
75 | {
76 |
77 | int j = 0;
78 | char c;
79 | char *word;
80 | int pos;
81 | size_t size = 0;
82 |
83 | if(fcpeek(i) == EOF){
84 | return NULL;
85 | }
86 |
87 | pos = ftell(i);
88 | c = getc(i);
89 | if( c == '\n' ){
90 | total_newlines++;
91 | }
92 |
93 | /* We first calculate the size of the word */
94 | while ( (c != EOF) && !isspace(c) ){
95 | /* Read and count new lines and characters */
96 |
97 | /* This new section handles the string word input count*/
98 | if ( c == '\"' ){
99 | size++;
100 | c = getc(i);
101 | while( c != '\"' ){
102 |
103 | if( c == '\n' ){
104 | error("file-not-known(feature-incomplete)", total_newlines, 0, "Badly formatted string! Exiting\n");
105 | }
106 |
107 | size++;
108 | c = getc(i);
109 |
110 | }
111 | }
112 | size++;
113 | c = getc(i);
114 | if( c == '\n' ){
115 | total_newlines++;
116 | }
117 |
118 | }
119 | fseek(i, -(ftell(i) - pos), SEEK_CUR);
120 |
121 | word = (char*)xmalloc(sizeof(char)*size + 1);
122 |
123 | c = getc(i);
124 |
125 | /* Then we copy the word the to malloc'ed space */
126 | while ( ((c != EOF) && !isspace(c)) && (j < size) ){
127 | /* This new section handles the new string copy! */
128 | if ( c == '\"' ){
129 | word[j] = c;
130 | j++;
131 | c = getc(i);
132 | word[j] = c;
133 |
134 | while( c != '\"' && (j < size) ){
135 | word[j] = c;
136 | j++;
137 | c = getc(i);
138 | }
139 | }
140 | word[j] = c;
141 | j++;
142 | c = getc(i);
143 | }
144 | word[size] = '\0';
145 |
146 |
147 | return word;
148 | }
149 |
150 | char *wordpeek(FILE *f)
151 | {
152 | return NULL;
153 | }
154 |
155 | void file_error(char *prog, char *do_this, char *ifilename, char *specifics, char *msg)
156 | {
157 | fprintf(stderr, "%s: cannot %s %s (%s):\n"
158 | "%s.\n", prog, do_this, ifilename, specifics, msg);
159 | exit(EXIT_FAILURE);
160 | }
161 |
162 | char *strip_whitesp(char *str)
163 | {
164 | return 0;
165 | }
166 |
167 |
168 | int get_build_date()
169 | {
170 | char buffer[12];
171 | time_t rtime;
172 | struct tm *timeinfo;
173 |
174 | time( &rtime );
175 | timeinfo = localtime( &rtime );
176 |
177 | strftime(buffer, 12, "%Y%m%d", timeinfo);
178 | return atoi(buffer);
179 | }
180 |
181 | char *copy_alloced(char *s)
182 | {
183 | char *t = (char*)xmalloc(sizeof(char)*strlen(s));
184 | strcpy(t, s);
185 | return t;
186 | }
187 |
188 |
189 | int get_column(FILE *i){
190 | int cur_pos = ftell(i);
191 | int offset = 0;
192 | char c = fcpeek(i);
193 |
194 | while( c != '\n' && (ftell(i) > 0) && c != EOF){
195 | fseek(i, -1, SEEK_CUR);
196 | offset++;
197 | c = fcpeek(i);
198 | }
199 | fseek(i, cur_pos, SEEK_CUR);
200 | return offset;
201 | }
202 |
203 | int intlit_comp(const void *a, const void *b)
204 | {
205 | if( *(int*)a > *(int*)b ) return 1;
206 | if( *(int*)a == *(int*)b ) return 0;
207 | if( *(int*)a < *(int*)b ) return -1;
208 | }
209 |
210 | int floatlit_comp(const void *a, const void *b)
211 | {
212 | if( *(double*)a > *(double*)b ) return 1;
213 | if( *(double*)a == *(double*)b ) return 0;
214 | if( *(double*)a < *(double*)b ) return -1;
215 | }
216 |
217 | char *cstr(char *s)
218 | {
219 | char *tmp = (char*)xmalloc(sizeof(char)*strlen(s) + 1);
220 | strcpy(tmp, s);
221 | return tmp;
222 | }
223 |
224 | int token_num(char *token)
225 | {
226 | int i;
227 | for(i = 0; i < strlen(token); i++){
228 | if(token[i] == ','){
229 | return 2;
230 | }
231 | }
232 | return 1;
233 | }
234 |
235 |
236 |
237 |
238 |
--------------------------------------------------------------------------------
/src/compiler/utils.h:
--------------------------------------------------------------------------------
1 | /** \file utils.h
2 | \brief Interface that holds common functions and housekeeping operations.
3 | */
4 |
5 | #ifndef _UTILS_H_
6 | #define _UTILS_H_
7 |
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 |
14 | #define VERSION "- 0.0.3 -" /**< Holds the current version (semver.org). */
15 | #define RELEASE 0 /**< Holds the current release candidate number. */
16 | #define BUILD_NUMBER 201 /**< Holds the current build number. */
17 | #define BUILD_DATE 20101231 /**< Holds the current build date in Year-Month-Day format. */
18 |
19 | #define INTERIM_FILENAME "data"
20 | #define DEFAULT_OUTPUT "a.out"
21 |
22 | #define TRUE 1
23 | #define FALSE 0
24 |
25 | #define DEBUG TRUE
26 |
27 | typedef struct file_struct_Tag {
28 | char calling_prog[64];
29 | char filename[64];
30 | char default_o[64];
31 | int cur_line;
32 | int cur_column;
33 | char cur_word[64];
34 | } file_struct;
35 |
36 |
37 | /* Globals */
38 |
39 | extern file_struct file;
40 | extern size_t total_newlines;
41 |
42 |
43 | /** Prints usage information and a listing of commands.
44 | */
45 | inline void usage(void);
46 | /** Prints version information.
47 | */
48 | inline void version(void);
49 |
50 | /** Scans the program input for the -o flag, and returns its argument.
51 | */
52 | inline char *scan_for_o(int argc, char *argv[]);
53 |
54 | inline char **get_files_from_argv(int argc, char *argv[]);
55 |
56 | /** Returns the current filesize of a file. It does this by fseeking to the
57 | last byte of the file, and return ftell().
58 | */
59 | int get_filesize(char *filename);
60 |
61 | /** Safety wrapper for malloc. Exits on error allocation. */
62 | void *xmalloc(int size);
63 |
64 | /** Returns the current character pointed to by the file discriptor. Does not
65 | modify the current file pointer
66 | */
67 | char fcpeek(FILE *f);
68 |
69 | /** Get the next word from the file stream, and increment the file pointer accordingly.
70 | All calls to this function return a malloc'ed string. It _must_ be freed.
71 | */
72 | char *getword(FILE *i);
73 |
74 | /** Peek the next word from the file stream, and do not increment the file pointer.
75 | All calls to this function return a malloc'ed string. It _must_ be freed.
76 | Further,
77 | */
78 |
79 | char *wordpeek(FILE *f);
80 |
81 | /** General file error function.
82 | */
83 | void file_error(char *prog, char *do_this, char *ifilename, char *specifics, char *msg);
84 |
85 | /**
86 | */
87 | int get_build_date();
88 |
89 | /**
90 | */
91 | int get_column(FILE *i);
92 |
93 |
94 | /**
95 | */
96 | char *copy_alloced(char *s);
97 |
98 | /**
99 | */
100 | int intlit_comp(const void *a, const void *b);
101 |
102 | /**
103 | */
104 | int floatlit_comp(const void *a, const void *b);
105 |
106 | /**
107 | */
108 | char *cstr(char *s);
109 |
110 | /**
111 | */
112 | int token_num(char *token);
113 |
114 |
115 |
116 | /* Debug Functions */
117 |
118 | /**
119 | */
120 | char *strip_whitesp(char *str);
121 |
122 |
123 |
124 |
125 |
126 | #endif
127 |
--------------------------------------------------------------------------------
/src/cvm/Makefile:
--------------------------------------------------------------------------------
1 | # C Virtual Machine Makefile
2 |
3 | # By Eudis Duran
4 |
5 | CC := gcc
6 | LIBS := -lm
7 | FLAGS := -Wall -O2
8 |
9 | OBJS := cvm.o
10 |
11 | TARGET:=cvm
12 |
13 | $(TARGET) : $(OBJS)
14 | $(CC) $(FLAGS) $(OBJS) -o $(TARGET) $(LIBS)
15 | @echo
16 | @echo "Done Building C Virtual Machine."
17 | @-rm *.o
18 | @cp cvm ../../examples/bin
19 | @echo
20 |
21 | cvm.o : cvm.c cvm.h
22 | @echo "(Modified) Compiling Translation Unit: cvm.c + cvm.h"
23 | $(CC) -c cvm.c -o cvm.o
24 |
25 | utils.o : ../compiler/utils.c ../compiler/utils.h
26 | @echo "(Modified) Compiling Translation Unit: utils.c + utils.h"
27 | $(CC) -c ../compiler/utils.c -o utils.o
28 |
--------------------------------------------------------------------------------
/src/cvm/cvm.c:
--------------------------------------------------------------------------------
1 | #include "cvm.h"
2 |
3 | int main(int argc, char *argv[])
4 | {
5 | if( argc == 1 ){
6 | usage();
7 | }
8 | else if ( argc == 2 ){
9 | run(argv[1]);
10 | }
11 | return EXIT_SUCCESS;
12 | }
13 |
14 |
15 | void usage()
16 | {
17 | printf("\nC Virtual Machine - By Eudis Duran (Spring 2011 Semester Project)\n"
18 | "\nUsage: cvm \n\n");
19 | }
20 |
21 | void run(char *program)
22 | {
23 | FILE *i = fopen(program, "rb");
24 |
25 | short code_count = 0;
26 | short data_count = 0;
27 | short str_data_end = 0;
28 |
29 | if( i == NULL ){
30 | printf("\nCould not open program file, exiting...\n");
31 | exit(EXIT_FAILURE);
32 | }
33 |
34 | int cur_pos = ftell(i);
35 | fseek(i, -6, SEEK_END);
36 |
37 | /* Determine Run Time Data Segment Start */
38 | fread(&str_data_end, sizeof(short), 1, i);
39 |
40 | /* Determine Data Segment size */
41 |
42 | fread(&data_count, sizeof(short), 1, i);
43 |
44 | /* Determine Code Segment size */
45 |
46 | fread(&code_count, sizeof(short), 1, i);
47 |
48 | fseek(i, cur_pos, SEEK_SET);
49 |
50 | /* Allocate data array (semi last short holds the code size) */
51 |
52 | data = (char*)malloc(sizeof(char)* data_count);
53 | fread(data, sizeof(char), data_count, i);
54 |
55 | /* Read in code array (last short holds the code size) */
56 |
57 | code = (Instruction*)malloc(sizeof(Instruction)* code_count);
58 | fread(code, sizeof(Instruction), code_count, i);
59 |
60 | ip = 0;
61 | sp = 0;
62 |
63 | /* This tests to see if we have any static strings allocated at all! */
64 | if( str_data_end != 0){
65 | dp = str_data_end + 1; /* The last byte is the terminating null, we cannot override it
66 | when assigning run time allocation! */
67 | }
68 | else {
69 | dp = 0;
70 | }
71 |
72 | /*
73 | int j;
74 | printf("code_count: %d, data_count: %d, dp: %d\n", code_count, data_count, dp);
75 | */
76 | /*
77 | int c;
78 | printf("Code Segment: ");
79 | for(c = 0; c < data_count; c++){
80 | printf("%x ", data[c]);
81 | }*/
82 |
83 | int alloc = 0; /**> Used as the base pointer for the static allocations (non-string)*/
84 |
85 | while( ip < code_count ){
86 |
87 | switch( code[ip].opcode ){
88 | case OP_ADD:
89 | stack[sp - 2].i += stack[sp - 1].i;
90 | sp--;
91 | break;
92 | case OP_PUSH:
93 | alloc = code[ip].operand.i;
94 | stack[sp].i = *(int*)(data + (dp + alloc));
95 | sp++;
96 | break;
97 | case OP_PUSHF:
98 | alloc = code[ip].operand.i;
99 | stack[sp].f = *(float*)(data + (dp + alloc));
100 | sp++;
101 | break;
102 | case OP_PUSHI:
103 | //printf("Push-i: %d\n", code[ip].operand.i);
104 | stack[sp].i = code[ip].operand.i;
105 | sp++;
106 | //print_stack(sp);
107 |
108 | break;
109 | case OP_POP:
110 | alloc = code[ip].operand.i;
111 | *(int*)(data + (dp + alloc)) = stack[sp - 1].i;
112 | sp--;
113 | break;
114 | case OP_POPEMPTY:
115 | stack[ip - 1].i = 0;
116 | sp--;
117 | break;
118 | case OP_POPF:
119 | alloc = code[ip].operand.i;
120 | *(float*)(data + (dp + alloc)) = stack[sp - 1].f;
121 | sp--;
122 | break;
123 | case OP_EXCH:
124 | break;
125 | case OP_DUP:
126 | stack[sp] = stack[sp - 1];
127 | sp++;
128 | break;
129 | case OP_ADDF:
130 | stack[sp - 2].f += stack[sp - 1].f;
131 | sp--;
132 | break;
133 | case OP_SUBF:
134 | stack[sp - 2].f -= stack[sp - 1].f;
135 | sp--;
136 | break;
137 | case OP_SUB:
138 | stack[sp - 2].i -= stack[sp - 1].i;
139 | sp--;
140 |
141 | break;
142 | case OP_MULF:
143 | stack[sp - 2].f *= stack[sp - 1].f;
144 | sp--;
145 | break;
146 | case OP_MUL:
147 | stack[sp - 2].i *= stack[sp - 1].i;
148 | sp--;
149 | break;
150 | case OP_DIV:
151 | stack[sp - 2].i /= stack[sp - 1].i;
152 | sp--;
153 | break;
154 | case OP_DIVF:
155 | stack[sp - 2].f /= stack[sp - 1].f;
156 | sp--;
157 | break;
158 | case OP_MOD:
159 | stack[sp - 2].i %= stack[sp - 1].i;
160 | sp--;
161 | break;
162 | case OP_AND:
163 | stack[sp - 2].i = stack[sp - 2].i && stack[sp - 1].i;
164 | sp--;
165 | break;
166 | case OP_OR:
167 | stack[sp - 2].i = stack[sp - 2].i && stack[sp - 1].i;
168 | sp--;
169 | break;
170 | case OP_EQL:
171 | stack[sp - 2].i = stack[sp - 2].i == stack[sp - 1].i;
172 | sp--;
173 | break;
174 | case OP_NEG:
175 | stack[sp - 1].i = -stack[sp - 1].i;
176 | break;
177 | case OP_NEGF:
178 | stack[sp - 1].f = -stack[sp - 1].f;
179 | break;
180 |
181 | case OP_NOT:
182 | stack[sp - 1].i = !stack[sp - 1].i;
183 | break;
184 | case OP_LSS:
185 | stack[sp - 2].i = stack[sp - 2].i < stack[sp - 1].i;
186 | sp--;
187 | break;
188 | case OP_GTR:
189 | stack[sp - 2].i = stack[sp - 2].i > stack[sp - 1].i;
190 | sp--;
191 | break;
192 | case OP_LEQ:
193 | stack[sp - 2].i = stack[sp - 2].i <= stack[sp - 1].i;
194 | sp--;
195 | break;
196 | case OP_GEQ:
197 | stack[sp - 2].i = stack[sp - 2].i >= stack[sp - 1].i;
198 | sp--;
199 | break;
200 | case OP_NEQ:
201 | stack[sp - 2].i = stack[sp - 2].i != stack[sp - 1].i;
202 | sp--;
203 | break;
204 | case OP_EQU:
205 | stack[sp - 2].i = stack[sp - 2].i == stack[sp - 1].i;
206 | sp--;
207 | break;
208 | case OP_CVI:
209 | stack[sp - 1].i = (int)stack[sp - 1].f;
210 | break;
211 | case OP_CVR:
212 | stack[sp - 1].f = (float)stack[sp - 1].i;
213 | break;
214 | case OP_JMP:
215 | /*
216 | printf("IP: %d\n",ip);
217 | printf("code: %d\n", code[ip].opcode);
218 | printf("oper: %d\n", code[ip].operand.i);
219 | printf("TopofStack: %d\n", stack[sp - 1].i);
220 | for(j = 0; j < code_count; j++){
221 | printf("%d: opcode: %d, operand: %d\n",j, code[j].opcode, code[j].operand.i);
222 | }*/
223 | ip = code[ip].operand.i - 1;
224 |
225 | break;
226 | case OP_JFALSE:
227 | /*
228 | printf("IP: %d\n",ip);
229 | printf("code: %d\n", code[ip].opcode);
230 | printf("oper: %d\n", code[ip].operand.i);
231 | printf("TopofStack: %d\n", stack[sp - 1].i);
232 | for(j = 0; j < code_count; j++){
233 | printf("%d: opcode: %d, operand: %d\n",j, code[j].opcode, code[j].operand.i);
234 | }*/
235 | if( stack[sp - 1].i == 0 ){
236 | ip = code[ip].operand.i - 1; /* -1 because we increment right after the break here
237 | so we need code to execute one instruction back on
238 | the next VM iteration! */
239 | }
240 | //sp--; /* If it's false, we rid the result */
241 | break;
242 | case OP_JTRUE:
243 | if( stack[sp - 1].i != 0 )
244 | ip = code[ip].operand.i - 1;
245 | break;
246 | case OP_HALT:
247 | exit(-1);
248 | break;
249 | case OP_WRITEINTID:
250 | printf("%d\n", *(int*)(data + code[ip].operand.i));
251 | break;
252 | case OP_WRITEINT:
253 | printf("%d\n", stack[sp - 1].i);
254 | sp--;
255 | break;
256 | case OP_WRITEFLOAT:
257 | printf("%f\n", stack[sp - 1].f);
258 | sp--;
259 | break;
260 | case OP_NOP:
261 | break;
262 | case OP_WRITESTRING:
263 |
264 | printf("%s", &data[code[ip].operand.i]);
265 | printf("\n");
266 |
267 | break;
268 |
269 | case OP_GET:
270 |
271 | alloc = code[ip].operand.i;
272 | int addr = stack[sp - 1].i;
273 | stack[sp - 1].i = *(int*)(data + (dp + stack[sp - 1].i));
274 |
275 | //printf("\nAddress: %d\n", alloc + addr);
276 | //printf("\nValue: %d\n", stack[sp - 1].i);
277 | sp++;
278 |
279 | case OP_PUT:
280 | alloc = code[ip].operand.i;
281 | *(int*)(data + (dp + stack[sp - 2].i)) = stack[sp - 1].i;
282 | sp--;
283 |
284 | default:
285 | break;
286 | }
287 | ip++;
288 | }
289 | /*
290 | printf("Code Segment: ");
291 | for(c = 0; c < data_count; c++){
292 | printf("%x ", data[c]);
293 | }*/
294 | }
295 |
296 | void print_stack(int sp)
297 | {
298 | int i;
299 | printf("\nBottom: ");
300 | for(i = 0; i < sp; i++){
301 | printf("%d < ", stack[i].i);
302 |
303 | }
304 | printf(": Top\n");
305 | }
306 |
--------------------------------------------------------------------------------
/src/cvm/cvm.h:
--------------------------------------------------------------------------------
1 | #ifndef _CVM_H_
2 | #define _CVM_H_
3 |
4 | #include
5 | #include
6 |
7 | #include "../compiler/utils.h"
8 |
9 | #define OP_PUSH 0
10 | #define OP_PUSHI 1
11 | #define OP_POP 2
12 | #define OP_EXCH 3
13 | #define OP_DUP 4
14 | #define OP_ADDF 5
15 | #define OP_ADD 6
16 | #define OP_SUBF 7
17 | #define OP_SUB 8
18 | #define OP_MULF 9
19 | #define OP_MUL 10
20 | #define OP_DIV 11
21 | #define OP_DIVF 12
22 | #define OP_AND 13
23 | #define OP_OR 14
24 | #define OP_EQL 15
25 | #define OP_NEG 16
26 | #define OP_NOT 17
27 | #define OP_LSS 18
28 | #define OP_GTR 19
29 | #define OP_LEQ 20
30 | #define OP_GEQ 21
31 | #define OP_CVI 22
32 | #define OP_CVR 23
33 | #define OP_JMP 24
34 | #define OP_JFALSE 25
35 | #define OP_JTRUE 26
36 | #define OP_HALT 27
37 | #define OP_WRITEINT 28
38 | #define OP_WRITEFLOAT 29
39 | #define OP_MOD 30
40 |
41 | #define OP_PUSHF 31
42 | #define OP_POPF 32
43 |
44 | #define OP_WRITEINTID 33
45 | #define OP_POPEMPTY 34
46 |
47 | #define OP_NOP 35
48 | #define OP_NEQ 36
49 | #define OP_EQU 37
50 | #define OP_NEGF 38
51 |
52 | #define OP_WRITESTRING 39
53 | #define OP_GET 40
54 | #define OP_PUT 41
55 |
56 | typedef unsigned char uchar;
57 | typedef unsigned int uint;
58 | typedef union Operand_TAG {
59 | int i;
60 | float f;
61 | } Operand;
62 |
63 | typedef struct Instruction_TAG {
64 | char opcode; /* 8-bit */
65 | Operand operand; /* 32-bit */
66 | }Instruction;
67 |
68 | /* Globals */
69 |
70 | size_t sp;
71 | size_t ip;
72 | size_t bp;
73 | size_t dp;
74 |
75 | Instruction *code;
76 | char *data;
77 |
78 | union stack_TAG {
79 | int i;
80 | float f;
81 | } stack[1024]; /* 1kb for stack */
82 |
83 |
84 |
85 | void usage();
86 |
87 | void run(char *program);
88 |
89 |
90 | void print_stack();
91 | #endif
92 |
--------------------------------------------------------------------------------
/src/cvm/drivers/main.c:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eudisd/c-compiler/9aa5e08fe4217accd4935b8120178e4e0377e0a0/src/cvm/drivers/main.c
--------------------------------------------------------------------------------