this repo has no description
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Import Rez source code from Retro68

Source repository: https://github.com/autc04/Retro68
Commit: 3992bf904a93d66a1feefa6c89af221a3430457e

+4617
+85
src/buildtools/Rez/CMakeLists.txt
··· 1 + # Copyright 2012 Wolfgang Thaller. 2 + # 3 + # This file is part of Retro68. 4 + # 5 + # Retro68 is free software: you can redistribute it and/or modify 6 + # it under the terms of the GNU General Public License as published by 7 + # the Free Software Foundation, either version 3 of the License, or 8 + # (at your option) any later version. 9 + # 10 + # Retro68 is distributed in the hope that it will be useful, 11 + # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 + # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 + # GNU General Public License for more details. 14 + # 15 + # You should have received a copy of the GNU General Public License 16 + # along with Retro68. If not, see <http://www.gnu.org/licenses/>. 17 + 18 + find_package(Boost COMPONENTS wave filesystem system thread regex program_options) 19 + 20 + # Look for bison. 21 + # We need Version 3, and Mac OS X still comes with an outdated version (2.3). 22 + # So we just add the path where the homebrew package manager installs its 23 + # "keg-only" version. Shouldn't hurt on Linux. 24 + set(CMAKE_PROGRAM_PATH ${CMAKE_PROGRAM_PATH} "/usr/local/opt/bison/bin") 25 + find_package(BISON 3.0.2) 26 + 27 + if(NOT Boost_FOUND) 28 + message(FATAL_ERROR "The boost libraries have not been found.") 29 + endif() 30 + 31 + if(NOT BISON_FOUND) 32 + message(FATAL_ERROR "GNU Bison version 3.0.2 or later is required.") 33 + endif() 34 + 35 + include_directories(. ${CMAKE_CURRENT_BINARY_DIR}) 36 + 37 + set(BISON_OUTPUTS ${CMAKE_CURRENT_BINARY_DIR}/RezParser.generated.cc ${CMAKE_CURRENT_BINARY_DIR}/RezParser.generated.hh 38 + ${CMAKE_CURRENT_BINARY_DIR}/location.hh ${CMAKE_CURRENT_BINARY_DIR}/position.hh 39 + ${CMAKE_CURRENT_BINARY_DIR}/stack.hh) 40 + 41 + add_custom_command(OUTPUT ${BISON_OUTPUTS} 42 + COMMAND ${BISON_EXECUTABLE} 43 + ARGS -o ${CMAKE_CURRENT_BINARY_DIR}/RezParser.generated.cc RezParser.yy 44 + DEPENDS RezParser.yy 45 + COMMENT "[BISON][RezParser] Building parser with bison ${BISON_VERSION}" 46 + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) 47 + 48 + 49 + add_library(RezLib 50 + RezParser.yy 51 + ${BISON_OUTPUTS} 52 + 53 + RezLexer.h 54 + RezLexer.cc 55 + RezLexerWaveToken.h 56 + RezLexerNextToken.cc 57 + 58 + RezWorld.cc 59 + RezWorld.h 60 + 61 + ResourceDefinitions.cc 62 + ResourceDefinitions.h 63 + 64 + Expression.cc 65 + Expression.h 66 + 67 + ResourceCompiler.cc 68 + ResourceCompiler.h 69 + 70 + ResSpec.h 71 + 72 + Diagnostic.h Diagnostic.cc 73 + ) 74 + target_link_libraries(RezLib ResourceFiles ${Boost_LIBRARIES}) 75 + target_include_directories(RezLib PRIVATE ${Boost_INCLUDE_DIR}) 76 + 77 + add_executable(Rez 78 + Rez.cc 79 + ) 80 + target_link_libraries(Rez RezLib ResourceFiles ${Boost_LIBRARIES}) 81 + target_include_directories(Rez PRIVATE ${Boost_INCLUDE_DIR}) 82 + 83 + install(TARGETS Rez RUNTIME DESTINATION bin) 84 + 85 + add_subdirectory(Test)
+674
src/buildtools/Rez/COPYING
··· 1 + GNU GENERAL PUBLIC LICENSE 2 + Version 3, 29 June 2007 3 + 4 + Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> 5 + Everyone is permitted to copy and distribute verbatim copies 6 + of this license document, but changing it is not allowed. 7 + 8 + Preamble 9 + 10 + The GNU General Public License is a free, copyleft license for 11 + software and other kinds of works. 12 + 13 + The licenses for most software and other practical works are designed 14 + to take away your freedom to share and change the works. By contrast, 15 + the GNU General Public License is intended to guarantee your freedom to 16 + share and change all versions of a program--to make sure it remains free 17 + software for all its users. We, the Free Software Foundation, use the 18 + GNU General Public License for most of our software; it applies also to 19 + any other work released this way by its authors. You can apply it to 20 + your programs, too. 21 + 22 + When we speak of free software, we are referring to freedom, not 23 + price. Our General Public Licenses are designed to make sure that you 24 + have the freedom to distribute copies of free software (and charge for 25 + them if you wish), that you receive source code or can get it if you 26 + want it, that you can change the software or use pieces of it in new 27 + free programs, and that you know you can do these things. 28 + 29 + To protect your rights, we need to prevent others from denying you 30 + these rights or asking you to surrender the rights. Therefore, you have 31 + certain responsibilities if you distribute copies of the software, or if 32 + you modify it: responsibilities to respect the freedom of others. 33 + 34 + For example, if you distribute copies of such a program, whether 35 + gratis or for a fee, you must pass on to the recipients the same 36 + freedoms that you received. You must make sure that they, too, receive 37 + or can get the source code. And you must show them these terms so they 38 + know their rights. 39 + 40 + Developers that use the GNU GPL protect your rights with two steps: 41 + (1) assert copyright on the software, and (2) offer you this License 42 + giving you legal permission to copy, distribute and/or modify it. 43 + 44 + For the developers' and authors' protection, the GPL clearly explains 45 + that there is no warranty for this free software. For both users' and 46 + authors' sake, the GPL requires that modified versions be marked as 47 + changed, so that their problems will not be attributed erroneously to 48 + authors of previous versions. 49 + 50 + Some devices are designed to deny users access to install or run 51 + modified versions of the software inside them, although the manufacturer 52 + can do so. This is fundamentally incompatible with the aim of 53 + protecting users' freedom to change the software. The systematic 54 + pattern of such abuse occurs in the area of products for individuals to 55 + use, which is precisely where it is most unacceptable. Therefore, we 56 + have designed this version of the GPL to prohibit the practice for those 57 + products. If such problems arise substantially in other domains, we 58 + stand ready to extend this provision to those domains in future versions 59 + of the GPL, as needed to protect the freedom of users. 60 + 61 + Finally, every program is threatened constantly by software patents. 62 + States should not allow patents to restrict development and use of 63 + software on general-purpose computers, but in those that do, we wish to 64 + avoid the special danger that patents applied to a free program could 65 + make it effectively proprietary. To prevent this, the GPL assures that 66 + patents cannot be used to render the program non-free. 67 + 68 + The precise terms and conditions for copying, distribution and 69 + modification follow. 70 + 71 + TERMS AND CONDITIONS 72 + 73 + 0. Definitions. 74 + 75 + "This License" refers to version 3 of the GNU General Public License. 76 + 77 + "Copyright" also means copyright-like laws that apply to other kinds of 78 + works, such as semiconductor masks. 79 + 80 + "The Program" refers to any copyrightable work licensed under this 81 + License. Each licensee is addressed as "you". "Licensees" and 82 + "recipients" may be individuals or organizations. 83 + 84 + To "modify" a work means to copy from or adapt all or part of the work 85 + in a fashion requiring copyright permission, other than the making of an 86 + exact copy. The resulting work is called a "modified version" of the 87 + earlier work or a work "based on" the earlier work. 88 + 89 + A "covered work" means either the unmodified Program or a work based 90 + on the Program. 91 + 92 + To "propagate" a work means to do anything with it that, without 93 + permission, would make you directly or secondarily liable for 94 + infringement under applicable copyright law, except executing it on a 95 + computer or modifying a private copy. Propagation includes copying, 96 + distribution (with or without modification), making available to the 97 + public, and in some countries other activities as well. 98 + 99 + To "convey" a work means any kind of propagation that enables other 100 + parties to make or receive copies. Mere interaction with a user through 101 + a computer network, with no transfer of a copy, is not conveying. 102 + 103 + An interactive user interface displays "Appropriate Legal Notices" 104 + to the extent that it includes a convenient and prominently visible 105 + feature that (1) displays an appropriate copyright notice, and (2) 106 + tells the user that there is no warranty for the work (except to the 107 + extent that warranties are provided), that licensees may convey the 108 + work under this License, and how to view a copy of this License. If 109 + the interface presents a list of user commands or options, such as a 110 + menu, a prominent item in the list meets this criterion. 111 + 112 + 1. Source Code. 113 + 114 + The "source code" for a work means the preferred form of the work 115 + for making modifications to it. "Object code" means any non-source 116 + form of a work. 117 + 118 + A "Standard Interface" means an interface that either is an official 119 + standard defined by a recognized standards body, or, in the case of 120 + interfaces specified for a particular programming language, one that 121 + is widely used among developers working in that language. 122 + 123 + The "System Libraries" of an executable work include anything, other 124 + than the work as a whole, that (a) is included in the normal form of 125 + packaging a Major Component, but which is not part of that Major 126 + Component, and (b) serves only to enable use of the work with that 127 + Major Component, or to implement a Standard Interface for which an 128 + implementation is available to the public in source code form. A 129 + "Major Component", in this context, means a major essential component 130 + (kernel, window system, and so on) of the specific operating system 131 + (if any) on which the executable work runs, or a compiler used to 132 + produce the work, or an object code interpreter used to run it. 133 + 134 + The "Corresponding Source" for a work in object code form means all 135 + the source code needed to generate, install, and (for an executable 136 + work) run the object code and to modify the work, including scripts to 137 + control those activities. However, it does not include the work's 138 + System Libraries, or general-purpose tools or generally available free 139 + programs which are used unmodified in performing those activities but 140 + which are not part of the work. For example, Corresponding Source 141 + includes interface definition files associated with source files for 142 + the work, and the source code for shared libraries and dynamically 143 + linked subprograms that the work is specifically designed to require, 144 + such as by intimate data communication or control flow between those 145 + subprograms and other parts of the work. 146 + 147 + The Corresponding Source need not include anything that users 148 + can regenerate automatically from other parts of the Corresponding 149 + Source. 150 + 151 + The Corresponding Source for a work in source code form is that 152 + same work. 153 + 154 + 2. Basic Permissions. 155 + 156 + All rights granted under this License are granted for the term of 157 + copyright on the Program, and are irrevocable provided the stated 158 + conditions are met. This License explicitly affirms your unlimited 159 + permission to run the unmodified Program. The output from running a 160 + covered work is covered by this License only if the output, given its 161 + content, constitutes a covered work. This License acknowledges your 162 + rights of fair use or other equivalent, as provided by copyright law. 163 + 164 + You may make, run and propagate covered works that you do not 165 + convey, without conditions so long as your license otherwise remains 166 + in force. You may convey covered works to others for the sole purpose 167 + of having them make modifications exclusively for you, or provide you 168 + with facilities for running those works, provided that you comply with 169 + the terms of this License in conveying all material for which you do 170 + not control copyright. Those thus making or running the covered works 171 + for you must do so exclusively on your behalf, under your direction 172 + and control, on terms that prohibit them from making any copies of 173 + your copyrighted material outside their relationship with you. 174 + 175 + Conveying under any other circumstances is permitted solely under 176 + the conditions stated below. Sublicensing is not allowed; section 10 177 + makes it unnecessary. 178 + 179 + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 + 181 + No covered work shall be deemed part of an effective technological 182 + measure under any applicable law fulfilling obligations under article 183 + 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 + similar laws prohibiting or restricting circumvention of such 185 + measures. 186 + 187 + When you convey a covered work, you waive any legal power to forbid 188 + circumvention of technological measures to the extent such circumvention 189 + is effected by exercising rights under this License with respect to 190 + the covered work, and you disclaim any intention to limit operation or 191 + modification of the work as a means of enforcing, against the work's 192 + users, your or third parties' legal rights to forbid circumvention of 193 + technological measures. 194 + 195 + 4. Conveying Verbatim Copies. 196 + 197 + You may convey verbatim copies of the Program's source code as you 198 + receive it, in any medium, provided that you conspicuously and 199 + appropriately publish on each copy an appropriate copyright notice; 200 + keep intact all notices stating that this License and any 201 + non-permissive terms added in accord with section 7 apply to the code; 202 + keep intact all notices of the absence of any warranty; and give all 203 + recipients a copy of this License along with the Program. 204 + 205 + You may charge any price or no price for each copy that you convey, 206 + and you may offer support or warranty protection for a fee. 207 + 208 + 5. Conveying Modified Source Versions. 209 + 210 + You may convey a work based on the Program, or the modifications to 211 + produce it from the Program, in the form of source code under the 212 + terms of section 4, provided that you also meet all of these conditions: 213 + 214 + a) The work must carry prominent notices stating that you modified 215 + it, and giving a relevant date. 216 + 217 + b) The work must carry prominent notices stating that it is 218 + released under this License and any conditions added under section 219 + 7. This requirement modifies the requirement in section 4 to 220 + "keep intact all notices". 221 + 222 + c) You must license the entire work, as a whole, under this 223 + License to anyone who comes into possession of a copy. This 224 + License will therefore apply, along with any applicable section 7 225 + additional terms, to the whole of the work, and all its parts, 226 + regardless of how they are packaged. This License gives no 227 + permission to license the work in any other way, but it does not 228 + invalidate such permission if you have separately received it. 229 + 230 + d) If the work has interactive user interfaces, each must display 231 + Appropriate Legal Notices; however, if the Program has interactive 232 + interfaces that do not display Appropriate Legal Notices, your 233 + work need not make them do so. 234 + 235 + A compilation of a covered work with other separate and independent 236 + works, which are not by their nature extensions of the covered work, 237 + and which are not combined with it such as to form a larger program, 238 + in or on a volume of a storage or distribution medium, is called an 239 + "aggregate" if the compilation and its resulting copyright are not 240 + used to limit the access or legal rights of the compilation's users 241 + beyond what the individual works permit. Inclusion of a covered work 242 + in an aggregate does not cause this License to apply to the other 243 + parts of the aggregate. 244 + 245 + 6. Conveying Non-Source Forms. 246 + 247 + You may convey a covered work in object code form under the terms 248 + of sections 4 and 5, provided that you also convey the 249 + machine-readable Corresponding Source under the terms of this License, 250 + in one of these ways: 251 + 252 + a) Convey the object code in, or embodied in, a physical product 253 + (including a physical distribution medium), accompanied by the 254 + Corresponding Source fixed on a durable physical medium 255 + customarily used for software interchange. 256 + 257 + b) Convey the object code in, or embodied in, a physical product 258 + (including a physical distribution medium), accompanied by a 259 + written offer, valid for at least three years and valid for as 260 + long as you offer spare parts or customer support for that product 261 + model, to give anyone who possesses the object code either (1) a 262 + copy of the Corresponding Source for all the software in the 263 + product that is covered by this License, on a durable physical 264 + medium customarily used for software interchange, for a price no 265 + more than your reasonable cost of physically performing this 266 + conveying of source, or (2) access to copy the 267 + Corresponding Source from a network server at no charge. 268 + 269 + c) Convey individual copies of the object code with a copy of the 270 + written offer to provide the Corresponding Source. This 271 + alternative is allowed only occasionally and noncommercially, and 272 + only if you received the object code with such an offer, in accord 273 + with subsection 6b. 274 + 275 + d) Convey the object code by offering access from a designated 276 + place (gratis or for a charge), and offer equivalent access to the 277 + Corresponding Source in the same way through the same place at no 278 + further charge. You need not require recipients to copy the 279 + Corresponding Source along with the object code. If the place to 280 + copy the object code is a network server, the Corresponding Source 281 + may be on a different server (operated by you or a third party) 282 + that supports equivalent copying facilities, provided you maintain 283 + clear directions next to the object code saying where to find the 284 + Corresponding Source. Regardless of what server hosts the 285 + Corresponding Source, you remain obligated to ensure that it is 286 + available for as long as needed to satisfy these requirements. 287 + 288 + e) Convey the object code using peer-to-peer transmission, provided 289 + you inform other peers where the object code and Corresponding 290 + Source of the work are being offered to the general public at no 291 + charge under subsection 6d. 292 + 293 + A separable portion of the object code, whose source code is excluded 294 + from the Corresponding Source as a System Library, need not be 295 + included in conveying the object code work. 296 + 297 + A "User Product" is either (1) a "consumer product", which means any 298 + tangible personal property which is normally used for personal, family, 299 + or household purposes, or (2) anything designed or sold for incorporation 300 + into a dwelling. In determining whether a product is a consumer product, 301 + doubtful cases shall be resolved in favor of coverage. For a particular 302 + product received by a particular user, "normally used" refers to a 303 + typical or common use of that class of product, regardless of the status 304 + of the particular user or of the way in which the particular user 305 + actually uses, or expects or is expected to use, the product. A product 306 + is a consumer product regardless of whether the product has substantial 307 + commercial, industrial or non-consumer uses, unless such uses represent 308 + the only significant mode of use of the product. 309 + 310 + "Installation Information" for a User Product means any methods, 311 + procedures, authorization keys, or other information required to install 312 + and execute modified versions of a covered work in that User Product from 313 + a modified version of its Corresponding Source. The information must 314 + suffice to ensure that the continued functioning of the modified object 315 + code is in no case prevented or interfered with solely because 316 + modification has been made. 317 + 318 + If you convey an object code work under this section in, or with, or 319 + specifically for use in, a User Product, and the conveying occurs as 320 + part of a transaction in which the right of possession and use of the 321 + User Product is transferred to the recipient in perpetuity or for a 322 + fixed term (regardless of how the transaction is characterized), the 323 + Corresponding Source conveyed under this section must be accompanied 324 + by the Installation Information. But this requirement does not apply 325 + if neither you nor any third party retains the ability to install 326 + modified object code on the User Product (for example, the work has 327 + been installed in ROM). 328 + 329 + The requirement to provide Installation Information does not include a 330 + requirement to continue to provide support service, warranty, or updates 331 + for a work that has been modified or installed by the recipient, or for 332 + the User Product in which it has been modified or installed. Access to a 333 + network may be denied when the modification itself materially and 334 + adversely affects the operation of the network or violates the rules and 335 + protocols for communication across the network. 336 + 337 + Corresponding Source conveyed, and Installation Information provided, 338 + in accord with this section must be in a format that is publicly 339 + documented (and with an implementation available to the public in 340 + source code form), and must require no special password or key for 341 + unpacking, reading or copying. 342 + 343 + 7. Additional Terms. 344 + 345 + "Additional permissions" are terms that supplement the terms of this 346 + License by making exceptions from one or more of its conditions. 347 + Additional permissions that are applicable to the entire Program shall 348 + be treated as though they were included in this License, to the extent 349 + that they are valid under applicable law. If additional permissions 350 + apply only to part of the Program, that part may be used separately 351 + under those permissions, but the entire Program remains governed by 352 + this License without regard to the additional permissions. 353 + 354 + When you convey a copy of a covered work, you may at your option 355 + remove any additional permissions from that copy, or from any part of 356 + it. (Additional permissions may be written to require their own 357 + removal in certain cases when you modify the work.) You may place 358 + additional permissions on material, added by you to a covered work, 359 + for which you have or can give appropriate copyright permission. 360 + 361 + Notwithstanding any other provision of this License, for material you 362 + add to a covered work, you may (if authorized by the copyright holders of 363 + that material) supplement the terms of this License with terms: 364 + 365 + a) Disclaiming warranty or limiting liability differently from the 366 + terms of sections 15 and 16 of this License; or 367 + 368 + b) Requiring preservation of specified reasonable legal notices or 369 + author attributions in that material or in the Appropriate Legal 370 + Notices displayed by works containing it; or 371 + 372 + c) Prohibiting misrepresentation of the origin of that material, or 373 + requiring that modified versions of such material be marked in 374 + reasonable ways as different from the original version; or 375 + 376 + d) Limiting the use for publicity purposes of names of licensors or 377 + authors of the material; or 378 + 379 + e) Declining to grant rights under trademark law for use of some 380 + trade names, trademarks, or service marks; or 381 + 382 + f) Requiring indemnification of licensors and authors of that 383 + material by anyone who conveys the material (or modified versions of 384 + it) with contractual assumptions of liability to the recipient, for 385 + any liability that these contractual assumptions directly impose on 386 + those licensors and authors. 387 + 388 + All other non-permissive additional terms are considered "further 389 + restrictions" within the meaning of section 10. If the Program as you 390 + received it, or any part of it, contains a notice stating that it is 391 + governed by this License along with a term that is a further 392 + restriction, you may remove that term. If a license document contains 393 + a further restriction but permits relicensing or conveying under this 394 + License, you may add to a covered work material governed by the terms 395 + of that license document, provided that the further restriction does 396 + not survive such relicensing or conveying. 397 + 398 + If you add terms to a covered work in accord with this section, you 399 + must place, in the relevant source files, a statement of the 400 + additional terms that apply to those files, or a notice indicating 401 + where to find the applicable terms. 402 + 403 + Additional terms, permissive or non-permissive, may be stated in the 404 + form of a separately written license, or stated as exceptions; 405 + the above requirements apply either way. 406 + 407 + 8. Termination. 408 + 409 + You may not propagate or modify a covered work except as expressly 410 + provided under this License. Any attempt otherwise to propagate or 411 + modify it is void, and will automatically terminate your rights under 412 + this License (including any patent licenses granted under the third 413 + paragraph of section 11). 414 + 415 + However, if you cease all violation of this License, then your 416 + license from a particular copyright holder is reinstated (a) 417 + provisionally, unless and until the copyright holder explicitly and 418 + finally terminates your license, and (b) permanently, if the copyright 419 + holder fails to notify you of the violation by some reasonable means 420 + prior to 60 days after the cessation. 421 + 422 + Moreover, your license from a particular copyright holder is 423 + reinstated permanently if the copyright holder notifies you of the 424 + violation by some reasonable means, this is the first time you have 425 + received notice of violation of this License (for any work) from that 426 + copyright holder, and you cure the violation prior to 30 days after 427 + your receipt of the notice. 428 + 429 + Termination of your rights under this section does not terminate the 430 + licenses of parties who have received copies or rights from you under 431 + this License. If your rights have been terminated and not permanently 432 + reinstated, you do not qualify to receive new licenses for the same 433 + material under section 10. 434 + 435 + 9. Acceptance Not Required for Having Copies. 436 + 437 + You are not required to accept this License in order to receive or 438 + run a copy of the Program. Ancillary propagation of a covered work 439 + occurring solely as a consequence of using peer-to-peer transmission 440 + to receive a copy likewise does not require acceptance. However, 441 + nothing other than this License grants you permission to propagate or 442 + modify any covered work. These actions infringe copyright if you do 443 + not accept this License. Therefore, by modifying or propagating a 444 + covered work, you indicate your acceptance of this License to do so. 445 + 446 + 10. Automatic Licensing of Downstream Recipients. 447 + 448 + Each time you convey a covered work, the recipient automatically 449 + receives a license from the original licensors, to run, modify and 450 + propagate that work, subject to this License. You are not responsible 451 + for enforcing compliance by third parties with this License. 452 + 453 + An "entity transaction" is a transaction transferring control of an 454 + organization, or substantially all assets of one, or subdividing an 455 + organization, or merging organizations. If propagation of a covered 456 + work results from an entity transaction, each party to that 457 + transaction who receives a copy of the work also receives whatever 458 + licenses to the work the party's predecessor in interest had or could 459 + give under the previous paragraph, plus a right to possession of the 460 + Corresponding Source of the work from the predecessor in interest, if 461 + the predecessor has it or can get it with reasonable efforts. 462 + 463 + You may not impose any further restrictions on the exercise of the 464 + rights granted or affirmed under this License. For example, you may 465 + not impose a license fee, royalty, or other charge for exercise of 466 + rights granted under this License, and you may not initiate litigation 467 + (including a cross-claim or counterclaim in a lawsuit) alleging that 468 + any patent claim is infringed by making, using, selling, offering for 469 + sale, or importing the Program or any portion of it. 470 + 471 + 11. Patents. 472 + 473 + A "contributor" is a copyright holder who authorizes use under this 474 + License of the Program or a work on which the Program is based. The 475 + work thus licensed is called the contributor's "contributor version". 476 + 477 + A contributor's "essential patent claims" are all patent claims 478 + owned or controlled by the contributor, whether already acquired or 479 + hereafter acquired, that would be infringed by some manner, permitted 480 + by this License, of making, using, or selling its contributor version, 481 + but do not include claims that would be infringed only as a 482 + consequence of further modification of the contributor version. For 483 + purposes of this definition, "control" includes the right to grant 484 + patent sublicenses in a manner consistent with the requirements of 485 + this License. 486 + 487 + Each contributor grants you a non-exclusive, worldwide, royalty-free 488 + patent license under the contributor's essential patent claims, to 489 + make, use, sell, offer for sale, import and otherwise run, modify and 490 + propagate the contents of its contributor version. 491 + 492 + In the following three paragraphs, a "patent license" is any express 493 + agreement or commitment, however denominated, not to enforce a patent 494 + (such as an express permission to practice a patent or covenant not to 495 + sue for patent infringement). To "grant" such a patent license to a 496 + party means to make such an agreement or commitment not to enforce a 497 + patent against the party. 498 + 499 + If you convey a covered work, knowingly relying on a patent license, 500 + and the Corresponding Source of the work is not available for anyone 501 + to copy, free of charge and under the terms of this License, through a 502 + publicly available network server or other readily accessible means, 503 + then you must either (1) cause the Corresponding Source to be so 504 + available, or (2) arrange to deprive yourself of the benefit of the 505 + patent license for this particular work, or (3) arrange, in a manner 506 + consistent with the requirements of this License, to extend the patent 507 + license to downstream recipients. "Knowingly relying" means you have 508 + actual knowledge that, but for the patent license, your conveying the 509 + covered work in a country, or your recipient's use of the covered work 510 + in a country, would infringe one or more identifiable patents in that 511 + country that you have reason to believe are valid. 512 + 513 + If, pursuant to or in connection with a single transaction or 514 + arrangement, you convey, or propagate by procuring conveyance of, a 515 + covered work, and grant a patent license to some of the parties 516 + receiving the covered work authorizing them to use, propagate, modify 517 + or convey a specific copy of the covered work, then the patent license 518 + you grant is automatically extended to all recipients of the covered 519 + work and works based on it. 520 + 521 + A patent license is "discriminatory" if it does not include within 522 + the scope of its coverage, prohibits the exercise of, or is 523 + conditioned on the non-exercise of one or more of the rights that are 524 + specifically granted under this License. You may not convey a covered 525 + work if you are a party to an arrangement with a third party that is 526 + in the business of distributing software, under which you make payment 527 + to the third party based on the extent of your activity of conveying 528 + the work, and under which the third party grants, to any of the 529 + parties who would receive the covered work from you, a discriminatory 530 + patent license (a) in connection with copies of the covered work 531 + conveyed by you (or copies made from those copies), or (b) primarily 532 + for and in connection with specific products or compilations that 533 + contain the covered work, unless you entered into that arrangement, 534 + or that patent license was granted, prior to 28 March 2007. 535 + 536 + Nothing in this License shall be construed as excluding or limiting 537 + any implied license or other defenses to infringement that may 538 + otherwise be available to you under applicable patent law. 539 + 540 + 12. No Surrender of Others' Freedom. 541 + 542 + If conditions are imposed on you (whether by court order, agreement or 543 + otherwise) that contradict the conditions of this License, they do not 544 + excuse you from the conditions of this License. If you cannot convey a 545 + covered work so as to satisfy simultaneously your obligations under this 546 + License and any other pertinent obligations, then as a consequence you may 547 + not convey it at all. For example, if you agree to terms that obligate you 548 + to collect a royalty for further conveying from those to whom you convey 549 + the Program, the only way you could satisfy both those terms and this 550 + License would be to refrain entirely from conveying the Program. 551 + 552 + 13. Use with the GNU Affero General Public License. 553 + 554 + Notwithstanding any other provision of this License, you have 555 + permission to link or combine any covered work with a work licensed 556 + under version 3 of the GNU Affero General Public License into a single 557 + combined work, and to convey the resulting work. The terms of this 558 + License will continue to apply to the part which is the covered work, 559 + but the special requirements of the GNU Affero General Public License, 560 + section 13, concerning interaction through a network will apply to the 561 + combination as such. 562 + 563 + 14. Revised Versions of this License. 564 + 565 + The Free Software Foundation may publish revised and/or new versions of 566 + the GNU General Public License from time to time. Such new versions will 567 + be similar in spirit to the present version, but may differ in detail to 568 + address new problems or concerns. 569 + 570 + Each version is given a distinguishing version number. If the 571 + Program specifies that a certain numbered version of the GNU General 572 + Public License "or any later version" applies to it, you have the 573 + option of following the terms and conditions either of that numbered 574 + version or of any later version published by the Free Software 575 + Foundation. If the Program does not specify a version number of the 576 + GNU General Public License, you may choose any version ever published 577 + by the Free Software Foundation. 578 + 579 + If the Program specifies that a proxy can decide which future 580 + versions of the GNU General Public License can be used, that proxy's 581 + public statement of acceptance of a version permanently authorizes you 582 + to choose that version for the Program. 583 + 584 + Later license versions may give you additional or different 585 + permissions. However, no additional obligations are imposed on any 586 + author or copyright holder as a result of your choosing to follow a 587 + later version. 588 + 589 + 15. Disclaimer of Warranty. 590 + 591 + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 + APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 + HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 + OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 + THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 + PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 + IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 + ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 + 600 + 16. Limitation of Liability. 601 + 602 + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 + WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 + THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 + GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 + USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 + DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 + PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 + EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 + SUCH DAMAGES. 611 + 612 + 17. Interpretation of Sections 15 and 16. 613 + 614 + If the disclaimer of warranty and limitation of liability provided 615 + above cannot be given local legal effect according to their terms, 616 + reviewing courts shall apply local law that most closely approximates 617 + an absolute waiver of all civil liability in connection with the 618 + Program, unless a warranty or assumption of liability accompanies a 619 + copy of the Program in return for a fee. 620 + 621 + END OF TERMS AND CONDITIONS 622 + 623 + How to Apply These Terms to Your New Programs 624 + 625 + If you develop a new program, and you want it to be of the greatest 626 + possible use to the public, the best way to achieve this is to make it 627 + free software which everyone can redistribute and change under these terms. 628 + 629 + To do so, attach the following notices to the program. It is safest 630 + to attach them to the start of each source file to most effectively 631 + state the exclusion of warranty; and each file should have at least 632 + the "copyright" line and a pointer to where the full notice is found. 633 + 634 + <one line to give the program's name and a brief idea of what it does.> 635 + Copyright (C) <year> <name of author> 636 + 637 + This program is free software: you can redistribute it and/or modify 638 + it under the terms of the GNU General Public License as published by 639 + the Free Software Foundation, either version 3 of the License, or 640 + (at your option) any later version. 641 + 642 + This program is distributed in the hope that it will be useful, 643 + but WITHOUT ANY WARRANTY; without even the implied warranty of 644 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 + GNU General Public License for more details. 646 + 647 + You should have received a copy of the GNU General Public License 648 + along with this program. If not, see <http://www.gnu.org/licenses/>. 649 + 650 + Also add information on how to contact you by electronic and paper mail. 651 + 652 + If the program does terminal interaction, make it output a short 653 + notice like this when it starts in an interactive mode: 654 + 655 + <program> Copyright (C) <year> <name of author> 656 + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 + This is free software, and you are welcome to redistribute it 658 + under certain conditions; type `show c' for details. 659 + 660 + The hypothetical commands `show w' and `show c' should show the appropriate 661 + parts of the General Public License. Of course, your program's commands 662 + might be different; for a GUI interface, you would use an "about box". 663 + 664 + You should also get your employer (if you work as a programmer) or school, 665 + if any, to sign a "copyright disclaimer" for the program, if necessary. 666 + For more information on this, and how to apply and follow the GNU GPL, see 667 + <http://www.gnu.org/licenses/>. 668 + 669 + The GNU General Public License does not permit incorporating your program 670 + into proprietary programs. If your program is a subroutine library, you 671 + may consider it more useful to permit linking proprietary applications with 672 + the library. If this is what you want to do, use the GNU Lesser General 673 + Public License instead of this License. But first, please read 674 + <http://www.gnu.org/philosophy/why-not-lgpl.html>.
+28
src/buildtools/Rez/Diagnostic.cc
··· 1 + #include "Diagnostic.h" 2 + 3 + Diagnostic::Diagnostic() 4 + { 5 + } 6 + 7 + Diagnostic::Diagnostic(Severity sev, std::string msg, yy::location loc) 8 + : severity(sev), message(msg), location(loc) 9 + { 10 + 11 + } 12 + 13 + 14 + std::ostream &operator<<(std::ostream &out, const Diagnostic &d) 15 + { 16 + //return out << d.location << ": " << d.message; 17 + const yy::location& loc = d.location; 18 + if (loc.begin.filename) 19 + out << *loc.begin.filename << ':'; 20 + out << loc.begin.line << ':' << loc.begin.column; 21 + out << ": "; 22 + if(d.severity >= Diagnostic::error) 23 + out << "error"; 24 + else 25 + out << "warning"; 26 + out << ": " << d.message; 27 + return out; 28 + }
+31
src/buildtools/Rez/Diagnostic.h
··· 1 + #ifndef DIAGNOSTIC_H 2 + #define DIAGNOSTIC_H 3 + 4 + #include <string> 5 + #include <iosfwd> 6 + #include "location.hh" 7 + 8 + class Diagnostic 9 + { 10 + public: 11 + enum Severity 12 + { 13 + warning, 14 + error, 15 + fatalError 16 + }; 17 + 18 + Diagnostic(); 19 + Diagnostic(Severity sev, std::string msg, yy::location loc); 20 + 21 + private: 22 + Severity severity; 23 + std::string message; 24 + yy::location location; 25 + 26 + friend std::ostream& operator<<(std::ostream&, const Diagnostic&); 27 + }; 28 + 29 + std::ostream& operator<<(std::ostream&, const Diagnostic&); 30 + 31 + #endif // DIAGNOSTIC_H
+233
src/buildtools/Rez/Expression.cc
··· 1 + #include "Expression.h" 2 + #include "ResourceCompiler.h" 3 + #include <cassert> 4 + #include <iostream> 5 + #include <fstream> 6 + #include "Diagnostic.h" 7 + 8 + int Expression::evaluateInt(ResourceCompiler *ctx) 9 + { 10 + error(ctx, "Expected an integer or integer expression here."); 11 + return 0; 12 + } 13 + 14 + std::string Expression::evaluateString(ResourceCompiler *ctx) 15 + { 16 + error(ctx, "Expected a string or string expression here."); 17 + return ""; 18 + } 19 + 20 + Expression::~Expression() 21 + { 22 + } 23 + 24 + void Expression::error(ResourceCompiler *ctx, std::string err) 25 + { 26 + ctx->problem(Diagnostic(Diagnostic::Severity::error, err, location)); 27 + } 28 + 29 + 30 + StringExpr::~StringExpr() 31 + { 32 + } 33 + 34 + std::string StringExpr::evaluateString(ResourceCompiler *ctx) 35 + { 36 + return str; 37 + } 38 + 39 + 40 + IntExpr::~IntExpr() 41 + { 42 + } 43 + 44 + int IntExpr::evaluateInt(ResourceCompiler *ctx) 45 + { 46 + return val; 47 + } 48 + 49 + 50 + void CompoundExpr::addItem(ExprPtr item) 51 + { 52 + items.push_back(item); 53 + } 54 + 55 + CompoundExpr::~CompoundExpr() 56 + { 57 + } 58 + 59 + 60 + BinaryExpr::~BinaryExpr() 61 + { 62 + } 63 + 64 + int BinaryExpr::evaluateInt(ResourceCompiler *ctx) 65 + { 66 + switch(op) 67 + { 68 + case BinaryOp::XOR: 69 + return a->evaluateInt(ctx) ^ b->evaluateInt(ctx); 70 + case BinaryOp::OR: 71 + return a->evaluateInt(ctx) | b->evaluateInt(ctx); 72 + case BinaryOp::AND: 73 + return a->evaluateInt(ctx) & b->evaluateInt(ctx); 74 + case BinaryOp::SHIFTLEFT: 75 + return a->evaluateInt(ctx) << b->evaluateInt(ctx); 76 + case BinaryOp::SHIFTRIGHT: 77 + return a->evaluateInt(ctx) >> b->evaluateInt(ctx); 78 + case BinaryOp::EQUAL: 79 + return a->evaluateInt(ctx) == b->evaluateInt(ctx); 80 + case BinaryOp::NOTEQUAL: 81 + return a->evaluateInt(ctx) != b->evaluateInt(ctx); 82 + case BinaryOp::PLUS: 83 + return a->evaluateInt(ctx) + b->evaluateInt(ctx); 84 + case BinaryOp::MINUS: 85 + return a->evaluateInt(ctx) - b->evaluateInt(ctx); 86 + case BinaryOp::MULTIPLY: 87 + return a->evaluateInt(ctx) * b->evaluateInt(ctx); 88 + case BinaryOp::DIVIDE: 89 + return a->evaluateInt(ctx) / b->evaluateInt(ctx); 90 + default: 91 + error(ctx, "Expected an integer or integer expression here."); 92 + return 0; 93 + } 94 + } 95 + 96 + std::string BinaryExpr::evaluateString(ResourceCompiler *ctx) 97 + { 98 + switch(op) 99 + { 100 + case BinaryOp::CONCAT: 101 + return a->evaluateString(ctx) + b->evaluateString(ctx); 102 + default: 103 + error(ctx, "Expected a string or string expression here."); 104 + return ""; 105 + } 106 + } 107 + 108 + 109 + UnaryExpr::~UnaryExpr() 110 + { 111 + } 112 + 113 + int UnaryExpr::evaluateInt(ResourceCompiler *ctx) 114 + { 115 + switch(op) 116 + { 117 + case UnaryOp::MINUS: 118 + return -a->evaluateInt(ctx); 119 + case UnaryOp::COMPLEMENT: 120 + return ~a->evaluateInt(ctx); 121 + default: 122 + error(ctx, "Expected an integer or integer expression here."); 123 + return 0; 124 + } 125 + } 126 + 127 + 128 + IdentifierExpr::IdentifierExpr(std::string id, yy::location loc) 129 + : Expression(loc), id(id) 130 + { 131 + } 132 + 133 + void IdentifierExpr::addArgument(ExprPtr e) 134 + { 135 + arguments.push_back(e); 136 + } 137 + 138 + ExprPtr IdentifierExpr::lookup(ResourceCompiler *ctx) 139 + { 140 + Subscripts sub; 141 + for(auto arg : arguments) 142 + sub.addSubscript(arg->evaluateInt(ctx)); 143 + ExprPtr val = ctx->lookupIdentifier(id, sub); 144 + if(!val) 145 + error(ctx, "Identifier \"" + id + "\" is not defined."); 146 + return val; 147 + } 148 + 149 + int IdentifierExpr::evaluateInt(ResourceCompiler *ctx) 150 + { 151 + if(ctx->isPrePass()) 152 + return 0; 153 + if(ExprPtr e = lookup(ctx)) 154 + return e->evaluateInt(ctx); 155 + else 156 + return 0; 157 + } 158 + 159 + std::string IdentifierExpr::evaluateString(ResourceCompiler *ctx) 160 + { 161 + if(ExprPtr e = lookup(ctx)) 162 + return e->evaluateString(ctx); 163 + else 164 + return ""; 165 + } 166 + 167 + 168 + CaseExpr::CaseExpr(const std::string &tag, CompoundExprPtr expr, yy::location loc) 169 + : Expression(loc), tag(tag), expr(expr) 170 + { 171 + } 172 + 173 + 174 + int CountOfExpr::evaluateInt(ResourceCompiler *ctx) 175 + { 176 + assert(arg->arguments.size() == 0); 177 + return ctx->getArrayCount(arg->id); 178 + } 179 + 180 + 181 + int ArrayIndexExpr::evaluateInt(ResourceCompiler *ctx) 182 + { 183 + assert(arg->arguments.size() == 0); 184 + return ctx->getArrayIndex(arg->id); 185 + } 186 + 187 + 188 + std::string ReadExpr::evaluateString(ResourceCompiler *ctx) 189 + { 190 + std::string filename = arg->evaluateString(ctx); 191 + std::ifstream instream(filename); 192 + if(!instream) 193 + { 194 + ctx->problem(Diagnostic(Diagnostic::Severity::error, "could not $$read file " + filename, location)); 195 + } 196 + return std::string(std::istreambuf_iterator<char>(instream.rdbuf()), 197 + std::istreambuf_iterator<char>()); 198 + } 199 + 200 + 201 + int UnimplementedExpr::evaluateInt(ResourceCompiler *ctx) 202 + { 203 + std::cerr << msg << std::endl; 204 + return 0; 205 + } 206 + 207 + std::string UnimplementedExpr::evaluateString(ResourceCompiler *ctx) 208 + { 209 + std::cerr << msg << std::endl; 210 + return ""; 211 + } 212 + 213 + 214 + PeekExpr::PeekExpr(ExprPtr addr, ExprPtr offset, ExprPtr size, yy::location loc) 215 + : Expression(loc), addr(addr), offset(offset), size(size) 216 + { 217 + } 218 + 219 + PeekExpr::PeekExpr(ExprPtr addr, int size, yy::location loc) 220 + : Expression(loc), 221 + addr(addr), 222 + offset(std::make_shared<IntExpr>(0,loc)), 223 + size(std::make_shared<IntExpr>(size,loc)) 224 + { 225 + } 226 + 227 + int PeekExpr::evaluateInt(ResourceCompiler *ctx) 228 + { 229 + int p = addr->evaluateInt(ctx) + offset->evaluateInt(ctx); 230 + int s = size->evaluateInt(ctx); 231 + 232 + return ctx->peek(p, s); 233 + }
+172
src/buildtools/Rez/Expression.h
··· 1 + #ifndef EXPRESSION_H 2 + #define EXPRESSION_H 3 + 4 + #include <memory> 5 + #include <vector> 6 + 7 + #include "location.hh" 8 + 9 + class ResourceCompiler; 10 + 11 + class Expression; 12 + class CompoundExpr; 13 + class IdentifierExpr; 14 + class CaseExpr; 15 + typedef std::shared_ptr<Expression> ExprPtr; 16 + typedef std::shared_ptr<CompoundExpr> CompoundExprPtr; 17 + typedef std::shared_ptr<IdentifierExpr> IdentifierExprPtr; 18 + typedef std::shared_ptr<CaseExpr> CaseExprPtr; 19 + 20 + 21 + enum class BinaryOp 22 + { 23 + XOR, OR, AND, SHIFTLEFT, SHIFTRIGHT, EQUAL, NOTEQUAL, PLUS, MINUS, MULTIPLY, DIVIDE, CONCAT 24 + }; 25 + 26 + enum class UnaryOp 27 + { 28 + MINUS, COMPLEMENT 29 + }; 30 + 31 + class TypeError 32 + { 33 + }; 34 + 35 + class Expression 36 + { 37 + public: 38 + yy::location location; 39 + 40 + Expression(yy::location loc) : location(loc) {} 41 + 42 + virtual int evaluateInt(ResourceCompiler *ctx); 43 + virtual std::string evaluateString(ResourceCompiler *ctx); 44 + virtual ~Expression(); 45 + 46 + void error(ResourceCompiler *ctx, std::string err); 47 + }; 48 + 49 + class StringExpr : public Expression 50 + { 51 + std::string str; 52 + public: 53 + StringExpr(const std::string& str, yy::location loc) : Expression(loc), str(str) {} 54 + ~StringExpr(); 55 + virtual std::string evaluateString(ResourceCompiler *ctx); 56 + }; 57 + 58 + class IntExpr : public Expression 59 + { 60 + int val; 61 + public: 62 + IntExpr(int val, yy::location loc) : Expression(loc), val(val) {} 63 + ~IntExpr(); 64 + 65 + virtual int evaluateInt(ResourceCompiler *ctx); 66 + }; 67 + 68 + class CompoundExpr : public Expression 69 + { 70 + std::vector<ExprPtr> items; 71 + public: 72 + CompoundExpr(yy::location loc) : Expression(loc) {} 73 + 74 + void addItem(ExprPtr item); 75 + ExprPtr getItem(int i) const { return items[i]; } 76 + int size() const { return items.size(); } 77 + 78 + ~CompoundExpr(); 79 + }; 80 + 81 + class CaseExpr : public Expression 82 + { 83 + std::string tag; 84 + CompoundExprPtr expr; 85 + friend class SwitchField; 86 + public: 87 + CaseExpr(const std::string& tag, CompoundExprPtr expr, yy::location loc); 88 + }; 89 + 90 + class BinaryExpr : public Expression 91 + { 92 + BinaryOp op; 93 + ExprPtr a, b; 94 + public: 95 + BinaryExpr(BinaryOp op, ExprPtr a, ExprPtr b, yy::location loc) 96 + : Expression(loc), op(op), a(a), b(b) {} 97 + ~BinaryExpr(); 98 + 99 + virtual int evaluateInt(ResourceCompiler *ctx); 100 + virtual std::string evaluateString(ResourceCompiler *ctx); 101 + }; 102 + 103 + class UnaryExpr : public Expression 104 + { 105 + UnaryOp op; 106 + ExprPtr a; 107 + public: 108 + UnaryExpr(UnaryOp op, ExprPtr a, yy::location loc) 109 + : Expression(loc), op(op), a(a) {} 110 + ~UnaryExpr(); 111 + 112 + virtual int evaluateInt(ResourceCompiler *ctx); 113 + }; 114 + 115 + class IdentifierExpr : public Expression 116 + { 117 + public: 118 + std::string id; 119 + std::vector<ExprPtr> arguments; 120 + IdentifierExpr(std::string id, yy::location loc); 121 + 122 + void addArgument(ExprPtr e); 123 + ExprPtr lookup(ResourceCompiler *ctx); 124 + virtual int evaluateInt(ResourceCompiler *ctx); 125 + virtual std::string evaluateString(ResourceCompiler *ctx); 126 + }; 127 + 128 + class CountOfExpr : public Expression 129 + { 130 + IdentifierExprPtr arg; 131 + public: 132 + CountOfExpr(IdentifierExprPtr arg, yy::location loc) : Expression(loc), arg(arg) {} 133 + virtual int evaluateInt(ResourceCompiler *ctx); 134 + }; 135 + 136 + class ArrayIndexExpr : public Expression 137 + { 138 + IdentifierExprPtr arg; 139 + public: 140 + ArrayIndexExpr(IdentifierExprPtr arg, yy::location loc) : Expression(loc), arg(arg) {} 141 + virtual int evaluateInt(ResourceCompiler *ctx); 142 + }; 143 + 144 + class ReadExpr : public Expression 145 + { 146 + ExprPtr arg; 147 + public: 148 + ReadExpr(ExprPtr arg, yy::location loc) : Expression(loc), arg(arg) {} 149 + virtual std::string evaluateString(ResourceCompiler *ctx); 150 + }; 151 + 152 + class UnimplementedExpr : public Expression 153 + { 154 + std::string msg; 155 + public: 156 + UnimplementedExpr(std::string msg, yy::location loc) : Expression(loc), msg(msg) {} 157 + virtual int evaluateInt(ResourceCompiler *ctx); 158 + virtual std::string evaluateString(ResourceCompiler *ctx); 159 + }; 160 + 161 + class PeekExpr : public Expression 162 + { 163 + ExprPtr addr; 164 + ExprPtr offset; 165 + ExprPtr size; 166 + public: 167 + PeekExpr(ExprPtr addr, ExprPtr offset, ExprPtr size, yy::location loc); 168 + PeekExpr(ExprPtr addr, int size, yy::location loc); 169 + virtual int evaluateInt(ResourceCompiler *ctx); 170 + }; 171 + 172 + #endif // EXPRESSION_H
+12
src/buildtools/Rez/README.md
··· 1 + Rez Resource Compiler 2 + ===================== 3 + 4 + A reimplementation of the classic Rez resource compiler. 5 + 6 + 7 + Known Bugs & Limitations 8 + ----------------- 9 + 10 + * `$ABCD` alternate syntax for hex numbers is not supported 11 + * hex strings not supported 12 + * Other than in Apple Rez, the preprocessor is case sensitive.
+24
src/buildtools/Rez/ResSpec.h
··· 1 + #ifndef REZSPEC_H 2 + #define REZSPEC_H 3 + 4 + #include "ResType.h" 5 + #include <string> 6 + 7 + class ResSpec : public ResRef 8 + { 9 + int attr_; 10 + std::string name_; 11 + 12 + public: 13 + ResSpec() : attr_(0) {} 14 + ResSpec(ResType type, int id, int attr = 0, std::string name = "") 15 + : ResRef(type, id), attr_(attr), name_(name) 16 + {} 17 + 18 + int& attr() { return attr_; } 19 + int attr() const { return attr_; } 20 + std::string& name() { return name_; } 21 + const std::string& name() const { return name_; } 22 + }; 23 + 24 + #endif // REZSPEC_H
+200
src/buildtools/Rez/ResourceCompiler.cc
··· 1 + #include "ResourceCompiler.h" 2 + #include <iostream> 3 + #include "ResourceDefinitions.h" 4 + #include "RezWorld.h" 5 + #include "Diagnostic.h" 6 + 7 + ResourceCompiler::ResourceCompiler( 8 + RezWorld& world, TypeDefinitionPtr type, CompoundExprPtr body, bool verboseFlag) 9 + : world(world), 10 + typeDefinition(type), 11 + body(body), 12 + currentField(nullptr) 13 + { 14 + this->verboseFlag = verboseFlag; 15 + } 16 + 17 + BinaryOutput::BinaryOutput() 18 + : verboseFlag(false) 19 + { 20 + reset(true); 21 + } 22 + 23 + void BinaryOutput::reset(bool prePass) 24 + { 25 + currentOffset = 0; 26 + if(!prePass) 27 + prePassData = std::move(data); 28 + data.clear(); 29 + this->prePass = prePass; 30 + } 31 + 32 + std::string BinaryOutput::resourceData() 33 + { 34 + return std::string(data.begin(), data.end()); 35 + } 36 + 37 + void BinaryOutput::write(int nBits, int value) 38 + { 39 + if(verboseFlag) 40 + std::cout << "[" << nBits << " bits] = " << std::hex << value << std::dec << std::endl; 41 + 42 + unsigned mask = 1 << (nBits-1); 43 + 44 + for(int i = 0; i < nBits; i++) 45 + { 46 + bool bit = (value & mask) != 0; 47 + 48 + if(currentOffset % 8 == 0) 49 + data.push_back(bit ? 0x80 : 0); 50 + else if(bit) 51 + data.back() |= (0x80 >> (currentOffset % 8)); 52 + ++currentOffset; 53 + 54 + mask >>= 1; 55 + } 56 + 57 + //currentOffset += nBits; 58 + } 59 + 60 + int BinaryOutput::peek(int bitPos, int size) 61 + { 62 + unsigned bytePos = bitPos / 8; 63 + unsigned endBytePos = (bitPos + size - 1) / 8 + 1; 64 + 65 + unsigned bitPosInByte = bitPos % 8; 66 + unsigned outPos = 32 - size; 67 + 68 + unsigned val = 0; 69 + 70 + for(unsigned i = bytePos; i != endBytePos; ++i) 71 + { 72 + unsigned byte; 73 + if(i < data.size()) 74 + byte = data[i]; 75 + else if(i < prePassData.size()) 76 + byte = prePassData[i]; 77 + else 78 + byte = 0; 79 + 80 + unsigned read = byte << (bitPosInByte + 24); 81 + val |= (read >> outPos); 82 + 83 + outPos += 8 - bitPosInByte; 84 + 85 + bitPosInByte = 0; 86 + } 87 + 88 + return val; 89 + } 90 + 91 + ExprPtr ResourceCompiler::lookupIdentifier(std::string name, const Subscripts &sub) 92 + { 93 + if(currentField) 94 + { 95 + if(ExprPtr val = currentField->lookupNamedValue(name)) 96 + { 97 + return val; 98 + } 99 + } 100 + 101 + auto p = labelValues.find(std::make_pair(name, sub)); 102 + if(p != labelValues.end()) 103 + return p->second; 104 + 105 + //std::cerr << "ID lookup failed: " << name << std::endl; 106 + 107 + return nullptr; 108 + } 109 + 110 + void ResourceCompiler::defineLabel(const std::string &name) 111 + { 112 + labelValues[std::make_pair(name,currentSubscripts)] = std::make_shared<IntExpr>(currentOffset, yy::location()); 113 + } 114 + 115 + void ResourceCompiler::compile() 116 + { 117 + if(verboseFlag) std::cout << "(first pass)\n"; 118 + reset(true); 119 + typeDefinition->compile(body, this, true); 120 + if(verboseFlag) std::cout << "(second pass)\n"; 121 + 122 + reset(false); 123 + typeDefinition->compile(body, this, false); 124 + if(verboseFlag) std::cout << "(done)\n"; 125 + } 126 + 127 + int ResourceCompiler::getArrayCount(const std::string &name) 128 + { 129 + Subscripts sub = currentSubscripts; 130 + for(;;) 131 + { 132 + auto p = arrayCounts.find(std::make_pair(name, sub)); 133 + if(p != arrayCounts.end()) 134 + return p->second; 135 + 136 + 137 + if(sub.empty()) 138 + return 0; /* ### */ 139 + sub.popSubscript(); 140 + } 141 + } 142 + 143 + int ResourceCompiler::getArrayIndex(const std::string &arrayName) 144 + { 145 + return curArrayIndices[arrayName]; 146 + } 147 + 148 + void ResourceCompiler::problem(Diagnostic d) 149 + { 150 + if(!prePass) 151 + world.problem(d); 152 + } 153 + 154 + void ResourceCompiler::beginArrayScope(std::string &arrayName, int index) 155 + { 156 + if(arrayName != "") 157 + { 158 + curArrayIndices[arrayName] = index; 159 + int& count = arrayCounts[std::make_pair(arrayName, currentSubscripts)]; 160 + if(count < index) 161 + count = index; 162 + arrayCounts[std::make_pair(arrayName, Subscripts())] = count; 163 + //std::cout << "count for " << arrayName << " is " << count << std::endl; 164 + } 165 + currentSubscripts.addSubscript(index); 166 + } 167 + 168 + Subscripts::Subscripts() 169 + { 170 + } 171 + 172 + Subscripts::~Subscripts() 173 + { 174 + } 175 + 176 + void Subscripts::addSubscript(int x) 177 + { 178 + subscripts.push_back(x); 179 + } 180 + 181 + void Subscripts::popSubscript() 182 + { 183 + subscripts.pop_back(); 184 + } 185 + 186 + bool Subscripts::operator<(const Subscripts &other) const 187 + { 188 + if(subscripts.size() < other.subscripts.size()) 189 + return true; 190 + if(other.subscripts.size() < subscripts.size()) 191 + return false; 192 + for(int i = 0, n = subscripts.size(); i < n; i++) 193 + { 194 + if(subscripts[i] < other.subscripts[i]) 195 + return true; 196 + else if(subscripts[i] > other.subscripts[i]) 197 + return false; 198 + } 199 + return false; 200 + }
+94
src/buildtools/Rez/ResourceCompiler.h
··· 1 + #ifndef RESOURCECOMPILER_H 2 + #define RESOURCECOMPILER_H 3 + 4 + #include "Expression.h" 5 + #include "ResourceDefinitions.h" 6 + 7 + class Field; 8 + class RezWorld; 9 + class Diagnostic; 10 + 11 + class Subscripts 12 + { 13 + std::vector<int> subscripts; 14 + public: 15 + Subscripts(); 16 + ~Subscripts(); 17 + 18 + void addSubscript(int x); 19 + void popSubscript(); 20 + bool operator<(const Subscripts& other) const; 21 + bool empty() const { return subscripts.empty(); } 22 + }; 23 + 24 + class BinaryOutput 25 + { 26 + protected: 27 + int currentOffset; 28 + std::vector<unsigned char> data; 29 + std::vector<unsigned char> prePassData; 30 + bool verboseFlag; 31 + bool prePass; 32 + public: 33 + BinaryOutput(); 34 + void reset(bool prePass); 35 + 36 + std::string resourceData(); 37 + 38 + void reserve(int nBits) { write(nBits, 0); } 39 + void write(int nBits, int value); 40 + int tell() { return currentOffset; } 41 + 42 + int peek(int bitPos, int size); 43 + 44 + bool isPrePass() { return prePass; } 45 + }; 46 + 47 + class ResourceCompiler : public BinaryOutput 48 + { 49 + RezWorld& world; 50 + TypeDefinitionPtr typeDefinition; 51 + CompoundExprPtr body; 52 + std::map<std::pair<std::string, Subscripts>, ExprPtr> labelValues; 53 + std::map<std::pair<std::string, Subscripts>, int> arrayCounts; 54 + std::map<std::string, int> curArrayIndices; 55 + Field* currentField; 56 + Subscripts currentSubscripts; 57 + 58 + void beginArrayScope(std::string& arrayName, int index); 59 + public: 60 + ResourceCompiler(RezWorld& world, TypeDefinitionPtr type, CompoundExprPtr body, bool verboseFlag); 61 + 62 + ExprPtr lookupIdentifier(std::string name, const Subscripts& sub = Subscripts()); 63 + 64 + void defineLabel(const std::string& name); 65 + void compile(); 66 + 67 + int getArrayCount(const std::string& arrayName); 68 + int getArrayIndex(const std::string& arrayName); 69 + 70 + 71 + class FieldScope 72 + { 73 + ResourceCompiler *compiler; 74 + public: 75 + FieldScope(ResourceCompiler* compiler, Field *field) 76 + : compiler(compiler) { compiler->currentField = field; } 77 + ~FieldScope() { compiler->currentField = nullptr; } 78 + }; 79 + 80 + class ArrayScope 81 + { 82 + ResourceCompiler *compiler; 83 + public: 84 + ArrayScope(ResourceCompiler* compiler, std::string& arrayName, int index) 85 + : compiler(compiler) { compiler->beginArrayScope(arrayName, index); } 86 + ~ArrayScope() { compiler->currentSubscripts.popSubscript(); } 87 + }; 88 + 89 + void problem(Diagnostic d); 90 + }; 91 + 92 + 93 + 94 + #endif // RESOURCECOMPILER_H
+342
src/buildtools/Rez/ResourceDefinitions.cc
··· 1 + #include "ResourceDefinitions.h" 2 + #include <ostream> 3 + #include <cassert> 4 + 5 + #include "ResourceCompiler.h" 6 + #include "Diagnostic.h" 7 + 8 + 9 + std::ostream &operator<<(std::ostream &out, TypeSpec ts) 10 + { 11 + out << ts.getType(); 12 + if(ts.hasID()) 13 + out << " (" << ts.getID() << ")"; 14 + return out; 15 + } 16 + 17 + 18 + FieldList::~FieldList() 19 + { 20 + 21 + } 22 + 23 + void FieldList::addField(FieldPtr field, yy::location loc) 24 + { 25 + field->location = loc; 26 + fields.push_back(field); 27 + } 28 + 29 + void FieldList::addLabel(std::string name, yy::location loc) 30 + { 31 + addField(std::make_shared<LabelField>(name), loc); 32 + } 33 + 34 + void FieldList::compile(ExprPtr expr, ResourceCompiler *compiler, bool prePass) 35 + { 36 + CompoundExprPtr compound = std::dynamic_pointer_cast<CompoundExpr>(expr); 37 + assert(compound); 38 + 39 + int i = 0; 40 + for(FieldPtr f : fields) 41 + { 42 + if(f->needsValue()) 43 + { 44 + if(i >= compound->size()) 45 + compiler->problem(Diagnostic(Diagnostic::error,"not enough values specified", compound->location)); 46 + else 47 + f->compile(compound->getItem(i++), compiler, prePass); 48 + } 49 + else 50 + f->compile(nullptr, compiler, prePass); 51 + } 52 + if(i < compound->size()) 53 + { 54 + compiler->problem(Diagnostic(Diagnostic::error,"extra value specified", 55 + compound->getItem(i)->location)); 56 + } 57 + } 58 + 59 + 60 + 61 + 62 + void SimpleField::addNamedValue(std::string n) 63 + { 64 + if(lastNamedValue) 65 + addNamedValue(n, std::make_shared<BinaryExpr>( 66 + BinaryOp::PLUS, lastNamedValue, std::make_shared<IntExpr>(1, yy::location()), yy::location())); 67 + else 68 + addNamedValue(n, std::make_shared<IntExpr>(0, yy::location())); 69 + } 70 + 71 + void SimpleField::addNamedValue(std::string n, ExprPtr val) 72 + { 73 + namedValues[n] = val; 74 + lastNamedValue = val; 75 + } 76 + 77 + ExprPtr SimpleField::lookupNamedValue(std::string n) 78 + { 79 + auto p = namedValues.find(n); 80 + if(p != namedValues.end()) 81 + return p->second; 82 + else 83 + return nullptr; 84 + } 85 + 86 + bool SimpleField::needsValue() 87 + { 88 + return !value; 89 + } 90 + 91 + void SimpleField::compile(ExprPtr expr, ResourceCompiler *compiler, bool prePass) 92 + { 93 + switch(type) 94 + { 95 + case Type::bitstring: 96 + case Type::boolean: 97 + case Type::byte: 98 + case Type::integer: 99 + case Type::longint: 100 + compileInt(expr, compiler, prePass); 101 + break; 102 + case Type::string: 103 + case Type::wstring: 104 + case Type::pstring: 105 + case Type::char_: 106 + compileString(expr, compiler, prePass); 107 + break; 108 + 109 + case Type::rect: 110 + case Type::point: 111 + compileCompound(expr, compiler, prePass); 112 + break; 113 + 114 + } 115 + } 116 + 117 + void SimpleField::compileString(ExprPtr expr, ResourceCompiler *compiler, bool prePass) 118 + { 119 + std::string str; 120 + { 121 + ResourceCompiler::FieldScope scope(compiler, this); 122 + str = (value ? value : expr)->evaluateString(compiler); 123 + } 124 + 125 + if(arrayCount || type == Type::char_) 126 + { 127 + unsigned requestedSize = type == Type::char_ ? 1 : arrayCount->evaluateInt(compiler); 128 + if(requestedSize < str.size()) 129 + str.erase(str.begin() + requestedSize, str.end()); 130 + else if(requestedSize > str.size()) 131 + str.insert(str.end(),requestedSize - str.size(), '\0'); 132 + } 133 + 134 + int count = str.size(); 135 + 136 + if(type == Type::pstring) 137 + { 138 + if(count > 255) 139 + { 140 + str.erase(str.begin() + 255, str.end()); 141 + count = 255; 142 + } 143 + compiler->write(8, count); 144 + } 145 + else if(type == Type::wstring) 146 + { 147 + if(count > 65535) 148 + { 149 + str.erase(str.begin() + 65535, str.end()); 150 + count = 65535; 151 + } 152 + compiler->write(16, count); 153 + } 154 + 155 + for(char c : str) 156 + compiler->write(8, c); 157 + } 158 + 159 + void SimpleField::compileInt(ExprPtr expr, ResourceCompiler *compiler, bool prePass) 160 + { 161 + int bitSize = 0; 162 + 163 + switch(type) 164 + { 165 + case Type::bitstring: 166 + bitSize = arrayCount->evaluateInt(compiler); 167 + break; 168 + case Type::boolean: 169 + bitSize = 1; 170 + break; 171 + case Type::byte: 172 + bitSize = 8; 173 + break; 174 + case Type::integer: 175 + bitSize = 16; 176 + break; 177 + case Type::longint: 178 + bitSize = 32; 179 + break; 180 + default: 181 + assert(false); 182 + } 183 + 184 + int actualValue = 0; 185 + ResourceCompiler::FieldScope scope(compiler, this); 186 + actualValue = (value ? value : expr)->evaluateInt(compiler); 187 + 188 + compiler->write(bitSize, actualValue); 189 + } 190 + 191 + void SimpleField::compileCompound(ExprPtr expr, ResourceCompiler *compiler, bool prePass) 192 + { 193 + ExprPtr val = value ? value : expr; 194 + if(IdentifierExprPtr id = std::dynamic_pointer_cast<IdentifierExpr>(val)) 195 + { 196 + ResourceCompiler::FieldScope scope(compiler, this); 197 + val = id->lookup(compiler); 198 + } 199 + 200 + int count = 0; 201 + switch(type) 202 + { 203 + case Type::rect: 204 + count = 4; 205 + break; 206 + case Type::point: 207 + count = 2; 208 + break; 209 + default: 210 + assert(false); 211 + } 212 + 213 + CompoundExprPtr compound = std::dynamic_pointer_cast<CompoundExpr>(val); 214 + if(!compound || compound->size() != count) 215 + { 216 + expr->error(compiler, std::string("expected ") + (type == Type::rect ? "rect {t,l,b,r}." : "point {v,h}.")); 217 + return; 218 + } 219 + assert(compound); 220 + assert(compound->size() == count); 221 + 222 + for(int i = 0; i < count; i++) 223 + { 224 + int x = compound->getItem(i)->evaluateInt(compiler); 225 + compiler->write(16, x); 226 + } 227 + } 228 + 229 + 230 + ArrayField::ArrayField(std::string name, ExprPtr count) 231 + : name(name), arrayCount(count) 232 + { 233 + } 234 + 235 + void ArrayField::compile(ExprPtr expr, ResourceCompiler *compiler, bool prePass) 236 + { 237 + CompoundExprPtr compound = std::dynamic_pointer_cast<CompoundExpr>(expr); 238 + assert(compound); 239 + 240 + 241 + int i = 0; 242 + int n = compound->size(); 243 + 244 + int iterations = 0; 245 + while(i < n) 246 + { 247 + ++iterations; 248 + ResourceCompiler::ArrayScope scope(compiler, name, iterations); 249 + for(FieldPtr f : fields) 250 + { 251 + if(f->needsValue()) 252 + { 253 + assert(i < n); 254 + f->compile(compound->getItem(i++), compiler, prePass); 255 + } 256 + else 257 + f->compile(nullptr, compiler, prePass); 258 + } 259 + } 260 + 261 + if(!prePass && arrayCount) 262 + { 263 + int expected = arrayCount->evaluateInt(compiler); 264 + assert(expected == iterations); 265 + } 266 + } 267 + 268 + 269 + LabelField::LabelField(std::string name) 270 + : name(name) 271 + { 272 + } 273 + 274 + bool LabelField::needsValue() 275 + { 276 + return false; 277 + } 278 + 279 + void LabelField::compile(ExprPtr expr, ResourceCompiler *compiler, bool prePass) 280 + { 281 + compiler->defineLabel(name); 282 + } 283 + 284 + 285 + void SwitchField::addCase(const std::string name, FieldListPtr alternative) 286 + { 287 + cases[name] = alternative; 288 + } 289 + 290 + void SwitchField::compile(ExprPtr expr, ResourceCompiler *compiler, bool prePass) 291 + { 292 + CaseExprPtr caseExpr = std::dynamic_pointer_cast<CaseExpr>(expr); 293 + assert(caseExpr); 294 + 295 + FieldListPtr caseDefinition = cases[caseExpr->tag]; 296 + assert(caseDefinition); 297 + 298 + caseDefinition->compile(caseExpr->expr, compiler, prePass); 299 + } 300 + 301 + 302 + FillAlignField::FillAlignField(FillAlignField::Type type, bool isAlign, ExprPtr count) 303 + : type(type), count(count), isAlign(isAlign) 304 + { 305 + 306 + } 307 + 308 + bool FillAlignField::needsValue() 309 + { 310 + return false; 311 + } 312 + 313 + void FillAlignField::compile(ExprPtr expr, ResourceCompiler *compiler, bool prePass) 314 + { 315 + int bitSize; 316 + switch(type) 317 + { 318 + case Type::bit: bitSize = 1; break; 319 + case Type::nibble: bitSize = 4; break; 320 + case Type::byte: bitSize = 8; break; 321 + case Type::word: bitSize = 16; break; 322 + case Type::long_: bitSize = 32; break; 323 + } 324 + 325 + int actualCount = 1; 326 + if(count) 327 + actualCount = count->evaluateInt(compiler); 328 + 329 + for(int i = 0; i < actualCount; i++) 330 + { 331 + int n; 332 + if(isAlign) 333 + { 334 + int mask = bitSize - 1; 335 + int pos = compiler->tell(); 336 + n = ((pos + mask) & ~mask) - pos; 337 + } 338 + else 339 + n = bitSize; 340 + compiler->write(n, 0); 341 + } 342 + }
+171
src/buildtools/Rez/ResourceDefinitions.h
··· 1 + #ifndef RESOURCEDEFINITIONS_H 2 + #define RESOURCEDEFINITIONS_H 3 + 4 + #include <iosfwd> 5 + #include <memory> 6 + #include <map> 7 + 8 + #include "Expression.h" 9 + #include "ResType.h" 10 + 11 + #include "location.hh" 12 + 13 + class TypeSpec 14 + { 15 + ResType type; 16 + int id; 17 + public: 18 + static const int noID = 65536; 19 + 20 + TypeSpec() : id(noID) {} 21 + TypeSpec(ResType type) : type(type), id(noID) {} 22 + TypeSpec(ResType type, int id) : type(type), id(id) {} 23 + 24 + ResType getType() const { return type; } 25 + int getID() const { return id; } 26 + 27 + bool hasID() const { return id != noID; } 28 + 29 + bool operator<(TypeSpec y) const 30 + { 31 + if(type < y.type) 32 + return true; 33 + else if(y.type < type) 34 + return false; 35 + else 36 + return id < y.id; 37 + } 38 + }; 39 + 40 + std::ostream& operator<<(std::ostream& out, TypeSpec ts); 41 + 42 + 43 + class ResourceCompiler; 44 + 45 + class Field 46 + { 47 + public: 48 + yy::location location; 49 + 50 + virtual ~Field() = default; 51 + 52 + virtual bool needsValue() { return true; } 53 + 54 + virtual void compile(ExprPtr expr, ResourceCompiler *compiler, bool prePass) = 0; 55 + 56 + virtual ExprPtr lookupNamedValue(std::string) { return nullptr; } 57 + }; 58 + typedef std::shared_ptr<Field> FieldPtr; 59 + 60 + class SimpleField : public Field 61 + { 62 + public: 63 + enum class Type 64 + { 65 + boolean, byte, integer, longint, rect, point, char_, 66 + pstring, wstring, string, bitstring 67 + }; 68 + 69 + enum class Attrs 70 + { 71 + none = 0, hex = 1, key = 2, unsigned_ = 4, literal = 8, binary = 16 72 + }; 73 + 74 + Type type; 75 + Attrs attrs = Attrs::none; 76 + ExprPtr arrayCount; 77 + 78 + ExprPtr value; 79 + std::map<std::string, ExprPtr> namedValues; 80 + ExprPtr lastNamedValue; 81 + 82 + void addNamedValue(std::string n); 83 + void addNamedValue(std::string n, ExprPtr val); 84 + ExprPtr lookupNamedValue(std::string); 85 + 86 + virtual bool needsValue(); 87 + virtual void compile(ExprPtr expr, ResourceCompiler *compiler, bool prePass); 88 + 89 + private: 90 + void compileString(ExprPtr expr, ResourceCompiler *compiler, bool prePass); 91 + void compileInt(ExprPtr expr, ResourceCompiler *compiler, bool prePass); 92 + void compileCompound(ExprPtr expr, ResourceCompiler *compiler, bool prePass); 93 + }; 94 + typedef std::shared_ptr<SimpleField> SimpleFieldPtr; 95 + 96 + class FillAlignField : public Field 97 + { 98 + public: 99 + enum class Type 100 + { 101 + bit, nibble, byte, word, long_ 102 + }; 103 + 104 + FillAlignField(Type type, bool isAlign, ExprPtr count = ExprPtr()); 105 + virtual bool needsValue(); 106 + virtual void compile(ExprPtr expr, ResourceCompiler *compiler, bool prePass); 107 + private: 108 + Type type; 109 + ExprPtr count; 110 + bool isAlign; 111 + }; 112 + 113 + inline SimpleField::Attrs operator|(SimpleField::Attrs a, SimpleField::Attrs b) 114 + { 115 + return SimpleField::Attrs( int(a) | int(b) ); 116 + } 117 + 118 + 119 + class LabelField : public Field 120 + { 121 + std::string name; 122 + public: 123 + LabelField(std::string name); 124 + 125 + virtual bool needsValue(); 126 + virtual void compile(ExprPtr expr, ResourceCompiler *compiler, bool prePass); 127 + }; 128 + typedef std::shared_ptr<LabelField> LabelFieldPtr; 129 + 130 + 131 + class FieldList : public Field 132 + { 133 + protected: 134 + std::vector<FieldPtr> fields; 135 + public: 136 + virtual ~FieldList(); 137 + void addField(FieldPtr field, yy::location loc); 138 + void addLabel(std::string name, yy::location loc); 139 + 140 + virtual void compile(ExprPtr expr, ResourceCompiler *compiler, bool prePass); 141 + }; 142 + typedef std::shared_ptr<FieldList> FieldListPtr; 143 + 144 + 145 + class ArrayField : public FieldList 146 + { 147 + std::string name; 148 + ExprPtr arrayCount; 149 + public: 150 + ArrayField(std::string name /* or empty */, ExprPtr count /* may be null*/); 151 + 152 + virtual void compile(ExprPtr expr, ResourceCompiler *compiler, bool prePass); 153 + }; 154 + typedef std::shared_ptr<ArrayField> ArrayFieldPtr; 155 + 156 + class SwitchField : public Field 157 + { 158 + std::map<std::string, FieldListPtr> cases; 159 + public: 160 + void addCase(const std::string name, FieldListPtr alternative); 161 + 162 + virtual void compile(ExprPtr expr, ResourceCompiler *compiler, bool prePass); 163 + }; 164 + typedef std::shared_ptr<SwitchField> SwitchFieldPtr; 165 + 166 + class TypeDefinition : public FieldList 167 + { 168 + }; 169 + typedef std::shared_ptr<TypeDefinition> TypeDefinitionPtr; 170 + 171 + #endif // RESOURCEDEFINITIONS_H
+50
src/buildtools/Rez/ResourceFiles/BinaryIO.cc
··· 1 + #include "BinaryIO.h" 2 + #include <iostream> 3 + #include <cassert> 4 + 5 + #include "ResType.h" 6 + 7 + void byte(std::ostream& out, int byte) 8 + { 9 + out.put((unsigned char)byte); 10 + } 11 + void word(std::ostream& out, int word) 12 + { 13 + byte(out,(word >> 8) & 0xFF); 14 + byte(out,word & 0xFF); 15 + } 16 + void ostype(std::ostream& out, ResType type) 17 + { 18 + longword(out, type); 19 + } 20 + void longword(std::ostream& out, int longword) 21 + { 22 + byte(out,(longword >> 24) & 0xFF); 23 + byte(out,(longword >> 16) & 0xFF); 24 + byte(out,(longword >> 8) & 0xFF); 25 + byte(out,longword & 0xFF); 26 + } 27 + 28 + int byte(std::istream& in) 29 + { 30 + return in.get() & 0xFF; 31 + } 32 + int word(std::istream& in) 33 + { 34 + int a = byte(in); 35 + int b = byte(in); 36 + return (a << 8) | b; 37 + } 38 + ResType ostype(std::istream& in) 39 + { 40 + return longword(in); 41 + } 42 + int longword(std::istream& in) 43 + { 44 + int a = byte(in); 45 + int b = byte(in); 46 + int c = byte(in); 47 + int d = byte(in); 48 + return (a << 24) | (b << 16) | (c << 8) | d; 49 + } 50 +
+19
src/buildtools/Rez/ResourceFiles/BinaryIO.h
··· 1 + #ifndef BINARYIO_H 2 + #define BINARYIO_H 3 + 4 + #include <iosfwd> 5 + #include <string> 6 + 7 + class ResType; 8 + 9 + void byte(std::ostream& out, int byte); 10 + void word(std::ostream& out, int word); 11 + void ostype(std::ostream& out, ResType type); 12 + void longword(std::ostream& out, int longword); 13 + 14 + int byte(std::istream& in); 15 + int word(std::istream& in); 16 + ResType ostype(std::istream& in); 17 + int longword(std::istream& in); 18 + 19 + #endif // BINARYIO_H
+38
src/buildtools/Rez/ResourceFiles/CMakeLists.txt
··· 1 + # Copyright 2014 Wolfgang Thaller. 2 + # 3 + # This file is part of Retro68. 4 + # 5 + # Retro68 is free software: you can redistribute it and/or modify 6 + # it under the terms of the GNU General Public License as published by 7 + # the Free Software Foundation, either version 3 of the License, or 8 + # (at your option) any later version. 9 + # 10 + # Retro68 is distributed in the hope that it will be useful, 11 + # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 + # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 + # GNU General Public License for more details. 14 + # 15 + # You should have received a copy of the GNU General Public License 16 + # along with Retro68. If not, see <http://www.gnu.org/licenses/>. 17 + 18 + find_package(Boost COMPONENTS filesystem system REQUIRED) 19 + 20 + add_library(ResourceFiles 21 + ResourceFork.h ResourceFork.cc 22 + BinaryIO.h BinaryIO.cc 23 + ResType.h ResType.cc 24 + ResourceFile.h ResourceFile.cc 25 + ) 26 + 27 + target_link_libraries(ResourceFiles ${Boost_LIBRARIES} ${CMAKE_INSTALL_PREFIX}/lib/libhfs.a) 28 + target_include_directories(ResourceFiles PUBLIC . 29 + PRIVATE ${CMAKE_INSTALL_PREFIX}/include 30 + ${Boost_INCLUDE_DIR}) 31 + 32 + find_package(Boost COMPONENTS program_options REQUIRED) 33 + 34 + add_executable(ResInfo ResInfo.cc) 35 + target_link_libraries(ResInfo ResourceFiles ${Boost_LIBRARIES}) 36 + target_include_directories(ResInfo PRIVATE ${Boost_INCLUDE_DIR}) 37 + 38 + install(TARGETS ResInfo RUNTIME DESTINATION bin)
+144
src/buildtools/Rez/ResourceFiles/ResInfo.cc
··· 1 + #include <iostream> 2 + #include <map> 3 + #include <string> 4 + #include "ResourceFile.h" 5 + #include "boost/program_options.hpp" 6 + namespace po = boost::program_options; 7 + using std::map; 8 + using std::string; 9 + 10 + static po::options_description desc; 11 + 12 + map<string,ResourceFile::Format> formats { 13 + #ifdef __APPLE__ 14 + {"real", ResourceFile::Format::real}, 15 + #endif 16 + {"macbin", ResourceFile::Format::macbin}, 17 + {"basilisk", ResourceFile::Format::basilisk}, 18 + {"applesingle", ResourceFile::Format::applesingle}, 19 + {"underscore_appledouble", ResourceFile::Format::underscore_appledouble} 20 + }; 21 + map<ResourceFile::Format,string> reverseFormats; 22 + 23 + static void usage() 24 + { 25 + std::cerr << "Usage: " << "ResInfo [options] input-file\n"; 26 + std::cerr << desc << std::endl; 27 + std::cerr << "Available Resource Fork formats are:\n"; 28 + for(auto p : formats) 29 + std::cerr << " " << p.first << std::endl; 30 + } 31 + 32 + 33 + int main(int argc, char *argv[]) 34 + { 35 + desc.add_options() 36 + ("help,h", "show this help message") 37 + ("type,t", "print file type") 38 + ("creator,c", "print creator code") 39 + ("all,a", "print all info") 40 + ("format,f", "print format") 41 + ("count,n", "print number of resources") 42 + ("size,s", "show data fork size") 43 + ("filename,l", "echo input file name") 44 + ("set-format,F", po::value<string>(), "resource fork format)") 45 + ; 46 + po::options_description hidden, alldesc; 47 + hidden.add_options() 48 + ("input", po::value<std::vector<string>>(), "input file" ) 49 + ; 50 + alldesc.add(desc).add(hidden); 51 + 52 + po::variables_map options; 53 + try 54 + { 55 + auto parsed = po::command_line_parser(argc, argv) 56 + .options(alldesc) 57 + .positional(po::positional_options_description().add("input", -1)) 58 + .style(po::command_line_style::default_style) 59 + .run(); 60 + 61 + po::store(parsed, options); 62 + } 63 + catch(po::error& e) 64 + { 65 + std::cerr << "ERROR: " << e.what() << std::endl << std::endl; 66 + usage(); 67 + return 1; 68 + } 69 + 70 + po::notify(options); 71 + 72 + if(options.count("help") || !options.count("input")) 73 + { 74 + usage(); 75 + return 0; 76 + } 77 + 78 + for(auto p : formats) 79 + reverseFormats[p.second] = p.first; 80 + 81 + bool showFilename = options.count("filename"); 82 + bool showType = options.count("type") != 0; 83 + bool showCreator = options.count("creator") != 0; 84 + bool showFormat = options.count("format") != 0; 85 + bool showCount = options.count("count") != 0; 86 + bool showSize = options.count("size") != 0; 87 + 88 + ResourceFile::Format format = ResourceFile::Format::autodetect; 89 + 90 + if(options.count("all")) 91 + showType = showCreator = showFormat = showCount = showSize = true; 92 + 93 + if(options.count("set-format")) 94 + { 95 + string s = options["set-format"].as<string>(); 96 + if(formats.find(s) != formats.end()) 97 + format = formats[s]; 98 + else 99 + { 100 + std::cerr << "Unknown format " << s << std::endl << std::endl; 101 + usage(); 102 + exit(1); 103 + } 104 + } 105 + 106 + if(options.count("input")) 107 + for(std::string fn : options["input"].as<std::vector<std::string>>()) 108 + { 109 + ResourceFile rsrcFile; 110 + 111 + if(!rsrcFile.read(fn, format)) 112 + { 113 + std::cerr << "Can't read file.\n"; 114 + return 1; 115 + } 116 + 117 + std::ostringstream out; 118 + if(showType) 119 + out << " " << rsrcFile.type; 120 + if(showCreator) 121 + out << " " << rsrcFile.creator; 122 + if(showFormat) 123 + out << " " << reverseFormats[rsrcFile.getFormat()]; 124 + if(showCount) 125 + out << " " << rsrcFile.resources.resources.size(); 126 + if(showSize) 127 + out << " " << rsrcFile.data.size(); 128 + 129 + string str = out.str(); 130 + if(str.size()) 131 + { 132 + if(showFilename) 133 + std::cout << fn << ": "; 134 + std::cout << out.str().substr(1) << std::endl; 135 + } 136 + else 137 + { 138 + if(showFilename) 139 + std::cout << fn << std::endl; 140 + } 141 + } 142 + 143 + return 0; 144 + }
+58
src/buildtools/Rez/ResourceFiles/ResType.cc
··· 1 + #include "ResType.h" 2 + #include <iostream> 3 + #include <cassert> 4 + 5 + ResType::ResType(const std::string &str) 6 + { 7 + auto p = str.begin(); 8 + auto e = str.end(); 9 + 10 + assert(str.size() == 4); 11 + 12 + x = 0; 13 + while(p != e) 14 + { 15 + x <<= 8; 16 + x |= (*p) & 0xFF; 17 + ++p; 18 + } 19 + } 20 + 21 + ResType::ResType(const char *s) 22 + { 23 + auto p = s; 24 + auto e = s + 4; 25 + 26 + assert(s[0] && s[1] && s[2] && s[3] && !s[4]); 27 + 28 + x = 0; 29 + while(p != e) 30 + { 31 + x <<= 8; 32 + x |= (*p) & 0xFF; 33 + ++p; 34 + } 35 + } 36 + 37 + 38 + ResType::operator std::string() 39 + { 40 + char c1 = static_cast<char>(x >> 24); 41 + char c2 = static_cast<char>(x >> 16); 42 + char c3 = static_cast<char>(x >> 8); 43 + char c4 = static_cast<char>(x); 44 + 45 + return std::string{ c1, c2, c3, c4 }; 46 + } 47 + 48 + std::ostream &operator<<(std::ostream &out, ResType t) 49 + { 50 + char c1 = static_cast<char>((int)t >> 24); 51 + char c2 = static_cast<char>((int)t >> 16); 52 + char c3 = static_cast<char>((int)t >> 8); 53 + char c4 = static_cast<char>((int)t); 54 + 55 + out << "'" << c1 << c2 << c3 << c4 << "'"; 56 + return out; 57 + } 58 +
+35
src/buildtools/Rez/ResourceFiles/ResType.h
··· 1 + #ifndef RESTYPE_H 2 + #define RESTYPE_H 3 + 4 + #include <string> 5 + #include <iosfwd> 6 + 7 + class ResType 8 + { 9 + int x; 10 + public: 11 + ResType() : x(0) {} 12 + ResType(int x) : x(x) {} 13 + ResType(const std::string& s); 14 + ResType(const char* s); 15 + 16 + operator int() const { return x; } 17 + bool operator<(ResType y) const { return x < y.x; } 18 + 19 + operator std::string(); 20 + }; 21 + 22 + std::ostream& operator<<(std::ostream& out, ResType t); 23 + 24 + struct ResRef : public std::pair<ResType, short> 25 + { 26 + ResRef() : std::pair<ResType, short>(ResType(), 0) {} 27 + ResRef(ResType t, int id) : std::pair<ResType, short>(t,id) {} 28 + 29 + ResType& type() { return first; } 30 + ResType type() const { return first; } 31 + short& id() { return second; } 32 + short id() const { return second; } 33 + }; 34 + 35 + #endif // RESTYPE_H
+586
src/buildtools/Rez/ResourceFiles/ResourceFile.cc
··· 1 + #include "ResourceFile.h" 2 + #include "BinaryIO.h" 3 + 4 + #include <boost/filesystem.hpp> 5 + #include "boost/filesystem/fstream.hpp" 6 + #include <sstream> 7 + #include <iostream> 8 + 9 + #ifdef __APPLE__ 10 + #include <sys/xattr.h> 11 + #endif 12 + extern "C" { 13 + #include "hfs.h" 14 + } 15 + 16 + namespace fs = boost::filesystem; 17 + 18 + // CRC 16 table lookup array 19 + static unsigned short CRC16Table[256] = 20 + {0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, 21 + 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF, 22 + 0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6, 23 + 0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE, 24 + 0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485, 25 + 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D, 26 + 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4, 27 + 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC, 28 + 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823, 29 + 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B, 30 + 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12, 31 + 0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A, 32 + 0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41, 33 + 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49, 34 + 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70, 35 + 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78, 36 + 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F, 37 + 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067, 38 + 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E, 39 + 0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256, 40 + 0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D, 41 + 0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, 42 + 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C, 43 + 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634, 44 + 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB, 45 + 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3, 46 + 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A, 47 + 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92, 48 + 0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9, 49 + 0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1, 50 + 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8, 51 + 0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0}; 52 + 53 + // CalculateCRC 54 + static unsigned short CalculateCRC(unsigned short CRC, const char* dataBlock, int dataSize) 55 + { 56 + while (dataSize) 57 + { 58 + CRC = (CRC << 8) ^ CRC16Table[((*dataBlock) ^ (CRC >> 8)) & 0x00FF]; 59 + dataBlock++; 60 + dataSize--; 61 + } 62 + 63 + return CRC; 64 + } 65 + 66 + static void writeMacBinary(std::ostream& out, std::string filename, 67 + ResType type, ResType creator, 68 + const Resources& rsrc, const std::string& data) 69 + { 70 + 71 + std::ostringstream resstream; 72 + rsrc.writeFork(resstream); 73 + 74 + const std::string& rsrcBytes = resstream.str(); 75 + 76 + 77 + std::ostringstream header; 78 + byte(header, 0); 79 + byte(header, filename.size()); 80 + header << filename; 81 + while((int)header.tellp() < 65) 82 + byte(header,0); 83 + ostype(header, type); 84 + ostype(header, creator); 85 + byte(header, 0); // flags 86 + byte(header, 0); 87 + word(header, 0); // position.v 88 + word(header, 0); // position.h 89 + word(header, 0); // folder id 90 + byte(header, 0); // protected flag 91 + byte(header, 0); 92 + longword(header, (int)data.size()); 93 + longword(header, (int)rsrcBytes.size()); 94 + longword(header, 0); // creation date 95 + longword(header, 0); // modification date 96 + while((int)header.tellp() < 124) 97 + byte(header,0); 98 + std::string headerData = header.str(); 99 + out << headerData; 100 + word(out, CalculateCRC(0, &headerData[0], headerData.size())); 101 + word(out, 0); 102 + out << data; 103 + while((int)out.tellp() % 128) 104 + byte(out,0); 105 + rsrc.writeFork(out); 106 + while((int)out.tellp() % 128) 107 + byte(out,0); 108 + } 109 + 110 + bool ResourceFile::read(std::string path, Format f) 111 + { 112 + if(!assign(path, f)) 113 + return false; 114 + return read(); 115 + } 116 + 117 + bool ResourceFile::write(std::string path, Format f) 118 + { 119 + if(!assign(path, f)) 120 + return false; 121 + return write(); 122 + } 123 + 124 + static bool CheckAppleDouble(fs::path path, std::string prefix) 125 + { 126 + fs::path adPath = path.parent_path() / (prefix + path.filename().string()); 127 + fs::ifstream in(adPath); 128 + if(in) 129 + { 130 + int magic1 = longword(in); 131 + 132 + if(in && magic1 == 0x00051607) 133 + { 134 + int magic2 = longword(in); 135 + if(in && magic2 == 0x00020000) 136 + return true; 137 + } 138 + } 139 + return false; 140 + } 141 + 142 + bool ResourceFile::assign(std::string pathstring, ResourceFile::Format f) 143 + { 144 + this->pathstring = pathstring; 145 + fs::path path(pathstring); 146 + 147 + this->filename = path.stem().string(); 148 + fs::path rsrcPath = path.parent_path() / ".rsrc" / path.filename(); 149 + fs::path finfPath = path.parent_path() / ".finf" / path.filename(); 150 + 151 + format = f; 152 + if(format == Format::autodetect) 153 + { 154 + if(path.extension() == ".bin") 155 + format = Format::macbin; 156 + else if(path.extension() == ".as") 157 + format = Format::applesingle; 158 + else if(path.extension() == ".dsk") 159 + format = Format::diskimage; 160 + else if(path.filename().string().substr(0,2) == "._") 161 + { 162 + path = path.parent_path() / path.filename().string().substr(2); 163 + format = Format::underscore_appledouble; 164 + this->pathstring = path.string(); 165 + } 166 + else if(path.filename().string()[0] == '%') 167 + { 168 + path = path.parent_path() / path.filename().string().substr(1); 169 + format = Format::percent_appledouble; 170 + this->pathstring = path.string(); 171 + } 172 + //else if(fs::exists(rsrcPath)) 173 + // format = Format::basilisk; 174 + } 175 + if(format == Format::autodetect) 176 + { 177 + if(CheckAppleDouble(path, "._")) 178 + format = Format::underscore_appledouble; 179 + if(CheckAppleDouble(path, "%")) 180 + format = Format::percent_appledouble; 181 + } 182 + if(format == Format::autodetect) 183 + { 184 + fs::ifstream in(path); 185 + if(in) 186 + { 187 + int magic1 = longword(in); 188 + if(in && magic1 == 0x00051600) 189 + { 190 + int magic2 = longword(in); 191 + if(in && magic2 == 0x00020000) 192 + format = Format::applesingle; 193 + } 194 + } 195 + } 196 + if(format == Format::autodetect) 197 + { 198 + #ifdef __APPLE__ 199 + format = Format::real; 200 + #else 201 + format = Format::basilisk; 202 + #endif 203 + } 204 + // std::cout << "assigned: " << pathstring << " format " << (int)format << "\n"; 205 + return true; 206 + } 207 + 208 + bool ResourceFile::read(std::istream& in, Format f) 209 + { 210 + switch(f) 211 + { 212 + case Format::applesingle: 213 + { 214 + if(longword(in) != 0x00051600) 215 + return false; 216 + if(longword(in) != 0x00020000) 217 + return false; 218 + in.seekg(24); 219 + int n = word(in); 220 + for(int i = 0; i < n; i++) 221 + { 222 + in.seekg(26 + i * 12); 223 + int what = longword(in); 224 + int off = longword(in); 225 + int len = longword(in); 226 + in.seekg(off); 227 + switch(what) 228 + { 229 + case 1: 230 + { 231 + std::vector<char> buf(len); 232 + in.read(buf.data(), len); 233 + data = std::string(buf.begin(), buf.end()); 234 + } 235 + break; 236 + case 2: 237 + resources = Resources(in); 238 + break; 239 + case 9: 240 + type = ostype(in); 241 + creator = ostype(in); 242 + break; 243 + } 244 + } 245 + } 246 + break; 247 + case Format::macbin: 248 + { 249 + if(byte(in) != 0) 250 + return false; 251 + if(byte(in) > 63) 252 + return false; 253 + in.seekg(65); 254 + type = ostype(in); 255 + creator = ostype(in); 256 + in.seekg(83); 257 + int datasize = longword(in); 258 + //int rsrcsize = longword(in); 259 + 260 + in.seekg(0); 261 + char header[124]; 262 + in.read(header, 124); 263 + unsigned short crc = CalculateCRC(0,header,124); 264 + if(word(in) != crc) 265 + return false; 266 + in.seekg(128); 267 + std::vector<char> buf(datasize); 268 + in.read(buf.data(), datasize); 269 + data = std::string(buf.begin(), buf.end()); 270 + datasize = ((int)datasize + 0x7F) & ~0x7F; 271 + in.seekg(128 + datasize); 272 + resources = Resources(in); 273 + } 274 + break; 275 + default: 276 + return false; 277 + } 278 + return true; 279 + } 280 + 281 + bool ResourceFile::read() 282 + { 283 + fs::path path(pathstring); 284 + 285 + type = creator = 0x3F3F3F3F; 286 + 287 + if(isSingleFork(format)) 288 + { 289 + fs::ifstream in(path); 290 + return read(in, format); 291 + } 292 + 293 + switch(format) 294 + { 295 + case Format::basilisk: 296 + { 297 + fs::ifstream dataIn(path); 298 + if(!dataIn) 299 + return false; 300 + data = std::string(std::istreambuf_iterator<char>(dataIn), 301 + std::istreambuf_iterator<char>()); 302 + 303 + fs::ifstream rsrcIn(path.parent_path() / ".rsrc" / path.filename()); 304 + if(rsrcIn) 305 + resources = Resources(rsrcIn); 306 + fs::ifstream finfIn(path.parent_path() / ".finf" / path.filename()); 307 + if(finfIn) 308 + { 309 + type = ostype(finfIn); 310 + creator = ostype(finfIn); 311 + } 312 + } 313 + break; 314 + #ifdef __APPLE__ 315 + case Format::real: 316 + { 317 + fs::ifstream dataIn(path); 318 + if(!dataIn) 319 + return false; 320 + data = std::string(std::istreambuf_iterator<char>(dataIn), 321 + std::istreambuf_iterator<char>()); 322 + fs::ifstream rsrcIn(path / "..namedfork" / "rsrc"); 323 + if(rsrcIn) 324 + resources = Resources(rsrcIn); 325 + 326 + char finf[32]; 327 + int n = getxattr(path.c_str(), XATTR_FINDERINFO_NAME, 328 + finf, 32, 0, 0); 329 + if(n > 0) 330 + { 331 + std::istringstream finfIn(std::string(finf, finf+n)); 332 + type = ostype(finfIn); 333 + creator = ostype(finfIn); 334 + } 335 + } 336 + break; 337 + #endif 338 + 339 + case Format::underscore_appledouble: 340 + case Format::percent_appledouble: 341 + { 342 + fs::ifstream dataIn(path); 343 + data = std::string(std::istreambuf_iterator<char>(dataIn), 344 + std::istreambuf_iterator<char>()); 345 + 346 + std::string prefix = format == Format::underscore_appledouble ? 347 + "._" : "%"; 348 + 349 + fs::path adPath = path.parent_path() / (prefix + path.filename().string()); 350 + fs::ifstream in(adPath); 351 + if(longword(in) != 0x00051607) 352 + return false; 353 + if(longword(in) != 0x00020000) 354 + return false; 355 + in.seekg(24); 356 + int n = word(in); 357 + for(int i = 0; i < n; i++) 358 + { 359 + in.seekg(26 + i * 12); 360 + int what = longword(in); 361 + int off = longword(in); 362 + //int len = longword(in); 363 + in.seekg(off); 364 + switch(what) 365 + { 366 + case 2: 367 + resources = Resources(in); 368 + break; 369 + case 9: 370 + type = ostype(in); 371 + creator = ostype(in); 372 + break; 373 + } 374 + } 375 + } 376 + break; 377 + default: 378 + return false; 379 + } 380 + return true; 381 + } 382 + 383 + bool ResourceFile::write(std::ostream& out, Format f) 384 + { 385 + switch(f) 386 + { 387 + case Format::macbin: 388 + { 389 + writeMacBinary(out, filename, type, creator, resources, data); 390 + } 391 + break; 392 + case Format::applesingle: 393 + { 394 + longword(out, 0x00051600); 395 + longword(out, 0x00020000); 396 + for(int i = 0; i < 16; i++) 397 + byte(out, 0); 398 + word(out, 3); 399 + std::streampos entries = out.tellp(); 400 + for(int i = 0; i < 3*3; i++) 401 + longword(out, 0); 402 + std::streampos dataStart = out.tellp(); 403 + out << data; 404 + std::streampos rsrcStart = out.tellp(); 405 + resources.writeFork(out); 406 + std::streampos finfStart = out.tellp(); 407 + ostype(out, type); 408 + ostype(out, creator); 409 + for(int i = 8; i < 32; i++) 410 + byte(out, 0); 411 + out.seekp(entries); 412 + longword(out, 1); 413 + longword(out, dataStart); 414 + longword(out, rsrcStart - dataStart); 415 + longword(out, 2); 416 + longword(out, rsrcStart); 417 + longword(out, finfStart - rsrcStart); 418 + longword(out, 9); 419 + longword(out, finfStart); 420 + longword(out, 32); 421 + } 422 + break; 423 + default: 424 + return false; 425 + } 426 + return true; 427 + } 428 + 429 + bool ResourceFile::write() 430 + { 431 + fs::path path(pathstring); 432 + 433 + if(isSingleFork(format)) 434 + { 435 + fs::ofstream out(path); 436 + return write(out, format); 437 + } 438 + 439 + switch(format) 440 + { 441 + case Format::basilisk: 442 + { 443 + fs::create_directory(path.parent_path() / ".rsrc"); 444 + fs::create_directory(path.parent_path() / ".finf"); 445 + 446 + fs::ofstream dataOut(path); 447 + fs::ofstream rsrcOut(path.parent_path() / ".rsrc" / path.filename()); 448 + fs::ofstream finfOut(path.parent_path() / ".finf" / path.filename()); 449 + 450 + dataOut << data; 451 + resources.writeFork(rsrcOut); 452 + 453 + ostype(finfOut, type); 454 + ostype(finfOut, creator); 455 + for(int i = 8; i < 32; i++) 456 + byte(finfOut, 0); 457 + } 458 + break; 459 + #ifdef __APPLE__ 460 + case Format::real: 461 + { 462 + fs::ofstream dataOut(path); 463 + fs::ofstream rsrcOut(path / "..namedfork" / "rsrc"); 464 + std::ostringstream finfOut; 465 + 466 + dataOut << data; 467 + resources.writeFork(rsrcOut); 468 + 469 + ostype(finfOut, type); 470 + ostype(finfOut, creator); 471 + for(int i = 8; i < 32; i++) 472 + byte(finfOut, 0); 473 + setxattr(path.c_str(), XATTR_FINDERINFO_NAME, 474 + finfOut.str().data(), 32, 0, 0); 475 + } 476 + break; 477 + #endif 478 + 479 + case Format::underscore_appledouble: 480 + case Format::percent_appledouble: 481 + { 482 + fs::ofstream dataOut(path); 483 + 484 + dataOut << data; 485 + 486 + std::string prefix = format == Format::underscore_appledouble ? 487 + "._" : "%"; 488 + 489 + fs::path adPath = path.parent_path() / (prefix + path.filename().string()); 490 + 491 + fs::ofstream out(adPath); 492 + 493 + longword(out, 0x00051607); 494 + longword(out, 0x00020000); 495 + 496 + for(int i = 0; i < 16; i++) 497 + byte(out, 0); 498 + word(out, 2); 499 + std::streampos entries = out.tellp(); 500 + for(int i = 0; i < 2*3; i++) 501 + longword(out, 0); 502 + std::streampos rsrcStart = out.tellp(); 503 + resources.writeFork(out); 504 + std::streampos finfStart = out.tellp(); 505 + ostype(out, type); 506 + ostype(out, creator); 507 + for(int i = 8; i < 32; i++) 508 + byte(out, 0); 509 + out.seekp(entries); 510 + longword(out, 2); 511 + longword(out, rsrcStart); 512 + longword(out, finfStart - rsrcStart); 513 + longword(out, 9); 514 + longword(out, finfStart); 515 + longword(out, 32); 516 + } 517 + break; 518 + 519 + case Format::diskimage: 520 + { 521 + std::ostringstream rsrcOut; 522 + resources.writeFork(rsrcOut); 523 + std::string rsrc = rsrcOut.str(); 524 + int size = rsrc.size(); 525 + 526 + size += 20 * 1024; 527 + size += 800*1024 - size % (800*1024); 528 + 529 + fs::ofstream(path, std::ios::binary | std::ios::trunc).seekp(size-1).put(0); 530 + 531 + hfs_format(pathstring.c_str(), 0, 0, path.stem().string().substr(0,27).c_str(), 0, NULL); 532 + hfsvol *vol = hfs_mount(pathstring.c_str(), 0, HFS_MODE_RDWR); 533 + if(!vol) 534 + return false; 535 + //hfs_setvol(vol, ) 536 + hfsfile *file = hfs_create(vol, (path.stem().string().substr(0,31)).c_str(), 537 + ((std::string)type).c_str(), ((std::string)creator).c_str()); 538 + hfs_setfork(file, 0); 539 + hfs_write(file, data.data(), data.size()); 540 + hfs_setfork(file, 1); 541 + hfs_write(file, rsrc.data(), rsrc.size()); 542 + 543 + hfs_close(file); 544 + hfs_umount(vol); 545 + 546 + } 547 + break; 548 + 549 + default: 550 + return false; 551 + } 552 + return true; 553 + } 554 + 555 + bool ResourceFile::hasPlainDataFork(ResourceFile::Format f) 556 + { 557 + switch(f) 558 + { 559 + #ifdef __APPLE__ 560 + case Format::real: 561 + #endif 562 + case Format::basilisk: 563 + case Format::underscore_appledouble: 564 + case Format::percent_appledouble: 565 + return true; 566 + default: 567 + return false; 568 + } 569 + } 570 + 571 + bool ResourceFile::hasPlainDataFork() 572 + { 573 + return hasPlainDataFork(format); 574 + } 575 + 576 + bool ResourceFile::isSingleFork(Format f) 577 + { 578 + switch(f) 579 + { 580 + case Format::macbin: 581 + case Format::applesingle: 582 + return true; 583 + default: 584 + return false; 585 + } 586 + }
+53
src/buildtools/Rez/ResourceFiles/ResourceFile.h
··· 1 + #ifndef RESOURCEFILE_H 2 + #define RESOURCEFILE_H 3 + 4 + #include <memory> 5 + #include <iosfwd> 6 + #include <string> 7 + 8 + #include "ResType.h" 9 + #include "ResourceFork.h" 10 + 11 + class ResourceFile 12 + { 13 + public: 14 + enum class Format 15 + { 16 + autodetect, 17 + #ifdef __APPLE__ 18 + real, 19 + #endif 20 + macbin, 21 + diskimage, 22 + basilisk, 23 + applesingle, 24 + underscore_appledouble, 25 + percent_appledouble 26 + }; 27 + 28 + bool read(std::string path, Format f = Format::autodetect); 29 + bool write(std::string path, Format f = Format::autodetect); 30 + bool read(std::istream& in, Format f); 31 + bool write(std::ostream& in, Format f); 32 + static bool hasPlainDataFork(Format f); 33 + bool hasPlainDataFork(); 34 + Format getFormat() { return format; } 35 + 36 + static bool isSingleFork(Format f); 37 + 38 + ResType type; 39 + ResType creator; 40 + Resources resources; 41 + std::string data; 42 + 43 + private: 44 + bool assign(std::string path, Format f = Format::autodetect); 45 + bool read(); 46 + bool write(); 47 + 48 + std::string pathstring; 49 + std::string filename; 50 + Format format = Format::autodetect; 51 + }; 52 + 53 + #endif // RESOURCEFILE_H
+162
src/buildtools/Rez/ResourceFiles/ResourceFork.cc
··· 1 + #include "ResourceFork.h" 2 + #include "BinaryIO.h" 3 + 4 + #include <iostream> 5 + #include <map> 6 + #include <vector> 7 + 8 + void Resources::addResources(const Resources& res) 9 + { 10 + for(auto& rr : res.resources) 11 + addResource(rr.second); 12 + } 13 + 14 + void Resources::writeFork(std::ostream& out) const 15 + { 16 + std::streampos start = out.tellp(); 17 + longword(out,0x100); 18 + longword(out,0); 19 + longword(out,0); 20 + longword(out,0); 21 + for(int i = 0; i < 0x100 - 16; i++) 22 + byte(out, 0); 23 + 24 + std::map< ResType, std::map<int, int> > resourceInfos; 25 + std::streampos datastart = out.tellp(); 26 + for(auto& rr : resources) 27 + { 28 + const Resource& r = rr.second; 29 + const std::string& data = r.getData(); 30 + unsigned offset = out.tellp() - datastart; 31 + offset = (r.getAttr() << 24) | (offset & 0xFFFFFF); 32 + resourceInfos[ r.getType() ][ r.getID() ] = (int)offset; 33 + longword(out, data.size()); 34 + out << data; 35 + } 36 + std::streampos dataend = out.tellp(); 37 + // while(out.tellp() % 0x100) 38 + // out.put(0); 39 + std::streampos resmap = out.tellp(); 40 + for(int i = 0; i < 16+4+2+2; i++) 41 + byte(out, 0); 42 + word(out,16+4+2+2+2+2); // offset to resource type list 43 + std::streampos resnameOffset = out.tellp(); 44 + word(out,0); 45 + std::streampos typelist = out.tellp(); 46 + word(out,resourceInfos.size() - 1); 47 + for(std::map< ResType, std::map<int, int> >::iterator p = resourceInfos.begin(); 48 + p != resourceInfos.end(); ++p) 49 + { 50 + if(p->second.size()) 51 + { 52 + ostype(out,p->first); 53 + word(out,p->second.size()-1); 54 + word(out,0); // replaced later 55 + } 56 + } 57 + int typeIndex = 0; 58 + int nameOffset = 0; 59 + for(std::map< ResType, std::map<int, int> >::iterator p = resourceInfos.begin(); 60 + p != resourceInfos.end(); ++p) 61 + { 62 + if(p->second.size()) 63 + { 64 + std::streampos pos = out.tellp(); 65 + out.seekp((int)typelist + 2 + 8 * typeIndex + 6); 66 + word(out, pos - typelist); 67 + out.seekp(pos); 68 + typeIndex++; 69 + 70 + for(std::map<int,int>::iterator q = p->second.begin(); q != p->second.end(); ++q) 71 + { 72 + std::string name = resources.find(ResRef(p->first, q->first))->second.getName(); 73 + word(out,q->first); 74 + if(name.size() == 0) 75 + word(out,-1); 76 + else 77 + { 78 + word(out, nameOffset); 79 + nameOffset += (name.size() > 255 ? 255 : name.size()) + 1; 80 + } 81 + longword(out,q->second); 82 + longword(out,0); 83 + } 84 + } 85 + } 86 + std::streampos resnames = out.tellp(); 87 + out.seekp(resnameOffset); 88 + word(out, resnames - resmap); 89 + out.seekp(resnames); 90 + 91 + for(std::map< ResType, std::map<int, int> >::iterator p = resourceInfos.begin(); 92 + p != resourceInfos.end(); ++p) 93 + { 94 + for(std::map<int,int>::iterator q = p->second.begin(); q != p->second.end(); ++q) 95 + { 96 + std::string name = resources.find(ResRef(p->first, q->first))->second.getName(); 97 + if(name.size() > 0) 98 + { 99 + int sz = name.size() > 255 ? 255 : name.size(); 100 + byte(out, sz); 101 + for(int i = 0; i < sz; i++) 102 + byte(out, name[i]); 103 + } 104 + } 105 + } 106 + 107 + std::streampos end = out.tellp(); 108 + out.seekp(start + std::streampos(4)); 109 + longword(out, resmap - start); 110 + longword(out, dataend - start - std::streampos(0x100)); 111 + longword(out, end - resmap); 112 + out.seekp(end); 113 + } 114 + 115 + Resources::Resources(std::istream &in) 116 + { 117 + std::streampos start = in.tellg(); 118 + int resdataOffset = longword(in); 119 + int resmapOffset = longword(in); 120 + 121 + in.seekg(start + std::streampos(resmapOffset + 16 + 4 + 2 + 2)); 122 + int typeListOffset = word(in); 123 + int nameListOffset = word(in); 124 + int nTypes = (word(in) + 1) & 0xFFFF; 125 + 126 + for(int i = 0; i < nTypes; i++) 127 + { 128 + in.seekg(start + std::streampos(resmapOffset + typeListOffset + 2 + i * 8)); 129 + std::string type = ostype(in); 130 + int nRes = (word(in) + 1) & 0xFFFF; 131 + int refListOffset = word(in); 132 + 133 + for(int j = 0; j < nRes; j++) 134 + { 135 + in.seekg(start + std::streampos(resmapOffset + typeListOffset + refListOffset + j * 12)); 136 + int id = (short) word(in); 137 + int nameOffset = word(in); 138 + int attr = byte(in); 139 + int off1 = byte(in); 140 + int off2 = byte(in); 141 + int off3 = byte(in); 142 + int offset = (off1 << 16) | (off2 << 8) | off3; 143 + std::string name; 144 + if(nameOffset != 0xFFFF) 145 + { 146 + in.seekg(start + std::streampos(resmapOffset + nameListOffset + nameOffset)); 147 + int nameLen = byte(in); 148 + char buf[256]; 149 + in.read(buf, nameLen); 150 + name = std::string(buf, nameLen); 151 + } 152 + 153 + in.seekg(start + std::streampos(resdataOffset + offset)); 154 + int size = longword(in); 155 + std::vector<char> tmp(size); 156 + in.read(tmp.data(), size); 157 + std::string data(tmp.data(), size); 158 + 159 + addResource(Resource(type, id, data, name, attr)); 160 + } 161 + } 162 + }
+49
src/buildtools/Rez/ResourceFiles/ResourceFork.h
··· 1 + #ifndef RESOURCEFORK_H 2 + #define RESOURCEFORK_H 3 + 4 + #include <string> 5 + #include <map> 6 + #include "ResType.h" 7 + 8 + class Resource 9 + { 10 + ResType type; 11 + short id; 12 + std::string name; 13 + std::string data; 14 + int attr; 15 + public: 16 + Resource() {} 17 + Resource(ResType type, int id, std::string data, std::string name = "", int attr = 0) 18 + : type(type), id(id), name(name), data(data), attr(attr) {} 19 + 20 + const std::string& getData() const { return data; } 21 + inline ResType getType() const { return type; } 22 + inline int getID() const { return id; } 23 + inline ResRef getTypeAndID() const { return ResRef(type, id); } 24 + std::string getName() const { return name; } 25 + int getAttr() const { return attr; } 26 + }; 27 + 28 + class Fork 29 + { 30 + public: 31 + virtual void writeFork(std::ostream& out) const { } 32 + virtual ~Fork() {} 33 + }; 34 + 35 + class Resources : public Fork 36 + { 37 + public: 38 + std::map<ResRef, Resource> resources; 39 + 40 + Resources() {} 41 + Resources(std::istream& in); 42 + void writeFork(std::ostream& out) const; 43 + void addResource(Resource res) { resources[res.getTypeAndID()] = res; } 44 + void addResources(const Resources& res); 45 + 46 + unsigned countResources() const { return resources.size(); } 47 + }; 48 + 49 + #endif // RESOURCEFORK_H
+174
src/buildtools/Rez/Rez.cc
··· 1 + #include <iostream> 2 + #include "boost/program_options.hpp" 3 + #include "boost/filesystem.hpp" 4 + #include "boost/filesystem/fstream.hpp" 5 + 6 + #include "RezParser.generated.hh" 7 + #include "RezLexer.h" 8 + #include "RezWorld.h" 9 + 10 + #include "ResourceFork.h" 11 + #include "BinaryIO.h" 12 + #include "ResourceFile.h" 13 + #include "Diagnostic.h" 14 + 15 + namespace po = boost::program_options; 16 + namespace fs = boost::filesystem; 17 + 18 + static po::options_description desc; 19 + 20 + static void usage() 21 + { 22 + std::cerr << "Usage: " << "Rez [options] input-file\n"; 23 + std::cerr << desc << std::endl; 24 + } 25 + 26 + static void CopyBinaryResources(RezWorld& world, const std::string& fn) 27 + { 28 + ResourceFile copyRsrc; 29 + if(!copyRsrc.read(fn)) 30 + { 31 + world.problem(Diagnostic(Diagnostic::error, "Could not read binary resource file " + fn, yy::location())); 32 + } 33 + else if(world.verboseFlag) 34 + { 35 + std::cerr << "Read " << copyRsrc.resources.countResources() << " resources from " << fn << "\n"; 36 + } 37 + 38 + world.getResources().addResources(copyRsrc.resources); 39 + } 40 + 41 + int main(int argc, const char *argv[]) 42 + { 43 + desc.add_options() 44 + ("help,h", "show this help message") 45 + ("output,o", po::value<std::string>()->default_value("rez.output.rsrc"), "output file") 46 + ("append,a", "append to existing output file") 47 + ("type,t", po::value<std::string>()->default_value("rsrc"), "output file finder type code") 48 + ("creator,c", po::value<std::string>()->default_value("RSED"), "output file finder creator code") 49 + ("define,D", po::value<std::vector<std::string>>(), "predefine preprocessor symbol") 50 + ("include,I", po::value<std::vector<std::string>>(), "add include file path") 51 + ("copy", po::value<std::vector<std::string>>(), "copy resources from other resource file") 52 + ("cc", po::value<std::vector<std::string>>(), "also write output to another file") 53 + ("debug,d", "debug logging") 54 + ("data", po::value<std::string>(), "copy data fork from another file") 55 + ; 56 + po::options_description hidden, alldesc; 57 + hidden.add_options() 58 + ("input", po::value<std::vector<std::string>>(), "input file" ) 59 + ; 60 + alldesc.add(desc).add(hidden); 61 + 62 + po::variables_map options; 63 + try 64 + { 65 + auto parsed = po::command_line_parser(argc, argv) 66 + .options(alldesc) 67 + .positional(po::positional_options_description().add("input", -1)) 68 + .style(po::command_line_style::default_style) 69 + .run(); 70 + 71 + po::store(parsed, options); 72 + } 73 + catch(po::error& e) 74 + { 75 + std::cerr << "ERROR: " << e.what() << std::endl << std::endl; 76 + usage(); 77 + return 1; 78 + } 79 + 80 + po::notify(options); 81 + 82 + if(options.count("help") 83 + || (!options.count("input") && !options.count("copy") 84 + && !options.count("output"))) 85 + { 86 + usage(); 87 + return 0; 88 + } 89 + 90 + RezWorld world; 91 + 92 + if(options.count("debug")) 93 + world.verboseFlag = true; 94 + 95 + std::string outfile = options["output"].as<std::string>(); 96 + ResourceFile rsrcFile; 97 + 98 + if(options.count("append")) 99 + { 100 + rsrcFile.read(outfile); 101 + 102 + world.getResources().addResources(rsrcFile.resources); 103 + } 104 + 105 + if(options.count("data")) 106 + { 107 + std::string fn = options["data"].as<std::string>(); 108 + ResourceFile dataFile; 109 + if(!dataFile.read(fn)) 110 + world.problem(Diagnostic(Diagnostic::error, "Could not read dataresource file " + fn, yy::location())); 111 + rsrcFile.data = dataFile.data; 112 + } 113 + 114 + if(options.count("copy")) 115 + for(std::string fn : options["copy"].as<std::vector<std::string>>()) 116 + CopyBinaryResources(world, fn); 117 + 118 + if(options.count("input")) 119 + for(std::string fn : options["input"].as<std::vector<std::string>>()) 120 + { 121 + fs::path path(fn); 122 + if(path.extension() == ".rsrc" || path.extension() == ".bin") 123 + { 124 + CopyBinaryResources(world, fn); 125 + } 126 + else 127 + { 128 + try 129 + { 130 + RezLexer lexer(world, fn); 131 + 132 + if(options.count("define")) 133 + for(std::string define : options["define"].as<std::vector<std::string>>()) 134 + lexer.addDefine(define); 135 + if(options.count("include")) 136 + for(std::string path : options["include"].as<std::vector<std::string>>()) 137 + lexer.addIncludePath(path); 138 + 139 + if(world.verboseFlag) 140 + { 141 + std::cerr << "Compiling " << fn << "...\n"; 142 + } 143 + 144 + RezParser parser(lexer, world); 145 + parser.parse(); 146 + } 147 + catch(...) 148 + { 149 + world.problem(Diagnostic(Diagnostic::fatalError,"unknown error",yy::location(&fn))); 150 + } 151 + } 152 + } 153 + 154 + if(world.hadErrors) 155 + return 1; 156 + 157 + rsrcFile.resources = world.getResources(); 158 + rsrcFile.creator = options["creator"].as<std::string>(); 159 + rsrcFile.type = options["type"].as<std::string>(); 160 + 161 + if(world.verboseFlag) 162 + { 163 + std::cerr << "Writing " << rsrcFile.resources.countResources() << " resources.\n"; 164 + } 165 + rsrcFile.write(outfile); 166 + 167 + if(options.count("cc")) 168 + for(std::string ccFile : options["cc"].as<std::vector<std::string>>()) 169 + { 170 + rsrcFile.write(ccFile); 171 + } 172 + 173 + return 0; 174 + }
+192
src/buildtools/Rez/RezLexer.cc
··· 1 + #include "RezLexer.h" 2 + 3 + #include <boost/wave.hpp> 4 + #include <boost/wave/cpplexer/cpp_lex_iterator.hpp> 5 + #include <boost/wave/token_ids.hpp> 6 + #include <boost/regex.hpp> 7 + 8 + #include "RezLexerWaveToken.h" 9 + #include "RezWorld.h" 10 + #include "Diagnostic.h" 11 + 12 + namespace wave = boost::wave; 13 + 14 + using namespace boost::wave; 15 + 16 + static std::string readContents(std::istream&& instream) 17 + { 18 + instream.unsetf(std::ios::skipws); 19 + 20 + return std::string(std::istreambuf_iterator<char>(instream.rdbuf()), 21 + std::istreambuf_iterator<char>()); 22 + } 23 + 24 + static std::string preFilter(std::string str) 25 + { 26 + boost::regex endif("#endif[^\r\n]*"); 27 + str = boost::regex_replace(str, endif, "#endif"); 28 + 29 + boost::regex dollar_escape("\\\\\\$([a-zA-Z0-9][a-zA-Z0-9])"); 30 + str = boost::regex_replace(str, dollar_escape, "\\\\0x$1"); 31 + 32 + if(str.size() == 0 || str[str.size()-1] != '\n') 33 + str += "\n"; 34 + return str; 35 + } 36 + 37 + struct load_file_to_string_filtered 38 + { 39 + template <typename IterContextT> 40 + class inner 41 + { 42 + public: 43 + template <typename PositionT> 44 + static void init_iterators(IterContextT &iter_ctx, 45 + PositionT const &act_pos, language_support language) 46 + { 47 + typedef typename IterContextT::iterator_type iterator_type; 48 + 49 + // read in the file 50 + std::ifstream instream(iter_ctx.filename.c_str()); 51 + if (!instream.is_open()) { 52 + BOOST_WAVE_THROW_CTX(iter_ctx.ctx, preprocess_exception, 53 + bad_include_file, iter_ctx.filename.c_str(), act_pos); 54 + return; 55 + } 56 + 57 + iter_ctx.instring = preFilter(readContents(std::move(instream))); 58 + 59 + iter_ctx.first = iterator_type( 60 + iter_ctx.instring.begin(), iter_ctx.instring.end(), 61 + PositionT(iter_ctx.filename), language); 62 + iter_ctx.last = iterator_type(); 63 + } 64 + 65 + private: 66 + std::string instring; 67 + }; 68 + }; 69 + 70 + 71 + 72 + typedef wave::cpplexer::lex_iterator< 73 + wave::cpplexer::lex_token<> > 74 + lex_iterator_type; 75 + typedef wave::context< 76 + std::string::iterator, lex_iterator_type, 77 + load_file_to_string_filtered> 78 + context_type; 79 + typedef context_type::iterator_type pp_iterator_type; 80 + 81 + struct RezLexer::Priv 82 + { 83 + std::string input; 84 + context_type ctx; 85 + pp_iterator_type iter; 86 + 87 + Priv(std::string data, std::string name) 88 + : input(data), ctx(input.begin(), input.end(), name.c_str()) 89 + { 90 + } 91 + }; 92 + 93 + static std::string readInitial(RezWorld& world, std::string filename) 94 + { 95 + std::ifstream in(filename); 96 + if(!in.is_open()) 97 + { 98 + world.problem(Diagnostic(Diagnostic::error, 99 + "could not open " + filename, yy::location())); 100 + } 101 + return readContents(std::move(in)); 102 + } 103 + 104 + RezLexer::RezLexer(RezWorld& world, std::string filename) 105 + : RezLexer(world, filename, readInitial(world,filename)) 106 + { 107 + } 108 + 109 + 110 + 111 + RezLexer::RezLexer(RezWorld& world, std::string filename, const std::string &data) 112 + : world(world), curFile(filename), lastLocation(&curFile) 113 + { 114 + pImpl.reset(new Priv(preFilter(data), filename)); 115 + 116 + pImpl->ctx.add_macro_definition("DeRez=0"); 117 + pImpl->ctx.add_macro_definition("Rez=1"); 118 + pImpl->ctx.add_macro_definition("true=1"); 119 + pImpl->ctx.add_macro_definition("false=0"); 120 + pImpl->ctx.add_macro_definition("TRUE=1"); 121 + pImpl->ctx.add_macro_definition("FALSE=0"); 122 + 123 + pImpl->iter = pImpl->ctx.begin(); 124 + } 125 + 126 + RezLexer::~RezLexer() 127 + { 128 + 129 + } 130 + 131 + 132 + 133 + void RezLexer::addDefine(std::string str) 134 + { 135 + pImpl->ctx.add_macro_definition(str); 136 + } 137 + 138 + void RezLexer::addIncludePath(std::string path) 139 + { 140 + std::size_t pos = path.find(':'); 141 + if(pos == std::string::npos) 142 + { 143 + pImpl->ctx.add_include_path(path.c_str()); 144 + } 145 + else 146 + { 147 + addIncludePath(path.substr(0,pos)); 148 + addIncludePath(path.substr(pos + 1)); 149 + } 150 + } 151 + 152 + bool RezLexer::atEnd() 153 + { 154 + return pImpl->iter == pImpl->ctx.end(); 155 + } 156 + 157 + RezLexer::WaveToken RezLexer::nextWave() 158 + { 159 + try 160 + { 161 + if(pImpl->iter == pImpl->ctx.end()) 162 + return WaveToken(); 163 + else 164 + { 165 + WaveToken tok = *pImpl->iter++; 166 + return tok; 167 + } 168 + } 169 + catch(const preprocess_exception& e) 170 + { 171 + curFile = e.file_name(); 172 + auto yypos = yy::position(&curFile, e.line_no(), e.column_no()); 173 + yy::location loc(yypos); 174 + lastLocation = loc; 175 + 176 + world.problem(Diagnostic( 177 + e.severity_level(e.get_errorcode()) >= util::severity_error 178 + ? Diagnostic::error 179 + : Diagnostic::warning, 180 + preprocess_exception::error_text(e.get_errorcode()), loc)); 181 + if(e.is_recoverable()) 182 + return nextWave(); 183 + else 184 + return WaveToken(); 185 + } 186 + } 187 + 188 + RezLexer::WaveToken RezLexer::peekWave() 189 + { 190 + return pImpl->iter == pImpl->ctx.end() ? WaveToken() : *pImpl->iter; 191 + } 192 +
+38
src/buildtools/Rez/RezLexer.h
··· 1 + #ifndef REZLEXER_H 2 + #define REZLEXER_H 3 + 4 + #include <memory> 5 + #include <string> 6 + 7 + #include "location.hh" 8 + 9 + class RezSymbol; 10 + class RezWorld; 11 + 12 + class RezLexer 13 + { 14 + RezWorld& world; 15 + struct Priv; 16 + std::unique_ptr<Priv> pImpl; 17 + 18 + std::string curFile; 19 + yy::location lastLocation; 20 + 21 + class WaveToken; 22 + 23 + bool atEnd(); 24 + WaveToken nextWave(); 25 + WaveToken peekWave(); 26 + 27 + public: 28 + RezLexer(RezWorld& world, std::string filename); 29 + RezLexer(RezWorld& world, std::string filename, const std::string& data); 30 + ~RezLexer(); 31 + 32 + RezSymbol nextToken(); 33 + 34 + void addDefine(std::string str); 35 + void addIncludePath(std::string path); 36 + }; 37 + 38 + #endif // REZLEXER_H
+295
src/buildtools/Rez/RezLexerNextToken.cc
··· 1 + #include "RezLexer.h" 2 + #include "RezLexerWaveToken.h" 3 + #include "RezParser.generated.hh" 4 + #include <unordered_map> 5 + 6 + #include <boost/regex.hpp> 7 + 8 + using namespace boost::wave; 9 + 10 + static int readInt(const char *str, const char *end = NULL, int baseOverride = 0) 11 + { 12 + int x = 0; 13 + 14 + int base = 10; 15 + 16 + if(baseOverride) 17 + base = baseOverride; 18 + else if(*str == '0') 19 + { 20 + base = 8; 21 + ++str; 22 + if(*str == 'x' || *str == 'X') 23 + { 24 + base = 16; 25 + ++str; 26 + } 27 + if(*str == 'b' || *str == 'B') 28 + { 29 + base = 2; 30 + ++str; 31 + } 32 + } 33 + else if(*str == 'b' || *str == 'B') 34 + { 35 + base = 2; 36 + ++str; 37 + } 38 + 39 + while(str != end && *str) 40 + { 41 + x *= base; 42 + if(*str >= 'a' && *str <= 'z') 43 + x += *str - 'a' + 10; 44 + else if(*str >= 'A' && *str <= 'Z') 45 + x += *str - 'A' + 10; 46 + else if(*str >= '0' && *str <= '9') 47 + x += *str - '0'; 48 + str++; 49 + } 50 + 51 + return x; 52 + } 53 + 54 + static int readCharLit(const char *str) 55 + { 56 + const char *p = str + 1; 57 + const char *e = str + strlen(str) - 1; 58 + 59 + if(e - p != 4) 60 + std::cout << "warning: CHAR LITERAL " << str << "\n"; 61 + 62 + int x = 0; 63 + while(p != e) 64 + { 65 + x <<= 8; 66 + x |= (*p) & 0xFF; 67 + ++p; 68 + } 69 + return x; 70 + } 71 + 72 + static std::string readStringLit(const char *str) 73 + { 74 + const char *p = str + 1; 75 + const char *e = str + strlen(str) - 1; 76 + 77 + std::ostringstream out; 78 + 79 + while(p != e) 80 + { 81 + if(*p == '\\') 82 + { 83 + ++p; 84 + if(p != e) 85 + { 86 + switch(*p) 87 + { 88 + case 'n': 89 + out << '\n'; ++p; 90 + break; 91 + case 'r': 92 + out << '\r'; ++p; 93 + break; 94 + case 't': 95 + out << '\t'; ++p; 96 + break; 97 + case '0': 98 + case '1': 99 + case '2': 100 + case '3': 101 + if(p + 3 > e) 102 + continue; 103 + if(p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) 104 + { 105 + if(p + 4 > e) 106 + continue; 107 + out << (char)readInt(p+2, p+4, 16); 108 + p += 4; 109 + } 110 + else 111 + { 112 + out << (char)readInt(p, p+3, 8); 113 + p += 3; 114 + } 115 + break; 116 + case '$': 117 + { 118 + if(p + 3 > e) 119 + continue; 120 + out << (char)readInt(p+1, p+3, 16); 121 + p += 3; 122 + } 123 + break; 124 + } 125 + } 126 + } 127 + else 128 + { 129 + out << *p++; 130 + } 131 + } 132 + 133 + return out.str(); 134 + } 135 + 136 + RezSymbol RezLexer::nextToken() 137 + { 138 + for(auto tok = nextWave(); tok != T_EOI && tok != T_EOF; tok = nextWave()) 139 + { 140 + if(IS_CATEGORY(tok, WhiteSpaceTokenType)) 141 + continue; 142 + else if(IS_CATEGORY(tok, EOLTokenType)) 143 + continue; 144 + else if(tok == T_PP_LINE) 145 + { 146 + while(tok != T_EOI && tok != T_EOF && !IS_CATEGORY(tok, EOLTokenType)) 147 + tok = nextWave(); 148 + continue; 149 + } 150 + else 151 + { 152 + //std::cout << "{" << std::hex << (token_id)tok << std::dec << "|" << tok.get_value() << "}\n"; 153 + 154 + auto pos = tok.get_position(); 155 + curFile = pos.get_file().c_str(); 156 + auto yypos = yy::position(&curFile, pos.get_line(), pos.get_column()); 157 + yy::location loc(yypos); 158 + lastLocation = loc; 159 + 160 + if(tok == (UnknownTokenType | '"')) 161 + { 162 + return RezParser::make_STRINGLIT("Hello, world.", loc); 163 + } 164 + else if(IS_CATEGORY(tok, IdentifierTokenType) || IS_CATEGORY(tok, KeywordTokenType) || IS_CATEGORY(tok, BoolLiteralTokenType)) 165 + { 166 + typedef decltype(&RezParser::make_TYPE) memfun; 167 + #define KEYWORD(upper, lower) \ 168 + { lower, &RezParser::make_ ## upper } 169 + 170 + static std::unordered_map<std::string, memfun> keywords = { 171 + KEYWORD(TYPE, "type"), 172 + KEYWORD(RESOURCE, "resource"), 173 + KEYWORD(DATA, "data"), 174 + KEYWORD(READ, "read"), 175 + KEYWORD(INCLUDE, "include"), 176 + KEYWORD(CHANGE, "change"), 177 + KEYWORD(DELETE, "delete"), 178 + 179 + KEYWORD(ARRAY,"array"), 180 + KEYWORD(SWITCH, "switch"), 181 + KEYWORD(CASE, "case"), 182 + KEYWORD(AS, "as"), 183 + KEYWORD(FILL,"fill"), 184 + KEYWORD(ALIGN, "align"), 185 + KEYWORD(HEX,"hex"), 186 + KEYWORD(KEY, "key"), 187 + KEYWORD(WIDE,"wide"), 188 + KEYWORD(UNSIGNED, "unsigned"), 189 + KEYWORD(BINARY, "binary"), 190 + KEYWORD(LITERAL, "literal"), 191 + KEYWORD(BOOLEAN, "boolean"), 192 + KEYWORD(BIT, "bit"), 193 + KEYWORD(NIBBLE, "nibble"), 194 + KEYWORD(BYTE, "byte"), 195 + KEYWORD(CHAR, "char"), 196 + KEYWORD(WORD, "word"), 197 + KEYWORD(INTEGER, "integer"), 198 + KEYWORD(LONG, "long"), 199 + KEYWORD(LONGINT, "longint"), 200 + KEYWORD(PSTRING, "pstring"), 201 + KEYWORD(PSTRING, "wstring"), 202 + KEYWORD(STRING, "string"), 203 + KEYWORD(POINT, "point"), 204 + KEYWORD(RECT, "rect"), 205 + KEYWORD(BITSTRING, "bitstring"), 206 + 207 + KEYWORD(INTEGER, "int"), 208 + KEYWORD(DOLLAR, "$"), 209 + 210 + KEYWORD(FUN_COUNTOF, "$$countof"), 211 + KEYWORD(FUN_ARRAYINDEX, "$$arrayindex"), 212 + KEYWORD(FUN_READ, "$$read"), 213 + KEYWORD(FUN_BITFIELD, "$$bitfield"), 214 + KEYWORD(FUN_WORD, "$$word"), 215 + KEYWORD(FUN_BYTE, "$$byte"), 216 + KEYWORD(FUN_LONG, "$$long"), 217 + }; 218 + 219 + std::string s = tok.get_value().c_str(); 220 + if(s.size() >= 2 && s[0] == '$' && std::all_of(s.begin()+1, s.end(), [](char c) { return isxdigit(c); })) 221 + return RezParser::make_INTLIT(readInt(s.c_str()+1, nullptr, 16), loc); 222 + 223 + std::string lower = s; 224 + std::transform(lower.begin(), lower.end(), lower.begin(), ::tolower); 225 + auto p = keywords.find(lower); 226 + if(p == keywords.end()) 227 + { 228 + //std::cout << "id: " << s << std::endl; 229 + return RezParser::make_IDENTIFIER(lower, loc); 230 + } 231 + else 232 + { 233 + //std::cout << "key: " << s << std::endl; 234 + return (*p->second)(loc); 235 + } 236 + } 237 + else if(tok == T_INTLIT) 238 + { 239 + if(tok.get_value() == "0") 240 + { 241 + auto tok2 = peekWave(); 242 + while(tok2 != T_EOI && tok2 != T_EOF && IS_CATEGORY(tok2, WhiteSpaceTokenType)) 243 + nextWave(), tok2 = peekWave(); 244 + 245 + //std::cout << "!" << std::hex << (token_id)tok2 << std::dec << "|" << tok2.get_value() << "!\n"; 246 + static boost::regex binlit("[bB][01]+"); 247 + if(tok2 == T_IDENTIFIER && boost::regex_match(tok2.get_value().c_str(), binlit)) 248 + tok = nextWave(); 249 + } 250 + return RezParser::make_INTLIT(readInt(tok.get_value().c_str()), loc); 251 + } 252 + else 253 + { 254 + #define NOVAL_TOK(name) \ 255 + case T_ ## name: /*std::cout << #name << std::endl;*/ return RezParser::make_ ## name(loc) 256 + switch(token_id(tok)) 257 + { 258 + case T_INTLIT: return RezParser::make_INTLIT(readInt(tok.get_value().c_str()), loc); 259 + 260 + case T_CHARLIT: return RezParser::make_CHARLIT(readCharLit(tok.get_value().c_str()), loc); 261 + case T_STRINGLIT: return RezParser::make_STRINGLIT(readStringLit(tok.get_value().c_str()), loc); 262 + 263 + NOVAL_TOK(LEFTBRACE); 264 + NOVAL_TOK(RIGHTBRACE); 265 + NOVAL_TOK(LEFTBRACKET); 266 + NOVAL_TOK(RIGHTBRACKET); 267 + NOVAL_TOK(LEFTPAREN); 268 + NOVAL_TOK(RIGHTPAREN); 269 + NOVAL_TOK(SEMICOLON); 270 + NOVAL_TOK(COMMA); 271 + NOVAL_TOK(PLUS); 272 + NOVAL_TOK(MINUS); 273 + NOVAL_TOK(DIVIDE); 274 + NOVAL_TOK(STAR); 275 + NOVAL_TOK(ASSIGN); 276 + NOVAL_TOK(COLON); 277 + NOVAL_TOK(SHIFTLEFT); 278 + NOVAL_TOK(SHIFTRIGHT); 279 + NOVAL_TOK(EQUAL); 280 + NOVAL_TOK(NOTEQUAL); 281 + NOVAL_TOK(AND); 282 + NOVAL_TOK(OR); 283 + NOVAL_TOK(XOR); 284 + NOVAL_TOK(COMPL); 285 + 286 + default: 287 + 288 + return RezParser::make_BADTOKEN(tok.get_value().c_str(), loc); 289 + } 290 + 291 + } 292 + } 293 + } 294 + return RezParser::symbol_type(RezParser::token_type(0), yy::location()); 295 + }
+15
src/buildtools/Rez/RezLexerWaveToken.h
··· 1 + #ifndef REZLEXERWAVETOKEN_H 2 + #define REZLEXERWAVETOKEN_H 3 + 4 + #include "RezLexer.h" 5 + 6 + #include <boost/wave/cpplexer/cpp_lex_iterator.hpp> 7 + 8 + class RezLexer::WaveToken : public boost::wave::cpplexer::lex_token<> 9 + { 10 + public: 11 + WaveToken() = default; 12 + WaveToken(const boost::wave::cpplexer::lex_token<> & o) : boost::wave::cpplexer::lex_token<>(o) {} 13 + }; 14 + 15 + #endif // REZLEXERWAVETOKEN_H
+509
src/buildtools/Rez/RezParser.yy
··· 1 + %require "3.0.2" 2 + %defines 3 + %define parser_class_name {RezParser} 4 + %skeleton "lalr1.cc" 5 + 6 + %locations; 7 + 8 + %define api.token.constructor 9 + %define api.value.type variant 10 + %define parse.assert 11 + 12 + %token<std::string> IDENTIFIER; 13 + %token<int> CHARLIT; 14 + %token<std::string> STRINGLIT; 15 + %token<int> INTLIT; 16 + 17 + %token<std::string> BADTOKEN; 18 + 19 + 20 + %token LEFTBRACE "{"; 21 + %token RIGHTBRACE "}"; 22 + %token LEFTBRACKET "["; 23 + %token RIGHTBRACKET "]"; 24 + %token LEFTPAREN "("; 25 + %token RIGHTPAREN ")"; 26 + %token SEMICOLON ";"; 27 + %token COMMA ","; 28 + %token PLUS "+"; 29 + %token MINUS "-"; 30 + %token DIVIDE "/"; 31 + %token STAR "*"; 32 + %token ASSIGN "="; 33 + %token COLON ":"; 34 + %token SHIFTLEFT "<<"; 35 + %token SHIFTRIGHT ">>"; 36 + %token EQUAL "=="; 37 + %token NOTEQUAL "!="; 38 + %token AND "&"; 39 + %token OR "|"; 40 + %token XOR "^"; 41 + %token COMPL "~"; 42 + %token DOLLAR "$"; 43 + 44 + %token TYPE "type"; 45 + %token RESOURCE "resource"; 46 + %token DATA "data"; 47 + %token READ "read"; 48 + %token INCLUDE "include"; 49 + %token CHANGE "change"; 50 + %token DELETE "delete"; 51 + 52 + 53 + %token ARRAY "array"; 54 + %token SWITCH "switch"; 55 + %token CASE "case"; 56 + %token AS "as"; 57 + %token FILL "fill"; 58 + %token ALIGN "align"; 59 + %token HEX "hex"; 60 + %token KEY "key"; 61 + %token WIDE "wide"; 62 + %token LITERAL "literal"; 63 + %token UNSIGNED "unsigned"; 64 + %token BINARY "binary"; 65 + 66 + %token BOOLEAN "boolean"; 67 + %token BIT "bit"; 68 + %token NIBBLE "nibble"; 69 + %token BYTE "byte"; 70 + %token CHAR "char"; 71 + %token WORD "word"; 72 + %token INTEGER "integer"; 73 + %token LONG "long"; 74 + %token LONGINT "longint"; 75 + %token PSTRING "pstring"; 76 + %token WSTRING "wstring"; 77 + %token STRING "string"; 78 + %token POINT "point"; 79 + %token RECT "rect"; 80 + %token BITSTRING "bitstring"; 81 + 82 + %token FUN_COUNTOF "$$countof"; 83 + %token FUN_ARRAYINDEX "$$arrayindex"; 84 + %token FUN_READ "$$read"; 85 + %token FUN_BITFIELD "$$bitfield"; 86 + %token FUN_WORD "$$word"; 87 + %token FUN_BYTE "$$byte"; 88 + %token FUN_LONG "$$long"; 89 + 90 + /* 91 + %left "|"; 92 + %left "^"; 93 + %left "&"; 94 + %left "==" "!="; 95 + %left ">>" "<<"; 96 + %left "+" "-"; 97 + %left "*" "/"; 98 + */ 99 + 100 + %param { RezLexer& lexer } 101 + %param { RezWorld& world } 102 + 103 + %code requires { 104 + #include "ResourceDefinitions.h" 105 + #include "Expression.h" 106 + #include "ResSpec.h" 107 + 108 + #define YY_NULLPTR nullptr 109 + class RezLexer; 110 + class RezWorld; 111 + } 112 + 113 + %code provides { 114 + using yy::RezParser; 115 + //using RezSymbol = yy::RezParser::symbol_type; 116 + 117 + class RezSymbol : public yy::RezParser::symbol_type 118 + { 119 + public: 120 + RezSymbol() = default; 121 + RezSymbol(yy::RezParser::symbol_type&& x) : yy::RezParser::symbol_type(std::move(x)) {} 122 + }; 123 + } 124 + 125 + %code { 126 + #include "RezLexer.h" 127 + #include "RezWorld.h" 128 + #include "ResourceCompiler.h" 129 + #include "Diagnostic.h" 130 + 131 + static yy::RezParser::symbol_type yylex(RezLexer& lexer, RezWorld&) 132 + { 133 + return lexer.nextToken(); 134 + } 135 + 136 + void yy::RezParser::error(const location_type& loc, std::string const& err) 137 + { 138 + world.problem(Diagnostic(Diagnostic::error, err, loc)); 139 + } 140 + 141 + static std::string fromHex(std::string hex) 142 + { 143 + std::string bin; 144 + int nibble; 145 + bool haveNibble = false; 146 + for(std::string::iterator p = hex.begin(); p != hex.end(); ++p) 147 + { 148 + if(std::isspace(*p)) 149 + continue; 150 + assert(isdigit(*p) || (tolower(*p) >= 'a' && tolower(*p) <= 'f')); 151 + int digit; 152 + if(isdigit(*p)) 153 + digit = *p - '0'; 154 + else 155 + digit = tolower(*p) - 'a' + 0xA; 156 + 157 + if(haveNibble) 158 + { 159 + bin += (char) ((nibble << 4) | digit); 160 + haveNibble = false; 161 + } 162 + else 163 + { 164 + nibble = digit; 165 + haveNibble = true; 166 + } 167 + } 168 + return bin; 169 + } 170 + 171 + } 172 + 173 + %% 174 + %start rez; 175 + 176 + rez : %empty 177 + | rez type_definition ";" 178 + | rez resource ";" 179 + | rez data ";" 180 + ; 181 + 182 + type_definition : "type" type_spec 183 + { 184 + TypeDefinitionPtr td = std::make_shared<TypeDefinition>(); 185 + world.addTypeDefinition($type_spec, td); 186 + world.fieldLists.push(td); 187 + } 188 + "{" field_definitions "}" 189 + { world.fieldLists.pop(); if(world.verboseFlag) std::cout << "TYPE " << $2 << std::endl; } 190 + | "type" type_spec "as" type_spec 191 + { 192 + if(world.verboseFlag) std::cout << "TYPE " << $2 << std::endl; 193 + auto spec = $4; 194 + world.addTypeDefinition($2, world.getTypeDefinition(spec.getType(), spec.getID(), @4)); 195 + } 196 + ; 197 + 198 + %type <ResType> res_type; 199 + res_type : CHARLIT { $$ = ResType($1); } ; 200 + 201 + %type <TypeSpec> type_spec; 202 + type_spec : res_type { $$ = TypeSpec($res_type); } 203 + | res_type "(" INTLIT ")" { $$ = TypeSpec($res_type, $INTLIT); } 204 + ; 205 + 206 + field_definitions : %empty 207 + | field_definitions IDENTIFIER ":" { world.fieldLists.top()->addLabel($2, @2); } 208 + | field_definitions ";" 209 + | field_definitions field_definition ";" { world.fieldLists.top()->addField($2, @2); } 210 + ; 211 + 212 + %type <FieldPtr> field_definition; 213 + field_definition: simple_field_definition { $$ = $1; } 214 + | array_definition { $$ = $1; } 215 + | switch_definition { $$ = $1; } 216 + | fill_statement { $$ = $1; } 217 + | align_statement { $$ = $1; } 218 + ; 219 + 220 + %type <SimpleFieldPtr> simple_field_definition; 221 + simple_field_definition: field_attributes simpletype array_count_opt value_spec_opt 222 + { 223 + $$ = std::make_shared<SimpleField>(); 224 + $$->attrs = $field_attributes; 225 + $$->type = $simpletype; 226 + $$->arrayCount = $array_count_opt; 227 + $$->value = $value_spec_opt; 228 + } 229 + | simple_field_definition IDENTIFIER 230 + { $$ = $1; $$->addNamedValue($IDENTIFIER); } 231 + | simple_field_definition IDENTIFIER "=" value 232 + { $$ = $1; $$->addNamedValue($IDENTIFIER, $value); } 233 + | simple_field_definition "," IDENTIFIER 234 + { $$ = $1; $$->addNamedValue($IDENTIFIER); } 235 + | simple_field_definition "," IDENTIFIER "=" value 236 + { $$ = $1; $$->addNamedValue($IDENTIFIER, $value); } 237 + ; 238 + 239 + %type <ExprPtr> array_count array_count_opt value_spec_opt value resource_item; 240 + %type <ExprPtr> expression expression1 expression2 ; 241 + %type <ExprPtr> expression3 expression4 expression5 ; 242 + %type <ExprPtr> expression6 expression7 expression8; 243 + 244 + value_spec_opt : %empty { $$ = nullptr; } | "=" value { $$ = $2; } ; 245 + 246 + %type <SimpleField::Type> simpletype; 247 + simpletype : "boolean" { $$ = SimpleField::Type::boolean; } 248 + | "byte" { $$ = SimpleField::Type::byte; } 249 + | "integer" { $$ = SimpleField::Type::integer; } 250 + | "longint" { $$ = SimpleField::Type::longint; } 251 + | "rect" { $$ = SimpleField::Type::rect; } 252 + | "point" { $$ = SimpleField::Type::point; } 253 + | "char" { $$ = SimpleField::Type::char_; } 254 + | "pstring" { $$ = SimpleField::Type::pstring; } 255 + | "wstring" { $$ = SimpleField::Type::wstring; } 256 + | "string" { $$ = SimpleField::Type::string; } 257 + | "bitstring" { $$ = SimpleField::Type::bitstring; } 258 + ; 259 + 260 + %type <FieldPtr> fill_statement align_statement; 261 + fill_statement : "fill" fill_unit array_count_opt 262 + { $$ = std::make_shared<FillAlignField>($fill_unit, false, $array_count_opt); } 263 + ; 264 + align_statement : "align" fill_unit 265 + { $$ = std::make_shared<FillAlignField>($fill_unit, true); } 266 + ; 267 + 268 + %type <FillAlignField::Type> fill_unit; 269 + fill_unit : "bit" { $$ = FillAlignField::Type::bit; } 270 + | "nibble" { $$ = FillAlignField::Type::nibble; } 271 + | "byte" { $$ = FillAlignField::Type::byte; } 272 + | "word" { $$ = FillAlignField::Type::word; } 273 + | "long" { $$ = FillAlignField::Type::long_; } 274 + ; 275 + 276 + %type <FieldPtr> array_definition; 277 + array_definition: 278 + array_attributes "array" array_name_opt array_count_opt 279 + { 280 + ArrayFieldPtr af = std::make_shared<ArrayField>($array_name_opt, $array_count_opt); 281 + world.fieldLists.push(af); 282 + } 283 + "{" field_definitions "}" 284 + { 285 + $$ = world.fieldLists.top(); 286 + world.fieldLists.pop(); 287 + } 288 + ; 289 + 290 + array_count : "[" expression "]" { $$ = $2; } 291 + array_count_opt : %empty { $$ = nullptr; } | array_count { $$ = $1; }; 292 + 293 + %type <std::string> array_name_opt; 294 + array_name_opt : %empty { $$ = ""; } | IDENTIFIER { $$ = $1; } ; 295 + 296 + array_attributes: %empty | "wide" ; 297 + 298 + %type <SimpleField::Attrs> field_attributes field_attribute; 299 + field_attributes: %empty { $$ = SimpleField::Attrs::none; } 300 + | field_attributes field_attribute { $$ = $1 | $2; } 301 + ; 302 + 303 + field_attribute : "hex" { $$ = SimpleField::Attrs::hex; } 304 + | "key" { $$ = SimpleField::Attrs::key; } 305 + | "unsigned" { $$ = SimpleField::Attrs::unsigned_; } 306 + | "literal" { $$ = SimpleField::Attrs::literal; } 307 + | "binary" { $$ = SimpleField::Attrs::binary; } 308 + ; 309 + 310 + %type <FieldPtr> switch_definition; 311 + switch_definition: 312 + "switch" 313 + { world.switches.push(std::make_shared<SwitchField>()); } 314 + "{" 315 + switch_cases 316 + "}" 317 + { 318 + $$ = world.switches.top(); 319 + world.switches.pop(); 320 + } 321 + ; 322 + 323 + switch_cases : %empty | switch_cases switch_case ; 324 + 325 + switch_case : "case" IDENTIFIER ":" 326 + { 327 + world.fieldLists.push(std::make_shared<FieldList>()); 328 + } 329 + field_definitions 330 + { 331 + world.switches.top()->addCase($IDENTIFIER, world.fieldLists.top()); 332 + world.fieldLists.pop(); 333 + } 334 + ; 335 + 336 + 337 + value : expression { $$ = $1; } 338 + | "{" resource_body "}" { $$ = $2; } 339 + | string_expression { $$ = $1; } 340 + ; 341 + 342 + expression : expression1 { $$ = $1; } 343 + | expression "^" expression1 { $$ = std::make_shared<BinaryExpr>(BinaryOp::XOR, $1, $3, @1); } 344 + ; 345 + 346 + expression1 : expression2 { $$ = $1; } 347 + | expression1 "&" expression2 { $$ = std::make_shared<BinaryExpr>(BinaryOp::AND, $1, $3, @1); } 348 + ; 349 + 350 + expression2 : expression3 { $$ = $1; } 351 + | expression2 "|" expression3 { $$ = std::make_shared<BinaryExpr>(BinaryOp::OR, $1, $3, @1); } 352 + ; 353 + 354 + expression3 : expression4 { $$ = $1; } 355 + | expression3 "==" expression4 { $$ = std::make_shared<BinaryExpr>(BinaryOp::EQUAL, $1, $3, @1); } 356 + | expression3 "!=" expression4 { $$ = std::make_shared<BinaryExpr>(BinaryOp::NOTEQUAL, $1, $3, @1); } 357 + ; 358 + 359 + expression4 : expression5 { $$ = $1; } 360 + | expression4 ">>" expression5 { $$ = std::make_shared<BinaryExpr>(BinaryOp::SHIFTRIGHT, $1, $3, @1); } 361 + | expression4 "<<" expression5 { $$ = std::make_shared<BinaryExpr>(BinaryOp::SHIFTLEFT, $1, $3, @1); } 362 + ; 363 + 364 + expression5 : expression6 { $$ = $1; } 365 + | expression5 "+" expression6 { $$ = std::make_shared<BinaryExpr>(BinaryOp::PLUS, $1, $3, @1); } 366 + | expression5 "-" expression6 { $$ = std::make_shared<BinaryExpr>(BinaryOp::MINUS, $1, $3, @1); } 367 + ; 368 + 369 + expression6 : expression7 { $$ = $1; } 370 + | expression6 "*" expression7 { $$ = std::make_shared<BinaryExpr>(BinaryOp::MULTIPLY, $1, $3, @1); } 371 + | expression6 "/" expression7 { $$ = std::make_shared<BinaryExpr>(BinaryOp::DIVIDE, $1, $3, @1); } 372 + ; 373 + expression7 : expression8 { $$ = $1; } 374 + | "-" expression7 { $$ = std::make_shared<UnaryExpr>(UnaryOp::MINUS, $2, @1); } 375 + | "+" expression7 { $$ = $2; } 376 + | "~" expression7 { $$ = std::make_shared<UnaryExpr>(UnaryOp::COMPLEMENT, $2, @1); } 377 + ; 378 + 379 + expression8 : INTLIT { $$ = std::make_shared<IntExpr>($1, @1); } 380 + | CHARLIT { $$ = std::make_shared<IntExpr>($1, @1); } 381 + 382 + | identifier_expression { $$ = $1; } 383 + | "(" expression ")" { $$ = $2; } 384 + 385 + | "$$countof" "(" identifier_expression ")" 386 + { $$ = std::make_shared<CountOfExpr>($identifier_expression, @1); } 387 + | "$$arrayindex" "(" identifier_expression ")" 388 + { $$ = std::make_shared<ArrayIndexExpr>($identifier_expression, @1); } 389 + | "$$bitfield" "(" expression "," expression "," expression ")" 390 + { $$ = std::make_shared<PeekExpr>($3, $5, $7, @1); } 391 + | "$$word" "(" expression ")" 392 + { $$ = std::make_shared<PeekExpr>($3, 16, @1); } 393 + | "$$byte" "(" expression ")" 394 + { $$ = std::make_shared<PeekExpr>($3, 8, @1); } 395 + | "$$long" "(" expression ")" 396 + { $$ = std::make_shared<PeekExpr>($3, 32, @1); } 397 + ; 398 + 399 + %type <IdentifierExprPtr> identifier_expression; 400 + identifier_expression : IDENTIFIER { $$ = std::make_shared<IdentifierExpr>($1, @1); } 401 + | IDENTIFIER 402 + { world.functionCalls.push(std::make_shared<IdentifierExpr>($1, @1)); } 403 + "[" function_argument_list1 "]" 404 + { $$ = world.functionCalls.top(); world.functionCalls.pop(); } 405 + ; 406 + 407 + function_argument_list : %empty | function_argument_list1 ; 408 + function_argument_list1 : expression 409 + { world.functionCalls.top()->addArgument($expression); } 410 + | function_argument_list "," expression 411 + { world.functionCalls.top()->addArgument($expression); } 412 + ; 413 + 414 + %type <ExprPtr> string_expression string_expression1; 415 + string_expression : string_expression1 { $$ = $1; } 416 + | string_expression string_expression1 417 + { $$ = std::make_shared<BinaryExpr>(BinaryOp::CONCAT, $1, $2, @1); } 418 + ; 419 + 420 + %type <std::string> stringlit; 421 + stringlit : STRINGLIT { $$ = $1; } 422 + | DOLLAR STRINGLIT { $$ = fromHex($2); } 423 + ; 424 + 425 + string_expression1 : stringlit { $$ = std::make_shared<StringExpr>($1, @1); } 426 + | "$$read" "(" string_expression ")" 427 + { $$ = std::make_shared<ReadExpr>($string_expression, @1); } 428 + ; 429 + 430 + resource : "resource" res_spec "{" resource_body "}" 431 + { 432 + world.addResource($res_spec, $resource_body, @1); 433 + } 434 + ; 435 + 436 + %type <ResSpec> res_spec; 437 + %type <ResSpec> resource_attributes; 438 + 439 + res_spec : res_type "(" expression resource_attributes ")" 440 + { 441 + $$ = $resource_attributes; 442 + $$.type() = $res_type; 443 + $$.id() = $expression->evaluateInt(nullptr); 444 + } 445 + ; 446 + 447 + resource_attributes : %empty { $$ = ResSpec(); } 448 + | resource_attributes "," IDENTIFIER 449 + { 450 + $$ = $1; 451 + if($IDENTIFIER == "changed") 452 + $$.attr() |= 2; 453 + else if($IDENTIFIER == "preload") 454 + $$.attr() |= 4; 455 + else if($IDENTIFIER == "protected") 456 + $$.attr() |= 8; 457 + else if($IDENTIFIER == "locked") 458 + $$.attr() |= 16; 459 + else if($IDENTIFIER == "purgeable") 460 + $$.attr() |= 32; 461 + else if($IDENTIFIER == "sysheap") 462 + $$.attr() |= 64; 463 + else if($IDENTIFIER == "unchanged") 464 + $$.attr() &= ~2; 465 + else if($IDENTIFIER == "nonpreload") 466 + $$.attr() &= ~4; 467 + else if($IDENTIFIER == "unprotected") 468 + $$.attr() &= ~8; 469 + else if($IDENTIFIER == "unlocked") 470 + $$.attr() &= ~16; 471 + else if($IDENTIFIER == "nonpurgeable") 472 + $$.attr() &= ~32; 473 + else if($IDENTIFIER == "appheap") 474 + $$.attr() &= ~64; 475 + else 476 + world.problem(Diagnostic(Diagnostic::error, "illegal attribute " + $IDENTIFIER, @1)); 477 + } 478 + | resource_attributes "," string_expression 479 + { 480 + $$ = $1; 481 + $$.name() = $3->evaluateString(nullptr); 482 + } 483 + ; 484 + 485 + 486 + 487 + %type <CompoundExprPtr> resource_body resource_body1; 488 + resource_body : %empty { $$ = std::make_shared<CompoundExpr>(yy::location()); } 489 + | resource_body1 { $$ = $1; $$->location = @1; } 490 + ; 491 + resource_body1 : resource_item { $$ = std::make_shared<CompoundExpr>(@1); $$->addItem($1); } 492 + | resource_body1 "," resource_item { $$ = $1; $$->addItem($3); } 493 + | resource_body1 ";" resource_item { $$ = $1; $$->addItem($3); } 494 + | resource_body1 ";" { $$ = $1; } 495 + | resource_body1 "," { $$ = $1; } 496 + ; 497 + 498 + resource_item : value { $$ = $1; } 499 + | IDENTIFIER "{" resource_body "}" { $$ = std::make_shared<CaseExpr>($IDENTIFIER, $resource_body, @1); } 500 + ; 501 + 502 + 503 + data : "data" res_spec "{" string_expression "}" 504 + { 505 + world.addData($res_spec, $string_expression->evaluateString(nullptr), @1); 506 + } 507 + ; 508 + 509 + %%
+58
src/buildtools/Rez/RezWorld.cc
··· 1 + #include "RezWorld.h" 2 + #include "ResourceCompiler.h" 3 + #include "ResourceFork.h" 4 + 5 + #include <iostream> 6 + 7 + #include "Diagnostic.h" 8 + 9 + RezWorld::RezWorld() 10 + : verboseFlag(false), hadErrors(false) 11 + { 12 + } 13 + 14 + void RezWorld::addTypeDefinition(TypeSpec spec, TypeDefinitionPtr type) 15 + { 16 + if(!type) 17 + return; 18 + types[spec] = type; 19 + } 20 + 21 + TypeDefinitionPtr RezWorld::getTypeDefinition(ResType type, int id, yy::location loc) 22 + { 23 + auto p = types.find(TypeSpec(type, id)); 24 + if(p != types.end()) 25 + return p->second; 26 + p = types.find(TypeSpec(type)); 27 + if(p != types.end()) 28 + return p->second; 29 + problem(Diagnostic(Diagnostic::Severity::error, "Can't find type definition for '" + std::string(type) + "'", loc)); 30 + 31 + return nullptr; 32 + } 33 + 34 + void RezWorld::addResource(ResSpec spec, CompoundExprPtr body, yy::location loc) 35 + { 36 + if(verboseFlag) 37 + std::cout << "RESOURCE " << spec.type() << "(" << spec.id() << ", " << "\"" << spec.name() << "\"" << spec.attr() << ")" << std::endl; 38 + TypeDefinitionPtr def = getTypeDefinition(spec.type(), spec.id(), loc); 39 + if(!def) 40 + return; 41 + ResourceCompiler compiler(*this, def, body, verboseFlag); 42 + compiler.compile(); 43 + 44 + resources.addResource(Resource(spec.type(), spec.id(), compiler.resourceData(), spec.name(), spec.attr())); 45 + } 46 + 47 + void RezWorld::addData(ResSpec spec, const std::string &data, yy::location loc) 48 + { 49 + if(verboseFlag) 50 + std::cout << "DATA " << spec.type() << "(" << spec.id() << ", " << "\"" << spec.name() << "\"" << spec.attr() << ")" << std::endl; 51 + resources.addResource(Resource(spec.type(), spec.id(), data, spec.name(), spec.attr())); 52 + } 53 + 54 + void RezWorld::problem(Diagnostic d) 55 + { 56 + hadErrors = true; 57 + std::cerr << d << std::endl; 58 + }
+43
src/buildtools/Rez/RezWorld.h
··· 1 + #ifndef REZWORLD_H 2 + #define REZWORLD_H 3 + 4 + #include <map> 5 + #include <stack> 6 + #include <string> 7 + #include "ResourceDefinitions.h" 8 + #include "Expression.h" 9 + #include "ResourceFork.h" 10 + #include "ResSpec.h" 11 + 12 + class Diagnostic; 13 + 14 + class RezWorld 15 + { 16 + friend class RezParser; 17 + 18 + std::map<TypeSpec, TypeDefinitionPtr> types; 19 + std::stack<FieldListPtr> fieldLists; 20 + std::stack<IdentifierExprPtr> functionCalls; 21 + std::stack<SwitchFieldPtr> switches; 22 + 23 + Resources resources; 24 + 25 + public: 26 + RezWorld(); 27 + void addTypeDefinition(TypeSpec spec, TypeDefinitionPtr type); 28 + 29 + TypeDefinitionPtr getTypeDefinition(ResType type, int id, yy::location loc); 30 + 31 + void addResource(ResSpec spec, CompoundExprPtr body, yy::location loc); 32 + void addData(ResSpec spec, const std::string& data, yy::location loc); 33 + 34 + Resources& getResources() { return resources; } 35 + 36 + bool verboseFlag; 37 + bool hadErrors; 38 + 39 + void problem(Diagnostic d); 40 + }; 41 + 42 + 43 + #endif // REZWORLD_H
+33
src/buildtools/Rez/Test.r
··· 1 + /*#include "Types.r" 2 + 3 + 4 + */ 5 + 6 + #include "/home/wolfgang/Projects/Retro68/CExamples/Sample.r" 7 + 8 + type 'TEST' { 9 + integer zero, one, two, answer = 42, missed; 10 + longint; 11 + integer = (after - before) / 8; 12 + integer = $$CountOf(foo); 13 + before: 14 + array foo { 15 + integer = $$ArrayIndex(foo); 16 + integer; 17 + integer; 18 + }; 19 + string; 20 + after: 21 + ; 22 + }; 23 + 24 + resource 'TEST' (128) { 25 + answer, 26 + 0x1234, 27 + { 1, 2; 3, 4; }, 28 + "Hello, " 29 + "world: " 30 + $"Abcd 1234"; 31 + }; 32 + 33 +