macros.pl 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. #!/usr/bin/perl
  2. ## --------------------------------------------------------------------------
  3. ##
  4. ## Copyright 1996-2009 The NASM Authors - All Rights Reserved
  5. ## See the file AUTHORS included with the NASM distribution for
  6. ## the specific copyright holders.
  7. ##
  8. ## Redistribution and use in source and binary forms, with or without
  9. ## modification, are permitted provided that the following
  10. ## conditions are met:
  11. ##
  12. ## * Redistributions of source code must retain the above copyright
  13. ## notice, this list of conditions and the following disclaimer.
  14. ## * Redistributions in binary form must reproduce the above
  15. ## copyright notice, this list of conditions and the following
  16. ## disclaimer in the documentation and/or other materials provided
  17. ## with the distribution.
  18. ##
  19. ## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
  20. ## CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
  21. ## INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  22. ## MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  23. ## DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  24. ## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  25. ## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  26. ## NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  27. ## LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28. ## HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  29. ## CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  30. ## OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
  31. ## EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  32. ##
  33. ## --------------------------------------------------------------------------
  34. #
  35. # macros.pl produce macros.c from standard.mac
  36. #
  37. require 'phash.ph';
  38. require 'asm/pptok.ph';
  39. use bytes;
  40. my $fname;
  41. my $line = 0;
  42. my $index = 0;
  43. my $tasm_count = 0;
  44. #
  45. # Print out a string as a character array
  46. #
  47. sub charcify(@) {
  48. my $l = '';
  49. my $c, $o;
  50. my $space = 1;
  51. my $quote = 0;
  52. foreach $o (unpack("C*", join('',@_))) {
  53. $c = pack("C", $o);
  54. if ($quote) {
  55. if ($o == $quote) {
  56. $quote = 0;
  57. }
  58. } elsif ($c =~ /^[\'\"\`]$/) {
  59. $quote = $o;
  60. } else {
  61. if ($c =~ /\s/) {
  62. next if ($space);
  63. $o = 32;
  64. $c = ' ';
  65. $space = 1;
  66. } elsif ($o > 126) {
  67. $space = 1; # Implicit space after compacted directive
  68. } else {
  69. $space = 0;
  70. }
  71. }
  72. if ($o < 32 || $o > 126 || $c eq '"' || $c eq "\\") {
  73. $l .= sprintf("%3d,", $o);
  74. } else {
  75. $c =~ s/\'/\\'/; # << sanitize single quote.
  76. $l .= "\'".$c."\',";
  77. }
  78. }
  79. return $l;
  80. }
  81. #
  82. # Generate macros.c
  83. #
  84. open(OUT, '>', 'macros/macros.c') or die "unable to open macros.c\n";
  85. print OUT "/*\n";
  86. print OUT " * Do not edit - this file auto-generated by macros.pl from:\n";
  87. print OUT " * ", join("\n * ", @ARGV), "\n";
  88. print OUT " */\n";
  89. print OUT "\n";
  90. print OUT "#include \"tables.h\"\n";
  91. print OUT "#include \"nasmlib.h\"\n";
  92. print OUT "#include \"hashtbl.h\"\n";
  93. print OUT "#include \"outform.h\"\n";
  94. print OUT "\n";
  95. my $name = undef;
  96. my $npkg = 0;
  97. my @pkg_list = ();
  98. my %pkg_number = ();
  99. my $pkg;
  100. my @out_list = ();
  101. my $outfmt;
  102. my $lastname;
  103. my $z;
  104. foreach $args ( @ARGV ) {
  105. my @file_list = glob ( $args );
  106. foreach $fname ( @file_list ) {
  107. open(INPUT,'<', $fname) or die "$0: $fname: $!\n";
  108. while (<INPUT>) {
  109. $line++;
  110. chomp;
  111. while (/^(.*)\\$/) {
  112. $_ = $1;
  113. $_ .= <INPUT>;
  114. chomp;
  115. $line++;
  116. }
  117. if (m/^OUT:\s*(.*\S)\s*$/) {
  118. undef $pkg;
  119. my @out_alias = split(/\s+/, $1);
  120. if (defined($name)) {
  121. printf OUT " /* %4d */ 0\n", $index++;
  122. print OUT "};\n#endif\n";
  123. undef $name;
  124. }
  125. $index = 0;
  126. print OUT "\n";
  127. my $pfx = '#if';
  128. foreach my $al (@out_alias) {
  129. print OUT $pfx, " defined(OF_\U${al}\E)";
  130. $pfx = ' ||';
  131. }
  132. $name = $out_alias[0] . '_stdmac';
  133. print OUT "\nconst unsigned char ${name}[] = {\n";
  134. print OUT " /* From $fname */\n";
  135. $lastname = $fname;
  136. push(@out_list, $out_alias[0]);
  137. $out_index{$out_alias[0]} = $index;
  138. } elsif (m/^STD:\s*(.*\S)\s*$/) {
  139. undef $pkg;
  140. my @out_alias = split(/\s+/, $1);
  141. if (defined($name)) {
  142. printf OUT " /* %4d */ 0\n", $index++;
  143. print OUT "};\n#endif\n";
  144. undef $name;
  145. }
  146. $index = 0;
  147. print OUT "\n#if 1";
  148. $name = 'nasm_stdmac_' . $out_alias[0];
  149. print OUT "\nconst unsigned char ${name}[] = {\n";
  150. print OUT " /* From $fname */\n";
  151. $lastname = $fname;
  152. push(@std_list, $out_alias[0]);
  153. $std_index{$std_alias[0]} = $index;
  154. } elsif (m/^USE:\s*(\S+)\s*$/) {
  155. $pkg = $1;
  156. if (defined($pkg_number{$pkg})) {
  157. die "$0: $fname: duplicate package: $pkg\n";
  158. }
  159. if (defined($name)) {
  160. printf OUT " /* %4d */ 0\n", $index++;
  161. print OUT "};\n#endif\n";
  162. undef $name;
  163. }
  164. $index = 0;
  165. print OUT "\n#if 1";
  166. $name = 'nasm_usemac_' . $pkg;
  167. print OUT "\nstatic const unsigned char ${name}[] = {\n";
  168. print OUT " /* From $fname */\n";
  169. $lastname = $fname;
  170. push(@pkg_list, $pkg);
  171. $pkg_number{$pkg} = $npkg++;
  172. $z = pack("C", $pptok_hash{'%define'}+128)."__USE_\U$pkg\E__";
  173. printf OUT " /* %4d */ %s0,\n", $index, charcify($z);
  174. $index += length($z)+1;
  175. } elsif (m/^\s*((\s*([^\"\';\s]+|\"[^\"]*\"|\'[^\']*\'))*)\s*(;.*)?$/) {
  176. my $s1, $s2, $pd, $ws;
  177. if (!defined($name)) {
  178. die "$0: $fname: macro declarations outside a known block\n";
  179. }
  180. $s1 = $1;
  181. $s2 = '';
  182. while ($s1 =~ /(\%[a-zA-Z_][a-zA-Z0-9_]*)((\s+)(.*)|)$/) {
  183. $s2 .= "$'";
  184. $pd = $1;
  185. $ws = $3;
  186. $s1 = $4;
  187. if (defined($pptok_hash{$pd}) &&
  188. $pptok_hash{$pd} <= 127) {
  189. $s2 .= pack("C", $pptok_hash{$pd}+128);
  190. } else {
  191. $s2 .= $pd.$ws;
  192. }
  193. }
  194. $s2 .= $s1;
  195. if (length($s2) > 0) {
  196. if ($lastname ne $fname) {
  197. print OUT "\n /* From $fname */\n";
  198. $lastname = $fname;
  199. }
  200. printf OUT " /* %4d */ %s0,\n",
  201. $index, charcify($s2);
  202. $index += length($s2)+1;
  203. }
  204. } else {
  205. die "$fname:$line: error unterminated quote";
  206. }
  207. }
  208. close(INPUT);
  209. }
  210. }
  211. if (defined($name)) {
  212. printf OUT " /* %4d */ 0\n", $index++;
  213. print OUT "};\n#endif\n";
  214. undef $name;
  215. }
  216. my @hashinfo = gen_perfect_hash(\%pkg_number);
  217. if (!@hashinfo) {
  218. die "$0: no hash found\n";
  219. }
  220. # Paranoia...
  221. verify_hash_table(\%pkg_number, \@hashinfo);
  222. my ($n, $sv, $g) = @hashinfo;
  223. die if ($n & ($n-1));
  224. print OUT "const unsigned char *nasm_stdmac_find_package(const char *package)\n";
  225. print OUT "{\n";
  226. print OUT " static const struct {\n";
  227. print OUT " const char *package;\n";
  228. print OUT " const unsigned char *macros;\n";
  229. print OUT " } packages[$npkg] = {\n";
  230. foreach $pkg (@pkg_list) {
  231. printf OUT " { \"%s\", nasm_usemac_%s },\n",
  232. $pkg, $pkg;
  233. }
  234. print OUT " };\n";
  235. # Put a large value in unused slots. This makes it extremely unlikely
  236. # that any combination that involves unused slot will pass the range test.
  237. # This speeds up rejection of unrecognized tokens, i.e. identifiers.
  238. print OUT "#define UNUSED (65535/3)\n";
  239. print OUT " static const int16_t hash1[$n] = {\n";
  240. for ($i = 0; $i < $n; $i++) {
  241. my $h = ${$g}[$i*2+0];
  242. print OUT " ", defined($h) ? $h : 'UNUSED', ",\n";
  243. }
  244. print OUT " };\n";
  245. print OUT " static const int16_t hash2[$n] = {\n";
  246. for ($i = 0; $i < $n; $i++) {
  247. my $h = ${$g}[$i*2+1];
  248. print OUT " ", defined($h) ? $h : 'UNUSED', ",\n";
  249. }
  250. print OUT " };\n";
  251. print OUT " uint32_t k1, k2;\n";
  252. print OUT " uint64_t crc;\n";
  253. # For correct overflow behavior, "ix" should be unsigned of the same
  254. # width as the hash arrays.
  255. print OUT " uint16_t ix;\n";
  256. print OUT "\n";
  257. printf OUT " crc = crc64i(UINT64_C(0x%08x%08x), package);\n",
  258. $$sv[0], $$sv[1];
  259. print OUT " k1 = (uint32_t)crc;\n";
  260. print OUT " k2 = (uint32_t)(crc >> 32);\n";
  261. print OUT "\n";
  262. printf OUT " ix = hash1[k1 & 0x%x] + hash2[k2 & 0x%x];\n", $n-1, $n-1;
  263. printf OUT " if (ix >= %d)\n", scalar(@pkg_list);
  264. print OUT " return NULL;\n";
  265. print OUT "\n";
  266. print OUT " if (nasm_stricmp(packages[ix].package, package))\n";
  267. print OUT " return NULL;\n";
  268. print OUT "\n";
  269. print OUT " return packages[ix].macros;\n";
  270. print OUT "}\n";
  271. close(OUT);