M1-macro.c 18 KB

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