M1-macro.c 19 KB

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