123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200 |
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <stdint.h>
- // getchar
- // putchar
- int hex_digit(int n) {
- if('0' <= n && n <= '9') {
- return n - '0';
- }
-
- if('a' <= n && n <= 'f') {
- return n - 'a' + 10;
- }
-
- if('A' <= n && n <= 'F') {
- return n - 'A' + 10;
- }
-
- fprintf(stderr, "X\n");
- exit(-1);
- }
- void skip_comment() {
- int nyb;
-
- do {
- nyb = getchar();
- if(nyb == EOF) exit(-1);
- if(nyb == '\n') return;
- } while(1);
- }
- #define MAXSIZE 4096
- #define MAXLBLS 100
- void read_lbl(unsigned char *lbl) {
- int nyb;
- int i = 0;
- do {
- nyb = getchar();
-
- if(nyb == ' ' || nyb == '\t' || nyb == '\n') {
- return;
- }
-
- lbl[i++] = nyb;
- } while(1);
- }
- #define MAXREFS 256
- unsigned char lbl[MAXLBLS][32] = { { 0 } };
- int lbl_place[MAXLBLS] = { 0 };
- int lbl_len = 0;
- int lookup_label(unsigned char *label) {
- for(int i = 0; i < lbl_len; i++) {
- if(!strcmp((char*)lbl[i],(char*)label))
- return lbl_place[i];
- }
- fprintf(stderr, "fail <%s>\n", label);
- exit(-1);
- }
- int main(void) {
- int nyb, oct;
-
- unsigned char c[MAXSIZE] = { 0 };
- int len = 0;
- int i;
- unsigned char ref_sigil[MAXREFS] = { 0 };
- unsigned char ref_lbl[MAXREFS][32] = { { 0 } };
- int ref_pos[MAXREFS] = { 0 };
- int ref_len = 0;
- int8_t u8;
- int16_t u16;
- int32_t u32;
- do {
- nyb = getchar();
- if(nyb == EOF) {
- break;
- }
- else if(nyb == '#') {
- skip_comment();
- continue;
- }
- else if(nyb == ' ' || nyb == '\t' || nyb == '\n') {
- continue;
- }
- else if(nyb == ':') {
- read_lbl(lbl[lbl_len]);
- lbl_place[lbl_len] = len;
-
- ////
- fprintf(stderr, "LBL: <%s>\n", lbl[lbl_len]);
-
- lbl_len++;
-
- continue;
- }
- else if(nyb == '.' || nyb == '@' || nyb == '$' || nyb == '*') {
- ref_sigil[ref_len] = nyb;
- read_lbl(ref_lbl[ref_len]);
-
- ////
- fprintf(stderr, "REF: [%c]<%s>\n", ref_sigil[ref_len], ref_lbl[ref_len]);
-
- ref_pos[ref_len] = len;
- ref_len++;
- switch(nyb) {
- case '.':
- c[len++] = 0xFF;
- break;
-
- case '@':
- c[len++] = 0xFF;
- c[len++] = 0xFF;
- break;
- case '$':
- c[len++] = 0xFF;
- c[len++] = 0xFF;
- break;
- case '*':
- c[len++] = 0xFF;
- c[len++] = 0xFF;
- c[len++] = 0xFF;
- c[len++] = 0xFF;
- break;
- default:
- fprintf(stderr, "A\n");
- exit(-1);
- }
- continue;
- }
-
- nyb = hex_digit(nyb);
- oct = nyb << 4;
- nyb = getchar();
- nyb = hex_digit(nyb);
- oct |= nyb;
- c[len++] = oct;
- } while(1);
- for(i = 0; i < ref_len; i++) {
- switch(ref_sigil[i]) {
- case '.':
- u8 = lookup_label(ref_lbl[i]) - ref_pos[i] - 1;
- c[ref_pos[i]] = u8 & 0xFF;
-
- break;
-
- case '@':
- u16 = lookup_label(ref_lbl[i]) - ref_pos[i] + 2;
- c[ref_pos[i]+1] = u16 & 0xFF;
- c[ref_pos[i]+0] = (u16 >> 8) & 0xFF;
-
- break;
-
- case '*':
- u32 = lookup_label(ref_lbl[i]) - ref_pos[i] - 4;
- c[ref_pos[i]+0] = u32 & 0xFF;
- c[ref_pos[i]+1] = (u32 >> 8) & 0xFF;
- c[ref_pos[i]+2] = (u32 >> 16) & 0xFF;
- c[ref_pos[i]+3] = (u32 >> 24) & 0xFF;
-
- break;
-
- case '$':
- u16 = lookup_label(ref_lbl[i]);
- c[ref_pos[i]+1] = u16 & 0xFF;
- c[ref_pos[i]+0] = (u16 >> 8) & 0xFF;
-
- break;
-
- default:
- fprintf(stderr, "B\n");
- exit(-1);
- }
-
- }
-
- for(i = 0; i < len; i++) {
- putchar(c[i]);
- }
- }
|