M1-macro.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926
  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. /* knight just needs a couple extra nulls to make string detection easier */
  334. if((KNIGHT == Architecture) && (HEX == ByteMode))
  335. {
  336. i = (((((i - 1) >> 2) + 1) << 3) + i);
  337. while( 0 < i)
  338. {
  339. i = i - 1;
  340. d[i] = '0';
  341. }
  342. }
  343. if(HEX == ByteMode)
  344. {
  345. while(0 != S[0])
  346. {
  347. S = S + 1;
  348. d[0] = table[S[0] >> 4];
  349. d[1] = table[S[0] & 0xF];
  350. d[2] = ' ';
  351. d = d + 3;
  352. }
  353. }
  354. else if(OCTAL == ByteMode)
  355. {
  356. while(0 != S[0])
  357. {
  358. S = S + 1;
  359. d[0] = table[S[0] >> 6];
  360. d[1] = table[(S[0] >> 3) & 0x7];
  361. d[2] = table[S[0] & 0x7];
  362. d[3] = ' ';
  363. d = d + 4;
  364. }
  365. }
  366. else if(BINARY == ByteMode)
  367. {
  368. while(0 != S[0])
  369. {
  370. S = S + 1;
  371. d[0] = table[S[0] >> 7];
  372. d[1] = table[(S[0] >> 6) & 0x1];
  373. d[2] = table[(S[0] >> 5) & 0x1];
  374. d[3] = table[(S[0] >> 4) & 0x1];
  375. d[4] = table[(S[0] >> 3) & 0x1];
  376. d[5] = table[(S[0] >> 2) & 0x1];
  377. d[6] = table[(S[0] >> 1) & 0x1];
  378. d[7] = table[S[0] & 0x1];
  379. d[8] = ' ';
  380. d = d + 9;
  381. }
  382. }
  383. }
  384. void process_string(struct blob* p)
  385. {
  386. struct blob* i;
  387. for(i = p; NULL != i; i = i->next)
  388. {
  389. if(STR == i->type)
  390. {
  391. if('\'' == i->Text[0])
  392. {
  393. i->Expression = i->Text + 1;
  394. }
  395. else if('"' == i->Text[0])
  396. {
  397. hexify_string(i);
  398. }
  399. }
  400. }
  401. }
  402. char* pad_nulls(int size, char* nil)
  403. {
  404. if(0 == size) return nil;
  405. require(size > 0, "negative null padding not possible\n");
  406. if(HEX == ByteMode) size = size * 2;
  407. else if (OCTAL == ByteMode) size = size * 3;
  408. else if (BINARY == ByteMode) size = size * 8;
  409. char* s = calloc(size + 1, sizeof(char));
  410. require(NULL != s, "Exhausted available memory\n");
  411. int i = 0;
  412. while(i < size)
  413. {
  414. s[i] = '0';
  415. i = i + 1;
  416. }
  417. return s;
  418. }
  419. void preserve_other(struct blob* p)
  420. {
  421. struct blob* i;
  422. char c;
  423. for(i = p; NULL != i; i = i->next)
  424. {
  425. if(NULL == i->Expression)
  426. {
  427. c = i->Text[0];
  428. if(in_set(c, "!@$~%&:^"))
  429. {
  430. i->Expression = i->Text;
  431. }
  432. else if('<' == c)
  433. {
  434. i->Expression = pad_nulls(strtoint(i->Text + 1), i->Text);
  435. }
  436. }
  437. }
  438. }
  439. void bound_values(int displacement, int number_of_bytes, int low, int high)
  440. {
  441. if((high < displacement) || (displacement < low))
  442. {
  443. fputs("A displacement of ", stderr);
  444. fputs(int2str(displacement, 10, TRUE), stderr);
  445. fputs(" does not fit in ", stderr);
  446. fputs(int2str(number_of_bytes, 10, TRUE), stderr);
  447. fputs(" bytes\n", stderr);
  448. exit(EXIT_FAILURE);
  449. }
  450. }
  451. void range_check(int displacement, int number_of_bytes, int absolute)
  452. {
  453. if(4 == number_of_bytes) return;
  454. else if(absolute && (3 == number_of_bytes))
  455. {
  456. bound_values(displacement, number_of_bytes, -8388609, 16777217);
  457. return;
  458. }
  459. else if(3 == number_of_bytes)
  460. {
  461. bound_values(displacement, number_of_bytes, -8388609, 8388608);
  462. return;
  463. }
  464. else if(absolute && (2 == number_of_bytes))
  465. {
  466. bound_values(displacement, number_of_bytes, -32769, 65536);
  467. return;
  468. }
  469. else if(2 == number_of_bytes)
  470. {
  471. bound_values(displacement, number_of_bytes, -32769, 32768);
  472. return;
  473. }
  474. else if(absolute && (1 == number_of_bytes))
  475. {
  476. bound_values(displacement, number_of_bytes, -1, 256);
  477. return;
  478. }
  479. else if(1 == number_of_bytes)
  480. { /* work around current only signed bytes */
  481. bound_values(displacement, number_of_bytes, -129, 256);
  482. return;
  483. }
  484. fputs("Received an invalid number of bytes in range_check\n", stderr);
  485. exit(EXIT_FAILURE);
  486. }
  487. char* express_number(int value, char c)
  488. {
  489. char* ch = calloc(42, sizeof(char));
  490. require(NULL != ch, "Exhausted available memory\n");
  491. int size;
  492. int number_of_bytes;
  493. int shift;
  494. int absolute = FALSE;
  495. if('!' == c) number_of_bytes = 1;
  496. else if('@' == c) number_of_bytes = 2;
  497. else if('$' == c)
  498. {
  499. number_of_bytes = 2;
  500. absolute = TRUE;
  501. }
  502. else if('~' == c) number_of_bytes = 3;
  503. else if('%' == c) number_of_bytes = 4;
  504. else if('&' == c)
  505. {
  506. number_of_bytes = 4;
  507. absolute = TRUE;
  508. }
  509. else
  510. {
  511. fputs("Given symbol ", stderr);
  512. fputc(c, stderr);
  513. fputs(" to express immediate value ", stderr);
  514. fputs(int2str(value, 10, TRUE), stderr);
  515. fputc('\n', stderr);
  516. exit(EXIT_FAILURE);
  517. }
  518. range_check(value, number_of_bytes, absolute);
  519. /* don't truncate prior to range check for -1 behavior */
  520. if('!' == c) value = value & 0xFF;
  521. else if(('@' == c) || ('$' == c)) value = value & 0xFFFF;
  522. else if('~' == c) value = value & 0xFFFFFF;
  523. else if(('%' == c) || ('&' == c)) value = value & 0xFFFFFFFF;
  524. if(HEX == ByteMode)
  525. {
  526. size = number_of_bytes * 2;
  527. shift = 4;
  528. }
  529. else if(OCTAL == ByteMode)
  530. {
  531. size = number_of_bytes * 3;
  532. shift = 3;
  533. }
  534. else if(BINARY == ByteMode)
  535. {
  536. size = number_of_bytes * 8;
  537. shift = 1;
  538. }
  539. else
  540. {
  541. fputs("Got invalid ByteMode in express_number\n", stderr);
  542. exit(EXIT_FAILURE);
  543. }
  544. stringify(ch, size, ByteMode, value, shift);
  545. if(!BigEndian) LittleEndian(ch, ByteMode);
  546. return ch;
  547. }
  548. char* express_word(int value, char c)
  549. {
  550. char* s = calloc(43, sizeof(char));
  551. s[0] = '.';
  552. char* ch = s + 1;
  553. require(NULL != ch, "Exhausted available memory\n");
  554. int size;
  555. int shift;
  556. int immediate;
  557. if('!' == c)
  558. {
  559. /* Corresponds to RISC-V I format */
  560. immediate = (value & 0xFFF) << 20;
  561. }
  562. else if('@' == c)
  563. {
  564. /* Corresponds to RISC-V S format */
  565. immediate = ((value & 0x1F) << 7) | ((value & 0xFE0) << (31 - 11));
  566. }
  567. else if('~' == c)
  568. {
  569. /* Corresponds with RISC-V U format */
  570. if ((value & 0xFFF) < 0x800)
  571. {
  572. immediate = value & 0xFFFFF000;
  573. }
  574. else
  575. {
  576. immediate = (value & 0xFFFFF000) + 0x1000;
  577. }
  578. }
  579. else if('%' == c)
  580. {
  581. /* provides an option for 32bit immediate constants */
  582. immediate = value & 0xFFFFFFFF;
  583. /* Drop the leading . */
  584. ch = s;
  585. }
  586. else
  587. {
  588. fputs("Given symbol ", stderr);
  589. fputc(c, stderr);
  590. fputs(" to express immediate value ", stderr);
  591. fputs(int2str(value, 10, TRUE), stderr);
  592. fputc('\n', stderr);
  593. exit(EXIT_FAILURE);
  594. }
  595. if(HEX == ByteMode)
  596. {
  597. size = 4 * 2;
  598. shift = 4;
  599. }
  600. else if(OCTAL == ByteMode)
  601. {
  602. size = 4 * 3;
  603. shift = 3;
  604. }
  605. else if(BINARY == ByteMode)
  606. {
  607. size = 4 * 8;
  608. shift = 1;
  609. }
  610. else
  611. {
  612. fputs("Got invalid ByteMode in express_number\n", stderr);
  613. exit(EXIT_FAILURE);
  614. }
  615. stringify(ch, size, ByteMode, immediate, shift);
  616. if(!BigEndian) LittleEndian(ch, ByteMode);
  617. return s;
  618. }
  619. void eval_immediates(struct blob* p)
  620. {
  621. struct blob* i;
  622. int value;
  623. for(i = p; NULL != i; i = i->next)
  624. {
  625. if(NEWLINE == i->type) continue;
  626. else if('<' == i->Text[0]) continue;
  627. else if(NULL == i->Expression)
  628. {
  629. if((X86 == Architecture) ||
  630. (AMD64 == Architecture) ||
  631. (ARMV7L == Architecture) ||
  632. (AARM64 == Architecture) ||
  633. (PPC64LE == Architecture) ||
  634. (KNIGHT == Architecture))
  635. {
  636. if(in_set(i->Text[0], "%~@!&$"))
  637. {
  638. value = strtoint(i->Text + 1);
  639. if(('0' == i->Text[1]) || (0 != value))
  640. {
  641. i->Expression = express_number(value, i->Text[0]);
  642. }
  643. }
  644. else if(KNIGHT == Architecture)
  645. {
  646. value = strtoint(i->Text);
  647. if(('0' == i->Text[0]) || (0 != value))
  648. {
  649. if(value > 65536) continue;
  650. else if(value > 32767) i->Expression = express_number(value, '$');
  651. else i->Expression = express_number(value, '@');
  652. }
  653. }
  654. }
  655. else if((RISCV32 == Architecture) || (RISCV64 == Architecture))
  656. {
  657. if(in_set(i->Text[0], "%~@!"))
  658. {
  659. value = strtoint(i->Text + 1);
  660. if(('0' == i->Text[1]) || (0 != value))
  661. {
  662. i->Expression = express_word(value, i->Text[0]);
  663. }
  664. }
  665. }
  666. else
  667. {
  668. fputs("Unknown architecture received in eval_immediates\n", stderr);
  669. exit(EXIT_FAILURE);
  670. }
  671. }
  672. }
  673. }
  674. void print_hex(struct Token* p)
  675. {
  676. struct Token* i;
  677. for(i = p; NULL != i; i = i->next)
  678. {
  679. if(NEWLINE == i->contents->type)
  680. {
  681. if(NULL == i->next) fputc('\n', destination_file);
  682. else if(NEWLINE != i->next->contents->type) fputc('\n', destination_file);
  683. }
  684. else if(NULL != i->contents->Expression)
  685. {
  686. fputs(i->contents->Expression, destination_file);
  687. if(NEWLINE != i->next->contents->type) fputc(' ', destination_file);
  688. }
  689. else
  690. {
  691. line_error(i->filename, i->linenumber);
  692. fputs("Received invalid other; ", stderr);
  693. fputs(i->contents->Text, stderr);
  694. fputs("\n", stderr);
  695. exit(EXIT_FAILURE);
  696. }
  697. }
  698. }
  699. /* Standard C main program */
  700. int main(int argc, char **argv)
  701. {
  702. /* If they don't specify the target architecture, assume knight */
  703. BigEndian = TRUE;
  704. Architecture = KNIGHT;
  705. destination_file = stdout;
  706. ByteMode = HEX;
  707. char* filename;
  708. char* arch;
  709. blob_count = 2;
  710. hash_table = calloc(65537, sizeof(struct blob*));
  711. require(NULL != hash_table, "failed to allocate hash_table\n");
  712. /* Create newline blob */
  713. newline_blob = calloc(1, sizeof(struct blob));
  714. require(NULL != newline_blob, "failed to allocate newline_blob\n");
  715. newline_blob->Text = "\n";
  716. newline_blob->Expression = "\n";
  717. newline_blob->type = NEWLINE;
  718. AddHash(newline_blob, "\n");
  719. /* Start the blob list with DEFINE and newline */
  720. blob_list = calloc(1, sizeof(struct blob));
  721. require(NULL != blob_list, "failed to allocate DEFINE blob\n");
  722. blob_list->Text = "DEFINE";
  723. define_blob = blob_list;
  724. blob_list->next = newline_blob;
  725. AddHash(define_blob, "DEFINE");
  726. /* Initialize scratch */
  727. SCRATCH = calloc(max_string + 1, sizeof(char));
  728. require(NULL != SCRATCH, "failed to allocate SCRATCH buffer");
  729. int option_index = 1;
  730. while(option_index <= argc)
  731. {
  732. if(NULL == argv[option_index])
  733. {
  734. option_index = option_index + 1;
  735. }
  736. else if(match(argv[option_index], "--big-endian"))
  737. {
  738. BigEndian = TRUE;
  739. option_index = option_index + 1;
  740. }
  741. else if(match(argv[option_index], "--little-endian"))
  742. {
  743. BigEndian = FALSE;
  744. option_index = option_index + 1;
  745. }
  746. else if(match(argv[option_index], "-A") || match(argv[option_index], "--architecture"))
  747. {
  748. arch = argv[option_index + 1];
  749. if(match("knight-native", arch) || match("knight-posix", arch)) Architecture = KNIGHT;
  750. else if(match("x86", arch)) Architecture = X86;
  751. else if(match("amd64", arch)) Architecture = AMD64;
  752. else if(match("armv7l", arch)) Architecture = ARMV7L;
  753. else if(match("aarch64", arch)) Architecture = AARM64;
  754. else if(match("ppc64le", arch)) Architecture = PPC64LE;
  755. else if(match("riscv32", arch)) Architecture = RISCV32;
  756. else if(match("riscv64", arch)) Architecture = RISCV64;
  757. else
  758. {
  759. fputs("Unknown architecture: ", stderr);
  760. fputs(arch, stderr);
  761. fputs(" know values are: knight-native, knight-posix, x86, amd64, armv7l, aarch64, ppc64le, riscv32 and riscv64", stderr);
  762. exit(EXIT_FAILURE);
  763. }
  764. option_index = option_index + 2;
  765. }
  766. else if(match(argv[option_index], "-b") || match(argv[option_index], "--binary"))
  767. {
  768. ByteMode = BINARY;
  769. option_index = option_index + 1;
  770. }
  771. else if(match(argv[option_index], "-h") || match(argv[option_index], "--help"))
  772. {
  773. fputs("Usage: ", stderr);
  774. fputs(argv[0], stderr);
  775. fputs(" --file FILENAME1 {-f FILENAME2} (--big-endian|--little-endian) ", stderr);
  776. fputs("[--architecture name]\nArchitectures: knight-native, knight-posix, x86, amd64, armv7, riscv32 and riscv64\n", stderr);
  777. fputs("To leverage octal or binary output: --octal, --binary\n", stderr);
  778. exit(EXIT_SUCCESS);
  779. }
  780. else if(match(argv[option_index], "-f") || match(argv[option_index], "--file"))
  781. {
  782. filename = argv[option_index + 1];
  783. source_file = fopen(filename, "r");
  784. if(NULL == source_file)
  785. {
  786. fputs("The file: ", stderr);
  787. fputs(argv[option_index + 1], stderr);
  788. fputs(" can not be opened!\n", stderr);
  789. exit(EXIT_FAILURE);
  790. }
  791. token_list = Tokenize_Line(token_list, filename);
  792. fclose(source_file);
  793. option_index = option_index + 2;
  794. }
  795. else if(match(argv[option_index], "-o") || match(argv[option_index], "--output"))
  796. {
  797. destination_file = fopen(argv[option_index + 1], "w");
  798. if(NULL == destination_file)
  799. {
  800. fputs("The file: ", stderr);
  801. fputs(argv[option_index + 1], stderr);
  802. fputs(" can not be opened!\n", stderr);
  803. exit(EXIT_FAILURE);
  804. }
  805. option_index = option_index + 2;
  806. }
  807. else if(match(argv[option_index], "-O") || match(argv[option_index], "--octal"))
  808. {
  809. ByteMode = OCTAL;
  810. option_index = option_index + 1;
  811. }
  812. else if(match(argv[option_index], "-V") || match(argv[option_index], "--version"))
  813. {
  814. fputs("M1 1.5.0\n", stdout);
  815. exit(EXIT_SUCCESS);
  816. }
  817. else
  818. {
  819. fputs("Unknown option\n", stderr);
  820. exit(EXIT_FAILURE);
  821. }
  822. }
  823. if(NULL == token_list)
  824. {
  825. fputs("Either no input files were given or they were empty\n", stderr);
  826. exit(EXIT_FAILURE);
  827. }
  828. token_list = reverse_list(token_list);
  829. line_macro(token_list);
  830. process_string(blob_list);
  831. eval_immediates(blob_list);
  832. preserve_other(blob_list);
  833. print_hex(token_list);
  834. fclose(destination_file);
  835. return EXIT_SUCCESS;
  836. }