M1-macro.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882
  1. /* -*- c-file-style: "linux";indent-tabs-mode:t -*- */
  2. /* Copyright (C) 2016 Jeremiah Orians
  3. * Copyright (C) 2017 Jan Nieuwenhuizen <janneke@gnu.org>
  4. * This file is part of mescc-tools.
  5. *
  6. * mescc-tools is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * mescc-tools is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with mescc-tools. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include <stdio.h>
  20. #include <stdlib.h>
  21. #include <string.h>
  22. #include <getopt.h>
  23. //CONSTANT max_string 4096
  24. #define max_string 4096
  25. //CONSTANT PROCESSED 1
  26. #define PROCESSED 1
  27. //CONSTANT STR 2
  28. #define STR 2
  29. //CONSTANT NEWLINE 3
  30. #define NEWLINE 3
  31. //CONSTANT TRUE 1
  32. #define TRUE 1
  33. //CONSTANT FALSE 0
  34. #define FALSE 0
  35. // CONSTANT KNIGHT 0
  36. #define KNIGHT 0
  37. // CONSTANT X86 1
  38. #define X86 1
  39. // CONSTANT AMD64 2
  40. #define AMD64 2
  41. // CONSTANT ARMV7L 40
  42. #define ARMV7L 40
  43. // CONSTANT AARM64 80
  44. #define AARM64 80
  45. // CONSTANT HEX 16
  46. #define HEX 16
  47. // CONSTANT OCTAL 8
  48. #define OCTAL 8
  49. // CONSTANT BINARY 2
  50. #define BINARY 2
  51. /* Imported functions */
  52. char* numerate_number(int a);
  53. int hex2char(int c);
  54. int in_set(int c, char* s);
  55. int match(char* a, char* b);
  56. int numerate_string(char *a);
  57. int string_length(char* a);
  58. void file_print(char* s, FILE* f);
  59. void require(int bool, char* error);
  60. struct blob
  61. {
  62. struct blob* next;
  63. int type;
  64. char* Text;
  65. char* Expression;
  66. struct blob* hash_next;
  67. };
  68. struct Token
  69. {
  70. struct Token* next;
  71. struct blob* contents;
  72. char* filename;
  73. int linenumber;
  74. };
  75. /* Globals */
  76. FILE* source_file;
  77. FILE* destination_file;
  78. int BigEndian;
  79. int BigBitEndian;
  80. int ByteMode;
  81. int Architecture;
  82. int linenumber;
  83. struct Token* token_list;
  84. struct blob* blob_list;
  85. struct blob* define_blob;
  86. struct blob* newline_blob;
  87. int blob_count;
  88. char* SCRATCH;
  89. struct blob** hash_table;
  90. void line_error(char* filename, int linenumber)
  91. {
  92. file_print(filename, stderr);
  93. file_print(":", stderr);
  94. file_print(numerate_number(linenumber), stderr);
  95. file_print(" :", stderr);
  96. }
  97. void ClearScratch()
  98. {
  99. int i = 0;
  100. int c = SCRATCH[i];
  101. while(0 != c)
  102. {
  103. SCRATCH[i] = 0;
  104. i = i + 1;
  105. c = SCRATCH[i];
  106. }
  107. }
  108. int GetHash(char* s)
  109. {
  110. int i = 5381;
  111. while(0 != s[0])
  112. {
  113. i = (i << 5) + i + s[0];
  114. s = s + 1;
  115. }
  116. return i & 0xFFFF;
  117. }
  118. struct blob* FindBlob()
  119. {
  120. int hash = GetHash(SCRATCH);
  121. struct blob* i = hash_table[hash];
  122. while(NULL != i)
  123. {
  124. if(match(SCRATCH, i->Text)) return i;
  125. i = i->hash_next;
  126. }
  127. return NULL;
  128. }
  129. void AddHash(struct blob* a, char* s)
  130. {
  131. int i = GetHash(s);
  132. a->hash_next = hash_table[i];
  133. hash_table[i] = a;
  134. }
  135. void NewBlob(int size)
  136. {
  137. blob_count = blob_count + 1;
  138. struct blob* a = calloc(1, sizeof(struct blob));
  139. require(NULL != a, "Exhusted available memory\n");
  140. a->Text = calloc(size + 1, sizeof(char));
  141. require(NULL != a->Text, "Exhusted available memory\n");
  142. int i = 0;
  143. while(i <= size)
  144. {
  145. a->Text[i] = SCRATCH[i];
  146. i = i + 1;
  147. }
  148. a->next = blob_list;
  149. blob_list = a;
  150. AddHash(a, SCRATCH);
  151. }
  152. struct Token* newToken(char* filename, int linenumber)
  153. {
  154. struct Token* p;
  155. p = calloc (1, sizeof (struct Token));
  156. require(NULL != p, "Exhusted available memory\n");
  157. p->filename = filename;
  158. p->linenumber = linenumber;
  159. return p;
  160. }
  161. struct Token* reverse_list(struct Token* head)
  162. {
  163. struct Token* root = NULL;
  164. struct Token* next;
  165. while(NULL != head)
  166. {
  167. next = head->next;
  168. head->next = root;
  169. root = head;
  170. head = next;
  171. }
  172. return root;
  173. }
  174. void purge_lineComment()
  175. {
  176. int c = fgetc(source_file);
  177. while(!in_set(c, "\n\r"))
  178. {
  179. if(EOF == c) break;
  180. c = fgetc(source_file);
  181. }
  182. }
  183. struct Token* append_newline(struct Token* head, char* filename)
  184. {
  185. linenumber = linenumber + 1;
  186. if(NULL == head) return NULL;
  187. if(NEWLINE == head->contents->type)
  188. {/* Don't waste whitespace*/
  189. return head;
  190. }
  191. struct Token* lf = newToken(filename, linenumber);
  192. lf->contents = newline_blob;
  193. lf->next = head;
  194. return lf;
  195. }
  196. struct Token* store_atom(struct Token* head, char c, char* filename)
  197. {
  198. ClearScratch();
  199. int ch = c;
  200. int i = 0;
  201. do
  202. {
  203. SCRATCH[i] = ch;
  204. ch = fgetc(source_file);
  205. i = i + 1;
  206. require(i < max_string, "storing atom of size larger than max_string\n");
  207. if(EOF == ch) break;
  208. } while (!in_set(ch, "\t\n "));
  209. head->contents = FindBlob();
  210. if(NULL == head->contents)
  211. {
  212. NewBlob(i);
  213. head->contents = blob_list;
  214. }
  215. if('\n' == ch)
  216. {
  217. return append_newline(head, filename);
  218. }
  219. return head;
  220. }
  221. struct blob* store_string(char c, char* filename)
  222. {
  223. ClearScratch();
  224. int ch = c;
  225. int i = 0;
  226. do
  227. {
  228. SCRATCH[i] = ch;
  229. i = i + 1;
  230. if('\n' == ch) linenumber = linenumber + 1;
  231. ch = fgetc(source_file);
  232. require(EOF != ch, "Unmatched \"!\n");
  233. if(max_string == i)
  234. {
  235. line_error(filename, linenumber);
  236. file_print("String: ", stderr);
  237. file_print(SCRATCH, stderr);
  238. file_print(" exceeds max string size\n", stderr);
  239. exit(EXIT_FAILURE);
  240. }
  241. } while(ch != c);
  242. struct blob* a = FindBlob();
  243. if(NULL == a)
  244. {
  245. NewBlob(i);
  246. a = blob_list;
  247. a->type = STR;
  248. }
  249. return a;
  250. }
  251. struct Token* Tokenize_Line(struct Token* head, char* filename)
  252. {
  253. int c;
  254. struct Token* p;
  255. linenumber = 1;
  256. do
  257. {
  258. restart:
  259. c = fgetc(source_file);
  260. if(in_set(c, ";#"))
  261. {
  262. purge_lineComment();
  263. head = append_newline(head, filename);
  264. goto restart;
  265. }
  266. if(in_set(c, "\t "))
  267. {
  268. goto restart;
  269. }
  270. if('\n' == c)
  271. {
  272. head = append_newline(head, filename);
  273. goto restart;
  274. }
  275. if(EOF == c)
  276. {
  277. head = append_newline(head, filename);
  278. goto done;
  279. }
  280. p = newToken(filename, linenumber);
  281. p->next = head;
  282. if(in_set(c, "'\""))
  283. {
  284. p->contents = store_string(c, filename);
  285. }
  286. else
  287. {
  288. p = store_atom(p, c, filename);
  289. }
  290. head = p;
  291. } while(TRUE);
  292. done:
  293. return head;
  294. }
  295. void line_macro(struct Token* p)
  296. {
  297. struct Token* i;
  298. for(i = p; NULL != i; i = i->next)
  299. {
  300. if(define_blob == i->contents)
  301. {
  302. require(NULL != i->next, "Macro name must exist\n");
  303. require(NULL != i->next->next, "Macro value must exist\n");
  304. if(PROCESSED == i->next->contents->type)
  305. {
  306. line_error(i->filename, i->linenumber);
  307. file_print("Multiple definitions for macro ", stderr);
  308. file_print(i->next->contents->Text, stderr);
  309. file_print("\n", stderr);
  310. exit(EXIT_FAILURE);
  311. }
  312. i->contents = newline_blob;
  313. if (STR == i->next->next->contents->type)
  314. {
  315. i->contents->Expression = i->next->next->contents->Text + 1;
  316. }
  317. else
  318. {
  319. i->next->contents->Expression = i->next->next->contents->Text;
  320. }
  321. i->next = i->next->next->next;
  322. }
  323. }
  324. }
  325. void hexify_string(struct blob* p)
  326. {
  327. char* table = "0123456789ABCDEF";
  328. int i = string_length(p->Text);
  329. int size;
  330. if(HEX == ByteMode) size = (((i << 1) + i) + 12);
  331. else if(OCTAL == ByteMode) size = (i << 2) + 1;
  332. else if(BINARY == ByteMode) size = (i << 3) + i + 1;
  333. else size = 1;
  334. require(1 != size, "hexify_string lacked a valid bytemode\n");
  335. char* d = calloc(size, sizeof(char));
  336. require(NULL != d, "Exhusted available memory\n");
  337. p->Expression = d;
  338. char* S = p->Text;
  339. if((KNIGHT == Architecture) && (HEX == ByteMode))
  340. {
  341. i = (((((i - 1) >> 2) + 1) << 3) + i);
  342. while( 0 < i)
  343. {
  344. i = i - 1;
  345. d[i] = '0';
  346. }
  347. }
  348. if(HEX == ByteMode)
  349. {
  350. while(0 != S[0])
  351. {
  352. S = S + 1;
  353. d[0] = table[S[0] >> 4];
  354. d[1] = table[S[0] & 0xF];
  355. d[2] = ' ';
  356. d = d + 3;
  357. }
  358. }
  359. else if(OCTAL == ByteMode)
  360. {
  361. while(0 != S[0])
  362. {
  363. S = S + 1;
  364. d[0] = table[S[0] >> 6];
  365. d[1] = table[(S[0] >> 3) & 0x7];
  366. d[2] = table[S[0] & 0x7];
  367. d[3] = ' ';
  368. d = d + 4;
  369. }
  370. }
  371. else if(BINARY == ByteMode)
  372. {
  373. while(0 != S[0])
  374. {
  375. S = S + 1;
  376. d[0] = table[S[0] >> 7];
  377. d[1] = table[(S[0] >> 6) & 0x1];
  378. d[2] = table[(S[0] >> 5) & 0x1];
  379. d[3] = table[(S[0] >> 4) & 0x1];
  380. d[4] = table[(S[0] >> 3) & 0x1];
  381. d[5] = table[(S[0] >> 2) & 0x1];
  382. d[6] = table[(S[0] >> 1) & 0x1];
  383. d[7] = table[S[0] & 0x1];
  384. d[8] = ' ';
  385. d = d + 9;
  386. }
  387. }
  388. }
  389. void process_string(struct blob* p)
  390. {
  391. struct blob* i;
  392. for(i = p; NULL != i; i = i->next)
  393. {
  394. if(STR == i->type)
  395. {
  396. if('\'' == i->Text[0])
  397. {
  398. i->Expression = i->Text + 1;
  399. }
  400. else if('"' == i->Text[0])
  401. {
  402. hexify_string(i);
  403. }
  404. }
  405. }
  406. }
  407. char* pad_nulls(int size, char* nil)
  408. {
  409. if(0 == size) return nil;
  410. require(size > 0, "negative null padding not possible\n");
  411. if(HEX == ByteMode) size = size * 2;
  412. else if (OCTAL == ByteMode) size = size * 3;
  413. else if (BINARY == ByteMode) size = size * 8;
  414. char* s = calloc(size + 1, sizeof(char));
  415. require(NULL != s, "Exhusted available memory\n");
  416. int i = 0;
  417. while(i < size)
  418. {
  419. s[i] = '0';
  420. i = i + 1;
  421. }
  422. return s;
  423. }
  424. void preserve_other(struct blob* p)
  425. {
  426. struct blob* i;
  427. char c;
  428. for(i = p; NULL != i; i = i->next)
  429. {
  430. if((NULL == i->Expression) && !(i->type & PROCESSED))
  431. {
  432. c = i->Text[0];
  433. if(in_set(c, "!@$~%&:^"))
  434. {
  435. i->Expression = i->Text;
  436. }
  437. else if('<' == c)
  438. {
  439. i->Expression = pad_nulls(numerate_string(i->Text + 1), i->Text);
  440. }
  441. }
  442. }
  443. }
  444. void bound_values(int displacement, int number_of_bytes, int low, int high)
  445. {
  446. if((high < displacement) || (displacement < low))
  447. {
  448. file_print("A displacement of ", stderr);
  449. file_print(numerate_number(displacement), stderr);
  450. file_print(" does not fit in ", stderr);
  451. file_print(numerate_number(number_of_bytes), stderr);
  452. file_print(" bytes\n", stderr);
  453. exit(EXIT_FAILURE);
  454. }
  455. }
  456. void range_check(int displacement, int number_of_bytes)
  457. {
  458. if(4 == number_of_bytes) return;
  459. else if(3 == number_of_bytes)
  460. {
  461. bound_values(displacement, number_of_bytes, -8388608, 16777216);
  462. return;
  463. }
  464. else if(2 == number_of_bytes)
  465. {
  466. bound_values(displacement, number_of_bytes, -32768, 65535);
  467. return;
  468. }
  469. else if(1 == number_of_bytes)
  470. {
  471. bound_values(displacement, number_of_bytes, -128, 255);
  472. return;
  473. }
  474. file_print("Received an invalid number of bytes in range_check\n", stderr);
  475. exit(EXIT_FAILURE);
  476. }
  477. void reverseBitOrder(char* c)
  478. {
  479. if(NULL == c) return;
  480. if(0 == c[1]) return;
  481. int hold = c[0];
  482. if(HEX == ByteMode)
  483. {
  484. c[0] = c[1];
  485. c[1] = hold;
  486. reverseBitOrder(c+2);
  487. }
  488. else if(OCTAL == ByteMode)
  489. {
  490. c[0] = c[2];
  491. c[2] = hold;
  492. reverseBitOrder(c+3);
  493. }
  494. else if(BINARY == ByteMode)
  495. {
  496. c[0] = c[7];
  497. c[7] = hold;
  498. hold = c[1];
  499. c[1] = c[6];
  500. c[6] = hold;
  501. hold = c[2];
  502. c[2] = c[5];
  503. c[5] = hold;
  504. hold = c[3];
  505. c[3] = c[4];
  506. c[4] = hold;
  507. reverseBitOrder(c+8);
  508. }
  509. }
  510. void LittleEndian(char* start)
  511. {
  512. char* end = start;
  513. char* c = start;
  514. while(0 != end[0]) end = end + 1;
  515. int hold;
  516. for(end = end - 1; start < end; start = start + 1)
  517. {
  518. hold = start[0];
  519. start[0] = end[0];
  520. end[0] = hold;
  521. end = end - 1;
  522. }
  523. if(BigBitEndian) reverseBitOrder(c);
  524. }
  525. int stringify(char* s, int digits, int divisor, int value, int shift)
  526. {
  527. int i = value;
  528. if(digits > 1)
  529. {
  530. i = stringify(s+1, (digits - 1), divisor, value, shift);
  531. }
  532. s[0] = hex2char(i & (divisor - 1));
  533. return (i >> shift);
  534. }
  535. char* express_number(int value, char c)
  536. {
  537. char* ch = calloc(42, sizeof(char));
  538. require(NULL != ch, "Exhusted available memory\n");
  539. int size;
  540. int number_of_bytes;
  541. int shift;
  542. if('!' == c)
  543. {
  544. number_of_bytes = 1;
  545. value = value & 0xFF;
  546. }
  547. else if('@' == c)
  548. {
  549. number_of_bytes = 2;
  550. value = value & 0xFFFF;
  551. }
  552. else if('~' == c)
  553. {
  554. number_of_bytes = 3;
  555. value = value & 0xFFFFFF;
  556. }
  557. else if('%' == c)
  558. {
  559. number_of_bytes = 4;
  560. value = value & 0xFFFFFFFF;
  561. }
  562. else
  563. {
  564. file_print("Given symbol ", stderr);
  565. fputc(c, stderr);
  566. file_print(" to express immediate value ", stderr);
  567. file_print(numerate_number(value), stderr);
  568. fputc('\n', stderr);
  569. exit(EXIT_FAILURE);
  570. }
  571. range_check(value, number_of_bytes);
  572. if(HEX == ByteMode)
  573. {
  574. size = number_of_bytes * 2;
  575. shift = 4;
  576. }
  577. else if(OCTAL == ByteMode)
  578. {
  579. size = number_of_bytes * 3;
  580. shift = 3;
  581. }
  582. else if(BINARY == ByteMode)
  583. {
  584. size = number_of_bytes * 8;
  585. shift = 1;
  586. }
  587. else
  588. {
  589. file_print("Got invalid ByteMode in express_number\n", stderr);
  590. exit(EXIT_FAILURE);
  591. }
  592. stringify(ch, size, ByteMode, value, shift);
  593. if(!BigEndian) LittleEndian(ch);
  594. else if(!BigBitEndian) reverseBitOrder(ch);
  595. return ch;
  596. }
  597. void eval_immediates(struct blob* p)
  598. {
  599. struct blob* i;
  600. int value;
  601. for(i = p; NULL != i; i = i->next)
  602. {
  603. if(PROCESSED == i->type) continue;
  604. else if(NEWLINE == i->type) continue;
  605. else if('<' == i->Text[0]) continue;
  606. else if(NULL == i->Expression)
  607. {
  608. if((X86 == Architecture) || (AMD64 == Architecture) || (ARMV7L == Architecture) || (AARM64 == Architecture))
  609. {
  610. if(in_set(i->Text[0], "%~@!"))
  611. {
  612. value = numerate_string(i->Text + 1);
  613. if(('0' == i->Text[1]) || (0 != value))
  614. {
  615. i->Expression = express_number(value, i->Text[0]);
  616. }
  617. }
  618. }
  619. else if(KNIGHT == Architecture)
  620. {
  621. value = numerate_string(i->Text);
  622. if(('0' == i->Text[0]) || (0 != value))
  623. {
  624. i->Expression = express_number(value, '@');
  625. }
  626. }
  627. else
  628. {
  629. file_print("Unknown architecture received in eval_immediates\n", stderr);
  630. exit(EXIT_FAILURE);
  631. }
  632. }
  633. }
  634. }
  635. void print_hex(struct Token* p)
  636. {
  637. struct Token* i;
  638. for(i = p; NULL != i; i = i->next)
  639. {
  640. if(NEWLINE == i->contents->type)
  641. {
  642. if(NULL == i->next) fputc('\n', destination_file);
  643. else if(NEWLINE != i->next->contents->type) fputc('\n', destination_file);
  644. }
  645. else if(NULL != i->contents->Expression)
  646. {
  647. file_print(i->contents->Expression, destination_file);
  648. if(NEWLINE != i->next->contents->type) fputc(' ', destination_file);
  649. }
  650. else
  651. {
  652. line_error(i->filename, i->linenumber);
  653. file_print("Received invalid other; ", stderr);
  654. file_print(i->contents->Text, stderr);
  655. file_print("\n", stderr);
  656. exit(EXIT_FAILURE);
  657. }
  658. }
  659. }
  660. /* Standard C main program */
  661. int main(int argc, char **argv)
  662. {
  663. BigEndian = TRUE;
  664. Architecture = KNIGHT;
  665. destination_file = stdout;
  666. BigBitEndian = TRUE;
  667. ByteMode = HEX;
  668. char* filename;
  669. char* arch;
  670. blob_count = 2;
  671. hash_table = calloc(65537, sizeof(struct blob*));
  672. /* Create newline blob */
  673. newline_blob = calloc(1, sizeof(struct blob));
  674. newline_blob->Text = "\n";
  675. newline_blob->Expression = "\n";
  676. newline_blob->type = NEWLINE;
  677. AddHash(newline_blob, "\n");
  678. /* Start the blob list with DEFINE and newline */
  679. blob_list = calloc(1, sizeof(struct blob));
  680. blob_list->Text = "DEFINE";
  681. define_blob = blob_list;
  682. blob_list->next = newline_blob;
  683. AddHash(define_blob, "DEFINE");
  684. /* Initialize scratch */
  685. SCRATCH = calloc(max_string + 1, sizeof(char));
  686. int option_index = 1;
  687. while(option_index <= argc)
  688. {
  689. if(NULL == argv[option_index])
  690. {
  691. option_index = option_index + 1;
  692. }
  693. else if(match(argv[option_index], "--BigEndian") || match(argv[option_index], "--big-endian"))
  694. {
  695. BigEndian = TRUE;
  696. option_index = option_index + 1;
  697. }
  698. else if(match(argv[option_index], "--LittleEndian") || match(argv[option_index], "--little-endian"))
  699. {
  700. BigEndian = FALSE;
  701. option_index = option_index + 1;
  702. }
  703. else if(match(argv[option_index], "-A") || match(argv[option_index], "--architecture"))
  704. {
  705. arch = argv[option_index + 1];
  706. if(match("knight-native", arch) || match("knight-posix", arch)) Architecture = KNIGHT;
  707. else if(match("x86", arch)) Architecture = X86;
  708. else if(match("amd64", arch)) Architecture = AMD64;
  709. else if(match("armv7l", arch)) Architecture = ARMV7L;
  710. else if(match("aarch64", arch)) Architecture = AARM64;
  711. else
  712. {
  713. file_print("Unknown architecture: ", stderr);
  714. file_print(arch, stderr);
  715. file_print(" know values are: knight-native, knight-posix, x86, amd64, armv7l and aarch64", stderr);
  716. exit(EXIT_FAILURE);
  717. }
  718. option_index = option_index + 2;
  719. }
  720. else if(match(argv[option_index], "-b") || match(argv[option_index], "--binary"))
  721. {
  722. ByteMode = BINARY;
  723. option_index = option_index + 1;
  724. }
  725. else if(match(argv[option_index], "-h") || match(argv[option_index], "--help"))
  726. {
  727. file_print("Usage: ", stderr);
  728. file_print(argv[0], stderr);
  729. file_print(" --file FILENAME1 {-f FILENAME2} (--big-endian|--little-endian) ", stderr);
  730. file_print("[--architecture name]\nArchitectures: knight-native, knight-posix, x86, amd64 and armv7\n", stderr);
  731. file_print("To leverage octal or binary output: --octal, --binary\n", stderr);
  732. exit(EXIT_SUCCESS);
  733. }
  734. else if(match(argv[option_index], "-f") || match(argv[option_index], "--file"))
  735. {
  736. filename = argv[option_index + 1];
  737. source_file = fopen(filename, "r");
  738. if(NULL == source_file)
  739. {
  740. file_print("The file: ", stderr);
  741. file_print(argv[option_index + 1], stderr);
  742. file_print(" can not be opened!\n", stderr);
  743. exit(EXIT_FAILURE);
  744. }
  745. token_list = Tokenize_Line(token_list, filename);
  746. fclose(source_file);
  747. option_index = option_index + 2;
  748. }
  749. else if(match(argv[option_index], "-o") || match(argv[option_index], "--output"))
  750. {
  751. destination_file = fopen(argv[option_index + 1], "w");
  752. if(NULL == destination_file)
  753. {
  754. file_print("The file: ", stderr);
  755. file_print(argv[option_index + 1], stderr);
  756. file_print(" can not be opened!\n", stderr);
  757. exit(EXIT_FAILURE);
  758. }
  759. option_index = option_index + 2;
  760. }
  761. else if(match(argv[option_index], "-O") || match(argv[option_index], "--octal"))
  762. {
  763. ByteMode = OCTAL;
  764. option_index = option_index + 1;
  765. }
  766. else if(match(argv[option_index], "-V") || match(argv[option_index], "--version"))
  767. {
  768. file_print("M1 1.0.0\n", stdout);
  769. exit(EXIT_SUCCESS);
  770. }
  771. else
  772. {
  773. file_print("Unknown option\n", stderr);
  774. exit(EXIT_FAILURE);
  775. }
  776. }
  777. if(NULL == token_list)
  778. {
  779. file_print("Either no input files were given or they were empty\n", stderr);
  780. exit(EXIT_FAILURE);
  781. }
  782. token_list = reverse_list(token_list);
  783. line_macro(token_list);
  784. process_string(blob_list);
  785. eval_immediates(blob_list);
  786. preserve_other(blob_list);
  787. print_hex(token_list);
  788. if (destination_file != stdout)
  789. {
  790. fclose(destination_file);
  791. }
  792. return EXIT_SUCCESS;
  793. }