2016-08-14 17:13:52 +01:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <stdbool.h>
|
|
|
|
#include <string.h>
|
|
|
|
#define max_string 63
|
|
|
|
|
|
|
|
FILE* source_file;
|
|
|
|
bool Reached_EOF;
|
|
|
|
|
|
|
|
struct Token
|
|
|
|
{
|
|
|
|
struct Token* next;
|
|
|
|
uint8_t type;
|
|
|
|
char* Text;
|
|
|
|
char* Expression;
|
|
|
|
};
|
|
|
|
|
|
|
|
enum type
|
|
|
|
{
|
|
|
|
macro = 1,
|
2016-08-25 03:56:37 +01:00
|
|
|
str = (1 << 1)
|
2016-08-14 17:13:52 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
struct Token* newToken()
|
|
|
|
{
|
|
|
|
struct Token* p;
|
|
|
|
|
|
|
|
p = calloc (1, sizeof (struct Token));
|
|
|
|
if (NULL == p)
|
|
|
|
{
|
|
|
|
fprintf (stderr, "calloc failed.\n");
|
|
|
|
exit (EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct Token* addToken(struct Token* head, struct Token* p)
|
|
|
|
{
|
|
|
|
if(NULL == head)
|
|
|
|
{
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
if(NULL == head->next)
|
|
|
|
{
|
|
|
|
head->next = p;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
addToken(head->next, p);
|
|
|
|
}
|
|
|
|
return head;
|
|
|
|
}
|
|
|
|
|
|
|
|
void purge_lineComment()
|
|
|
|
{
|
|
|
|
int c = fgetc(source_file);
|
|
|
|
while((10 != c) && (13 != c))
|
|
|
|
{
|
|
|
|
c = fgetc(source_file);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-08-25 03:56:37 +01:00
|
|
|
char* store_atom(char c)
|
2016-08-14 17:13:52 +01:00
|
|
|
{
|
|
|
|
char* store = calloc(max_string + 1, sizeof(char));
|
2016-08-25 03:56:37 +01:00
|
|
|
int32_t ch;
|
|
|
|
uint32_t i = 0;
|
|
|
|
ch = c;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
store[i] = (char)ch;
|
|
|
|
ch = fgetc(source_file);
|
|
|
|
i = i + 1;
|
|
|
|
} while ((9 != ch) && (10 != ch) && (32 != ch));
|
|
|
|
|
|
|
|
return store;
|
|
|
|
}
|
|
|
|
|
|
|
|
char* store_string(char c)
|
|
|
|
{
|
|
|
|
char* store = calloc(max_string + 1, sizeof(char));
|
|
|
|
int32_t ch;
|
|
|
|
uint32_t i = 0;
|
|
|
|
ch = c;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
store[i] = (char)ch;
|
|
|
|
i = i + 1;
|
|
|
|
ch = fgetc(source_file);
|
|
|
|
} while(ch != c);
|
|
|
|
|
|
|
|
return store;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct Token* Tokenize_Line(struct Token* head)
|
|
|
|
{
|
|
|
|
|
2016-08-14 17:13:52 +01:00
|
|
|
int32_t c;
|
2016-08-25 03:56:37 +01:00
|
|
|
c = fgetc(source_file);
|
2016-08-14 17:13:52 +01:00
|
|
|
|
2016-08-25 03:56:37 +01:00
|
|
|
if((35 == c) || (59 == c))
|
2016-08-14 17:13:52 +01:00
|
|
|
{
|
2016-08-25 03:56:37 +01:00
|
|
|
purge_lineComment();
|
|
|
|
return Tokenize_Line(head);
|
|
|
|
}
|
|
|
|
|
|
|
|
if((9 == c) || (10 == c) || (32 == c))
|
|
|
|
{
|
|
|
|
return Tokenize_Line(head);
|
|
|
|
}
|
|
|
|
|
|
|
|
struct Token* p = newToken();
|
|
|
|
if(-1 == c)
|
|
|
|
{
|
|
|
|
Reached_EOF = true;
|
|
|
|
free(p);
|
|
|
|
return head;
|
|
|
|
}
|
|
|
|
else if((34 == c) || (39 == c))
|
|
|
|
{
|
|
|
|
p->Text = store_string(c);
|
|
|
|
p->type = str;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
p->Text = store_atom(c);
|
2016-08-14 17:13:52 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return addToken(head, p);
|
|
|
|
}
|
|
|
|
|
|
|
|
void setExpression(struct Token* p, char match[], char Exp[])
|
|
|
|
{
|
|
|
|
/* Leave macros alone */
|
|
|
|
if((p->type & macro))
|
|
|
|
{
|
2016-10-02 01:50:06 +01:00
|
|
|
setExpression(p->next, match, Exp);
|
2016-08-14 17:13:52 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Only if there is an exact match replace */
|
|
|
|
if(0 == strncmp(p->Text, match, max_string))
|
|
|
|
{
|
|
|
|
p->Expression = Exp;
|
|
|
|
}
|
2016-10-02 01:50:06 +01:00
|
|
|
|
|
|
|
if(NULL != p->next)
|
|
|
|
{
|
|
|
|
setExpression(p->next, match, Exp);
|
|
|
|
}
|
|
|
|
|
2016-08-14 17:13:52 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void identify_macros(struct Token* p)
|
|
|
|
{
|
|
|
|
if(0 == strncmp(p->Text, "DEFINE", max_string))
|
|
|
|
{
|
|
|
|
p->type = macro;
|
2016-09-07 02:19:32 +01:00
|
|
|
p->Text = p->next->Text;
|
2016-10-02 20:48:47 +01:00
|
|
|
if(p->next->next->type & str)
|
|
|
|
{
|
|
|
|
p->Expression = p->next->next->Text + 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
p->Expression = p->next->next->Text;
|
|
|
|
}
|
2016-09-07 02:19:32 +01:00
|
|
|
p->next = p->next->next->next;
|
2016-08-14 17:13:52 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if(NULL != p->next)
|
|
|
|
{
|
|
|
|
identify_macros(p->next);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void line_macro(struct Token* p)
|
|
|
|
{
|
2016-09-07 02:19:32 +01:00
|
|
|
if(p->type & macro)
|
2016-08-14 17:13:52 +01:00
|
|
|
{
|
2016-09-07 02:19:32 +01:00
|
|
|
setExpression(p->next, p->Text, p->Expression);
|
2016-08-14 17:13:52 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if(NULL != p->next)
|
|
|
|
{
|
|
|
|
line_macro(p->next);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-08-25 03:56:37 +01:00
|
|
|
void hexify_string(struct Token* p)
|
|
|
|
{
|
|
|
|
char table[16] = {0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46};
|
|
|
|
int i = ((strnlen(p->Text + 1 , max_string)/4) + 1) * 8;
|
|
|
|
|
|
|
|
char* d = calloc(max_string, sizeof(char));
|
|
|
|
p->Expression = d;
|
|
|
|
|
|
|
|
while(0 < i)
|
|
|
|
{
|
|
|
|
i = i - 1;
|
|
|
|
d[i] = 0x30;
|
|
|
|
}
|
|
|
|
|
|
|
|
while( i < max_string)
|
|
|
|
{
|
|
|
|
if(0 == p->Text[i+1])
|
|
|
|
{
|
|
|
|
i = max_string;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
d[2*i] = table[p->Text[i+1] / 16];
|
|
|
|
d[2*i + 1] = table[p->Text[i+1] % 16];
|
|
|
|
i = i + 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void process_string(struct Token* p)
|
|
|
|
{
|
|
|
|
if(p->type & str)
|
|
|
|
{
|
|
|
|
if('\'' == p->Text[0])
|
|
|
|
{
|
|
|
|
p->Expression = p->Text + 1;
|
|
|
|
}
|
|
|
|
else if('"' == p->Text[0])
|
|
|
|
{
|
|
|
|
hexify_string(p);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(NULL != p->next)
|
|
|
|
{
|
|
|
|
process_string(p->next);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-08-14 17:13:52 +01:00
|
|
|
void preserve_other(struct Token* p)
|
|
|
|
{
|
|
|
|
if(NULL != p->next)
|
|
|
|
{
|
|
|
|
preserve_other(p->next);
|
|
|
|
}
|
|
|
|
|
|
|
|
if((NULL == p->Expression) && !(p->type & macro))
|
|
|
|
{
|
|
|
|
p->Expression = p->Text;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
uint16_t numerate_string(char a[])
|
|
|
|
{
|
|
|
|
char *ptr;
|
|
|
|
return (uint16_t)strtol(a, &ptr, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void eval_immediates(struct Token* p)
|
|
|
|
{
|
|
|
|
if(NULL != p->next)
|
|
|
|
{
|
|
|
|
eval_immediates(p->next);
|
|
|
|
}
|
|
|
|
|
|
|
|
if((NULL == p->Expression) && !(p->type & macro))
|
|
|
|
{
|
|
|
|
uint16_t value;
|
|
|
|
value = numerate_string(p->Text);
|
|
|
|
|
|
|
|
if(('0' == p->Text[0]) || (0 != value))
|
|
|
|
{
|
|
|
|
char* c = calloc(5, sizeof(char));
|
|
|
|
sprintf(c, "%04x", value);
|
|
|
|
p->Expression = c;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void print_hex(struct Token* p)
|
|
|
|
{
|
2016-09-07 02:19:32 +01:00
|
|
|
if(p->type ^ macro)
|
2016-08-14 17:13:52 +01:00
|
|
|
{
|
|
|
|
fprintf(stdout, "\n%s", p->Expression);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(NULL != p->next)
|
|
|
|
{
|
|
|
|
print_hex(p->next);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
fprintf(stdout, "\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Standard C main program */
|
|
|
|
int main(int argc, char **argv)
|
|
|
|
{
|
|
|
|
/* Make sure we have a program tape to run */
|
|
|
|
if (argc < 2)
|
|
|
|
{
|
|
|
|
fprintf(stderr, "Usage: %s $FileName\nWhere $FileName is the name of the paper tape of the program being run\n", argv[0]);
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
source_file = fopen(argv[1], "r");
|
|
|
|
|
|
|
|
Reached_EOF = false;
|
|
|
|
struct Token* head = NULL;
|
|
|
|
while(!Reached_EOF)
|
|
|
|
{
|
|
|
|
head = Tokenize_Line(head);
|
|
|
|
}
|
|
|
|
|
|
|
|
identify_macros(head);
|
|
|
|
line_macro(head);
|
2016-08-25 03:56:37 +01:00
|
|
|
process_string(head);
|
2016-08-14 17:13:52 +01:00
|
|
|
eval_immediates(head);
|
|
|
|
preserve_other(head);
|
|
|
|
print_hex(head);
|
|
|
|
|
|
|
|
return EXIT_SUCCESS;
|
|
|
|
}
|