pax_global_header00006660000000000000000000000064123105032170014504gustar00rootroot0000000000000052 comment=c6f36cbafa979710b809f117562773dbd6825918 dev86-0.16.21/000077500000000000000000000000001231050321700126075ustar00rootroot00000000000000dev86-0.16.21/COPYING000066400000000000000000000430761231050321700136540ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 675 Mass Ave, Cambridge, MA 02139, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS Appendix: How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 19yy This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19yy name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. dev86-0.16.21/Changes000066400000000000000000000567651231050321700141250ustar00rootroot00000000000000For version 0.16.*. > Sorry forgot to flip this back: perror and strerror are back to using the /lib/liberror.txt file for all 8086 Elks modes. Only i386 has the file linked. Elksemu now traps accesses to this file and substitutes a fake. > Added vararg macros to new preprocessor. > Builtin CPP removed for __BCC__ compile, bcc-cc1 fit in 16bit but crashes. Thirty two bit works fine, gcc or bcc. (almost any 32bit.) > Added __BCC_VERSION__ macro, defined by bcc.c contains hex version no. > Bugfix for offsets generated by #asm when using -O option to bcc-cc1. Extra compile option ASM_USES_CALLEE_REGS. > Extra checking and bugfix for mixing char values with long shifts. > WARNING to distributions: I've altered the install scripts and paths you will want to check them. Altered paths for bcc.c and normal installs, defaults should now be good for distributions where bcc is a cross compiler. If you set the PREFIX to / it'll install to suggested Native paths. As86_encap moved to LIBDIR. > I've altered 'perror' and 'strerror' to be normal when compiled for everything except libc_f.a. Only with that library will it look for the liberror.txt file and it now looks in "/lib/liberror.txt" only. This means there's no need to install it anywhere except ELKS itself. > Change -Mg option to use uclibc as glibc2 seems to have stopped working. > ar.c switch to using strerror. > Move elksemu, it's used like a shared library but is best treated like an emulator so it's now installed in DISTBIN. Also on Linux-386 it's compiled using the system compiler. > Use the POSIX -R argument to cp rather than the normal standard -r because some new systems have decided to stop supporting their '-r' option. > Oops, the constant error strings in the assembler were char pointers not char arrays, small waste of space. > Allow for Linux-2.6 32bit dev_t. > More changes so it compiles better on 'other' machines. Removed some GNU-Make'isms in the top header file. > It seems that CYGWin's problem with _P is inherited from BSD. It also seems most of my problems come from BSD recently, haven't they realised that they down own the 'Unix Standard' anymore and haven't since SYSV got popular. > Some changes for cygwin, it isn't quite as nasty as compiling for minix but it doesn't miss by much! > Compiling for the 'tcc' complier, nice and easy. > Hitting bcc.c again, bcc-cpp now the default. > Some bugfixes for DEC Alpha -- 64 bit longs! Constant folding still done with 64bit longs though. > The fopen function (and friends) is now a real function not a macro. > Ctype.h updated to ansi. > Libraries appear to compile properly with -O and -ansi now. > Copt's hash string table adjusted; should now have fewer pathological cases. > Order of copt's rule processing reversed; it now works from the top of a rule file to the bottom. Also comment lines may be include in the match lines. !BCC_EOS added to bcc-cc1 for 'end of statment'. > bcc-cc1's asm("") now works in declare mode too. > New independed cpp added, has both K&R and Ansi modes. Changes made to the embedded cpp too to try and fix some bad bits. > Conditional assembler added around push and pop of 'si' and 'di' if the optimiser (and as86's optimiser) are to be run. > Signed keyword added to bcc-cc1 for 'signed char' also works with other int types but is usually just a noiseword. > As86 macro syntax altered, you now don't have to include any brackets. > Gcc warnings in ar86 cleaned up. > Mk_dist now makes incremental patch files too. > Update magic file. > Various updates to the bios libc, the vt52 and ansi emulations are now seperated (and can be both included if needed) and don't have to be linked. Conio functions work properly in bios and msdos. > Added -v (version) > as86 and ld86 now delete their binary outputs if there were errors. > Added more 'set' commands generated by '#asm' lines. The new ones begin with '.' rather than '_' an are based off the 'bp' register rather than the 'sp' register. > Various unused, test and old document files removed. > as86 modified to use normal malloc routines - no longer has limited input file size. > as6809 repaired, appears to work. > as86 error display adjusted, some errors demoted to warnings. > Complete re-write of bcc.c driver program. Should now be easier to modify, does have more versatility so that things that were formerly compile time options are all run time. > #asm and #endasm now interact with statment processing inside functions. If statments and case labels no longer need special layout however #asm must be placed between statments now. > The __heap_top virtual constant added, allows the -H option to be used with the -d option in the linker. > Conio routines added, merged with bios_getc/bios_putc routines which now no longer exist under those names. > monitor.out now copes with very old zimages, like the memtest86 program, and has 'Retry' prompt for disk errors. > msdos.s and tarboot.s loading of non-a.out executables adjusted for dos BIN like files. > Standalone library startup adjusted to allow execution of a '-d' executable from DOS, if __argr.x.cflag is set this is running under DOS. > Compile for DOS again, disable cpm86 headers under DOS. > Minor bugfix for as86 binary output re sizeof(int)/K&R problem. For version 0.16.0. > As major bugs seem to be absent 0.16.0 is escaping. > Seperated the multi-pass optimisation from the jump extension. We now have the -j back to it's old meaning and -O added to help shorten instructions. > Fix for nested conditionals in the assembler. > Fix for listing to unusual locations; assembler tried to list non-existant lines. > Removed lots of warning from the ar86 code. (__STDC__ flags too) > Stop trying to strip scripts on install. > Remove non-working versions of malloc and stdio from libc directories. > Lots of changes in the 'bootblocks' example code. > Updated 'make distribution' to be all in the distribution. > bin86 Makefile adjusted so that the as86 script isn't installed with -s. For version 0.15.0. > Added support for archives to nm86/objdump86 and size86. > ar86 added. Used for Linux because RedHat is broken. > Bugfixes on utmpent and friends. > A bit more in the manpages on how to use the assembler etc. > Bug fixes in stdio, fp->mode cached too much, buffer type mixup. > Altered initial make variables, you only need to modify 'PREFIX=' to allow installs into /usr/local. > The BIOS library has a simple MSDOS fs file reader now, based on the code from monitor.out. > Added bin86-0.... source distribution archive. > Fixed bug in -t option to as/bcc (for moving the text segment) > Lines that have a unexpected character are now listed by the assembler not just ignored. > Added assembly externals in as86_encap generated code. > I appear to have bcc generating a consistant set of code fragments for floating point operations. No floating libs though ... > Lots of bootblocks changes including Added lsys.com to install the dosfs boot sector under dos. monitor.out now (finally!) loads zImage files. Monitor.out now works with a TAR "filesystem" on a floppy. Added two compile time options (-DTARFLOPPY and -DDOSFLOPPY) for smaller executables to only boot linux-386 from a floppy. Makeboot can install the mbr. Removed the ELKS specific code from the minixfs loader, added a helper program to load and relocate ELKS. One config file for booting a [b]zImage. DOSFS boot can boot any named file. > Fixed/avoided some problems with the optimiser breaking hand optimised code. > I've made some alterations to the header files in an effort to merge the ELKS kernel files with fewer problems. > Oops, Claudio says that qsort went the wrong way, hmm. > Added some more library code for MSDOS programs, there's still more to go. > Removed the 'libc-8086' distribution tgz file. For version 0.14.0. > Objdump86 utility added, also includes nm86 and size86 that work on as86's object files and elks executables. > Added ability to put ELKSSRC=/././. on initial make command line. > Some bug fixes and buffering improvements for stdio2. > Changed output of linker -m option to be more verbose (useful). > Linker errors are now directed to STDERR on unix/elks. > Alterations to elksemu and the C library to be closer to elks, 0.13.1+ should not need a patch to work with 0.0.60+ ELKS. > Link symbol dump now flags local variables differently to exported. > Fixes for libc/misc/crypt.c, they do change the values of the encrypted password so beware. > as86_encap now uses a static array and #defines. > Added -t flag to as86 and bcc to move the text segment for this object into another one. > Moved segments 4..14 so that instead of being attached above the data segment they now sit between the text and data segments in the final a.out, this is where they'd be needed for medium model. > Added -x option to bcc to prevent it linking in crt0.o. > Added various improvemnts to the optimiser, I don't think it'll generate illegal code now for "-O", "-O1", or "-Oi". The last inlines the functions __get_es(), __seg_es(), __poke_es(), __peek_es() etc. > Code generator improvement for integer multiply and shifts. (Including making it far less keen to do multiple shifts instead of a multiply. > Code generator fix to remove incorrect (but accepted by the assembler) addressing modes like: mov ax,#_ar[bx] > Been messing with boot block stuff again, still can't get it to load zImages (bzImages ok tho). Minix.c can't load an ELKS kernel either, it's looking like there isn't actually enough room :-( > Fix to elksemu for breakages caused by glibc. > Other fixes to elksemu for execve(), dup(), readdir() etc functions. For version 0.13.0. > Removed too eager 'typeconv.c' warning. > Well, I just broken everything! To be exact if Dev86 sees a directory called ${ELKSSRC:-/usr/src/elks}/include it'll assume that is the equlivent of libc/kinclude and use that in preference. I've sent off a patch so that elks-0.0.* should be compatible but meantime there are bound to be lots of problems caused by shuffling of include files. (Later: Actually doesn't seem too bad) > Added '-g' to gcc options, make sure install has '-s' to strip symbols. > Grrrr, missing files in bootblocks directory, I didn't have them all. OK, as part of the dist script I'll have to do a 'make other' ... Some other bits there too ... > Minor alteration to opening files in ld to fix problem when share.exe loaded under dos. > Added Config.dflt for default libc configuration flags. I can now re-introduce Joel's standard I/O functions ... but they haven't been updated in a while ... > Addition to minix.c to use allow BB to determine the track size by trial and error (not intuit from superblock) to allow mis-sized filesystems on a floppy. Also add some error retries to the floppy version. > Squeeze the minix BB a bit more, DOTS is now working again. > Can now do 'use16 8086' in assembler instead of 'use16 86' also 'use16 80386' > Add 'make install-ln', this installs _symbolic_links_ to the dev directory in the normal directories. This means you don't have to do a make install after re-compiling. But it also means the 'install' is dependent on the dev dirs. > Add ability to use overrides on the command line of the initial make, and have them saved, for CC, CFLAGS, LDFLAGS, PREFIX, BINDIR and LIBDIR. Includes minor alteration to bcc.c and as86_encap. > Added in 'objchop' as an option in the ld directory. > The cpu type warnings were worrying some people so I've set the initial value of the '-w' flag to off, use -w- to turn them back on. The -W flag to bcc now does this too. > Added the ELKS_SETUP from Ken Yap to minix.c. > Added __ELKS__, __8086__ and __i386__ #defines for relevent bcc configs. > Clarified some of the copyrights, esp for Bruce's stuff. > Added a few changes to clean up compiles on an AIX/RS6000. It still needs gnu-make installed and is only tested with gcc though. (Because of IBM's recent contribution to increasing the popularity of GCC) For version 0.12.0. > Notice the change in the version numbers, as long as I'm releasing the upto the minute patches I thought I'd better give everyone a way of keeping track. So now the 0.X.0 are the main releases, the 0.X.Y are interim patches. > I've added a new output binary for ld86, it can now do the broken relocatable a.out that bin86 produces. I don't like this but it does let me move ld86 back to /usr/bin without breaking DOSEMU. Note! If you've installed vsn 0.0.11 or earlier you will need to uninstall it before installing this one. > Altered makefiles for GNU-make 3.74, GNU-make no longer generates automatic 'rm' commands so I have to do it manually. > Altered makefiles again, starting to get non GNU makefile working. > Added some cleanups to ifdef.c. (voids etc) > Assembler now understands monadic '-' and '+' operations (for copt). > Improved the type conversion functions, they should now work on most machines. There may still be some problems with sizeof(long) == 8 tho, added some warnings/traps. > Improved the auto-detection and auto-rejection of ld is more likely to compile even if a.out.h is completely incompatible (leaving out native support). > Fix for stdio, there was a problem if the OS only did a partial write. > Alter align() macros to use ssize_t iff both __STDC__ and _POSIX_SOURCE are defined. > Add some changes for compiling under AIX. Assember and BCC appear to work, ld has problems with AIX's 'ar' command - problem: AIX's make and gmake won't like the smell of a standard following ar86 command ... hmmm. > Changes in bootblocks, minix.c can now be compiled for a hard disk (works on dosemu, dunno about the real thing tho), fixes for mbr.s re preboot facility. Addition to minix.c to fix number of sectors in bpb for floppy. For version 0.0.11. > New, most recent, version of unproto inserted. > AAARG! First_arg_in_ax breaks stdarg.h! As a consequence printf wasn't working, now why didn't _you_ notice! OK. printf now uses varargs, that is more likely to work and does for printf & scanf. > Added -Mc for 'caller saves' _without_ first_arg_in_ax. As this uses the normal libc there are likely to be problems with library -> user callbacks. > Added -Ml for 386 'Large linux' compile. > Added -Mn for 'normal' elks compiles so the default for dos can be -Md > Brand new, an optimiser has been added, it's in its early stages yet the 8086 (plain -O) version seems ok. The 386 generator (-O3) is definitly missing some requirements. It's probably not a good idea to use -Ml and -O. (Later: The 8086 can generate bad code it seems, oh well) > Some changes to the makefile, minix make will now _try_ to compile bcc, it doesn't seem to succeed yet though. Also because of this I've gone back over the headers, should be better on non-ansi or non-posix systems now. BTW: minix make has no chance with compiling libc so I've added another zip archive containing just the compiled libcs. > Add the -a-, -j-, -g-, -u- and -w- flags to as86; specifically for -w- to allow easy enabling of assembler warnings while using bcc. > Bugfix for assembler 'ifc' pseudo op. > Bugfix for preprocessor and unterminated last line of included file. > Add minix syscall detector to elksemu, I may make it into an emulator ... > I've split of the 8086 ELKS and i386 Linux libc stuff into seperate directories. I expect Chad will want to take over the 8086 one for a while. Plus some other files moved around to help new users. For version 0.0.10. > Some serious changes to the makefiles, practically a rewrite of them. 'make', 'make all', 'make install', 'make clean' and 'make realclean' do the expected things. 'make distribution' should let you create the partial and binary dirtributions from the full source. > The makefiles now allow multiple libc binaries to co-exist. > The makefiles now allow a _full_ compile without installing anything. > In part because of the makefile changes a lot of files in the library have been moved, this is a large portion of the patch size. > ifdef.c added as part of makefile changes, I'm not quite sure if I like this way of doing things but it's ok for the mo. > MSDOS, in the output of *.bin files from as86 skipped areas have zeros written not semi-random bytes. > MSDOS (+ other machines where sizeof(char*) != sizeof(int)) problem with macros resolved, they appear to work correctly now. > NCC added, this is a different version of bcc with libs and include dirs in the same format as the MSDOS driver. This is used for 'uninstalled' compiling and also if you do: $ ln -s `pwd`/bcc/ncc $HOME/bin/bcc The bcc will use the 'uninstalled' include and library files for when you don't have root access. > -H option added to ld86, this controls the size of the heap or 'chmem' field in the executable. > BOOT-Blocks, makeboot can be compiled as a DOS COM, bootblock for msdos filesystem completed, this will allow lilo, monitor.out or any Linux-86 standalone executable to be executed from an msdos floppy. Makeboot can also install several other types of bootblock. > Monitor.out now includes 'bzimage' command, which will boot a Linux-i386 bzImage with command line and initrd. > 'skip.s' bootblock fixed. > A few more functions now work in 'standalone' mode, malloc() especially. -Rob For version 0.0.9. > The debian stuff has been removed again, Christoph want's to keep contol of the debian specific files. > I've done some changes to the makefiles, it'll now honour CC=XXX on the make command line. > The assembler now works again compiled under bcc, it tried to allocate too much memory. > Major change to the assembler, '-j' not auto-sizes jumps this requires a change to at least 3 passes. Sometimes it'll say it needs another -j because lengthing jumps cause others to fail, two -j's will give it lots of passes :-) > The second large change is an effort to identify when instructions are not right for a specific processor and generate a warning. The use16 and use32 instructions now have an optional argument of a processor type (86,186..686). Also bcc has a '-W' to remove the -w it passes to the assembler. > Altered the way bcc deals with LOCALPREFIX, now under DOS it picks this up based on the path to the executable. > Fixed a bug introduced by the 'cpp in asm' change in 0.0.8, bcc-cc1 wasn't compiling under bcc. > Two new bootblocks in the 'examples' mbr.s is an MBR (no really :-)) msdos.s is unfinished but even this far allows lilo to be used on an MSDOS filesystem floppy. > Changed ld to _check_ the magic on files inside an archive, this cures the problem caused by long names inserted by gnu-ar. Also it notices if an archive has been included in an archive and will link that too. > Changed ld to do a final check that it knows what sort of a.out.h file it's got, if this fails '-N' is disabled. > Ld changed so for 16 bit exes the heap is limited to 32k. > getcwd and execvp added, sash should now work. Also added to the 386-lib except execvp won't run scripts without '#!' > Nasty bug with syscalls of > 3 args in 386 code fixed, none of them would have been working correctly. For version 0.0.8. > Christoph Lameter has provided a patch for installation using the debian packaging, I've probably broken it :-) > Doselks has been added in, it's not that big really. > Triggered by the debian stuff the makefiles can now create a pure binary installation tree, nothing needed in /usr/src. If kinclude is configured out the include directory will reference /usr/src/linuxmt > Some good changes to the linker today, it will generate a Linux-386 (That's right, growed up linux) executable. It's still very fragile but it does work. The '-r' option now works, but unlike bin86-0.3 it creates a _Linux_ OMAGIC file. This means that bcc -G works, the names are mangled by ld86 such that if it was compiled with ELF the OMAGIC will successfully link in an ELF environment. Beware older versions of GCC-binutils can segfault in this situation. > Bit of sneakyness for the assembler, org will accept negative values ... > Made a few changes to idcc, I think I'll translate it to C soon. > Fixed a couple of problems with the preprocessor WRT hashes not at the start of a line and quotes in ifdef'd out code. > Missed a bet in the kernel patch and module, the old one wouldn't execute impure executables it will now. > Fixed matching bug in elksemu, A piece of code was commented out for some reason ... oops. > Some of the error reporting in the linker has improved, if it can't open libc it now says so! > Some 386 specific stuff has been added to libc, mainly the syscall generator, startup stuff and BCC's 386 floating point code. > Change in malloc, Linux-386 limits +ve brk() changes to 32Mb, the malloc will now allow for this ... Phew! grab.c will grab about 3Gb of virtual memory, with 1Gb chunks, when compiled in 386 mode! One oddity, glibc (quite an old one) hangs when trying to free if grab.c is compiled static. > Hunted down the most important 16 bit dependancies in dis88, it seems to generate a reasonable output file now. Plus a couple of fiddles in the disassembler, personally I prefer Hex and I've added a couple of markers for 386 code (use opr32, use adr32, seg fs/gs) and the -f flag to force disassembly of any file. > The i386 compile uncovered a bug in alloca, In fact the move to 386 has been amazingly painless, practically everything so far has worked first time or nearly so ... Wow! > Added minimal dirent to i386-lib, elksemu now compiles under BCC-386 AND WORKS! > Trying to compile bash, it does some hackish stuff with the preprocessor and uncovered a couple of problems, fixed. Now I need more float stuff. > Added for bcc-cc1, code between #asm and #endasm _is_ scanned for #defined words and functions, it didn't effect the libc at all. Of course we now need some way to put multiple instructions in one #define, I've nominated '^' as the statement terminator, I didn't have many choices :-( > Added '-t' for bcc-cc1 when bcc gets -S -Rob For version 0.0.7. I've been making quite a few changes to the assembler: The 'include' or 'get' command now works. The '-b' and '-s' options are now quite useful for bootblocks or encapsulated code. The standard input is now a valid source for the assemble (but only on 'big' machines). Various other functions now work, macros, 'jmp near', 'jmpi qword $100000,$1000', and other bug fixes. As86_encap script added. Some of the 256 char line limits have been removed for non-bcc compiles. The linker will now fail more gracefully for reversed 'org's and complain about too large segments. Bcc-cc1 will now compile under itself, with some limitations, and appears to generate correct output. There are problems tho in that I think the heap<->stack saftey margin is too short and I've disconnected all code for floating point features. The components will all compile and seem to work quite well using MSC 5.1 under dos and will probably compile using other dos compilers. BCC cannot compile itself under dos because the libs to fake the unix syscalls under dos are currently too large. A number of fixes have been added that were apperently in another version of the tools to aid operation on other machines, there's now a better chance of these programs working on 'big-endian' machines. Various bits and pieces have been added to the libs, including some time functions (but these need a _small_ way of dealing with "DST"). -Rob dev86-0.16.21/Contributors000066400000000000000000000020101231050321700152200ustar00rootroot00000000000000Top of the list, without whom this wouldn't be here... Bruce Evans Then there's me, I'm controlling the releases of Dev86 and have the master files. Robert de Bath The files are available at linux.mit.edu with the source and yesterday's patch file available via http://cix.co.uk/~mayday/ We're all available through the Linux-8086 mailing list at: linux-8086@vger.kernel.org Rob. Finally the list itself, if you're missing send me a patch :-) Alan Cox Nat Friedman Steven Huang Steffen Kaiser Shane Kerr Gero Kuhlmann Chad Page Dick Porter Dale Schumacher Wietse Venema Joel Weber II Claudio Matsuoka Andrew Chittenden John Coffman dev86-0.16.21/GNUmakefile000066400000000000000000000003521231050321700146610ustar00rootroot00000000000000# # Flag that we're using GNU make. # all: phony @$(MAKE) $(MAKEARG) -f Makefile IFDEFFLAGS=-DGNUMAKE IFDEFNAME=ifdefg $@ %: phony @$(MAKE) $(MAKEARG) -f Makefile IFDEFFLAGS=-DGNUMAKE IFDEFNAME=ifdefg $@ phony: ; GNUmakefile: ; dev86-0.16.21/MAGIC000066400000000000000000000023721231050321700133560ustar00rootroot00000000000000Useful bits for /etc/magic: #------------------------------------------------------------------------------ # Linux 8086 executable 0 lelong&0xFF0000FF 0xC30000E9 Linux-8086 executable, headerless >5 string . >>4 string >\0 \b, libc version %s 0 lelong&0xFF00FFFF 0x04000301 Linux-8086 executable >2 byte&0x01 !0 \b, unmapped zero page >2 byte&0x20 0 \b, impure >2 byte&0x20 !0 >>2 byte&0x10 !0 \b, A_EXEC >2 byte&0x02 !0 \b, A_PAL >2 byte&0x04 !0 \b, A_NSYM >2 byte&0x08 !0 \b, A_STAND >2 byte&0x40 !0 \b, A_PURE >2 byte&0x80 !0 \b, A_TOVLY >28 long !0 \b, not stripped >37 string . >>36 string >\0 \b, libc version %s # Other ld86 executable formats ... 0 lelong 0x10200301 Minix-386 executable >28 long !0 not stripped 0 lelong 0x10100301 Minix-386 impure executable >28 long !0 not stripped 0 lelong&0xFF00FFFF 0x10000301 ld86 I80386 executable >28 long !0 not stripped # Never seen formats. # 0 belong&0xFFFF00FF 0x0103000B ld86 M68K executable # 0 belong&0xFFFF00FF 0x0103000C ld86 NS16K executable # 0 belong&0xFFFF00FF 0x01030017 ld86 SPARC executable # AS86/LD86 object files. # There is _no_ difference between 16 and 32 bit .o files that file can see. 0 string \243\206\001\0 Linux-8086 object file dev86-0.16.21/Makefile000066400000000000000000000044321231050321700142520ustar00rootroot00000000000000# Copyright (C) 1997 Robert de Bath # This file is part of the Linux-8086 Development environment and is # distributed under the GNU General Public License. VERSION=0.16.21 TARGETS=install clean other \ bcc86 unproto copt as86 ld86 elksemu \ install-all install-bcc install-emu install-lib \ install-lib2 install-ln install-man install-other \ all-libs alt-libs library lib-386 lib-bsd lib-dos lib-fast lib-stand \ config tests dis88 doselks bootblocks ld86r ELKSSRC= /usr/src/elks PREFIX= /usr BINDIR= $(PREFIX)/bin LIBDIR= $(PREFIX)/lib/bcc INCLDIR= $(PREFIX)/lib/bcc ASLDDIR= $(BINDIR) MANDIR= $(PREFIX)/man CFLAGS= -O IFDEFNAME= ifdef # Some makes take the last of a list as the default ... all: make.fil PATH="`pwd`/bin:$$PATH" $(MAKE) -f make.fil VERSION=$(VERSION) TOPDIR=`pwd` $@ $(TARGETS): make.fil PATH="`pwd`/bin:$$PATH" $(MAKE) -f make.fil VERSION=$(VERSION) TOPDIR=`pwd` $@ $(TARGETS): ld: ld86 as: as86 realclean: -[ ! -f make.fil ] || $(MAKE) -f make.fil VERSION=$(VERSION) TOPDIR=`pwd` $@ -rm -f make.fil ifdef ifdefg make.fil: $(IFDEFNAME) makefile.in ./$(IFDEFNAME) -MU $(IFDEFOPTS) makefile.in >tmp.mak echo > tmp.sed [ "$(BINDIR)" != "//bin" ] || echo >> tmp.sed "s:%BINDIR%:/bin:" [ "$(LIBDIR)" != "//lib/bcc" ] || echo >> tmp.sed "s:%LIBDIR%:/lib:" [ "$(INCLDIR)" != "//lib/bcc" ] || echo >> tmp.sed "s:%INCLDIR%:/usr:" [ "$(ASLDDIR)" != "//bin" ] || echo >> tmp.sed "s:%ASLDDIR%:/bin:" [ "$(MANDIR)" != "//man" ] || echo >> tmp.sed "s:%MANDIR%:/usr/man:" echo >> tmp.sed "s:%PREFIX%:$(PREFIX):" echo >> tmp.sed "s:%BINDIR%:$(BINDIR):" echo >> tmp.sed "s:%INCLDIR%:$(INCLDIR):" echo >> tmp.sed "s:%LIBDIR%:$(LIBDIR):" echo >> tmp.sed "s:%ASLDDIR%:$(ASLDDIR):" echo >> tmp.sed "s:%MANDIR%:$(MANDIR):" echo >> tmp.sed "s:%ELKSSRC%:$(ELKSSRC):" echo >> tmp.sed "s:%CC%:$(CC):" echo >> tmp.sed "s:%CFLAGS%:$(CFLAGS):" echo >> tmp.sed "s:%LDFLAGS%:$(LDFLAGS):" sed -f tmp.sed < tmp.mak > make.tmp mv -f make.tmp make.fil @rm -f tmp.mak tmp.sed $(IFDEFNAME): ifdef.c $(CC) $(IFDEFARCH) $(CFLAGS) $(IFDEFFLAGS) $(LDFLAGS) -o $(IFDEFNAME) ifdef.c uninstall: @echo 'Sorry, no go; it was just wrong.' false distribution: @[ `id -u` -eq 0 ] || fakeroot -- sh ./Mk_dist $(VERSION) @[ `id -u` -ne 0 ] || sh ./Mk_dist $(VERSION) dev86-0.16.21/Mk_dist000066400000000000000000000131061231050321700141250ustar00rootroot00000000000000#!/bin/bash - # # This script builds _and checks_ all the distribution files from my source # directory. It's very selective because I've got a lot of historical and # other 'junk' in the same directory. (120Mb at the last count!) # trap "exit 1" 1 2 3 15 DIR="`pwd`" TMPDIR=/tmp/Linux-86 TMPSRC=linux86 ARCDIR="$DIR"/dev86arc SRCDIRS='bcc cpp unproto as ar ld copt man elksemu dis88 tests libbsd bin86' DISTFILES='Makefile README COPYING Changes Contributors MAGIC mkcompile GNUmakefile libcompat ifdef.c makefile.in Mk_dist' VERSION="$1" TMPDIST=$TMPDIR/$TMPSRC rm -rf ${TMPDIR} mkdir -p ${TMPDIST} [ "$VERSION" = '' ] && { echo 'Usage: $0 ' 1>&2 exit 1 } #----------------------------------------------------------------------- echo Copying most program files. make -s -C bin86 ungrab || exit cp -a $DISTFILES $SRCDIRS ${TMPDIST} #----------------------------------------------------------------------- echo Copying libc. LIBC_FILES='Makefile Make.defs crt0.c README COPYING KERNEL New_subdir Pre_main Config_sh Config.dflt' mkdir ${TMPDIST}/libc ( cd libc LIBC_DIRS="`for i in */Makefile */Config; do dirname $i; done | sort -u`" cp -a $LIBC_FILES include $LIBC_DIRS ${TMPDIST}/libc/. ) #----------------------------------------------------------------------- echo Copying bootblocks and doselks. make -s -C bootblocks distribution make -s -C doselks distribution mkdir ${TMPDIST}/bootblocks ( cd ${TMPDIST}/bootblocks ; tar xzf /tmp/bootblocks.tar.gz ) mkdir ${TMPDIST}/doselks ( cd ${TMPDIST}/doselks ; tar xzf /tmp/doselks.tar.gz ) [ "`id -un`" = "root" ] && { chown -R root:0 ${TMPDIST} chmod -R og=u-w ${TMPDIST} } rm -f /tmp/bootblocks.tar.gz /tmp/doselks.tar.gz /tmp/libc-8086-$VERSION.tar.gz MINOR=${VERSION##*.} MAJOR=${VERSION%.*} MID=${MAJOR##*.} MAJOR=${MAJOR%.*} OLDVER= case "$VERSION" in 0.0.0 ) BASEVER=0.0.0.0 ;; # Naa. *.0.0 ) BASEVER=$((MAJOR-1)).$MID.$MINOR ;; *.*.0 ) BASEVER=$MAJOR.$((MID-1)).$MINOR ;; * ) BASEVER=$MAJOR.$MID.$((MINOR-1)) OLDVER=$MAJOR.$MID.0 ;; esac if [ "$MAJOR.$MID.$((MINOR-1))" != "$BASEVER" ] then PATCHNAME="$VERSION-$BASEVER" else PATCHNAME="$VERSION" fi [ -f $ARCDIR/Dev86src-$BASEVER.tar.gz ] && { echo "Extracting previous version ($BASEVER)" mkdir ${TMPDIST}.tmp ( cd ${TMPDIST}.tmp tar xzf $ARCDIR/Dev86src-$BASEVER.tar.gz mv * ${TMPDIST}.old ) rmdir ${TMPDIST}.tmp } [ "$OLDVER" != "" -a -f $ARCDIR/Dev86src-$OLDVER.tar.gz ] && { echo "Extracting previous version ($OLDVER)" mkdir ${TMPDIST}.tmp ( cd ${TMPDIST}.tmp tar xzf $ARCDIR/Dev86src-$OLDVER.tar.gz mv * ${TMPDIST}.vold ) rmdir ${TMPDIST}.tmp } # ARCDIR=${TMPDIR}/arc ; mkdir -p ${ARCDIR} cd ${TMPDIST} echo COPY COMPLETE -- Switched to ${TMPDIST}, ARCDIR now $ARCDIR echo #----------------------------------------------------------------------- # # echo 'Ensuring clean tree' cd ${TMPDIST} make -s clean realclean mv as/obj1 ${TMPDIST}-obj1 EXCL="`find . -name '*.o' -o -name '*.obj' \ -o -name '*.lib' -o -name '*.bak' \ -o -name '*~' -o -name '*.exe' \ -o -name '*.orig' -o -name '*.rej' \ `" mv ${TMPDIST}-obj1 as/obj1 rm -f $EXCL rm -f `find . -type l` cd ${TMPDIR} [ -d ${TMPSRC}.old ] && { echo "Generating patch against version $BASEVER." mv ${TMPSRC}.old/bootblocks boot.old mv ${TMPSRC}/bootblocks boot diff -Nurd ${TMPSRC}.old ${TMPSRC} > ${ARCDIR}/patch-$PATCHNAME mv boot.old ${TMPSRC}.old/bootblocks mv boot ${TMPSRC}/bootblocks diff -Nurd ${TMPSRC}.old/bootblocks ${TMPSRC}/bootblocks >> ${ARCDIR}/patch-$PATCHNAME gzip -f9 ${ARCDIR}/patch-$PATCHNAME } [ -d ${TMPSRC}.vold ] && { echo "Generating patch against version $OLDVER." mv ${TMPSRC}.vold/bootblocks boot.old mv ${TMPSRC}/bootblocks boot diff -Nurd ${TMPSRC}.vold ${TMPSRC} > ${ARCDIR}/patch-$VERSION-$OLDVER mv boot.old ${TMPSRC}.vold/bootblocks mv boot ${TMPSRC}/bootblocks diff -Nurd ${TMPSRC}.vold/bootblocks ${TMPSRC}/bootblocks >> ${ARCDIR}/patch-$VERSION-$OLDVER gzip -f9 ${ARCDIR}/patch-$VERSION-$OLDVER } mkdir -p ${ARCDIR} echo Creating full source archive. ln -s ${TMPSRC} dev86-$VERSION tar cf ${ARCDIR}/Dev86src-$VERSION.tar dev86-$VERSION/* gzip -f9 ${ARCDIR}/Dev86src-$VERSION.tar echo Creating as86 source archive. ln -s ${TMPSRC}/as as86-$VERSION cp -p ${TMPSRC}/man/as86.1 as86-$VERSION/as86.1 cp -p ${TMPSRC}/COPYING as86-$VERSION/COPYING echo '#define VERSION "'"$VERSION"'"' > as86-$VERSION/version.h tar cf ${ARCDIR}/as86-$VERSION.tar `find as86-$VERSION/* -prune -type f` gzip -f9 ${ARCDIR}/as86-*.tar echo Creating bin86 source archive. make -s -C ${TMPSRC}/bin86 VERSION=${VERSION} grab ln -s ${TMPSRC}/bin86 bin86-$VERSION echo '#define VERSION "'"$VERSION"'"' > bin86-$VERSION/ld/version.h tar chf ${ARCDIR}/bin86-$VERSION.tar bin86-$VERSION make -s -C ${TMPSRC}/bin86 ungrab gzip -f9 ${ARCDIR}/bin86-*.tar ################################################################### echo Compile up the binaries. cd ${TMPDIR} || exit 1 mkdir -p ${TMPDIST}.ins make -C ${TMPDIST} install install-other \ ARFLAGS=q ELKSSRC=/dev/null \ DIST=${TMPDIST}.ins 'ASLDDIR=$(BINDIR)' || exit make -C ${TMPDIST} other || exit tar cf ${ARCDIR}/Dev86bin-$VERSION.tar -C ${TMPDIST}.ins . rm -f ${ARCDIR}/Dev86clb-$VERSION.zip Bcc ln -s ${TMPDIST} Bcc zip -9rpk ${ARCDIR}/Dev86clb-$VERSION.zip \ Bcc/lib/crt0.o Bcc/lib/libc.a Bcc/lib/libbsd.a \ Bcc/lib/libdos.a Bcc/lib/libc_f.a Bcc/lib/libc_s.a \ Bcc/lib/i386/crt0.o Bcc/lib/i386/libc.a || exit rm Bcc gzip -9f ${ARCDIR}/Dev86bin-$VERSION.tar || exit echo Process completed. dev86-0.16.21/README000066400000000000000000000134671231050321700135020ustar00rootroot00000000000000This is a development environment for ELKS-86 and standalone 8086 code. All you need to do is 'make' from the top directory and the main parts of the package will be made. These can be tested by using the 'ncc' program from the newly created bin subdirectory. (ncc is a varient of the bcc driver program that doesn't need to be installed to be used). Use 'make install' to install them. Some other bits can be built by 'make other' and installed with 'make install-other'. Note the the make files for the libraries can only be run using GNU-make but version 3.82 has a bug (No. 30612) that prevents this working properly. If you want it to install under /usr/local instead you can specify the prefix on the first make ie: 'make PREFIX=/usr/local' this is remembered until 'make.fil' is rebuilt. The manual pages in the man subdirectory are matched to these programs, there are also some hints for using as86 well. The tests and bootblocks directories give some example code. The bcc command defaults to using /usr/lib/bcc/include and /usr/lib/bcc the libraries _and_ include files are copied to these locations by install. This can be changed by overriding 'PREFIX=/usr/...' or 'LIBDIR=/usr/...' on the initial make. Also available in the same way are the BINDIR, INCLDIR, ASLDDIR, MANDIR and ELSESRC. The 'ELKSSRC=/usr/src/elks' variable can be altered if you have ELKS on path different from the default or ELKSSRC=/dev/null uses the supplied ELKS headers. The ASLDDIR variable can be used to move as86 and ld86 into the LIBDIR with 'ASLDDIR=$(LIBDIR)'. The final '/include' is added to the end of INCLDIR. In the unlikely event you're makeing a non-cross development environment you can, on the initial make, do "make PREFIX=/' to have the libraries and include files in 'Native' locations. Note: These prefix options only effect the 'bcc.c' driver program and the install scripts, all the others get their paths from bcc.c. The ELKSSRC location can, however, greatly effect how the ELKS libraries are built. If you don't want to install in the locations specified above there is also a DIST= argument to make install that is used to specify the distribution root to install to. The last option is not to install at all. All the executables in the bin directory can be moved to whereever you wish except for bcc and ncc. To use bcc at any other location you can create a symlink from your new location to the 'ncc' executable and it will be able to find the libraries in the build directory: eg: cp ar86 elksemu objdump86 $HOME/bin/. cp as86 as86_encap ld86 $HOME/bin/. # Optional. ln -s `pwd`/ncc $HOME/bin/bcc All the versions of the library are built by make; 'normal', 'fast', 'MSDOS', 'standalone' and Linux-i386. You use the other libraries like this: 'FAST' $ bcc -Mf prog.c -o prog Caller saves $ bcc -Mc prog.c -o prog MSDOS $ bcc -Md prog.c -o prog.com Standalone $ bcc -Ms prog.c -o prog.sys Linux-i386 $ bcc -Ml prog.c -o prog The 'Fast' and 'Caller saves' versions alter the function call assember in an effort to make it smaller and faster. The 'MSDOS' version creates _small_ model (64k+64k) COM files. Because of DOS limitations the filesize is limited to about 65000 bytes but the BSS and Stack can be upto 64k on top of that. The 'standalone' version creates executables like normal ELKS a.out files but with no operating system calls, just BIOS ones. These files are suitable for running on a bare machine started by one of the boot blocks in the bootblocks subdirectory. If you add a '-d' option to the link stage the a.out header will be removed. The Linux-i386 version generates static Linux OMAGIC a.out programs, they need neither elksemu nor a.out shared libraries to run. Unfortunatly these can no longer be converted to ELF executables as Linux will not execute unpageable ELF executables. To allow conversion to ELF if you pass the '-z' flag to 'bcc -Ml' the linker will now create QMAGIC a.out executables, these are somewhat larger but can be converted with objcopy. If you want to install everything in one go just login as root an do: $ make install-all The as86 and ld86 with this are _different_ from the minimum version needed for the linux-i386 kernel and can replace them, versions before 0.12.0 will not work with this version of bcc. I suggest you install the kernel patch or load the module to allow transparent execution of elks executables. If you're using a post 2.1.43 or 2.0.36 kernel the only module you need is the binfmt_misc driver configured like this: echo ':i86-elks:M::\x01\x03\x20\x00:\xff\xff\xff\x83:/usr/bin/elksemu:' \ > /proc/sys/fs/binfmt_misc/register The elksemu executable must be stored in /usr/bin/elksemu or the above line adjusted. Previous kernel versions need a special module or patch described in elksemu/README (All the options need the elksemu executable installed correctly) Copyrights ---------- The `bcc', 'as' and `ld' parts of the distribution are now covered by the GPL. The `bccfp' library now in the libc/i386fp directory is under the LGPL. (Primary copyright holder Bruce Evans) The contents of the libc and libbsd subdirectories are under the LGPL with a few noted exceptions. The programs in 'tests', elksemu, copt and the bootblocks directory are under the GPL. Dis88 is freely distributable if the source is distributed also. Unproto is freely distributable as long as Wietse Venema and the "Mathematics and Computing Science Dept. Eindhoven University of Technology. The Netherlands." is given credit. In libc the regular expression routine and the printf/scanf functions are not under LGPL, the former is 'freely distributable' the latter is public domain. See the COPYING file in this directory for the GPL and the COPYING file in the libc directory for the LGPL. -- Rob. (Robert de Bath ) dev86-0.16.21/ar/000077500000000000000000000000001231050321700132115ustar00rootroot00000000000000dev86-0.16.21/ar/Makefile000066400000000000000000000013171231050321700146530ustar00rootroot00000000000000# Copyright (c) 1999 Greg Haerr # This file is part of the Linux-8086 Development environment and is # distributed under the GNU General Public License. LIBDIR =/usr/bin CFLAGS =-O LDFLAGS = DEFS = OBJS= ar.o alloca.o all: ar86 ar86: $(OBJS) $(CC) $(LDFLAGS) $(OBJS) -o $@ install: ar86 install -d $(LIBDIR) install -m 755 ar86 $(LIBDIR) clean realclean clobber: rm -f *.o ar86 ar ar.h rel_aout.h $(OBJS): ar.h rel_aout.h ar.h: test -f ar.h || \ { rm -f ar.h ; ln -s ../libc/include/ar.h . ; } || \ ln ../libc/include/ar.h . rel_aout.h: test -f rel_aout.h || \ { rm -f rel_aout.h ; ln -s ../ld/rel_aout.h . ; } || \ ln ../ld/rel_aout.h . .c.o: $(CC) $(CFLAGS) $(DEFS) -c $< -o $@ dev86-0.16.21/ar/alloca.c000066400000000000000000000025331231050321700146130ustar00rootroot00000000000000 #ifdef __STDC__ #include #else #include #include #endif #if defined(__TINYC__) || defined(__HP_cc) typedef union mem_cell { union mem_cell *next; /* A pointer to the next mem */ unsigned int size; /* An int >= sizeof pointer */ char *depth; /* For the alloca hack */ } mem; #define m_size(p) ((p) [0].size) /* For malloc */ #define m_next(p) ((p) [1].next) /* For malloc and alloca */ #define m_deep(p) ((p) [0].depth) /* For alloca */ static mem *alloca_stack = 0; void * alloca(size) size_t size; { auto char probe; /* Probes stack depth: */ register mem *hp; /* * Reclaim garbage, defined as all alloca'd storage that was allocated * from deeper in the stack than currently. */ for (hp = alloca_stack; hp != 0;) if (m_deep(hp) < &probe) { register mem *np = m_next(hp); free((void *) hp); /* Collect garbage. */ hp = np; /* -> next header. */ } else break; /* Rest are not deeper. */ alloca_stack = hp; /* -> last valid storage. */ if (size == 0) return 0; /* No allocation required. */ hp = (mem *) malloc(sizeof(mem)*2 + size); if (hp == 0) return hp; m_next(hp) = alloca_stack; m_deep(hp) = &probe; alloca_stack = hp; /* User storage begins just after header. */ return (void *) (hp + 2); } #endif dev86-0.16.21/ar/ar.c000066400000000000000000001461151231050321700137670ustar00rootroot00000000000000/* ar.c - Archive modify and extract. Copyright (C) 1988, 1990 Free Software Foundation, Inc. ar86 changes by Greg Haerr This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #ifdef __STDC__ #include #include #include #include #endif #include #include #include #include #include #include "ar.h" #include "rel_aout.h" #if defined(__BCC__) || defined(__HP_cc) #define HAVE_RENAME #undef HAVE_FSYNC #define SHORT_FILENAME #else #define HAVE_FCHMOD #define HAVE_RENAME #undef HAVE_FSYNC #endif #define HAVE_TRAILING_SLASH_IN_NAME #ifdef __GNUC__ # ifndef alloca # define alloca __builtin_alloca # endif #else # if defined(sparc) || defined(HAVE_ALLOCA_H) # include # endif #endif #ifdef USG #define bcopy(source, dest, size) memcpy((dest), (source), (size)) #define bcmp(a, b, size) memcmp((a), (b), (size)) #define bzero(s, size) memset((s), 0, (size)) #endif /* Locking is normally disabled because fcntl hangs on the Sun and it isn't supported properly across NFS anyway. */ /* This structure is used internally to represent the info on a member of an archive. This is to make it easier to change format. */ struct member_desc { /* Name of member. */ char *name; /* The following fields are stored in the member header as decimal or octal numerals, but in this structure they are stored as machine numbers. */ int mode; /* Protection mode from member header. */ long int date; /* Last modify date as stored in member header. */ unsigned int size; /* Bytes of member's data, from member header. */ int uid, gid; /* UID and GID fields copied from member header. */ unsigned int offset;/* Offset in archive of the header of this member. */ unsigned int data_offset;/* Offset of first data byte of the member. */ /* The next field does not describe where the member was in the old archive, but rather where it will be in the modified archive. It is set up by write_archive. */ unsigned int new_offset; /* Offset of this member in new archive */ /* Symdef data for member. Used only for files being inserted. */ struct symdef *symdefs; unsigned int nsymdefs; /* Number of entries of symdef data. */ unsigned int string_size; /* Size of strings needed by symdef data. */ }; /* Each symbol is recorded by something like this. */ struct symdef { union { unsigned long int stringoffset; char *name; } s; unsigned long int offset; }; /* Nonzero means it's the name of an existing member; position new or moved files with respect to this one. */ char *posname; /* How to use `posname': POS_BEFORE means position before that member. POS_AFTER means position after that member. POS_DEFAULT if position by default; then `posname' should also be zero. */ enum { POS_DEFAULT, POS_BEFORE, POS_AFTER } postype; /* Nonzero means describe each action performed. */ int verbose; /* Nonzero means don't warn about creating the archive file if necessary. */ int silent_create; /* Nonzero means don't replace existing members whose dates are more recent than the corresponding files. */ int newer_only; /* Nonzero means preserve dates of members when extracting them. */ int preserve_dates; /* Operation to be performed. */ #define DELETE 1 #define REPLACE 2 #define PRINT_TABLE 3 #define PRINT_FILES 4 #define EXTRACT 5 #define MOVE 6 #define QUICK_APPEND 7 int operation; /* Name of archive file. */ char *archive; /* Descriptor on which we have locked the original archive file, or -1 if this has not been done. */ int lock_indesc; /* Pointer to tail of `argv', at first subfile name argument, or zero if no such were specified. */ char **files; /* Nonzero means write a __.SYMDEF member into the modified archive. */ int symdef_flag; /* Nonzero means __.SYMDEF member exists in old archive. */ int symdef_exists; /* Nonzero means don't update __.SYMDEF unless the flag was given. */ int ignore_symdef; /* Total number of symdef entries we will have. */ unsigned long int nsymdefs; /* Symdef data from old archive (set up only if we need it) */ struct symdef *old_symdefs; /* Number of symdefs in remaining in old_symdefs. */ unsigned int num_old_symdefs; /* Number of symdefs old_symdefs had when it was read in. */ unsigned long int original_num_symdefs; /* String table from old __.SYMDEF member. */ char *old_strings; /* Size of old_strings */ unsigned long int old_strings_size; /* String table to be written into __.SYMDEF member. */ char *new_strings; /* Size of new_strings */ unsigned long int new_strings_size; /* An archive map is a chain of these structures. Each structure describes one member of the archive. The chain is in the same order as the members are. */ struct mapelt { struct member_desc info; struct mapelt *next; }; struct mapelt *maplast; /* If nonzero, this is the map-element for the __.SYMDEF member and we should update the time of that member just before finishing. */ struct mapelt *symdef_mapelt; /* Header that we wrote for the __.SYMDEF member. */ struct ar_hdr symdef_header; /* Name this program was run with. */ char *program_name; #ifndef __STDC__ char *xmalloc (), *xrealloc (); void free (); void add_to_map (), delete_from_map (); int insert_in_map (); void print_descr (); char *concat (); void scan (); void extract_members (); void extract_member (); void print_contents (); void write_symdef_member (); void read_old_symdefs (); void two_operations (); void usage (), fatal (), error (), error3(), error_with_file (); void perror_with_name (), pfatal_with_name (); void write_archive (); void touch_symdef_member (); void update_symdefs (); void delete_members (), move_members (), replace_members (); void quick_append (); char *basename (); void print_modes (); char *make_tempname (); void copy_out_member (); #define const #else /* Grrr. */ extern void error (char * s1, char * s2); extern void error3 (char * s1, char * s2, char * s3); extern void fatal (char * s1, char * s2); extern void extract_members (void (*function) (struct member_desc member, FILE *istream)); extern void scan (void (*function) (struct member_desc member, FILE *istream), int crflag); extern char *basename (char *path); extern char *concat (const char *s1, const char *s2, const char *s3); extern char *make_tempname (char *name); extern char *xmalloc (unsigned int size); extern char *xrealloc (char *ptr, unsigned int size); extern int filter_symbols (struct nlist *syms, unsigned int symcount); extern int insert_in_map (char *name, struct mapelt *map, struct mapelt *after); extern int main (int argc, char **argv); extern int move_in_map (char *name, struct mapelt *map, struct mapelt *after); extern int read_header_info (struct mapelt *mapelt, int desc, long int offset, long int *syms_offset, unsigned int *syms_size, long int *strs_offset, unsigned int *strs_size); extern struct mapelt *find_mapelt (struct mapelt *map, char *name); extern struct mapelt *find_mapelt_noerror (struct mapelt *map, register char *name); extern struct mapelt *last_mapelt (struct mapelt *map); extern struct mapelt *make_map (int nonexistent_ok); extern struct mapelt *prev_mapelt (struct mapelt *map, struct mapelt *elt); extern void add_to_map (struct member_desc member, FILE * istream); extern void close_archive (void); extern void copy_out_member (struct mapelt *mapelt, int archive_indesc, int outdesc, char *outname); extern void delete_from_map (char *name, struct mapelt *map); extern void delete_members (void); extern void error_with_file (char *string, struct mapelt *mapelt); extern void extract_member (struct member_desc member, FILE *istream); extern void header_from_map (struct ar_hdr *header, struct mapelt *mapelt); extern void lock_for_update (void); extern void make_new_symdefs (struct mapelt *mapelt, int archive_indesc); extern void move_members (void); extern void mywrite (int desc, void *buf, int bytes, char *file); extern void perror_with_name (char *name); extern void pfatal_with_name (char *name); extern void print_contents (struct member_desc member, FILE *istream); extern void print_descr (struct member_desc member, FILE * instream); extern void print_modes (int modes); extern void quick_append (void); extern void read_old_symdefs (struct mapelt *map, int archive_indesc); extern void replace_members (void); extern void touch_symdef_member (int outdesc, char *outname); extern void two_operations (void); extern void update_symdefs (struct mapelt *map, int archive_indesc); extern void usage (char *s1, int val); extern void write_archive (struct mapelt *map, int appendflag); extern void write_symdef_member (struct mapelt *mapelt, struct mapelt *map, int outdesc, char *outname); #endif /* Output BYTES of data at BUF to the descriptor DESC. FILE is the name of the file (for error messages). */ void mywrite (desc, pbuf, bytes, file) int desc; void *pbuf; int bytes; char *file; { register int val; register char * buf = pbuf; while (bytes > 0) { val = write (desc, buf, bytes); if (val <= 0) perror_with_name (file); buf += val; bytes -= val; } } int main (argc, argv) int argc; char **argv; { int i; operation = 0; verbose = 0; newer_only = 0; silent_create = 0; posname = 0; postype = POS_DEFAULT; preserve_dates = 0; symdef_flag = 0; symdef_exists = 0; ignore_symdef = 0; symdef_mapelt = 0; files = 0; lock_indesc = -1; program_name = argv[0]; if (argc < 2) usage ("too few command arguments", 0); { char *key = argv[1]; char *p = key; char c; if (*p == '-') p++; while ((c = *p++)) { switch (c) { case 'a': postype = POS_AFTER; break; case 'b': postype = POS_BEFORE; break; case 'c': silent_create = 1; break; case 'd': if (operation) two_operations (); operation = DELETE; break; case 'i': postype = POS_BEFORE; break; case 'l': break; case 'm': if (operation) two_operations (); operation = MOVE; break; case 'o': preserve_dates = 1; break; case 'p': if (operation) two_operations (); operation = PRINT_FILES; break; case 'q': if (operation) two_operations (); operation = QUICK_APPEND; break; case 'r': if (operation) two_operations (); operation = REPLACE; break; case 's': symdef_flag = 1; break; case 't': if (operation) two_operations (); operation = PRINT_TABLE; break; case 'u': operation = REPLACE; newer_only = 1; break; case 'v': verbose = 1; break; case 'x': if (operation) two_operations (); operation = EXTRACT; break; } } } if (operation == 0 && symdef_flag) operation = REPLACE; if (operation == 0) usage ("no operation specified", 0); i = 2; if (postype != POS_DEFAULT) { if (i < argc) posname = argv[i++]; else usage ("no position operand", 0); } if (i >= argc) usage ("no archive specified", 0); archive = argv[i++]; if (i < argc) { files = &argv[i]; while (i < argc) if (!strcmp (argv[i++], "__.SYMDEF")) { ignore_symdef = 1; break; } } switch (operation) { case EXTRACT: extract_members (extract_member); break; case PRINT_TABLE: extract_members (print_descr); break; case PRINT_FILES: extract_members (print_contents); break; case DELETE: if (files != 0) delete_members (); break; case MOVE: if (files != 0) move_members (); break; case REPLACE: if (files != 0 || symdef_flag) replace_members (); break; case QUICK_APPEND: if (files != 0) quick_append (); break; default: usage ("invalid operation %d", operation); } exit (0); } void two_operations () { usage ("two different operation switches specified", 0); } void scan (function, crflag) #ifdef __STDC__ void (*function) (struct member_desc member, FILE *istream); #else void (*function) (); #endif int crflag; { FILE *arcstream = fopen (archive, "r"); if (arcstream == 0 && crflag) /* Creation-warning, if desired, will happen later. */ return; if (arcstream == 0) { perror_with_name (archive); exit (1); } { char buf[SARMAG]; int nread = fread (buf, 1, SARMAG, arcstream); if (nread != SARMAG || bcmp (buf, ARMAG, SARMAG)) fatal ("file %s not a valid archive", archive); } /* Now find the members one by one. */ { int member_offset = SARMAG; while (1) { int nread; struct ar_hdr member_header; struct member_desc member_desc; char name [1 + sizeof member_header.ar_name]; if (fseek (arcstream, member_offset, 0) < 0) perror_with_name (archive); nread = fread (&member_header, 1, sizeof (struct ar_hdr), arcstream); if (nread == 0) /* No data left means end of file; that is OK. */ break; if (nread != sizeof (member_header) || bcmp (member_header.ar_fmag, ARFMAG, 2)) fatal ("file %s not a valid archive", archive); bcopy (member_header.ar_name, name, sizeof member_header.ar_name); { char *p = name + sizeof member_header.ar_name; *p = '\0'; while (p > name && *--p == ' ') *p = '\0'; #if defined(USG) || defined(HAVE_TRAILING_SLASH_IN_NAME) if (*p == '/') /* Since V.2, names are terminated with '/' */ *p = '\0'; #endif } member_desc.name = name; sscanf (member_header.ar_mode, "%o", &member_desc.mode); member_desc.date = atoi (member_header.ar_date); member_desc.size = atoi (member_header.ar_size); member_desc.uid = atoi (member_header.ar_uid); member_desc.gid = atoi (member_header.ar_gid); member_desc.offset = member_offset; member_desc.data_offset = member_offset + sizeof (member_header); member_desc.new_offset = 0; member_desc.symdefs = 0; member_desc.nsymdefs = 0; member_desc.string_size = 0; if (!ignore_symdef && !strcmp (name, "__.SYMDEF")) symdef_exists = 1; function (member_desc, arcstream); member_offset += sizeof (member_header) + member_desc.size; if (member_offset & 1) ++member_offset; } } fclose (arcstream); } void print_descr (member, instream) struct member_desc member; FILE * instream; { char *timestring; if (!verbose) { puts (member.name); return; } print_modes (member.mode); timestring = ctime (&member.date); printf (" %2d/%2d %6d %12.12s %4.4s %s\n", member.uid, member.gid, member.size, timestring + 4, timestring + 20, member.name); } void print_modes (modes) int modes; { putchar (modes & 0400 ? 'r' : '-'); putchar (modes & 0200 ? 'w' : '-'); putchar (modes & 0100 ? 'x' : '-'); putchar (modes & 040 ? 'r' : '-'); putchar (modes & 020 ? 'w' : '-'); putchar (modes & 010 ? 'x' : '-'); putchar (modes & 04 ? 'r' : '-'); putchar (modes & 02 ? 'w' : '-'); putchar (modes & 01 ? 'x' : '-'); } #define BUFSIZE 1024 void extract_member (member, istream) struct member_desc member; FILE *istream; { int ncopied = 0; FILE *ostream; fseek (istream, member.data_offset, 0); ostream = fopen (member.name, "w"); if (!ostream) { perror_with_name (member.name); return; } if (verbose) printf ("x - %s\n", member.name); while (ncopied < member.size) { char buf [BUFSIZE]; int tocopy = member.size - ncopied; int nread; if (tocopy > BUFSIZE) tocopy = BUFSIZE; nread = fread (buf, 1, tocopy, istream); if (nread != tocopy) fatal ("error reading archive %s", archive); fwrite (buf, 1, nread, ostream); ncopied += tocopy; } #ifdef HAVE_FCHMOD fchmod (fileno (ostream), member.mode); #else chmod (member.name, member.mode); #endif if (ferror (ostream) || fclose (ostream) != 0) error ("%s: I/O error", member.name); if (preserve_dates) { #if defined(USG) || defined(__BCC__) long tv[2]; tv[0] = member.date; tv[1] = member.date; utime (member.name, tv); #else struct timeval tv[2]; tv[0].tv_sec = member.date; tv[0].tv_usec = 0; tv[1].tv_sec = member.date; tv[1].tv_usec = 0; utimes (member.name, tv); #endif } } void print_contents (member, istream) struct member_desc member; FILE *istream; { int ncopied = 0; fseek (istream, member.data_offset, 0); if (verbose) printf ("\n\n\n", member.name); while (ncopied < member.size) { char buf [BUFSIZE]; int tocopy = member.size - ncopied; int nread; if (tocopy > BUFSIZE) tocopy = BUFSIZE; nread = fread (buf, 1, tocopy, istream); if (nread != tocopy) fatal ("file %s not a valid archive", archive); fwrite (buf, 1, nread, stdout); ncopied += tocopy; } } /* Make a map of the existing members of the archive: their names, positions and sizes. */ /* If `nonexistent_ok' is nonzero, just return 0 for an archive that does not exist. This will cause the ordinary supersede procedure to create a new archive. */ struct mapelt * make_map (nonexistent_ok) int nonexistent_ok; { struct mapelt mapstart; mapstart.next = 0; maplast = &mapstart; scan (add_to_map, nonexistent_ok); return mapstart.next; } void add_to_map (member, istream) struct member_desc member; FILE * istream; { struct mapelt *mapelt = (struct mapelt *) xmalloc (sizeof (struct mapelt)); mapelt->info = member; mapelt->info.name = concat (mapelt->info.name, "", ""); maplast->next = mapelt; mapelt->next = 0; maplast = mapelt; } /* Return the last element of the specified map. */ struct mapelt * last_mapelt (map) struct mapelt *map; { struct mapelt *tail = map; while (tail->next) tail = tail->next; return tail; } /* Return the element of the specified map which precedes elt. */ struct mapelt * prev_mapelt (map, elt) struct mapelt *map, *elt; { struct mapelt *tail = map; while (tail->next && tail->next != elt) tail = tail->next; if (tail->next) return tail; return 0; } /* Return the element of the specified map which has the specified name. */ struct mapelt * find_mapelt_noerror (map, name) struct mapelt *map; register char *name; { register struct mapelt *tail; unsigned int len; int dot_o; name = basename (name); len = strlen (name); dot_o = name[len - 2] == '.' && name[len - 1] == 'o'; for (tail = map; tail != 0; tail = tail->next) { if (tail->info.name == 0) continue; if (!strncmp (tail->info.name, name, 13)) { unsigned int eltlen = strlen (tail->info.name); if (len <= 13 || eltlen <= 13) return tail; else { char *p = tail->info.name + 13; if (dot_o && p[0] == '.' && p[1] == 'o' && p[2] == '\0') return tail; else if (!strncmp (p, name + 13, (len > eltlen ? len : eltlen) - 13)) return tail; } } } return 0; } struct mapelt * find_mapelt (map, name) struct mapelt *map; char *name; { register struct mapelt *found = find_mapelt_noerror (map, name); if (found == 0) error ("no member named `%s'", name); return found; } /* Before looking at the archive, if we are going to update it based on looking at its current contents, make an exclusive lock on it. The lock is released when `write_archive' is called. */ void lock_for_update () { /* Open the existing archive file; if that fails, create an empty one. */ lock_indesc = open (archive, O_RDWR, 0); if (lock_indesc < 0) { int outdesc; if (!silent_create) printf ("Creating archive file `%s'\n", archive); outdesc = open (archive, O_WRONLY | O_APPEND | O_CREAT, 0666); if (outdesc < 0) pfatal_with_name (archive); mywrite (outdesc, ARMAG, SARMAG, archive); close (outdesc); /* Now we had better be able to open for update! */ lock_indesc = open (archive, O_RDWR, 0); if (lock_indesc < 0) { unlink (archive); pfatal_with_name (archive); } } #ifdef LOCKS /* Lock the old file so that it won't be updated by two programs at once. This uses the fcntl locking facility found on Sun systems which is also in POSIX. (Perhaps it comes from sysV.) Note that merely reading an archive does not require a lock, because we use `rename' to update the whole file atomically. */ { struct flock lock; lock.l_type = F_WRLCK; lock.l_whence = 0; lock.l_start = 0; lock.l_len = 0; while (1) { int value = fcntl (lock_indesc, F_SETLKW, &lock); if (value >= 0) break; else if (errno == EINTR) continue; else pfatal_with_name ("locking archive"); } } #endif } /* Unlock archive and close the file descriptor. */ void close_archive () { #ifdef LOCKS { struct flock lock; /* Unlock the old archive. */ lock.l_type = F_UNLCK; lock.l_whence = 0; lock.l_start = 0; lock.l_len = 0; fcntl (lock_indesc, F_SETLK, &lock); } #endif /* Close the archive. If we renamed a new one, the old one disappears. */ close (lock_indesc); } /* Write a new archive file from a given map. */ /* When a map is used as the pattern for a new archive, each element represents one member to put in it, and the order of elements controls the order of writing. Ordinarily, the element describes a member of the old archive, to be copied into the new one. If the `offset' field of the element's info is 0, then the element describes a file to be copied into the new archive. The `name' field is the file's name. If the `name' field of an element is 0, the element is ignored. This makes it easy to specify deletion of archive members. Every operation that will eventually call `write_archive' should call `lock_for_update' before beginning to do any I/O on the archive file. */ void write_archive (map, appendflag) struct mapelt *map; int appendflag; { char *tempname = make_tempname (archive); int indesc = lock_indesc; int outdesc; char *outname; struct mapelt *tail; /* Now open the output. */ if (!appendflag) { /* Updating an existing archive normally. Write output as TEMPNAME and rename at the end. There can never be two invocations trying to do this at once, because of the lock made on the old archive file. */ outdesc = open (tempname, O_WRONLY | O_CREAT, 0666); if (outdesc < 0) pfatal_with_name (tempname); outname = tempname; mywrite (outdesc, ARMAG, SARMAG, outname); } else { /* Fast-append to existing archive. */ outdesc = open (archive, O_WRONLY | O_APPEND, 0); if (outdesc < 0) pfatal_with_name (archive); outname = archive; } /* If archive has or should have a __.SYMDEF member, compute the contents for it. */ if (symdef_flag || symdef_exists) { if (symdef_exists) read_old_symdefs (map, indesc); else { struct mapelt *this = (struct mapelt *) xmalloc (sizeof (struct mapelt)); this->info.name = "__.SYMDEF"; this->info.offset = SARMAG; this->info.data_offset = SARMAG + sizeof (struct ar_hdr); this->info.new_offset = 0; this->info.date = 0; this->info.size = 0; this->info.uid = 0; this->info.gid = 0; this->info.mode = 0666; this->info.symdefs = 0; this->info.nsymdefs = 0; this->info.string_size = 0; this->next = map; map = this; original_num_symdefs = 0; old_strings_size = 0; } update_symdefs (map, indesc); } /* Copy the members into the output, either from the old archive or from specified files. */ for (tail = map; tail != 0; tail = tail->next) { if ((symdef_flag || symdef_exists) && tail->info.name && !strcmp (tail->info.name, "__.SYMDEF") #if 0 && tail->info.date==0 #endif ) write_symdef_member (tail, map, outdesc, outname); else copy_out_member (tail, indesc, outdesc, outname); } if (symdef_mapelt != 0) { /* Check for members whose data offsets weren't known when the symdef member was first written. */ int doneany = 0; for (tail = map; tail != 0; tail = tail->next) if (tail->info.offset == 0) { /* Fix up the symdefs. */ register unsigned int i; for (i = 0; i < tail->info.nsymdefs; ++i) tail->info.symdefs[i].offset = tail->info.new_offset; doneany = 1; } if (doneany) { /* Some files had bad symdefs; rewrite the symdef member. */ lseek (outdesc, symdef_mapelt->info.offset, 0); write_symdef_member (symdef_mapelt, map, outdesc, outname); } } /* Mark the __.SYMDEF member as up to date. */ if (symdef_mapelt != 0) touch_symdef_member (outdesc, outname); /* Install the new output under the intended name. */ #ifdef HAVE_FSYNC fsync (outdesc); #endif close (outdesc); if (!appendflag) if (rename (tempname, archive)) pfatal_with_name (tempname); close_archive (); } void header_from_map (header, mapelt) struct ar_hdr *header; struct mapelt *mapelt; { unsigned int namelen; char *p; /* Zero the header, then store in the data as text. */ bzero ((char *) header, sizeof (*header)); p = basename (mapelt->info.name); strncpy (header->ar_name, p, sizeof (header->ar_name)); namelen = strlen (p); if (namelen >= sizeof (header->ar_name)) { if (mapelt->info.name[namelen - 2] == '.' && mapelt->info.name[namelen - 1] == 'o') { header->ar_name[sizeof (header->ar_name) - 3] = '.'; header->ar_name[sizeof (header->ar_name) - 2] = 'o'; } header->ar_name[sizeof (header->ar_name) - 1] = '\0'; error3 ("member name `%s' truncated to `%s'", mapelt->info.name, header->ar_name); } #if defined(USG) || defined(HAVE_TRAILING_SLASH_IN_NAME) { /* System V tacks a trailing '/' onto the end of the name */ char *np = header->ar_name; char *end = np + sizeof (header->ar_name); while (np < end && *np) np++; *np = '/'; } #endif sprintf (header->ar_date, "%ld", mapelt->info.date); sprintf (header->ar_size, "%d", mapelt->info.size); sprintf (header->ar_uid, "%d", mapelt->info.uid); sprintf (header->ar_gid, "%d", mapelt->info.gid); sprintf (header->ar_mode, "%o", mapelt->info.mode); strncpy (header->ar_fmag, ARFMAG, sizeof (header->ar_fmag)); /* Change all remaining nulls in the header into spaces. */ { char *end = (char *) &header[1]; register char *np; for (np = (char *) header; np < end; ++np) if (*np == '\0') *np = ' '; } } /* gets just the file part of name */ char * basename (path) char *path; { char *save, *start; for (start = save = path; *path; path++) if (*path == '/') save = path + 1; if (save != start) return save; else return start; } /* writes to file open on OUTDESC with name OUTNAME. */ void copy_out_member (mapelt, archive_indesc, outdesc, outname) struct mapelt *mapelt; int archive_indesc; int outdesc; char *outname; { struct ar_hdr header; int indesc; if (mapelt->info.name == 0) /* This element was cancelled. */ return; header_from_map (&header, mapelt); if (mapelt->info.offset != 0) { indesc = archive_indesc; lseek (indesc, mapelt->info.data_offset, 0); } else { indesc = open (mapelt->info.name, 0, 0); if (indesc < 0) { perror_with_name (mapelt->info.name); return; } } mywrite (outdesc, &header, sizeof (header), outname); if (mapelt->info.data_offset == 0) mapelt->info.data_offset = lseek (outdesc, 0L, 1); { char buf[BUFSIZE]; int tocopy = mapelt->info.size; while (tocopy > 0) { int thistime = tocopy; if (thistime > BUFSIZE) thistime = BUFSIZE; read (indesc, buf, thistime); mywrite (outdesc, buf, thistime, outname); tocopy -= thistime; } } if (indesc != archive_indesc) close (indesc); if (mapelt->info.size & 1) mywrite (outdesc, "\n", 1, outname); } /* Update the time of the __.SYMDEF member; done when we updated that member, just before we close the new archive file. It is open on OUTDESC and its name is OUTNAME. */ void touch_symdef_member (outdesc, outname) int outdesc; char *outname; { struct stat statbuf; int i; /* See what mtime the archive file has as a result of our writing it. */ fstat (outdesc, &statbuf); /* Advance member's time to that time. */ bzero (symdef_header.ar_date, sizeof symdef_header.ar_date); sprintf (symdef_header.ar_date, "%ld", statbuf.st_mtime); for (i = 0; i < sizeof symdef_header.ar_date; i++) if (symdef_header.ar_date[i] == 0) symdef_header.ar_date[i] = ' '; /* Write back this member's header with the new time. */ if (lseek (outdesc, symdef_mapelt->info.new_offset, 0) >= 0) mywrite (outdesc, &symdef_header, sizeof symdef_header, outname); } char * make_tempname (name) char *name; { #if defined(USG) || defined(SHORT_FILENAME) /* sigh. 14 character filenames are *wonderful*, just *wonderful*. */ char *p = basename (name); char *q, *r; if (p != name) { q = concat (name, "", ""); /* get a fresh copy */ r = basename (q); /* r points just after last '/' */ *--r = '\0'; return concat (q, "/t_", p); } else if (strlen (name) >= 14) return concat ("t_", name, ""); else #endif return concat (name, "", "_supersede"); } void delete_members () { struct mapelt *map = make_map (0); struct mapelt mapstart; char **p; mapstart.info.name = 0; mapstart.next = map; map = &mapstart; lock_for_update (); if (files) for (p = files; *p; p++) { /* If user says to delete the __.SYMDEF member, don't make a new one to replace it. */ if (!strcmp (*p, "__.SYMDEF")) symdef_exists = 0; delete_from_map (*p, map); } write_archive (map->next, 0); } void delete_from_map (name, map) char *name; struct mapelt *map; { struct mapelt *this = find_mapelt (map, name); if (!this) return; this->info.name = 0; if (verbose) printf ("d - %s\n", name); } void move_members () { struct mapelt *map = make_map (0); char **p; struct mapelt *after_mapelt = 0; struct mapelt mapstart; struct mapelt *change_map; mapstart.info.name = 0; mapstart.next = map; change_map = &mapstart; lock_for_update (); switch (postype) { case POS_DEFAULT: after_mapelt = last_mapelt (change_map); break; case POS_AFTER: after_mapelt = find_mapelt (map, posname); break; case POS_BEFORE: after_mapelt = prev_mapelt (change_map, find_mapelt (map, posname)); } /* Failure to find specified "before" or "after" member is a fatal error; message has already been printed. */ if (!after_mapelt) exit (1); if (files) for (p = files; *p; p++) { if (move_in_map (*p, change_map, after_mapelt)) after_mapelt = after_mapelt->next; } write_archive (map, 0); } int move_in_map (name, map, after) char *name; struct mapelt *map, *after; { struct mapelt *this = find_mapelt (map, name); struct mapelt *prev; if (!this) return 0; prev = prev_mapelt (map, this); prev->next = this->next; this->next = after->next; after->next = this; return 1; } /* Insert files into the archive. */ void replace_members () { struct mapelt *map = make_map (1); struct mapelt mapstart; struct mapelt *after_mapelt = 0; struct mapelt *change_map; char **p; int changed; mapstart.info.name = 0; mapstart.next = map; change_map = &mapstart; lock_for_update (); switch (postype) { case POS_DEFAULT: after_mapelt = last_mapelt (change_map); break; case POS_AFTER: after_mapelt = find_mapelt (map, posname); break; case POS_BEFORE: after_mapelt = prev_mapelt (change_map, find_mapelt (map, posname)); } /* Failure to find specified "before" or "after" member is a fatal error; the message has already been printed. */ if (after_mapelt == 0) exit (1); changed = 0; if (files != 0) for (p = files; *p != 0; ++p) if (insert_in_map (*p, change_map, after_mapelt)) { after_mapelt = after_mapelt->next; changed = 1; } change_map = change_map->next; if (!changed && (!symdef_flag || symdef_exists)) /* Nothing changed. */ close_archive (); else write_archive (change_map, 0); } /* Handle the "quick insert" operation. */ void quick_append () { struct mapelt *map; struct mapelt *after; struct mapelt mapstart; char **p; mapstart.info.name = 0; mapstart.next = 0; map = &mapstart; after = map; lock_for_update (); /* Insert the specified files into the "map", but is a map of the inserted files only, and starts out empty. */ if (files) for (p = files; *p; p++) { if (insert_in_map (*p, map, after)) after = after->next; } /* Append these files to the end of the existing archive file. */ write_archive (map->next, 1); } /* Insert an entry for name NAME into the map MAP after the map entry AFTER. Delete an old entry for NAME. MAP is assumed to start with a dummy entry, which facilitates insertion at the beginning of the list. Return 1 if successful, 0 if did nothing because file NAME doesn't exist or (optionally) is older. */ int insert_in_map (name, map, after) char *name; struct mapelt *map, *after; { struct mapelt *old = find_mapelt_noerror (map, name); struct mapelt *this; struct stat status; if (stat (name, &status)) { perror_with_name (name); return 0; } if (old && newer_only && status.st_mtime <= old->info.date) return 0; if (old) /* Delete the old one. */ old->info.name = 0; this = (struct mapelt *) xmalloc (sizeof (struct mapelt)); this->info.name = name; this->info.offset = 0; this->info.data_offset = 0; this->info.date = status.st_mtime; this->info.size = status.st_size; this->info.uid = status.st_uid; this->info.gid = status.st_gid; this->info.mode = status.st_mode; /* Always place a __.SYMDEF member first in the archive, regardless of any position specifications. */ if (! strcmp (name, "__.SYMDEF")) this->next = map->next, map->next = this; else this->next = after->next, after->next = this; if (verbose) printf ("%c - %s\n", old == 0 ? 'a' : 'r', this->info.name); return 1; } /* Apply a function to each of the specified members. */ void extract_members (function) #ifdef __STDC__ void (*function) (struct member_desc member, FILE *istream); #else void (*function) (); #endif { struct mapelt *map; FILE *arcstream; char **p; if (!files) { /* Handle case where we want to operate on every member. No need to make a map and search it for this. */ scan (function, 0); return; } arcstream = fopen (archive, "r"); if (!arcstream) fatal ("failure opening archive %s for the second time", archive); map = make_map (0); for (p = files; *p; p++) { struct mapelt *this = find_mapelt (map, *p); if (!this) continue; function (this->info, arcstream); } fclose (arcstream); } /* Write the __.SYMDEF member from data in core. OUTDESC and OUTNAME are descriptor and name of file to write to. */ void write_symdef_member (mapelt, map, outdesc, outname) struct mapelt *mapelt; struct mapelt *map; int outdesc; char *outname; { struct ar_hdr header; struct mapelt *mapptr; unsigned long int symdefs_size; if (mapelt->info.name == 0) /* This element was cancelled. */ return; header_from_map (&header, mapelt); bcopy (&header, &symdef_header, sizeof header); mywrite (outdesc, &header, sizeof (header), outname); /* Write the number of symdefs. */ symdefs_size = nsymdefs * sizeof (struct symdef); #ifdef HOST_TARGET_ENDIANESS_DIFFERS md_number_to_chars (symdefs_size, sizeof symdefs_size, (unsigned char *) &symdefs_size); #endif mywrite (outdesc, &symdefs_size, sizeof symdefs_size, outname); /* Write symdefs surviving from old archive. */ #ifdef HOST_TARGET_ENDIANESS_DIFFERS md_symdefs_to_chars ((struct md_symdef *) old_symdefs, num_old_symdefs, (unsigned char *) old_symdefs); #endif mywrite (outdesc, old_symdefs, num_old_symdefs * sizeof (struct symdef), outname); #ifdef HOST_TARGET_ENDIANESS_DIFFERS md_chars_to_symdefs ((unsigned char *) old_symdefs, (struct md_symdef *) old_symdefs, num_old_symdefs); #endif /* Write symdefs for new members. */ for (mapptr = map; mapptr != 0; mapptr = mapptr->next) if (mapptr->info.nsymdefs != 0) { #ifdef HOST_TARGET_ENDIANESS_DIFFERS md_symdefs_to_chars ((struct md_symdef *) mapptr->info.symdefs, mapptr->info.nsymdefs, (unsigned char *) mapptr->info.symdefs); #endif write (outdesc, mapptr->info.symdefs, mapptr->info.nsymdefs * sizeof (struct symdef)); #ifdef HOST_TARGET_ENDIANESS_DIFFERS md_chars_to_symdefs ((unsigned char *) mapptr->info.symdefs, (struct md_symdef *) mapptr->info.symdefs, mapptr->info.nsymdefs); #endif } /* Write the string table size. */ #ifdef HOST_TARGET_ENDIANESS_DIFFERS md_number_to_chars (new_strings_size, sizeof new_strings_size, (unsigned char *) &new_strings_size); #endif mywrite (outdesc, &new_strings_size, sizeof new_strings_size, outname); #ifdef HOST_TARGET_ENDIANESS_DIFFERS new_strings_size = md_chars_to_number ((unsigned char *) &new_strings_size, sizeof new_strings_size); #endif /* Write the string table. */ mywrite (outdesc, new_strings, new_strings_size, outname); if (mapelt->info.size & 1) mywrite (outdesc, "", 1, outname); } void read_old_symdefs (map, archive_indesc) struct mapelt *map; int archive_indesc; { struct mapelt *mapelt; char *data; int val; int symdefs_size; mapelt = find_mapelt_noerror (map, "__.SYMDEF"); if (!mapelt) abort (); /* Only call here if an old one exists */ data = (char *) xmalloc (mapelt->info.size); lseek (archive_indesc, mapelt->info.data_offset, 0); val = read (archive_indesc, data, mapelt->info.size); #ifdef HOST_TARGET_ENDIANESS_DIFFERS symdefs_size = md_chars_to_number ((unsigned char *) data, sizeof symdefs_size); #else symdefs_size = *(unsigned long int *) data; #endif original_num_symdefs = symdefs_size / sizeof (struct symdef); old_symdefs = (struct symdef *) (data + sizeof (symdefs_size)); #ifdef HOST_TARGET_ENDIANESS_DIFFERS md_chars_to_symdefs ((unsigned char *) old_symdefs, (struct md_symdef *) old_symdefs, original_num_symdefs); #endif old_strings = ((char *) (old_symdefs + original_num_symdefs) + sizeof (symdefs_size)); #ifdef HOST_TARGET_ENDIANESS_DIFFERS old_strings_size = md_chars_to_number ((unsigned char *) (old_symdefs + original_num_symdefs), sizeof old_strings_size); #else old_strings_size = *(unsigned long int *) (old_symdefs + original_num_symdefs); #endif } /* Read various information from the header of an object file. Return 0 for failure or 1 for success. */ int read_header_info (mapelt, desc, offset, syms_offset, syms_size, strs_offset, strs_size) struct mapelt *mapelt; int desc; long int offset; long int *syms_offset; unsigned int *syms_size; long int *strs_offset; unsigned int *strs_size; { struct exec hdr; int len; lseek (desc, offset, 0); #ifdef HEADER_SEEK_FD HEADER_SEEK_FD (desc); #endif len = read (desc, (char *) &hdr, sizeof hdr); #ifdef HOST_TARGET_ENDIANESS_DIFFERS md_chars_to_hdr ((unsigned char *) &hdr, &hdr); #endif if (len == sizeof hdr && !N_BADMAG(hdr)) { *syms_offset = N_SYMOFF (hdr); *syms_size = hdr.a_syms; *strs_offset = N_STROFF (hdr); lseek (desc, N_STROFF (hdr) + offset, 0); if (read (desc, (char *) strs_size, sizeof *strs_size) != sizeof *strs_size) { error_with_file ("failure reading string table size in ", mapelt); return 0; } #ifdef HOST_TARGET_ENDIANESS_DIFFERS *strs_size = md_chars_to_number ((unsigned char *) strs_size, sizeof *strs_size); #endif return 1; } error_with_file ("bad format (not an object file) in ", mapelt); return 0; } /* Create the info.symdefs for a new member by reading the file it is coming from. */ void make_new_symdefs (mapelt, archive_indesc) struct mapelt *mapelt; int archive_indesc; { int indesc; char *name = mapelt->info.name; long int syms_offset, strs_offset; unsigned int syms_size, strs_size; struct nlist *symbols; int symcount; char *strings; register unsigned int i; unsigned long int offset; if (name == 0) /* Deleted member. */ abort (); if (mapelt->info.offset != 0) { indesc = archive_indesc; lseek (indesc, mapelt->info.data_offset, 0); offset = mapelt->info.data_offset; } else { indesc = open (mapelt->info.name, 0, 0); if (indesc < 0) { perror_with_name (mapelt->info.name); return; } offset = 0; } if (!read_header_info (mapelt, indesc, offset, &syms_offset, &syms_size, &strs_offset, &strs_size)) { if (mapelt->info.offset == 0) close (indesc); return; } /* Number of symbol entries in the file. */ symcount = syms_size / sizeof (struct nlist); /* Allocate temporary space for the symbol entries. */ symbols = (struct nlist *) alloca (syms_size); /* Read in the symbols. */ lseek (indesc, syms_offset + offset, 0); if (read (indesc, (char *) symbols, syms_size) != syms_size) { error_with_file ("premature end of file in symbols of ", mapelt); if (mapelt->info.offset == 0) (void) close (indesc); return; } #ifdef HOST_TARGET_ENDIANESS_DIFFERS md_chars_to_nlist ((unsigned char *) symbols, symbols, symcount); #endif /* The string table size includes the size word. */ if (strs_size < sizeof (strs_size)) { error_with_file ("bad string table size in ", mapelt); if (mapelt->info.offset == 0) (void) close (indesc); return; } strs_size -= sizeof (strs_size); /* Allocate permanent space for the string table. */ strings = (char *) xmalloc (strs_size); /* Read in the strings. */ lseek (indesc, offset + strs_offset + sizeof strs_size, 0); if (read (indesc, strings, strs_size) != strs_size) { error_with_file ("premature end of file in strings of ", mapelt); if (mapelt->info.offset == 0) (void) close (indesc); return; } if (indesc != archive_indesc) (void) close (indesc); /* Discard the symbols we don't want to mention; compact the rest down. */ symcount = filter_symbols (symbols, symcount); mapelt->info.symdefs = (struct symdef *) xmalloc (symcount * sizeof (struct symdef)); mapelt->info.nsymdefs = symcount; mapelt->info.string_size = 0; for (i = 0; i < symcount; ++i) { unsigned long int stroff = symbols[i].n_un.n_strx - sizeof (strs_size); char *symname = strings + stroff; if (stroff > strs_size) { char buf[100]; sprintf (buf, "ridiculous string offset %lu in symbol %u of ", stroff + sizeof (strs_size), i); error_with_file (buf, mapelt); return; } mapelt->info.symdefs[i].s.name = symname; mapelt->info.string_size += strlen (symname) + 1; } } /* Choose which symbol entries to mention in __.SYMDEF; compact them downward to get rid of the rest. Return the number of symbols left. */ int filter_symbols (syms, symcount) struct nlist *syms; unsigned int symcount; { struct nlist *from, *to; struct nlist *end = syms + symcount; for (to = from = syms; from < end; ++from) if ((from->n_type & N_EXT) && (from->n_type != N_EXT || from->n_value != 0)) *to++ = *from; return to - syms; } /* Update the __.SYMDEF data before writing a new archive. */ void update_symdefs (map, archive_indesc) struct mapelt *map; int archive_indesc; { struct mapelt *tail; int pos; register unsigned int i; unsigned int len; struct symdef *s; unsigned long int deleted_strings_size = 0; nsymdefs = original_num_symdefs; num_old_symdefs = original_num_symdefs; new_strings_size = old_strings_size; if (nsymdefs != 0) { /* We already had a __.SYMDEF member, so just update it. */ /* Mark as canceled any old symdefs for members being deleted. */ for (tail = map; tail != 0; tail = tail->next) { if (tail->info.name == 0) { /* Old member being deleted. Delete its symdef entries too. */ for (i = 0; i < original_num_symdefs; i++) if (old_symdefs[i].offset == tail->info.offset) { old_symdefs[i].offset = 0; --nsymdefs; deleted_strings_size += strlen (old_strings + old_symdefs[i].s.stringoffset) + 1; } } } /* Compactify old symdefs. */ { register unsigned int j = 0; for (i = 0; i < num_old_symdefs; ++i) { if (j != i) old_symdefs[j] = old_symdefs[i]; if (old_symdefs[i].offset != 0) ++j; } num_old_symdefs -= i - j; } /* Create symdef data for any new members. */ for (tail = map; tail != 0; tail = tail->next) { if (tail->info.offset != 0 || tail->info.name == 0 || !strcmp (tail->info.name, "__.SYMDEF")) continue; make_new_symdefs (tail, archive_indesc); nsymdefs += tail->info.nsymdefs; new_strings_size += tail->info.string_size; } } else { /* Create symdef data for all existing members. */ for (tail = map; tail != 0; tail = tail->next) { if (tail->info.name == 0 || !strcmp (tail->info.name, "__.SYMDEF")) continue; make_new_symdefs (tail, archive_indesc); nsymdefs += tail->info.nsymdefs; new_strings_size += tail->info.string_size; } } new_strings_size -= deleted_strings_size; old_strings_size -= deleted_strings_size; /* Now we know the size of __.SYMDEF, so assign the positions of all the members. */ tail = find_mapelt_noerror (map, "__.SYMDEF"); tail->info.size = (sizeof (nsymdefs) + (nsymdefs * sizeof (struct symdef)) + sizeof (new_strings_size) + new_strings_size); symdef_mapelt = tail; pos = SARMAG; for (tail = map; tail != 0; tail = tail->next) { if (tail->info.name == 0) /* Ignore deleted members. */ continue; tail->info.new_offset = pos; pos += sizeof (struct ar_hdr) + tail->info.size; if (tail->info.size & 1) ++pos; } /* Now update the offsets in the symdef data to be the new offsets rather than the old ones. */ for (tail = map; tail != 0; tail = tail->next) { if (tail->info.name == 0) continue; if (tail->info.symdefs == 0) /* Member without new symdef data. Check the old symdef data; it may be included there. */ for (i = 0; i < num_old_symdefs; i++) { if (old_symdefs[i].offset == tail->info.offset) old_symdefs[i].offset = tail->info.new_offset; } else for (i = 0; i < tail->info.nsymdefs; i++) tail->info.symdefs[i].offset = tail->info.new_offset; } /* Generate new, combined string table and put each string's offset into the symdef that refers to it. Note that old symdefs ref their strings by offsets into old_strings but new symdefs contain addresses of strings. */ new_strings = (char *) xmalloc (new_strings_size); pos = 0; /* Write the strings of the old symdefs and update the structures to contain indices into the string table instead of strings. */ for (i = 0; i < num_old_symdefs; i++) { strcpy (new_strings + pos, old_strings + old_symdefs[i].s.stringoffset); old_symdefs[i].s.stringoffset = pos; pos += strlen (new_strings + pos) + 1; } if (pos < old_strings_size) { unsigned int d = old_strings_size - pos; /* Correct the string table size. */ new_strings_size -= d; /* Correct the size of the `__.SYMDEF' member, since it contains the string table. */ symdef_mapelt->info.size -= d; } else if (pos > old_strings_size) fatal ("Old archive's string size was %u too small.", (void*)(pos - old_strings_size)); for (tail = map; tail != 0; tail = tail->next) if (tail->info.symdefs) { len = tail->info.nsymdefs; s = tail->info.symdefs; for (i = 0; i < len; i++) { strcpy (new_strings + pos, s[i].s.name); s[i].s.stringoffset = pos; pos += strlen (new_strings + pos) + 1; } } if (pos != new_strings_size) fatal ("internal error: inconsistency in new_strings_size", 0); } /* Print error message and usage message, and exit. */ void usage (s1, val) char *s1; int val; { char vbuf[16]; sprintf(vbuf, "%d", val); error (s1, vbuf); fprintf (stderr, "\ Usage: %s [d|m|p|q|r|t|x [[abi [position-name] [cilouv]] archive file...\n", program_name); exit (1); } /* Print error message and exit. */ void fatal (s1, s2) char *s1, *s2; { error (s1, s2); exit (1); } /* Print error message. `s1' is printf control string, the rest are args. */ void error (s1, s2) char *s1, *s2; { fprintf (stderr, "%s: ", program_name); fprintf (stderr, s1, s2); fprintf (stderr, "\n"); } void error3 (s1, s2, s3) char *s1, *s2, *s3; { fprintf (stderr, "%s: ", program_name); fprintf (stderr, s1, s2, s3); fprintf (stderr, "\n"); } void error_with_file (string, mapelt) char *string; struct mapelt *mapelt; { fprintf (stderr, "%s: ", program_name); fprintf (stderr, "%s", string); if (mapelt->info.offset != 0) fprintf (stderr, "%s(%s)", archive, mapelt->info.name); else fprintf (stderr, "%s", mapelt->info.name); fprintf (stderr, "\n"); } void perror_with_name (name) char *name; { error (concat ("", strerror(errno), " for %s"), name); } void pfatal_with_name (name) char *name; { fatal (concat ("", strerror(errno), " for %s"), name); } /* Return a newly-allocated string whose contents concatenate those of S1, S2, and S3. */ char * concat (s1, s2, s3) const char *s1, *s2, *s3; { int len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3); char *result = (char *) xmalloc (len1 + len2 + len3 + 1); strcpy (result, s1); strcpy (result + len1, s2); strcpy (result + len1 + len2, s3); *(result + len1 + len2 + len3) = 0; return result; } /* Like malloc but get fatal error if memory is exhausted. */ char * xmalloc (size) unsigned int size; { #ifdef MALLOC_0_RETURNS_NULL char *result = malloc (size ? size : 1); #else char *result = malloc (size); #endif if (result == 0) fatal ("virtual memory exhausted", 0); return result; } char * xrealloc (ptr, size) char *ptr; unsigned int size; { char *result = realloc (ptr, size); if (result == 0) fatal ("virtual memory exhausted", 0); return result; } #ifndef HAVE_RENAME int rename (from, to) char *from, *to; { (void)unlink (to); if (link (from, to) < 0 || unlink (from) < 0) return -1; else return 0; } #else #ifdef ATT int Error; #endif #endif dev86-0.16.21/as/000077500000000000000000000000001231050321700132125ustar00rootroot00000000000000dev86-0.16.21/as/6809/000077500000000000000000000000001231050321700136205ustar00rootroot00000000000000dev86-0.16.21/as/6809/const.h000066400000000000000000000262611231050321700151260ustar00rootroot00000000000000#define align(x) /* ((x) = ((int) (x) + (4-1)) & ~(4-1)) */ #define LOW_BYTE 0 /* must be changed for big-endian */ /* const.h - constants for assembler */ /* major switches */ #undef I80386 /* generate 80386 code */ #define MC6809 /* generate 6809 code */ #define MNSIZE /* allow byte size in mnemonic, e.g. "movb" */ #undef SOS_EDOS /* source OS is EDOS */ /* defaults */ #define DIRCHAR '/' /* character separating filename from dir */ #define INBUFSIZE 8192 #define SOS_EOLSTR "\012" /* defaults modified by switches */ #ifdef SOS_EDOS # undef INBUFSIZE # define INBUFSIZE 512 # undef SOS_EOLSTR # define SOS_EOLSTR "\015\012" # define STAKSIZ 256 /* table grows up to stack less this */ #endif /* booleans */ #define FALSE 0 #define TRUE 1 /* ASCII constants */ #define ETB 23 /* C tricks */ #define EXTERN extern #define FORWARD static #define PRIVATE static #define PUBLIC #define NULL 0 /* O/S constants */ #define CREAT_PERMS 0666 #define EOF (-1) #define STDIN 0 #define STDOUT 1 /* register codes (internal to assembler) */ #ifdef I80386 /* index regs must be first */ #define BPREG 0 #define BXREG 1 #define DIREG 2 #define SIREG 3 #define MAX16BITINDREG 3 #define EAXREG 4 #define EBPREG 5 #define EBXREG 6 #define ECXREG 7 #define EDIREG 8 #define EDXREG 9 #define ESIREG 10 #define ESPREG 11 #define MAXINDREG 11 #define AXREG 12 #define CXREG 13 #define DXREG 14 #define SPREG 15 #define AHREG 16 #define ALREG 17 #define BHREG 18 #define BLREG 19 #define CHREG 20 #define CLREG 21 #define DHREG 22 #define DLREG 23 #define CSREG 24 #define DSREG 25 #define ESREG 26 #define FSREG 27 #define GSREG 28 #define SSREG 29 #define CR0REG 30 #define CR2REG 31 #define CR3REG 32 #define DR0REG 33 #define DR1REG 34 #define DR2REG 35 #define DR3REG 36 #define DR6REG 37 #define DR7REG 38 #define TR6REG 39 #define TR7REG 40 #define NOREG 41 #endif /* I80386 */ #ifdef MC6809 /* index regs must be first, then PC, then other regs */ #define AREG 5 #define BREG 6 #define CCREG 7 #define DPREG 8 #define DREG 9 #define MAXINDREG 3 #define NOREG 10 #define PCREG 4 #define SREG 0 #define UREG 1 #define XREG 2 #define YREG 3 #endif #ifdef I80386 /* type and size keywords */ #define BYTEOP 0 #define DWORDOP 1 #define FWORDOP 2 #define FAROP 3 #define PTROP 4 #define PWORDOP 5 #define QWORDOP 6 #define TBYTEOP 7 #define WORDOP 8 #endif /* special chars */ #define EOL 0 #define MACROCHAR '?' /* symbol codes */ /* the first 2 must be from chars in identifiers */ #define IDENT 0 #define INTCONST 1 /* the next few are best for other possibly-multi-char tokens */ #define ADDOP 2 /* also ++ */ #define BINCONST 3 #define CHARCONST 4 #define GREATERTHAN 5 /* also >> and context-sensitive */ #define HEXCONST 6 #define LESSTHAN 7 /* also << and context-sensitive */ #define SUBOP 8 /* also -- */ #define WHITESPACE 9 #define ANDOP 10 #define COMMA 11 #define EOLSYM 12 #define EQOP 13 #define IMMEDIATE 14 #define INDIRECT 15 #define LBRACKET 16 #define LPAREN 17 #define MACROARG 18 #define NOTOP 19 #define OROP 20 #define OTHERSYM 21 #define POSTINCOP 22 #define PREDECOP 23 #define RBRACKET 24 #define RPAREN 25 #define SLASH 26 /* context-sensitive */ #define SLOP 27 #define SROP 28 #define STAR 29 /* context-sensitive */ #define STRINGCONST 30 #define COLON 31 /* these are from assembler errors module */ /* syntax errors */ #define COMEXP 0 #define DELEXP 1 #define FACEXP 2 #define IREGEXP 3 #define LABEXP 4 #define LPEXP 5 #define OPEXP 6 #define RBEXP 7 #define REGEXP 8 #define RPEXP 9 #define SPEXP 10 /* expression errors */ #define ABSREQ 11 #define NONIMPREQ 12 #define RELBAD 13 /* label errors */ #define ILLAB 14 #define MACUID 15 #define MISLAB 16 #define MNUID 17 #define REGUID 18 #define RELAB 19 #define UNBLAB 20 #define UNLAB 21 #define VARLAB 22 /* addressing errors */ #define ABOUNDS 23 #define DBOUNDS 24 #define ILLMOD 25 #define ILLREG 26 /* control structure errors */ #define ELSEBAD 27 #define ELSEIFBAD 27 #define ENDBBAD 28 #define ENDIFBAD 27 #define EOFBLOCK 29 #define EOFIF 30 #define EOFLC 31 #define EOFMAC 32 #define FAILERR 33 /* overflow errors */ #define BLOCKOV 34 #define BWRAP 35 #define COUNTOV 36 #define COUNTUN 37 #define GETOV 38 #define IFOV 39 #define LINLONG 40 #define MACOV 41 #define OBJSYMOV 42 #define OWRITE 43 #define PAROV 44 #define SYMOV 45 #define SYMOUTOV 46 /* i/o errors */ #define OBJOUT 47 /* miscellaneous errors */ #define CTLINS 48 #define FURTHER 49 #define NOIMPORT 50 #define NOTIMPLEMENTED 51 #define REENTER 52 #define SEGREL 53 /* warnings */ #define MINWARN 54 #define ALREADY 54 #define SHORTB 55 /* symbol table entry */ /* type entry contains following flags */ #define ENTBIT (1<<0) /* entry point (=OBJ_N_MASK) */ #define COMMBIT (1<<1) /* common */ #define LABIT (1<<2) /* label (a PC location or defined by EQU) */ #define MNREGBIT (1<<3) /* mnemonic for op or pseudo-op, or register */ #define MACBIT (1<<4) /* macro */ #define REDBIT (1<<5) /* redefined */ #define VARBIT (1<<6) /* variable (i.e. something defined by SET) */ #define EXPBIT (1<<7) /* exported (= OBJ_E_MASK) */ /* data entry contains following flags, valid */ /* for expressions as well as syms */ #define PAGE1 (1<<0) /* page 1 machine op = MNREGBIT \ PAGE1 */ #define PAGE2 (1<<1) /* page 2 machine op = MNREGBIT \ PAGE2 */ #define REGBIT (1<<2) /* register = MNREGBIT \ REGBIT */ #define SIZEBIT (1<<3) /* sizing mnemonic = MNREGBIT \ SIZEBIT */ #define SEGM 15 /* 1st 4 bits reused for segment if !MNREGBIT */ #define RELBIT (1<<4) /* relative (= OBJ_A_MASK) */ #define FORBIT (1<<5) /* forward referenced */ #define IMPBIT (1<<6) /* imported (= OBJ_I_MASK) */ #define UNDBIT (1<<7) /* undefined */ /* pseudo-op routine numbers */ /* conditionals are first, this is used to test if op is a conditional */ #define ELSEOP 0 #define ELSEIFOP 1 #define ELSEIFCOP 2 #define ENDIFOP 3 #define IFOP 4 #define IFCOP 5 #define MAXCOND 6 /* limit of conditionals */ #define BLOCKOP 6 #define COMMOP 7 #define ENDOP 8 #define ENDBOP 9 #define ENTEROP 10 #define ENTRYOP 11 #define EQUOP 12 #define EXPORTOP 13 #define FAILOP 14 #define FCBOP 15 #define FCCOP 16 #define FDBOP 17 #define GETOP 18 #define IDENTOP 19 #define IMPORTOP 20 #define _LISTOP 21 #define LOCOP 22 #define _MACLISTOP 23 #define MACROOP 24 #define _MAPOP 25 #define ORGOP 26 #define RMBOP 27 #define SETOP 28 #define SETDPOP 29 #define _WARNOP 30 #ifdef I80386 /* further pseudo-ops */ #define BSSOP 31 #define COMMOP1 32 #define DATAOP 33 #define TEXTOP 34 #define USE16OP 35 #define USE32OP 36 /* machine-op routine numbers */ #define ARPL 37 #define BCC 38 #define BOUND 39 #define CALL 40 #define DIVMUL 41 #define ENTER 42 #define GROUP1 43 #define GROUP2 44 #define GROUP6 45 #define GROUP7 46 #define GROUP8 47 #define GvEv 48 #define IMUL 49 #define IN 50 #define INCDEC 51 #define INHER 52 #define INHER16 53 #define INHER32 54 #define INHER_A 55 #define INT 56 #define JCC 57 #define JCXZ 58 #define LEA 59 #define LOAD_FULL_POINTER 60 #define MOV 61 #define MOVX 62 #define NEGNOT 63 #define OUT 64 #define PUSHPOP 65 #define RET 66 #define RETF 67 #define SEG 68 #define SETCC 69 #define SH_DOUBLE 70 #define TEST 71 #define XCHG 72 /* further pseudo-ops */ #define BLKWOP 73 #define EVENOP 74 #define FQBOP 75 #define ALIGNOP 76 /* further machine-ops */ #define CALLI 77 /* yet further pseudo-ops */ #define LCOMMOP 78 #define LCOMMOP1 79 #endif /* I80386 */ #ifdef MC6809 /* machine-op routine numbers */ #define ALL 31 /* all address modes allowed, like LDA */ #define ALTER 32 /* all but immediate, like STA */ #define IMMED 33 /* immediate only (ANDCC, ORCC) */ #define INDEXD 34 /* indexed (LEA's) */ #define INHER 35 /* inherent, like CLC or CLRA */ #define LONG 36 /* long branches */ #define SHORT 37 /* short branches */ #define SSTAK 38 /* S-stack (PSHS, PULS) */ #define SWAP 39 /* TFR, EXG */ #define USTAK 40 /* U-stack (PSHU,PULU) */ /* yet further pseudo-ops */ #define LCOMMOP 41 #endif /* object code format (Introl) */ #define OBJ_SEGSZ_TWO 0x02 /* size 2 code for segment size descriptor */ #define OBJ_MAX_ABS_LEN 64 /* max length of chunk of absolute code */ #define OBJ_ABS 0x40 /* absolute code command */ #define OBJ_OFFSET_REL 0x80 /* offset relocation command */ #define OBJ_SET_SEG 0x20 /* set segment command */ #define OBJ_SKIP_1 0x11 /* skip with 1 byte count */ #define OBJ_SKIP_2 0x12 /* skip with 2 byte count */ #define OBJ_SKIP_4 0x13 /* skip with 4 byte count */ #define OBJ_SYMBOL_REL 0xC0 /* symbol relocation command */ #define OBJ_A_MASK 0x10 /* absolute bit(symbols) */ #if OBJ_A_MASK - RELBIT /* must match internal format (~byte 1 -> 0) */ oops - RELBIT misplaced #endif #define OBJ_E_MASK 0x80 /* exported bit (symbols) */ #if OBJ_E_MASK - EXPBIT /* must match internal format (byte 0 -> 0) */ oops - EXPBIT misplaced #endif #define OBJ_I_MASK 0x40 /* imported bit (symbols) */ #if OBJ_I_MASK - IMPBIT /* must match internal format (byte 1 -> 0) */ oops - IMPBIT misplaced #endif #define OBJ_N_MASK 0x01 /* entry bit (symbols) */ #if OBJ_N_MASK - ENTBIT /* must match internal format (byte 0 -> 1) */ oops - ENTBIT misplaced #endif #define OBJ_SA_MASK 0x20 /* size allocation bit (symbols) */ #define OBJ_SZ_ONE 0x40 /* size one code for symbol value */ #define OBJ_SZ_TWO 0x80 /* size two code for symbol value */ #define OBJ_SZ_FOUR 0xC0 /* size four code for symbol value */ #define OBJ_R_MASK 0x20 /* PC-rel bit (off & sym reloc commands) */ #define OBJ_SEGM_MASK 0x0F /* segment mask (symbols, off reloc command) */ #define OBJ_OF_MASK 0x03 /* offset size code for symbol reloc */ #define OBJ_S_MASK 0x04 /* symbol number size code for symbol reloc */ #define SYMLIS_NAMELEN 26 #define SYMLIS_LEN (sizeof (struct sym_listing_s)) #define FILNAMLEN 64 /* max length of a file name */ #define LINLEN 256 /* max length of input line */ #define LINUM_LEN 5 /* length of formatted line number */ #define SPTSIZ 1024 /* number of symbol ptrs */ /* pseudo-op flags */ #define POPHI 1 /* set to print hi byte of adr */ #define POPLO 2 /* to print lo byte of ADR */ #define POPLC 4 /* to print LC */ #define POPLONG 8 /* to print high word of ADR */ #define MAXBLOCK 8 /* max nesting level of BLOCK stack */ #define MAXGET 8 /* max nesting level of GET stack */ #define MAXIF 8 /* max nesting level of IF stack */ #define MACPSIZ (128/sizeof (struct schain_s)) /* size of macro param buffer */ #define MAXMAC 8 /* max nesting level of macro stack */ #define NLOC 16 /* number of location counters */ #ifdef I80386 #define NO_SIB 0340 /* illegal sib (3 with 4) to mean no sib */ #endif /* special segments */ #define BSSLOC 3 #define DATALOC 3 #define DPLOC 2 #define STRLOC 1 #define TEXTLOC 0 dev86-0.16.21/as/Makefile000066400000000000000000000030051231050321700146500ustar00rootroot00000000000000 CFLAGS=-O LDFLAGS=-s LIBDIR=/usr/bin BINDIR=/usr/bin OBJS =as.o assemble.o errors.o express.o \ genbin.o genlist.o genobj.o gensym.o \ keywords.o macro.o mops.o pops.o readsrc.o \ scan.o table.o typeconv.o alloc.o all: as86 as86_encap as86: $(OBJS) $(CC) $(LDFLAGS) $(OBJS) -o $@ as86_encap: as86_encap.sh sed -e "s:%%LIBDIR%%:$(LIBDIR):" -e "s:%%BINDIR%%:$(BINDIR):" \ < as86_encap.sh > tmp @mv -f tmp $@ chmod +x $@ install: all install -d $(LIBDIR) install -m 755 as86 $(LIBDIR) install -d $(BINDIR) install -m 755 as86_encap $(BINDIR)/as86_encap -@rm -f tmp clean realclean clobber: rm -f *.o as86 as86_encap .c.o: $(CC) $(CFLAGS) -c $< $(OBJS): const.h errors.h as.o: const.h type.h byteord.h macro.h file.h flag.h globvar.h assemble.o: const.h type.h address.h globvar.h opcode.h scan.h error.o: const.h type.h express.o: const.h type.h address.h globvar.h scan.h source.h genbin.o: const.h type.h address.h file.h globvar.h genlist.o: const.h type.h address.h flag.h file.h globvar.h macro.h scan.h \ source.h genobj.o: const.h type.h address.h file.h globvar.h gensym.o: const.h type.h flag.h file.h globvar.h keywords.o: const.h type.h globvar.h opcode.h macro.o: const.h type.h globvar.h scan.h macro.h mops.o: const.h type.h globvar.h opcode.h scan.h address.h pops.o: const.h type.h address.h flag.h globvar.h opcode.h scan.h readsrc.o: const.h type.h flag.h file.h globvar.h macro.h scan.h source.h scan.o: const.h type.h globvar.h scan.h table.o: const.h type.h globvar.h opcode.h scan.h dev86-0.16.21/as/address.h000066400000000000000000000015031231050321700150070ustar00rootroot00000000000000/* address.h - global variables involving addresses for assembler */ EXTERN struct address_s lastexp;/* last expression parsed */ EXTERN union { char fcbuf[LINLEN - 6]; /* buffer for fcb and fcc data */ /* data is absolute in 1 char pieces */ /* limited by FCC\t"" etc on line */ struct address_s fdbuf[(LINLEN - 4) / 2]; /* buffer for fdb data */ /* data can be of any 2-byte adr type */ /* limited by FDB\t and commas on line */ #if SIZEOF_OFFSET_T > 2 struct address_s fqbuf[(LINLEN - 4) / 4]; /* buffer for fqb data */ /* data can be of any 4-byte adr type */ /* limited by FQB\t and commas on line */ #endif } databuf; EXTERN bool_t fcflag; EXTERN bool_t fdflag; #if SIZEOF_OFFSET_T > 2 EXTERN bool_t fqflag; #endif EXTERN struct address_s immadr; EXTERN smallcount_t immcount; dev86-0.16.21/as/align.h000066400000000000000000000006321231050321700144560ustar00rootroot00000000000000/* align.h - memory alignment requirements for linker */ /* Copyright (C) 1994 Bruce Evans */ #ifndef S_ALIGNMENT # define align(x) #else #if defined(__STDC__) && defined(_POSIX_SOURCE) # define align(x) ((x)=(void *) \ (((ssize_t)(x) + (S_ALIGNMENT-1)) & ~(S_ALIGNMENT-1))) #else # define align(x) ((x)=(void *) \ ((char *)(x) + ((S_ALIGNMENT-(char)(x)) & (S_ALIGNMENT-1)))) #endif #endif dev86-0.16.21/as/alloc.c000066400000000000000000000031211231050321700144450ustar00rootroot00000000000000 #include "syshead.h" #include "const.h" #include "type.h" #include "align.h" PRIVATE char NOMEMEORY[] = "Cannot allocate sufficient memory"; #ifdef USE_FIXED_HEAP PRIVATE char *heapend; /* end of free space for symbol list */ PRIVATE char *heapptr; /* next free space in symbol list */ #endif #ifndef USE_FIXED_HEAP PRIVATE char tempbuf[2048]; #endif void init_heap() { #ifdef USE_FIXED_HEAP #ifndef USERMEM #define USERMEM 0xAC00U #endif #ifdef __AS386_16__ int stk; heapptr = sbrk(0); heapend = ((char*)&stk) - STAKSIZ - 16; brk(heapend); if(sbrk(0) != heapend) as_abort(NOMEMEORY); #else #ifdef SOS_EDOS heapend = stackreg() - STAKSIZ; #else heapptr = malloc(USERMEM); heapend = heapptr + USERMEM; if (heapptr == 0) as_abort(NOMEMEORY); #endif #endif #endif } void * temp_buf() { #ifdef USE_FIXED_HEAP return heapptr; #else return tempbuf; #endif } void * asalloc(size) unsigned int size; { void * rv; #ifdef USE_FIXED_HEAP align(heapptr); if (heapptr+size < heapend) { rv = heapptr; heapptr += size; } else rv = 0; #else rv = malloc(size); #endif if (rv == 0 && size) as_abort(NOMEMEORY); return rv; } void * asrealloc(oldptr, size) void * oldptr; unsigned int size; { void * rv; #ifdef USE_FIXED_HEAP if (oldptr == 0) return asalloc(size); if ((char*)oldptr+size < heapend) { heapptr = (char*)oldptr + size; rv = oldptr; } else rv = 0; #else rv = realloc(oldptr, size); #endif if (rv == 0) as_abort(NOMEMEORY); return rv; } dev86-0.16.21/as/as.c000066400000000000000000000165221231050321700137670ustar00rootroot00000000000000/* as.c - assembler */ /* usage: as source [-b [bin]] [-lm [list]] [-n name] [-o obj] [-s sym] [-guw] in any order (but no repeated file options) */ #include "syshead.h" #include "const.h" #include "type.h" #include "byteord.h" #include "macro.h" #undef EXTERN #define EXTERN #include "file.h" #include "flag.h" #include "globvar.h" #include "version.h" PUBLIC char hexdigit[] = "0123456789ABCDEF"; /* XXX - ld uses lower case */ PRIVATE struct block_s hid_blockstak[MAXBLOCK]; /* block stack */ PRIVATE struct lc_s hid_lctab[NLOC]; /* location counter table */ PRIVATE struct if_s hid_ifstak[MAXBLOCK]; /* if stack */ PRIVATE struct schain_s hid_mcpar[MACPSIZ]; /* MACRO params */ PRIVATE struct macro_s hid_macstak[MAXBLOCK]; /* macro stack */ PRIVATE struct sym_s *hid_spt[SPTSIZ]; /* hash table */ PRIVATE char * binfilename = 0; PRIVATE char * objfilename = 0; PRIVATE int keep_bad_output = 0; FORWARD void initp1 P((void)); FORWARD int my_creat P((char *name, char *message)); FORWARD void process_args P((int argc, char **argv)); FORWARD void summary P((fd_t fd)); FORWARD void summ_number P((unsigned num)); FORWARD void usage P((void)); PUBLIC int main(argc, argv) int argc; char **argv; { init_heap(); initp1(); initp1p2(); inst_keywords(); initbin(); initobj(); initsource(); typeconv_init(INT_BIG_ENDIAN, LONG_BIG_ENDIAN); as_warn.global = TRUE; /* constant */ as_warn.semaphore = -1; last_pass=1; process_args(argc, argv); initscan(); line_zero(); assemble(); /* doesn't return, maybe use setjmp */ /* NOTREACHED */ return 0; } PUBLIC void as_abort(message) char *message; { write(STDOUT, "as: ", 4); write(STDOUT, message, strlen(message)); write(STDOUT, "\n", 1); exit(1); } PUBLIC void finishup() { bintrailer(); objtrailer(); if (list.global ||symgen) gensym(); /* output to lstfil and/or symfil */ if (list.global ||toterr != 0 || totwarn != 0) summary(lstfil); if (lstfil != STDOUT && (toterr != 0 || totwarn != 0)) summary(STDOUT); statistics(); /* If an output binary is in error remove it */ close(binfil); binfil=0; close(objfil); objfil=0; if (toterr != 0 && !keep_bad_output) { if(binfilename) unlink(binfilename); if(objfilename) unlink(objfilename); } exit(toterr != 0 ? 1 : 0); /* should close output files and check */ } /* initialise constant nonzero values */ PRIVATE void initp1() { #ifdef I80386 idefsize = defsize = 2; /* I think this is probably safer (RDB) */ #endif #if 0 idefsize = defsize = sizeof (char *) > 2 ? 4 : 2; #endif lctabtop = lctab + NLOC; lstfil = STDOUT; mapnum = 15; /* default map number for symbol table */ spt_top = (spt = hid_spt) + SPTSIZ; } /* initialise nonzero values which start same each pass */ PUBLIC void initp1p2() { register struct lc_s *lcp; dirty_pass = 0; ifflag = TRUE; pedata = UNDBIT; /* program entry point not defined */ blockstak = hid_blockstak + MAXBLOCK; ifstak = hid_ifstak + MAXIF; macstak = hid_macstak + MAXMAC; macptop = (macpar = hid_mcpar) + MACPSIZ; lctabtop = (lcptr = lctab = hid_lctab) + NLOC; for (lcp = lctab; lcp < lctabtop; ++lcp) { lcp->data = lcdata = RELBIT; /* lc relocatable until 1st ORG */ lcp->lc = lc = 0; } } PUBLIC void line_zero() { if( textseg >= 0 ) ptext(); } PRIVATE int my_creat(name, message) char *name; char *message; { int fd; #ifdef O_BINARY if ((fd = open(name, O_RDWR|O_BINARY|O_CREAT|O_TRUNC, CREAT_PERMS)) < 0 || fd > 255) #else if ((fd = creat(name, CREAT_PERMS)) < 0 || fd > 255) #endif as_abort(message); return fd; } PRIVATE void process_args(argc, argv) int argc; char **argv; { char *arg; bool_t isnextarg; char *nextarg = 0; int opened_file = 0; int flag_state; #ifdef I80386 setcpu(0xF); #endif textseg = -1; if (argc <= 1) usage(); do { arg = *++argv; if (arg[0] == '-' && arg[1] != '\0') { flag_state = 1; if (arg[2] == '-' && arg[3] == 0 ) flag_state = 0; else if (arg[2] != 0) usage(); /* no multiple options */ isnextarg = FALSE; if (argc > 2) { nextarg = argv[1]; if (nextarg[0] != 0 && nextarg[0] != '-') isnextarg = TRUE; } switch (arg[1]) { case 'v': outfd = STDOUT; writes("as86 version: "); #ifdef VERSION writesn(VERSION); #else writesn("Unknown!"); #endif exit(1); #ifdef I80386 case '0': case '1': case '2': idefsize = defsize = 0x2; setcpu(arg[1]-'0'); break; case '3': idefsize = defsize = 0x4; setcpu(0xF); break; case 'a': asld_compatible = flag_state; break; #endif case 'b': if (!isnextarg || binfil != 0) usage(); binfil = my_creat(binfilename=nextarg, "error creating binary file"); binaryg = TRUE; --argc; ++argv; break; case 'g': globals_only_in_obj = flag_state; break; #ifdef I80386 case 'j': jumps_long = flag_state; break; case 'O': if( flag_state ) last_pass = 2; else last_pass = 1; break; #endif case 'l': list.global = TRUE; goto get_any_list_file; case 'm': maclist.global = TRUE; get_any_list_file: if (isnextarg) { if (lstfil != STDOUT) usage(); lstfil = my_creat(nextarg, "error creating list file"); --argc; ++argv; } break; case 'n': if (!isnextarg) usage(); truefilename = nextarg; --argc; ++argv; break; case 'o': if (!isnextarg || objfil != 0) usage(); objectg = TRUE; objfil = my_creat(objfilename=nextarg, "error creating object file"); --argc; ++argv; break; case 's': if (!isnextarg || symfil != 0) usage(); symgen = TRUE; symfil = my_creat(nextarg, "error creating symbol file"); --argc; ++argv; break; case 't': if (!isnextarg || binfil != 0) usage(); textseg = atoi(nextarg); if(textseg>0) textseg+=BSSLOC; --argc; ++argv; break; case 'u': if( flag_state ) inidata = IMPBIT | SEGM; else inidata = 0; break; case 'w': if( flag_state ) as_warn.semaphore = -1; else as_warn.semaphore = 0; break; case 'k': keep_bad_output = 1; break; default: usage(); /* bad option */ } } else if (infil != 0) usage(); /* no multiple sources */ else { if (strlen(arg) > FILNAMLEN) as_abort("source file name too long"); infiln = infil0 = 1; infil = open_input(strcpy(filnamptr, arg)); opened_file = 1; } } while (--argc != 1); if( !opened_file ) { infiln = infil0 = 1; infil = open_input(strcpy(filnamptr, "-")); } #ifdef I80386 origcpuid = cpuid; #endif inidata = (~binaryg & inidata) | (RELBIT | UNDBIT); } /* IMPBIT from inidata unless binaryg */ PRIVATE void summary(fd) int fd; { outfd = fd; writenl(); summ_number(toterr); writesn(" errors"); summ_number(totwarn); writesn(" warnings"); } PRIVATE void summ_number(num) unsigned num; { /* format number like line numbers */ char buf[16]; *build_number(num, LINUM_LEN, buf) = 0; writes(buf); } PRIVATE void usage() { as_abort( #ifdef I80386 "usage: as [-03agjuwO] [-b [bin]] [-lm [list]] [-n name] [-o obj] [-s sym] src"); #else "usage: as [-guw] [-b [bin]] [-lm [list]] [-n name] [-o obj] [-s sym] src"); #endif } dev86-0.16.21/as/as86_encap.sh000066400000000000000000000055351231050321700155050ustar00rootroot00000000000000#!/bin/sh - # # This file is simply an example of what can be done using the new binary # and symbol table output functions. As shown it can be used to produce # a C file containing the encapsulated binary of the assembly, plus any # public symbols in the source are accessable to the C program. # # Use it in a makefile: # # .s.v: # as86_encap $*.s $*.v $*_ $(AS86FLAGS) # [ $# -lt 2 ] && { echo "Usage: `basename $0` infile outfile prefix [as86 opts]" 1>&2 exit 1 } trap "rm -f _$$.* ; exit 99" 1 2 3 15 LIBDIR='%%LIBDIR%%' # Set by make install BINDIR='%%BINDIR%%' # Set by make install # If the one set by install fails then try a couple of others. [ -x "$LIBDIR/as86" ] || LIBDIR="`dirname $0`" [ -x "$LIBDIR/as86" ] || LIBDIR="$BINDIR" [ -x "$LIBDIR/as86" ] || LIBDIR="`dirname $0`/../lib" [ -x "$LIBDIR/as86" ] || LIBDIR=/usr/bin IFILE="$1" OFILE="$2" PREFIX="`basename $IFILE .s`_" shift ; shift if [ $# -ge 1 ] then case "$1" in -* ) ;; [A-Za-z_]* ) PREFIX="$1" shift ;; esac fi RV=0 $LIBDIR/as86 "$@" "$IFILE" -b _$$.bin -s _$$.sym || RV=$? echo '#ifndef __ASSEMBLY__' > _$$.0 echo >> _$$.0 echo '#else' > _$$.3 echo >> _$$.3 echo '#endif' > _$$.5 [ "$RV" = 0 ] && { ( sort _$$.sym echo %%%% od -v -t uC _$$.bin ) | \ awk -v prefix=$PREFIX -v ofile=_$$ ' BEGIN{ sname = prefix "start"; sn_file= ofile ".1"; bn_file= ofile ".2"; as_file= ofile ".4"; } /^%%%%$/ { flg++; if( flg == 1 ) { if( !started ) { printf "#define %s 0\n", sname > sn_file; printf "%s = 0\n", sname > as_file; } printf "static char %sdata[] = {\n", prefix >bn_file; bincount=0; } next; } flg==0 { if(NF == 0) next; if( substr($2,1,4) == "0000" ) $2=substr($2,5); if( $1 == "+" && $4 == "$start" ) { printf "#define %s 0x%s\n", sname, $2 > sn_file; printf "%s = $%s\n", sname, $2 > as_file; started = 1; } else if( substr($3, 1, 1) == "E" && $4 != "start" && $4 != "size" && $4 != "data" ) { printf "#define %s%s 0x%s\n", prefix, $4, $2 > sn_file; printf "%s%s = $%s\n", prefix, $4, $2 > as_file; } next; } flg==1 { if(NF == 0) next; printf " " > bn_file; for(i=2;i<=NF;i++) { if( $i >= 32 && $i < 127 && $i != 39 && $i != 92 ) printf("\047%c\047,", $i) > bn_file; else printf("%3d,", $i) > bn_file; bincount++; } printf "\n" > bn_file; } END { printf "};\n\n" > bn_file; printf "#define %ssize %d\n\n", prefix, bincount > sn_file; printf "%ssize = $%04x\n\n", prefix, bincount > as_file; } ' RV=$? } [ "$RV" = 0 ] && { if [ "X$OFILE" = "X-" ] then cat _$$.[0-9] else cat _$$.[0-9] > "$OFILE" || RV=$? fi } rm -f _$$.* exit $RV dev86-0.16.21/as/as86_to_data000066400000000000000000000037521231050321700154200ustar00rootroot00000000000000#!/bin/sh - # # This file is simply an example of what can be done using the new binary # and symbol table output functions. It produces a byte array with the # symbols in the object as array references within it. # # The output is a Linux OMAGIC binary created by ld86 -N, this means the # object can be linked directly to C-functions created by the same GCC that # compiled ld86. # # Use it in a makefile: # # .s86.o: # as86_to_data $*.s86 $*.o $(AS86FLAGS) # [ $# -lt 2 ] && { echo "Usage: `basename $0` infile outfile [as86 opts]" 1>&2 exit 1 } trap "rm -f _$$.* ; exit 99" 1 2 3 15 LIBDIR='%%LIBDIR%%' # Set by make install [ -d "$LIBDIR" ] || LIBDIR='%%BINDIR%%' [ -d "$LIBDIR" ] || LIBDIR=/usr/bin IFILE="$1" OFILE="$2" shift ; shift RV=0 $LIBDIR/as86 "$@" "$IFILE" -b _$$.bin -s _$$.sym || RV=$? [ "$RV" = 0 ] && { ( cat _$$.sym echo %%%% od -v -t uC _$$.bin echo %%%% ) | \ awk > _$$.v ' BEGIN{ startaddr=""; printf ".text\n.data\n"; } /^%%%%$/ { flg++; next; } flg==0 { if(NF == 0) next; if( substr($2,1,4) == "0000" ) $2=substr($2,5); if( $1 == "+" && $4 == "$start" ) { if( $2 != "0000" ) startaddr=" - $" $2; } else if( substr($3, 1, 1) == "E" && $4 != "start" && $4 != "size" && $4 != "data" ) { printf "export _%s\n", $4 printf "_%s = * + $%s%s\n\n", $4, $2, startaddr; } next; } flg==1 { if(NF <= 1) next; printf " .byte "; for(i=2;i 2 pfqb, #endif pget, pglobl, pident, pimport, plcomm, plcomm1, plist, ploc, pmaclist, pmacro, pmap, porg, pproceof, prmb, psect, pset, psetdp, ptext, #ifdef I80386 puse16, puse32, #endif pwarn, /* end of pseudo-ops */ #ifdef I80386 mbcc, mbswap, mcall, mcalli, mdivmul, menter, mEwGw, mExGx, mf_inher, mf_m, mf_m2, mf_m2_ax, mf_m2_m4, mf_m2_m4_m8, mf_m4_m8_optst, mf_m4_m8_st, mf_m4_m8_stst, mf_m4_m8_m10_st, mf_m10, mf_optst, mf_st, mf_stst, mf_w_inher, mf_w_m, mf_w_m2, mf_w_m2_ax, mgroup1, mgroup2, mgroup6, mgroup7, mgroup8, mGvEv, mGvMa, mGvMp, mimul, min, mincdec, minher, minher16, minher32, minhera, mint, mjcc, mjcxz, mlea, mmov, mmovx, mnegnot, mout, mpushpop, mret, mseg, msetcc, mshdouble, mtest, mxchg, #endif /* I80386 */ #ifdef MC6809 mall, /* all address modes allowed, like LDA */ malter, /* all but immediate, like STA */ mimmed, /* immediate only (ANDCC, ORCC) */ mindex, /* indexed (LEA's) */ minher, /* inherent, like CLC or CLRA */ mlong, /* long branches */ mshort, /* short branches */ msstak, /* S-stack (PSHS, PULS) */ mswap, /* TFR, EXG */ mustak, /* U-stack (PSHU,PULU) */ #endif /* MC6809 */ }; FORWARD void asline P((void)); /* This uses registers as follows: A is for work and is not preserved by the subroutines.B holds the last symbol code, X usually points to data about the last symbol, U usually holds the value of last expression or symbol, and Y points to the current char. The value in Y is needed by READCH and GETSYM. EXPRES needs B and Y, and returns a value in U. If the expression starts with an identifier, X must point to its string. LOOKUP needs a string pointer in X and length in A. It returns a table pointer in X (unless not assembling and not found), symbol type in A and overflow in CC. */ PUBLIC void assemble() { while (TRUE) { asline(); if (label != NUL_PTR) /* must be confirmed if still set */ { /* it is nulled by EQU, COMM and SET */ #ifndef MC6809 #define NEEDENDLABEL ILLAB if (nocolonlabel) error(NEEDENDLABEL); #endif if(pass && label->value_reg_or_op.value != oldlabel) { dirty_pass = TRUE; if( pass == last_pass ) error(UNSTABLE_LABEL); } label->type |= LABIT; /* confirm, perhaps redundant */ if (label->type & REDBIT) { /* REDBIT meant 'GLOBLBIT' while LABIT was not set. */ label->type |= EXPBIT; label->type &= ~REDBIT; } if ((mcount | popflags) == 0) /* unaccompanied label, display adr like EQU and SET */ showlabel(); label = NUL_PTR; /* reset for next line */ } skipline(); listline(); genbin(); genobj(); binmbuf = lc += lcjump #ifdef I80386 + immcount #endif ; } } PRIVATE void asline() { register struct sym_s *symptr; postb = popflags = pcrflag = #ifdef I80386 sprefix = oprefix = aprefix = #endif immcount = lastexp.data = lcjump = 0; #ifdef I80386 sib = NO_SIB; #endif #if SIZEOF_OFFSET_T > 2 fqflag = #endif fdflag = fcflag = FALSE; cpuwarn(); readline(); getsym(); if (sym != IDENT) /* expect label, mnemonic or macro */ { /* Warn if not a comment marker or a hash (for /lib/cpp) */ if( sym != EOLSYM && sym != IMMEDIATE ) list_force = TRUE; return; /* anything else is a comment */ } symptr = gsymptr; if (!ifflag) /* not assembling, just test for IF/ELSE/ELSEIF/ENDIF */ { if (symptr == NUL_PTR || !(symptr->type & MNREGBIT) || symptr->data & REGBIT || symptr->value_reg_or_op.op.routine >= MIN_NONCOND) return; } else if (!(symptr->type & (MACBIT | MNREGBIT))) /* not macro, op, pseudo-op or register, expect label */ { oldlabel = symptr->value_reg_or_op.value; if ((nocolonlabel = (*lineptr - ':')) == 0) /* exported label? */ { sym = COLON; ++lineptr; } if (symptr->type & (LABIT | VARBIT)) { if (symptr->type & REDBIT) labelerror(RELAB); label = symptr; if (pass && !(symptr->type & VARBIT) /*&& last_pass>1*/) { label->data = (label->data & FORBIT) | lcdata; label->value_reg_or_op.value = lc; } } else if (checksegrel(symptr)) { symptr->type &= ~COMMBIT; /* ignore COMM, PCOMM gives warning */ #ifdef MC6809 #if 0 if (sym == COLON) symptr->type |= EXPBIT; #endif #endif /* remember if forward referenced */ symptr->data = (symptr->data & FORBIT) | lcdata; symptr->value_reg_or_op.value = lc; /* unless changed by EQU,COMM or SET */ label = symptr; } getsym(); if (sym != IDENT) { if (sym == EQOP) { getsym(); pequ(); } return; /* anything but ident is comment */ } symptr = gsymptr; } if (symptr->type & MACBIT) { entermac(symptr); return; } if (!(symptr->type & MNREGBIT)) { error(OPEXP); return; } if (symptr->data & REGBIT) { error(REGUID); return; } mnsize = 0; if ((page = (symptr->data & (PAGE1 | PAGE2))) != 0) { #ifdef MNSIZE if (page == (PAGE1 | PAGE2)) { mnsize = 1; page = 0; } else #endif { #ifdef PAGE2_OPCODE if (page == PAGE2) page = PAGE2_OPCODE; else #endif page = PAGE1_OPCODE; mcount = 1; } } opcode = symptr->value_reg_or_op.op.opcode; #ifdef I80386 needcpu((page==0 && ((opcode&0xF0) == 0x60||(opcode&0xF6)==0xC0))?1:0); #endif routine = rout_table[symptr->value_reg_or_op.op.routine]; getsym(); (*routine)(); #ifdef I80386 /* We handle "rep[ne]" refix as separate instruction; check if its use is valid */ if (opcode == 0xF2 || opcode == 0xF3) { /* REP */ rep = opcode; /* Not another prefix */ } else if (opcode != 0x2E && /* CSEG */ opcode != 0x3E && /* DSEG */ opcode != 0x26 && /* ESEG */ opcode != 0x64 && /* FSEG */ opcode != 0x65 && /* GSEG */ opcode != 0x36 && /* SSEG */ opcode != 0xF0) { /* LOCK */ if (rep == 0xF2 && (opcode&0xF6) != 0xA6) /* REPNE CMPS/SCAS */ error (REPNE_STRING); if (rep == 0xF3 && !((opcode&0xFC) == 0x6C || /* REP INS/OUTS */ (opcode&0xFC) == 0xA4 || /* REP MOVS/CMPS */ (opcode&0xFC) == 0xAC || /* REP SCAS/LODS */ (opcode&0xFE) == 0xAA)) /* REP STOS */ error (REP_STRING); rep = 0; } #endif if (sym != EOLSYM) error(JUNK_AFTER_OPERANDS); #ifdef I80386 needcpu(page==PAGE1_OPCODE?2:0); if (aprefix != 0) ++mcount; if (oprefix != 0) ++mcount; if (sprefix != 0) ++mcount; #endif } dev86-0.16.21/as/bin/000077500000000000000000000000001231050321700137625ustar00rootroot00000000000000dev86-0.16.21/as/bin/calljmp.bin000066400000000000000000000002221231050321700160720ustar00rootroot00000000000000ˆš è|fÿÐfÿÓfÿÑfÿÒfÿÔfÿÕfÿÖfÿ×gÿgÿgfÿèUfÿÐfÿÓfÿÑfÿÒfÿÔfÿÕfÿÖfÿ×fÿê ë3ÿàÿãÿáÿâÿäÿåÿæÿçÿ'ÿ'ÿ'ëfÿàfÿãfÿáfÿâfÿäfÿåfÿæfÿçfÿ'ÿdev86-0.16.21/as/bin/ea.bin000066400000000000000000000006711231050321700150450ustar00rootroot00000000000000¯gf‹gf‹gf‹gf‹gf‹gf‹gf¡4gf‹gf‹@gf‹Agf‹Bgf‹Cgf‹Dgf‹Egf‹Fgf‹Ggf‹€4gf‹4gf‹‚4gf‹ƒ4gf‹„4gf‹…4gf‹†4gf‹‡4ˆÀˆàˆØˆøˆÈˆèˆÐˆðf‰Àf‰Èf‰Ðf‰Øf‰àf‰èf‰ðf‰øf‹f‹f‹f‹f¡xV4f‹f‹f‹@f‹Af‹Bf‹Cf‹Ef‹Ff‹Gf‹€xV4f‹xV4f‹‚xV4f‹ƒxV4f‹…xV4f‹†xV4f‹‡xV4‰À‰È‰Ð‰Ø‰à‰è‰ð‰øf‹pf‹qf‹rf‹sf‹tf‹uxV4f‹vf‹wf‹Dpf‹Dqf‹Drf‹Dsf‹Dtf‹D$f‹Duf‹Dvf‹Dwf‹„pxV4f‹„qxV4f‹„rxV4f‹„sxV4f‹„txV4f‹„$xV4f‹„uxV4f‹„vxV4f‹„wxV4ÿdev86-0.16.21/as/bin/each.bin000066400000000000000000000012211231050321700153500ustar00rootroot00000000000000‡7Õ Ô ?fµfµf#µcµfbµf¼µf½µËf£µf»µf³µf«µÿµf˜˜øüúõf;µ¦f§§f§µf™™'/ÿ µ÷4µÈô÷<µ÷,µä ÿµlfmmÍ Î<µfÏÏuÿ$µŸfµfµÉµµfŵfĵf´µfµµf²µµ4µð¬f­­âfµµf‹µf‹µ"À¤f¥¥f¾µf¶µ÷$µ÷µ÷µf µæ nfooµfaafÿ4µf``fœœÑµÑµÑµÑ µóóóòòÃËžÑ$µÑ<µÑ$µÑ,µfµ®f¯¯•µµ µf¤µf¬µµ$µùýûªf«« µf+µf…µ$µ,µ› fÁµf‡µ×f3µÿdev86-0.16.21/as/bin/f.bin000066400000000000000000000002651231050321700147040ustar00rootroot00000000000000«ÜØØÁÜÁÜ3Ø3ØñÞÁß#ß3ØÜØÑØÑÝÁÝáÝáÞÚßÛß+ÙÝÛ+ÙÁÙ+Ù;Ù#Ý3Ù3Ý#Ý;ßàÙÝÝÑ›Ù;›Ý;›ßà›Ý3›Ù3ÙÐÙàÙáÙäÙåÙèÙéÙêÙëÙìÙíÙîÙðÙñÙòÙóÙôÙõÙöÙ÷ÙøÙùÙúÙûÙüÙýÙþÙÿÚé›ÛàÛà›ÛáÛá›ÛâÛâ›ÛãÛãÛäÞÙÿdev86-0.16.21/as/bin/fadd.bin000066400000000000000000000011351231050321700153520ustar00rootroot00000000000000SfUf‰åg‹Fg‹Vg‹^ g‹Nè£O‰Sf]Ãñ€UWV‰Ï‰Öæÿÿÿçÿÿÿ9þw r9Øs‡Ê‡þ“æÿÿçÿÿÎÏÁéÁê‰Íf)Ñf÷Ùfƒù7s2f1Õfåu*€ù s*­Ý­ûÓïØþ)Ûf‰Ñfáÿ÷Æ té{ëbéÀé‹é¬÷½ÿtòfƒïf÷ßfQf‰ù¥Æ¥è¥ÝÓãfYf)ùr;ý€w r…Ûu¨tƒÀƒÖ)í)Û÷Æ ufâf ÊÁâæÿÿ ò^_]Ã)Ò‰Ð^_]ÃÑîÑØÑÝÑÛfAfùu¬ºàÿ)À^_]Àé ­Ý­ûÓïøƒÖ‡Ýé=ÿÿÿ¤Æ¤è¤ÝÁã€ér±éJÿÿÿ)í€ù s­Ý­ûÓï÷ÝØþ)Ûf‰Ñfáÿé&ÿÿÿ€é ­Ý­ûÓï÷Û÷݃ÛøƒÞ‡Ýf‰Ñfáÿéÿÿÿé]ÿÿÿëþéVÿÿÿUWV‰Ö‰ÏÁêÁéf‰Õf1ÍfåfâÿtÕfáÿtÎfÑférËfùÿwÂæÿÿçÿÿÎÏfQfU‰Á÷ã‰Õ“÷æPR‰ð÷ç‰Ö‘÷çÅXЃÖZÕȃÖfZfYfƒÁ épþÿÿÿdev86-0.16.21/as/bin/farcall.bin000066400000000000000000000000511231050321700160540ustar00rootroot00000000000000šgÿgÿêÿ.gÿ.ÿdev86-0.16.21/as/bin/group1.bin000066400000000000000000000001631231050321700156710ustar00rootroot00000000000000if4xV4€ÃfÃ4ÃxV4g€g€Gg€gf4gxV4g€gfƒýgƒýÙfÙÙggfgggfgÙ Ù8ÙÙ(ÙÙ0Ùÿdev86-0.16.21/as/bin/group6.bin000066400000000000000000000000461231050321700156760ustar00rootroot00000000000000ÐgÛgF ág,ÿdev86-0.16.21/as/bin/group7.bin000066400000000000000000000000651231050321700157000ustar00rootroot00000000000000+gggg?gF ðg70ãÿdev86-0.16.21/as/bin/imul.bin000066400000000000000000000001671231050321700154260ustar00rootroot00000000000000möëö.f÷ëf÷.÷ë÷.f¯Ãf¯¯Ã¯fkÃfkkÃkgf¯g¯fkÀkÀfiÃ,fi,iÃà“ià“gf¯,¯à“fiÀ,iÀà“ÿdev86-0.16.21/as/bin/incdec.bin000066400000000000000000000001641231050321700157020ustar00rootroot00000000000000jþÀþÄþÃþÇþÁþÅþÂþÆgÿgþf@fCfAfBfDfEfFfGgfÿ@CABDEFGgÿþÈþÌþËþÏþÉþÍþÊþÎgÿgþfHfKfIfJfLfMfNfOgfÿHKIJLMNOgÿÿdev86-0.16.21/as/bin/inher.bin000066400000000000000000000002011231050321700155520ustar00rootroot00000000000000w7?øüúõ¦'/ôÎlŸÉð¬¤nóóòž®ùýûª›˜™f˜f™§f§mfmÏfÏ­f­¥f¥ofoafaf`f`œfœ¯f¯««××f˜f™˜™f§§fmmfÏÏf­­f¥¥foofaaff``fœœf¯¯f«f«××ÿdev86-0.16.21/as/bin/inout.bin000066400000000000000000000000661231050321700156140ustar00rootroot00000000000000,íììfífííä äfå fåå åïîîfïfïïæ æfç fçeç çÿdev86-0.16.21/as/bin/movspec.bin000066400000000000000000000012521231050321700161300ustar00rootroot00000000000000  À Ð Ø!À!È!Ð!Ø!ð!ø$Ø$à$è$ð$ø"À"Ð"Ø#À#È#Ð#Ø#ð#ø&Ø&à&è&ð&ø Ã Ó Û!Ã!Ë!Ó!Û!ó!û$Û$ã$ë$ó$û"Ã"Ó"Û#Ã#Ë#Ó#Û#ó#û&Û&ã&ë&ó&û Á Ñ Ù!Á!É!Ñ!Ù!ñ!ù$Ù$á$é$ñ$ù"Á"Ñ"Ù#Á#É#Ñ#Ù#ñ#ù&Ù&á&é&ñ&ù Â Ò Ú!Â!Ê!Ò!Ú!ò!ú$Ú$â$ê$ò$ú"Â"Ò"Ú#Â#Ê#Ò#Ú#ò#ú&Ú&â&ê&ò&ú Æ Ö Þ!Æ!Î!Ö!Þ!ö!þ$Þ$æ$î$ö$þ"Æ"Ö"Þ#Æ#Î#Ö#Þ#ö#þ&Þ&æ&î&ö&þ Ç × ß!Ç!Ï!×!ß!÷!ÿ$ß$ç$ï$÷$ÿ"Ç"×"ß#Ç#Ï#×#ß#÷#ÿ&ß&ç&ï&÷&ÿ Ä Ô Ü!Ä!Ì!Ô!Ü!ô!ü$Ü$ä$ì$ô$ü"Ä"Ô"Ü#Ä#Ì#Ô#Ü#ô#ü&Ü&ä&ì&ô&ü Å Õ Ý!Å!Í!Õ!Ý!õ!ý$Ý$å$í$õ$ý"Å"Õ"Ý#Å#Í#Õ#Ý#õ#ý&Ý&å&í&õ&ýÿdev86-0.16.21/as/bin/pushpop.bin000066400000000000000000000002001231050321700161420ustar00rootroot00000000000000vjgÿ7fjÿfPfSfQfRfTfUfVfWffff f¨fh4fh4gfÿ7PSQRTUVWhxV4hxV4gÿ7gfXf[fYfZf\f]f^f_fff¡f©fgfX[YZ\]^_gÿdev86-0.16.21/as/bin/seg.bin000066400000000000000000000000201231050321700152220ustar00rootroot00000000000000.>&de6ÿdev86-0.16.21/as/bin/shdouble.bin000066400000000000000000000000751231050321700162630ustar00rootroot000000000000003f¤Øf¤Ë¤òf¥Ù¤Ögf¤g¤gf¥g¥f¬Ëf­Ùÿdev86-0.16.21/as/bin/shift.bin000066400000000000000000000004241231050321700155710ustar00rootroot00000000000000 ÒÐÒÔÒÓÒ×ÒÑÒÕÒÒÒÖgÓgÒfÓÐfÓÓfÓÑfÓÒfÓÔfÓÕfÓÖfÓ×gfÓÓÐÓÓÓÑÓÒÓÔÓÕÓÖÓ×gÓÐÐÐÔÐÓÐ×ÐÑÐÕÐÒÐÖgÑgÐfÑÐfÑÓfÑÑfÑÒfÑÔfÑÕfÑÖfÑ×gfÑÑÐÑÓÑÑÑÒÑÔÑÕÑÖÑ×gÑÀÐÀÔÀÓÀ×ÀÑÀÕÀÒÀÖgÁgÀÀÐfÁÐfÁÓfÁÑfÁÒfÁÔfÁÕfÁÖfÁ×gfÁÁÐÁÓÁÑÁÒÁÔÁÕÁÖÁ×gÁfÁØfÁÀfÁÈfÁàfÁøfÁàfÁèÿdev86-0.16.21/as/bin/xchg.bin000066400000000000000000000003521231050321700154050ustar00rootroot00000000000000àff“f‘f’f”f•f–f—ff“f‘f’f”f•f–f—“‘’”•–—“‘’”•–—†À†à†Ø†ø†Ë†ë†Ó†óg†g†'g†g†?g†g†/g†g†7g†g†'g†g†?g†g†/g†g†7gf‡gf‡gf‡gf‡gf‡'gf‡/gf‡7gf‡?gf‡gf‡gf‡gf‡gf‡'gf‡/gf‡7gf‡?g‡g‡g‡g‡g‡'g‡/g‡7g‡?f‡f‡f‡ f‡f‡#f‡+f‡3f‡;ÿdev86-0.16.21/as/byteord.h000066400000000000000000000007611231050321700150370ustar00rootroot00000000000000/* byteord.h - byte order dependencies for C compiler, assembler, linker */ /* These are for the targets of everything and for linker source too. */ #ifdef I8086 # define INT_BIG_ENDIAN 0 # define LONG_BIG_ENDIAN 0 /* except longs are back to front for Xenix */ #endif #ifdef I80386 # define INT_BIG_ENDIAN 0 # define LONG_BIG_ENDIAN 0 #endif #ifdef MC6809 # define INT_BIG_ENDIAN 1 /* byte order in words is high-low */ # define LONG_BIG_ENDIAN 1 /* byte order in longs is high-low */ #endif dev86-0.16.21/as/chk000077500000000000000000000004571231050321700137130ustar00rootroot00000000000000 compile() { # /lib/elksemu ./as86 -3 -k "$@" ./as86 -3 -k "$@" } for i in `ls asm/*.asm` do j=`basename $i .asm` compile asm/$j.asm -b $j.bin -o $j.obj > /dev/null cmp $j.obj obj1/$j.obj # compile asm/$j.asm -b $j.bin > /dev/null # cmp $j.bin bin/$j.bin rm -f $j.bin $j.obj $j.asm done dev86-0.16.21/as/const.h000066400000000000000000000160571231050321700145220ustar00rootroot00000000000000 /* Speed and space hacks for BCC */ #ifdef __AS386_16__ #define LOW_BYTE 0 /* must be changed for big-endian */ #else #define S_ALIGNMENT sizeof(long) #endif /* const.h - constants for assembler */ /* major switches */ /* #define MC6809 */ /* generate 6809 code */ #ifndef MC6809 #define I80386 /* generate 80386 code */ #endif #define MNSIZE /* allow byte size in mnemonic, e.g. "movb" */ #undef SOS_EDOS /* source OS is EDOS */ /* defaults */ #define DIRCHAR '/' /* character separating filename from dir */ #define INBUFSIZE 8192 #define SOS_EOLSTR "\012" /* defaults modified by switches */ #ifdef SOS_EDOS # undef INBUFSIZE # define INBUFSIZE 512 # undef SOS_EOLSTR # define SOS_EOLSTR "\015\012" # define STAKSIZ 256 /* table grows up to stack less this */ #endif #ifdef __AS386_16__ # undef INBUFSIZE # define INBUFSIZE 512 # define STAKSIZ 512 /* table grows up to stack less this */ #endif /* booleans */ #define FALSE 0 #define TRUE 1 /* ASCII constants */ #define ETB 23 /* C tricks */ #define EXTERN extern #define FORWARD static #define PRIVATE static #define PUBLIC #define NUL_PTR ((void*)0) /* O/S constants */ #define CREAT_PERMS 0666 #define EOF (-1) #define STDIN 0 #define STDOUT 1 enum { /* Register codes (internal to assembler). */ #ifdef I80386 /* Index regs must be first. */ BPREG, BXREG, DIREG, SIREG, #define MAX16BITINDREG SIREG EAXREG, EBPREG, EBXREG, ECXREG, EDIREG, EDXREG, ESIREG, ESPREG, #define MAXINDREG ESPREG AXREG, CXREG, DXREG, SPREG, AHREG, ALREG, BHREG, BLREG, CHREG, CLREG, DHREG, DLREG, CSREG, DSREG, ESREG, FSREG, GSREG, SSREG, CR0REG, CR2REG, CR3REG, DR0REG, DR1REG, DR2REG, DR3REG, DR6REG, DR7REG, TR3REG, TR4REG, TR5REG, TR6REG, TR7REG, ST0REG, ST1REG, ST2REG, ST3REG, ST4REG, ST5REG, ST6REG, ST7REG, #endif /* I80386 */ #ifdef MC6809 /* Index regs must be first, then PC. */ SREG, UREG, XREG, YREG, #define MAXINDREG YREG PCREG, AREG, BREG, CCREG, DPREG, DREG, #endif /* MC6809 */ NOREG }; #ifdef I80386 enum { /* Type and size keywords. */ BYTEOP, DWORDOP, FWORDOP, FAROP, PTROP, PWORDOP, QWORDOP, TBYTEOP, WORDOP }; #endif /* I80386 */ /* special chars */ #define EOL 0 #define MACROCHAR '?' enum { /* Symbol codes. */ /* The first 2 must be from chars in identifiers. */ IDENT, INTCONST, /* The next few are best for other possibly-multi-char tokens. */ ADDOP, /* also ++ */ BINCONST, CHARCONST, GREATERTHAN, /* also >> and context-sensitive */ HEXCONST, LESSTHAN, /* also << and context-sensitive */ SUBOP, /* also -- */ WHITESPACE, ANDOP, COMMA, EOLSYM, EQOP, IMMEDIATE, INDIRECT, LBRACKET, LPAREN, MACROARG, NOTOP, OROP, OTHERSYM, POSTINCOP, PREDECOP, RBRACKET, RPAREN, SLASH, /* context-sensitive */ SLOP, SROP, STAR, /* context-sensitive */ STRINGCONST, COLON }; /* symbol table entry */ /* type entry contains following flags */ #define ENTBIT (1<<0) /* entry point (= OBJ_N_MASK) */ #define COMMBIT (1<<1) /* common */ #define LABIT (1<<2) /* label (a PC location or defined by EQU) */ #define MNREGBIT (1<<3) /* mnemonic for op or pseudo-op, or register */ #define MACBIT (1<<4) /* macro */ #define REDBIT (1<<5) /* redefined (if with LABIT or VARBIT), to do * with SA_MASK (if with COMMBIT), otherwise * means globl */ #define VARBIT (1<<6) /* variable (i.e. something defined by SET) */ #define EXPBIT (1<<7) /* exported (= OBJ_E_MASK) */ /* data entry contains following flags, valid */ /* for expressions as well as syms */ #define PAGE1 (1<<0) /* page 1 machine op = MNREGBIT | PAGE1 */ #define PAGE2 (1<<1) /* page 2 machine op = MNREGBIT | PAGE2 */ #define REGBIT (1<<2) /* register = MNREGBIT | REGBIT */ #define SIZEBIT (1<<3) /* sizing mnemonic = MNREGBIT | SIZEBIT */ #define SEGM 0x0F /* 1st 4 bits reused for segment if !MNREGBIT */ #define RELBIT (1<<4) /* relative (= OBJ_A_MASK) */ #define FORBIT (1<<5) /* forward referenced */ #define IMPBIT (1<<6) /* imported (= OBJ_I_MASK) */ #define UNDBIT (1<<7) /* undefined */ /* object code format (Introl) */ #define OBJ_SEGSZ_TWO 0x02 /* size 2 code for segment size descriptor */ #define OBJ_MAX_ABS_LEN 64 /* max length of chunk of absolute code */ #define OBJ_ABS 0x40 /* absolute code command */ #define OBJ_OFFSET_REL 0x80 /* offset relocation command */ #define OBJ_SET_SEG 0x20 /* set segment command */ #define OBJ_SKIP_1 0x11 /* skip with 1 byte count */ #define OBJ_SKIP_2 0x12 /* skip with 2 byte count */ #define OBJ_SKIP_4 0x13 /* skip with 4 byte count */ #define OBJ_SYMBOL_REL 0xC0 /* symbol relocation command */ #define OBJ_A_MASK 0x10 /* absolute bit(symbols) */ #if OBJ_A_MASK - RELBIT /* must match internal format (~byte 1 -> 0) */ oops - RELBIT misplaced #endif #define OBJ_E_MASK 0x80 /* exported bit (symbols) */ #if OBJ_E_MASK - EXPBIT /* must match internal format (byte 0 -> 0) */ oops - EXPBIT misplaced #endif #define OBJ_I_MASK 0x40 /* imported bit (symbols) */ #if OBJ_I_MASK - IMPBIT /* must match internal format (byte 1 -> 0) */ oops - IMPBIT misplaced #endif #define OBJ_N_MASK 0x01 /* entry bit (symbols) */ #if OBJ_N_MASK - ENTBIT /* must match internal format (byte 0 -> 1) */ oops - ENTBIT misplaced #endif #define OBJ_SA_MASK 0x20 /* size allocation bit (symbols) */ #define OBJ_SZ_ONE 0x40 /* size one code for symbol value */ #define OBJ_SZ_TWO 0x80 /* size two code for symbol value */ #define OBJ_SZ_FOUR 0xC0 /* size four code for symbol value */ #define OBJ_R_MASK 0x20 /* PC-rel bit (off & sym reloc commands) */ #define OBJ_SEGM_MASK 0x0F /* segment mask (symbols, off reloc command) */ #define OBJ_OF_MASK 0x03 /* offset size code for symbol reloc */ #define OBJ_S_MASK 0x04 /* symbol number size code for symbol reloc */ #define SYMLIS_NAMELEN 26 #define SYMLIS_LEN (sizeof (struct sym_listing_s)) #define FILNAMLEN 64 /* max length of a file name */ #define LINLEN 256 /* max length of input line */ #define LINUM_LEN 5 /* length of formatted line number */ #define SPTSIZ 1024 /* number of symbol ptrs */ /* pseudo-op flags */ #define POPHI 1 /* set to print hi byte of adr */ #define POPLO 2 /* to print lo byte of ADR */ #define POPLC 4 /* to print LC */ #define POPLONG 8 /* to print high word of ADR */ #define MAXBLOCK 8 /* max nesting level of BLOCK stack */ #define MAXGET 8 /* max nesting level of GET stack */ #define MAXIF 8 /* max nesting level of IF stack */ #define MACPSIZ (128 / sizeof (struct schain_s)) /* size of macro param buffer */ #define MAXMAC 8 /* max nesting level of macro stack */ #define NLOC 16 /* number of location counters */ #ifdef I80386 #define NO_SIB 0340 /* illegal sib (3 with 4) to mean no sib */ #endif /* special segments */ #define BSSLOC 3 #define DATALOC 3 #define DPLOC 2 #define STRLOC 1 #define TEXTLOC 0 #include "errors.h" dev86-0.16.21/as/errors.c000066400000000000000000000117521231050321700147000ustar00rootroot00000000000000 #include "syshead.h" #include "const.h" #include "errors.h" /* Error codes. */ /* Syntax errors. */ PUBLIC char COMEXP[] = "comma expected"; PUBLIC char DELEXP[] = "delimiter expected"; PUBLIC char FACEXP[] = "factor expected"; PUBLIC char IREGEXP[] = "index register expected"; PUBLIC char LABEXP[] = "label expected"; PUBLIC char LPEXP[] = "left parentheses expected"; PUBLIC char OPEXP[] = "opcode expected"; PUBLIC char RBEXP[] = "right bracket expected"; PUBLIC char REGEXP[] = "register expected"; PUBLIC char RPEXP[] = "right parentheses expected"; PUBLIC char SPEXP[] = "space expected"; /* Expression errors. */ PUBLIC char ABSREQ[] = "absolute expression required"; PUBLIC char NONIMPREQ[] = "non-imported expression required"; PUBLIC char RELBAD[] = "relocation impossible"; /* Label errors. */ PUBLIC char ILLAB[] = "illegal label"; PUBLIC char MACUID[] = "MACRO used as identifier"; PUBLIC char MISLAB[] = "missing label"; PUBLIC char MNUID[] = "opcode used as identifier"; PUBLIC char REGUID[] = "register used as identifier"; PUBLIC char RELAB[] = "redefined label"; PUBLIC char UNBLAB[] = "unbound label"; PUBLIC char UNLAB[] = "undefined label"; PUBLIC char VARLAB[] = "variable used as label"; /* Addressing errors. */ PUBLIC char ABOUNDS[] = "address out of bounds"; PUBLIC char DBOUNDS[] = "data out of bounds"; PUBLIC char ILLMOD[] = "illegal address mode"; PUBLIC char ILLREG[] = "illegal register"; /* Control structure errors. */ PUBLIC char ELSEBAD[] = "no matching IF"; PUBLIC char ENDBBAD[] = "no matching BLOCK"; PUBLIC char EOFBLOCK[] = "end of file in BLOCK"; PUBLIC char EOFIF[] = "end of file in IF"; PUBLIC char EOFLC[] = "location counter was undefined at end"; PUBLIC char EOFMAC[] = "end of file in MACRO"; PUBLIC char FAILERR[] = "user-generated error"; /* Overflow errors. */ PUBLIC char BLOCKOV[] = "BLOCK stack overflow"; PUBLIC char BWRAP[] = "binary file wrap-around"; PUBLIC char COUNTOV[] = "counter overflow"; PUBLIC char COUNTUN[] = "counter underflow"; PUBLIC char GETOV[] = "GET stack overflow"; PUBLIC char IFOV[] = "IF stack overflow"; PUBLIC char LINLONG[] = "line too long"; PUBLIC char MACOV[] = "MACRO stack overflow"; PUBLIC char OBJSYMOV[] = "object symbol table overflow"; PUBLIC char OWRITE[] = "program overwrite"; PUBLIC char PAROV[] = "parameter table overflow"; PUBLIC char SYMOV[] = "symbol table overflow"; PUBLIC char SYMOUTOV[] = "output symbol table overflow"; /* I/O errors. */ PUBLIC char OBJOUT[] = "error writing object file"; /* Miscellaneous errors. */ PUBLIC char AL_AX_EAX_EXP[] = "al ax or eax expected"; PUBLIC char CTLINS[] = "control character in string"; PUBLIC char FURTHER[] = "futher errors suppressed"; PUBLIC char ILL_IMM_MODE[] = "illegal immediate mode"; PUBLIC char ILL_IND_TO_IND[] = "illegal indirect to indirect"; PUBLIC char ILL_IND[] = "illegal indirection"; PUBLIC char ILL_IND_PTR[] = "illegal indirection from previous 'ptr'"; PUBLIC char ILL_SCALE[] = "illegal scale"; PUBLIC char ILL_SECTION[] = "illegal section"; PUBLIC char ILL_SEG_REG[] = "illegal segment register"; PUBLIC char ILL_SOURCE_EA[] = "illegal source effective address"; PUBLIC char ILL_SIZE[] = "illegal size"; PUBLIC char IMM_REQ[] = "immediate expression expected"; PUBLIC char INDEX_REG_EXP[] = "index register expected"; PUBLIC char IND_REQ[] = "indirect expression required"; PUBLIC char MISMATCHED_SIZE[] = "mismatched size"; PUBLIC char NOIMPORT[] = "no imports with binary file output"; PUBLIC char REENTER[] = "multiple ENTER pseudo-ops"; PUBLIC char REL_REQ[] = "relative expression required"; PUBLIC char REPEATED_DISPL[] = "repeated displacement"; PUBLIC char SEGREL[] = "segment or relocatability redefined"; PUBLIC char SEG_REG_REQ[] = "segment register required"; PUBLIC char SIZE_UNK[] = "size unknown"; PUBLIC char UNKNOWN_ESCAPE_SEQUENCE[] = "unknown escape sequence"; PUBLIC char FP_REG_REQ[] = "FP register required"; PUBLIC char FP_REG_NOT_ALLOWED[] = "FP register not allowed"; PUBLIC char ILL_FP_REG[] = "illegal FP register"; PUBLIC char ILL_FP_REG_PAIR[] = "illegal FP register pair"; PUBLIC char JUNK_AFTER_OPERANDS[] = "junk after operands"; PUBLIC char ALREADY[] = "already defined"; PUBLIC char UNSTABLE_LABEL[] = "label moved in last pass add -O?"; PUBLIC char REPNE_STRING[] = "CMPS or SCAS expected"; PUBLIC char REP_STRING[] = "string instruction expected"; /* Warnings. */ PUBLIC char CPUCLASH[] = "instruction illegal for current cpu"; PUBLIC char SHORTB[] = "short branch would do"; dev86-0.16.21/as/errors.h000066400000000000000000000126601231050321700147040ustar00rootroot00000000000000 #ifndef _H_ERRORS #define _H_ERRORS /* Error codes. */ /* Syntax errors. */ EXTERN char COMEXP[]; /* "comma expected" */ EXTERN char DELEXP[]; /* "delimiter expected" */ EXTERN char FACEXP[]; /* "factor expected" */ EXTERN char IREGEXP[]; /* "index register expected" */ EXTERN char LABEXP[]; /* "label expected" */ EXTERN char LPEXP[]; /* "left parentheses expected" */ EXTERN char OPEXP[]; /* "opcode expected" */ EXTERN char RBEXP[]; /* "right bracket expected" */ EXTERN char REGEXP[]; /* "register expected" */ EXTERN char RPEXP[]; /* "right parentheses expected" */ EXTERN char SPEXP[]; /* "space expected" */ /* Expression errors. */ EXTERN char ABSREQ[]; /* "absolute expression required" */ EXTERN char NONIMPREQ[]; /* "non-imported expression required" */ EXTERN char RELBAD[]; /* "relocation impossible" */ /* Label errors. */ EXTERN char ILLAB[]; /* "illegal label" */ EXTERN char MACUID[]; /* "MACRO used as identifier" */ EXTERN char MISLAB[]; /* "missing label" */ EXTERN char MNUID[]; /* "opcode used as identifier" */ EXTERN char REGUID[]; /* "register used as identifier" */ EXTERN char RELAB[]; /* "redefined label" */ EXTERN char UNBLAB[]; /* "unbound label" */ EXTERN char UNLAB[]; /* "undefined label" */ EXTERN char VARLAB[]; /* "variable used as label" */ /* Addressing errors. */ EXTERN char ABOUNDS[]; /* "address out of bounds" */ EXTERN char DBOUNDS[]; /* "data out of bounds" */ EXTERN char ILLMOD[]; /* "illegal address mode" */ EXTERN char ILLREG[]; /* "illegal register" */ /* Control structure errors. */ EXTERN char ELSEBAD[]; /* "no matching IF" */ #define ELSEIFBAD ELSEBAD EXTERN char ENDBBAD[]; /* "no matching BLOCK" */ #define ENDIFBAD ELSEBAD EXTERN char EOFBLOCK[]; /* "end of file in BLOCK" */ EXTERN char EOFIF[]; /* "end of file in IF" */ EXTERN char EOFLC[]; /* "location counter was undefined at end" */ EXTERN char EOFMAC[]; /* "end of file in MACRO" */ EXTERN char FAILERR[]; /* "user-generated error" */ /* Overflow errors. */ EXTERN char BLOCKOV[]; /* "BLOCK stack overflow" */ EXTERN char BWRAP[]; /* "binary file wrap-around" */ EXTERN char COUNTOV[]; /* "counter overflow" */ EXTERN char COUNTUN[]; /* "counter underflow" */ EXTERN char GETOV[]; /* "GET stack overflow" */ EXTERN char IFOV[]; /* "IF stack overflow" */ EXTERN char LINLONG[]; /* "line too long" */ EXTERN char MACOV[]; /* "MACRO stack overflow" */ EXTERN char OBJSYMOV[]; /* "object symbol table overflow" */ EXTERN char OWRITE[]; /* "program overwrite" */ EXTERN char PAROV[]; /* "parameter table overflow" */ EXTERN char SYMOV[]; /* "symbol table overflow" */ EXTERN char SYMOUTOV[]; /* "output symbol table overflow" */ /* I/O errors. */ EXTERN char OBJOUT[]; /* "error writing object file" */ /* Miscellaneous errors. */ EXTERN char AL_AX_EAX_EXP[]; /* "al ax or eax expected" */ EXTERN char CTLINS[]; /* "control character in string" */ EXTERN char FURTHER[]; /* "futher errors suppressed" */ EXTERN char ILL_IMM_MODE[]; /* "illegal immediate mode" */ EXTERN char ILL_IND_TO_IND[]; /* "illegal indirect to indirect" */ EXTERN char ILL_IND[]; /* "illegal indirection" */ EXTERN char ILL_IND_PTR[]; /* "illegal indirection from previous 'ptr'" */ EXTERN char ILL_SCALE[]; /* "illegal scale" */ EXTERN char ILL_SECTION[]; /* "illegal section" */ EXTERN char ILL_SEG_REG[]; /* "illegal segment register" */ EXTERN char ILL_SOURCE_EA[]; /* "illegal source effective address" */ EXTERN char ILL_SIZE[]; /* "illegal size" */ EXTERN char IMM_REQ[]; /* "immediate expression expected" */ EXTERN char INDEX_REG_EXP[]; /* "index register expected" */ EXTERN char IND_REQ[]; /* "indirect expression required" */ EXTERN char MISMATCHED_SIZE[]; /* "mismatched size" */ EXTERN char NOIMPORT[]; /* "no imports with binary file output" */ EXTERN char REENTER[]; /* "multiple ENTER pseudo-ops" */ EXTERN char REL_REQ[]; /* "relative expression required" */ EXTERN char REPEATED_DISPL[]; /* "repeated displacement" */ EXTERN char SEGREL[]; /* "segment or relocatability redefined" */ EXTERN char SEG_REG_REQ[]; /* "segment register required" */ EXTERN char SIZE_UNK[]; /* "size unknown" */ EXTERN char UNKNOWN_ESCAPE_SEQUENCE[]; /* "unknown escape sequence" */ EXTERN char FP_REG_REQ[]; /* "FP register required" */ EXTERN char FP_REG_NOT_ALLOWED[]; /* "FP register not allowed" */ EXTERN char ILL_FP_REG[]; /* "illegal FP register" */ EXTERN char ILL_FP_REG_PAIR[]; /* "illegal FP register pair" */ EXTERN char JUNK_AFTER_OPERANDS[]; /* "junk after operands" */ EXTERN char ALREADY[]; /* "already defined" */ EXTERN char UNSTABLE_LABEL[]; /* "label moved in last pass add -O?" */ EXTERN char REPNE_STRING[]; /* "CMPS or SCAS expected" */ EXTERN char REP_STRING[]; /* "string instruction expected" */ /* Warnings. */ EXTERN char CPUCLASH[]; /* "instruction illegal for current cpu" */ EXTERN char SHORTB[]; /* "short branch would do" */ #endif dev86-0.16.21/as/express.c000066400000000000000000000204111231050321700150450ustar00rootroot00000000000000/* express.c - expression handler for assembler */ #include "syshead.h" #include "const.h" #include "type.h" #include "address.h" #include "globvar.h" #include "scan.h" #include "source.h" FORWARD void experror P((char * err_str)); FORWARD void expundefined P((void)); FORWARD void simple2 P((void)); FORWARD void simple P((void)); FORWARD void term P((void)); FORWARD void factor2 P((void)); PUBLIC void absexpres() { expres(); chkabs(); } /* check lastexp.data is abs */ PUBLIC void chkabs() { if (lastexp.data & RELBIT) { if (pass == last_pass) error(ABSREQ); expundefined(); } } PRIVATE void experror(err_str) char * err_str; { error(err_str); expundefined(); } PRIVATE void expundefined() { if( last_pass == 1 ) lastexp.data = FORBIT | UNDBIT; else lastexp.data = UNDBIT; } PUBLIC void nonimpexpres() { expres(); if (lastexp.data & IMPBIT) experror(NONIMPREQ); } /* generate relocation error if pass 2, make lastexp.data forward&undefined */ PUBLIC void showrelbad() { if (pass == last_pass) error(RELBAD); expundefined(); } PUBLIC void symabsexpres() { getsym(); absexpres(); } PUBLIC void symexpres() { getsym(); expres(); } /* expres() parses expression = simple expression [op simple expression], where op is =, < or >. Parameters: sym, number in number, identifier from symname to lineptr - 1. Returns value in lastexp. */ PUBLIC void expres() { offset_t leftoffset; simple(); leftoffset = lastexp.offset; if (sym == EQOP) { simple2(); if (leftoffset == lastexp.offset) lastexp.offset = -1; else lastexp.offset = 0; } else if (sym == LESSTHAN) { /* context-sensitive, LESSTHAN really means less than here */ simple2(); if (leftoffset < lastexp.offset) lastexp.offset = -1; else lastexp.offset = 0; } else if (sym == GREATERTHAN) { /* context-sensitive, GREATERTHAN really means greater than here */ simple2(); if (leftoffset > lastexp.offset) lastexp.offset = -1; else lastexp.offset = 0; } } /* get symbol and 2nd simple expression, check both rel or both abs */ PRIVATE void simple2() { unsigned char leftdata; leftdata = lastexp.data; getsym(); simple(); if ((leftdata | lastexp.data) & IMPBIT || (leftdata ^ lastexp.data) & (RELBIT | SEGM)) showrelbad(); else lastexp.data = (leftdata & lastexp.data) & ~(RELBIT | SEGM); } /* simple() parses simple expression = [+-] term {op term}, where op is +, -, or \ (OR). */ PRIVATE void simple() { offset_t leftoffset; unsigned char leftdata; if (sym == ADDOP || sym == SUBOP) lastexp.data = lastexp.offset = 0; else term(); while (TRUE) { leftoffset = lastexp.offset; leftdata = lastexp.data; if (sym == ADDOP) { getsym(); term(); if (leftdata & lastexp.data & RELBIT) showrelbad(); /* rel + rel no good */ else lastexp.data |= leftdata; lastexp.offset += leftoffset; } else if (sym == SUBOP) { getsym(); term(); /* check not abs - rel or rel - rel with mismatch */ if (lastexp.data & RELBIT && (!(leftdata & RELBIT) || (leftdata | lastexp.data) & IMPBIT || (leftdata ^ lastexp.data) & (RELBIT | SEGM))) showrelbad(); else lastexp.data = ((leftdata | lastexp.data) & ~(RELBIT | SEGM)) | ((leftdata ^ lastexp.data) & (RELBIT | SEGM)); lastexp.offset = leftoffset - lastexp.offset; } else if (sym == OROP) { getsym(); term(); lastexp.data |= leftdata; chkabs(); /* both must be absolute */ lastexp.offset |= leftoffset; } else return; } } /* term() parses term = factor {op factor}, where op is *, /, &, <<, or >>. */ PRIVATE void term() { offset_t leftoffset; factor(); while (TRUE) { leftoffset = lastexp.offset; if (sym == STAR) { /* context-sensitive, STAR means multiplication here */ factor2(); lastexp.offset *= leftoffset; } else if (sym == SLASH) { /* context-sensitive, SLASH means division here */ factor2(); lastexp.offset = leftoffset / lastexp.offset; } else if (sym == ANDOP) { factor2(); lastexp.offset &= leftoffset; } else if (sym == SLOP) { factor2(); lastexp.offset = leftoffset << lastexp.offset; } else if (sym == SROP) { factor2(); lastexp.offset = leftoffset >> lastexp.offset; } else return; } } /* get symbol and 2nd or later factor, check both abs */ PRIVATE void factor2() { unsigned char leftdata; leftdata = lastexp.data; getsym(); factor(); lastexp.data |= leftdata; chkabs(); } /* factor() parses factor = number | identifier | * | (expression) | ! factor, ! is complementation. Returns value in lastexp.offset, possible flags IMPBIT, FORBIT, RELBIT and UNDBIT in lastexp.data, and segment in SEGM part of lastexp.data, and lastexp.sym at imported symbol if IMPBIT. If the factor is an identifier, LOOKUP is used to get its value (so the ident is installed in the symbol table if necessary, with default flags inidata). If the identifier is not a label, (could be imported, or later in the program), its FORBIT is set. The expression FORBIT, IMPBIT, RELBIT, UNDBIT and SEGM are then taken from the identifier. */ PUBLIC void factor() { switch (sym) { case SLASH: /* context-sensitive, SLASH means a hex number here */ context_hexconst(); case INTCONST: lastexp.data = 0; /* absolute & not forward or undefined */ lastexp.offset = number; getsym(); return; case IDENT: { register struct sym_s *symptr; symptr = gsymptr; if (symptr->type & (MNREGBIT | MACBIT)) experror(symptr->type & MACBIT ? MACUID : symptr->data & REGBIT ? REGUID : MNUID); else { if (!(symptr->type & (LABIT | VARBIT))) { if( last_pass == 1 ) symptr->data |= FORBIT; lastexp.sym = symptr; } if (pass != last_pass) { if( last_pass == 1 ) lastexp.data = symptr->data & (FORBIT | RELBIT | UNDBIT | SEGM); else lastexp.data = symptr->data & (RELBIT | UNDBIT | SEGM); /* possible flags for pass 1 */ lastexp.offset = symptr->value_reg_or_op.value; } else { if ((lastexp.data = symptr->data) & IMPBIT) lastexp.offset = 0; /* value != 0 for commons */ /* OK even if UNDBIT */ else { lastexp.offset = symptr->value_reg_or_op.value; if (lastexp.data & UNDBIT) experror(UNBLAB); } } } getsym(); return; } #ifndef MC6809 case LBRACKET: if (!asld_compatible) break; /* error, LPAREN is the grouping symbol */ getsym(); expres(); if (sym != RBRACKET) error(RBEXP); else getsym(); return; #endif case LPAREN: #ifndef MC6809 if (asld_compatible) break; /* error, LBRACKET is the grouping symbol */ #endif getsym(); expres(); if (sym != RPAREN) error(RPEXP); else getsym(); return; case NOTOP: getsym(); factor(); chkabs(); lastexp.offset = ~lastexp.offset; return; case ADDOP: getsym(); factor(); return; case SUBOP: getsym(); factor(); chkabs(); lastexp.offset = -lastexp.offset; return; case STAR: /* context-sensitive, STAR means location counter here */ lastexp.offset = lc; if ((lastexp.data = lcdata) & UNDBIT && pass == last_pass) experror(UNBLAB); getsym(); return; } experror(FACEXP); } /* string compare for IFC/ELSEIFC expects (,) returns logical value in lastexp */ PUBLIC void scompare() { /* prepare flags for OK, lastexp.offset for error */ lastexp.data = lastexp.offset = 0; if (sym != LPAREN) experror(LPEXP); else { register char *string1; register char *string2; for (string2 = string1 = lineptr; *string2 != ','; ++string2) if (*string2 == 0 || *string2 == ')') { symname = string2; experror(COMEXP); return; } string2++; while (*string1++ == *string2++) ; if (string2[-1] == ')') { if (string1[-1] == ',') lastexp.offset = TRUE; /* else leave FALSE */ lineptr = string2; } else /* FALSE, keep reading to verify syntax */ { for (; *string2 != ')'; ++string2) if (*string2 == 0 || *string2 == ',') { symname = string2; experror(RPEXP); } lineptr = ++string2; } getsym(); } } dev86-0.16.21/as/file.h000066400000000000000000000012611231050321700143020ustar00rootroot00000000000000/* file.h - global variables involving files for assembler */ EXTERN char *filnamptr; /* file name pointer */ EXTERN char *truefilename; /* in case actual source name is a tmpname */ EXTERN fd_t infil; /* current input file (stacked, 0 = memory) */ /* Output fds */ EXTERN unsigned char outfd; /* output fd for writer fns */ EXTERN fd_t binfil; /* binary output file (0 = memory) */ EXTERN fd_t lstfil; /* list output file (0 = standard) */ EXTERN fd_t objfil; /* object output file */ EXTERN fd_t symfil; /* symbol table output file */ /* readsrc internals */ EXTERN unsigned infil0; /* Number of first input area */ EXTERN unsigned infiln; /* Number of current input area */ dev86-0.16.21/as/flag.h000066400000000000000000000003351231050321700142750ustar00rootroot00000000000000/* flag.h - global structured-flag variables for assembler */ EXTERN struct flags_s list; /* listing on/off */ EXTERN struct flags_s maclist; /* list macros on/off */ EXTERN struct flags_s as_warn; /* warnings on/off */ dev86-0.16.21/as/genbin.c000066400000000000000000000130061231050321700146200ustar00rootroot00000000000000/* genbin.c - binary code generation routines for assembler */ #include "syshead.h" #include "const.h" #include "type.h" #include "address.h" #include "file.h" #include "globvar.h" #ifdef USE_FIXED_HEAP PRIVATE char *asmbeg; /* beginning of assembler code */ /* for overwrite check */ /* bss-init to zero = NULL and not changed */ #endif /* Sneaky stuff, the start of a binary file can be _negative_ for the I80386 assembler. The -ve addresses are ones over 2GB (or "org -32") */ #ifdef I80386 PRIVATE soffset_t binfbuf; /* binary code buffer for file (counter) */ PRIVATE soffset_t binmax; /* maximum value of binmbuf for pass 1 */ PRIVATE soffset_t binmin; /* minimum value of binmbuf for pass 1 */ #define PT soffset_t #else PRIVATE offset_t binfbuf; /* binary code buffer for file (counter) */ PRIVATE offset_t binmax; /* maximum value of binmbuf for pass 1 */ PRIVATE offset_t binmin; /* minimum value of binmbuf for pass 1 */ #define PT offset_t #endif FORWARD void putbinoffset P((offset_t offset, count_t size)); /* write header to binary file */ PUBLIC void binheader() { #ifdef BINSYM if ((outfd = binfil) != 0x0 && binmbuf_set && binmax >= binmin) { writec(0x0); /* binary header byte */ #ifdef LONG_BINHEADER writeoff(binmax - binmin); /* program length */ writeoff(binfbuf = binmin); /* program start */ #else writew((unsigned) (binmax - binmin)); /* program length */ writew((unsigned) (binfbuf = binmin)); /* program start */ #endif } #else if ( ( outfd = symfil ) && binmbuf_set && binmax >= binmin) { int sft; writec('+'); writec(' '); for(sft=SIZEOF_OFFSET_T*8-4; sft >= 0; sft-=4) writec(hexdigit[(binmin>>sft) & 0xF]); writesn(" ----- $start"); writec('+'); writec(' '); for(sft=SIZEOF_OFFSET_T*8-4; sft >= 0; sft-=4) writec(hexdigit[(binmax>>sft) & 0xF]); writesn(" ----- $end"); binfbuf = binmin; /* program start */ } #endif } /* write trailer to binary file */ PUBLIC void bintrailer() { #ifdef BINSYM if ((outfd = binfil) != 0x0 && (pedata & UNDBIT) != UNDBIT && binmbuf_set) { writec(0xFF); /* binary trailer byte */ writew(0x0); /* further trailer bytes */ #ifdef LONG_BINHEADER writeoff(pedata & UNDBIT ? binmin : progent); /* entry point */ #else writew(pedata & UNDBIT ? (unsigned) binmin : (unsigned) progent); #endif } #endif } /* generate binary code for current line */ PUBLIC void genbin() { struct address_s *adrptr; char *bufptr; unsigned char remaining; if (binaryg && mcount != 0x0) { if (popflags) { if (fcflag) { bufptr = databuf.fcbuf; remaining = mcount; do putbin(*bufptr++); while (--remaining != 0x0); } if (fdflag) { adrptr = databuf.fdbuf; remaining = mcount; do { putbinoffset(adrptr->offset, 0x2); ++adrptr; } while ((remaining -= 0x2) != 0x0); } #if SIZEOF_OFFSET_T > 0x2 if (fqflag) { adrptr = databuf.fqbuf; remaining = mcount; do { putbinoffset(adrptr->offset, 0x4); ++adrptr; } while ((remaining -= 0x4) != 0x0); } #endif } else { remaining = mcount - 0x1; /* count opcode immediately */ #ifdef I80386 if (aprefix != 0x0) { putbin(aprefix); --remaining; } if (oprefix != 0x0) { putbin(oprefix); --remaining; } if (sprefix != 0x0) { putbin(sprefix); --remaining; } #endif if (page != 0x0) { putbin(page); --remaining; } putbin(opcode); if (remaining != 0x0) { if (postb != 0x0) { putbin(postb); --remaining; } #ifdef I80386 if (sib != NO_SIB) { putbin(sib); --remaining; } #endif if (remaining != 0x0) putbinoffset(lastexp.offset, remaining); } #ifdef I80386 if (immcount != 0x0) putbinoffset(immadr.offset, immcount); #endif } /* else no code for this instruction, or already generated */ } } /* initialise private variables */ PUBLIC void initbin() { #ifdef I80386 binmin = ((offset_t)-1 >>1); /* greater than anything */ #else binmin = -1; /* greater than anything */ #endif } /* write char to binary file or directly to memory */ PUBLIC void putbin(ch) opcode_pt ch; { if (binfil != 0x0) { if (!binaryc) /* pass 1, just record limits */ { if ((PT)binmbuf < binmin) binmin = binmbuf; binmbuf++; if ((PT)binmbuf > binmax) binmax = binmbuf; } else { #if 0 if (binfbuf > (PT)binmbuf) { error(BWRAP); /* file buffer ahead of memory buffer */ } else #endif { #ifdef MSDOS static PT zapptr = 0; #endif outfd = binfil; #ifdef MSDOS while (binfbuf < (PT)binmbuf && binfbuf >= zapptr+binmin) { writec(0); ++binfbuf; ++zapptr; } #endif if( binfbuf != (PT)binmbuf) if( lseek(binfil, (long)((PT)binmbuf-binfbuf), 1) < 0 ) error(BWRAP); binfbuf = binmbuf; writec(ch); binmbuf = ++binfbuf; } } } #ifdef USE_FIXED_HEAP else if (binaryc && !(lcdata & UNDBIT)) /* memory output, and enabled */ { register char *bufptr; if ((bufptr = (char *) binmbuf) >= asmbeg && bufptr < temp_buf()) error(OWRITE); else *bufptr = ch; ++binmbuf; } #endif } /* write sized offset to binary file or directly to memory */ PRIVATE void putbinoffset(offset, size) offset_t offset; count_t size; { char buf[sizeof offset]; #if SIZEOF_OFFSET_T > 0x2 u4cn(buf, offset, size); #else u2cn(buf, offset, size); #endif putbin(buf[0]); if (size > 0x1) putbin(buf[1]); if (size > 0x2) { putbin(buf[2]); putbin(buf[3]); } } dev86-0.16.21/as/genlist.c000066400000000000000000000235101231050321700150240ustar00rootroot00000000000000/* genlist.c - generate listing and error reports for assembler */ #include "syshead.h" #include "const.h" #include "type.h" #include "address.h" #include "flag.h" #include "file.h" #include "globvar.h" #include "macro.h" #include "scan.h" #include "source.h" #define CODE_LIST_LENGTH (sizeof (struct code_listing_s) - 1) /* length of formatted code listing */ #define MAXERR 6 /* maximum errors listed per line */ struct error_s /* to record error info */ { char * err_str; unsigned char position; }; /* code listing format */ struct code_listing_s { union linum_macro_u { char linum[LINUM_LEN]; struct { char pad[1]; char mark[1]; char level[1]; } macro; } linum_or_macro; char padlinum[1]; char lc[4]; char padlc[1]; #ifdef I80386 char lprefix[2]; char aprefix[2]; char oprefix[2]; char sprefix[2]; #endif char page[2]; char opcode[2]; char postb[2]; #ifdef I80386 char sib[2]; #endif char padopcode[1]; #if SIZEOF_OFFSET_T > 2 char displ4[2]; char displ3[2]; #endif char displ2[2]; char displ1[2]; char reldispl[1]; char paddispl[1]; #ifdef I80386 char imm4[2]; char imm3[2]; char imm2[2]; char imm1[2]; char relimm[1]; char padimm[1]; #endif char nullterm; }; PRIVATE struct error_s errbuf[MAXERR]; /* error buffer */ PRIVATE unsigned char errcount; /* # errors in line */ PRIVATE bool_t erroverflow; /* set if too many errors on line */ FORWARD char *build_1hex_number P((opcode_pt num, char *where)); FORWARD void list1 P((fd_t fd)); FORWARD void listcode P((void)); FORWARD void listerrors P((void)); FORWARD void paderrorline P((unsigned nspaces)); /* format 1 byte number as 2 hex digits, return ptr to end */ PRIVATE char *build_1hex_number(num, where) opcode_pt num; register char *where; { where[0] = hexdigit[((unsigned) num % 256) / 16]; where[1] = hexdigit[(unsigned) num % 16]; return where + 2; } /* format 2 byte number as 4 hex digits, return ptr to end */ PUBLIC char *build_2hex_number(num, where) unsigned num; char *where; { return build_1hex_number((opcode_pt) num, build_1hex_number((opcode_pt) (num / 256), where)); } /* format 2 byte number as decimal with given width (pad with leading '0's) */ /* return ptr to end */ PUBLIC char *build_number(num, width, where) unsigned num; unsigned width; register char *where; { static unsigned powers_of_10[] = {1, 10, 100, 1000, 10000,}; unsigned char digit; unsigned char power; register unsigned power_of_10; power = 5; /* actually 1 more than power */ do { for (digit = '0', power_of_10 = (powers_of_10 - 1)[power]; num >= power_of_10; num -= power_of_10) ++digit; if (power <= width) *where++ = digit; } while (--power != 0); return where; } /* record number and position of error (or error buffer overflow) */ PUBLIC void warning(err_str) char * err_str; { if (!as_warn.current) return; ++totwarn; --toterr; error(err_str); } PUBLIC void error(err_str) char * err_str; { register struct error_s *errptr; register struct error_s *errptrlow; unsigned char position; if (errcount >= MAXERR) erroverflow = TRUE; else { position = symname - linebuf; for (errptr = errbuf + errcount; errptr > errbuf && errptr->position > position; errptr = errptrlow) { errptrlow = errptr - 1; errptr->err_str = errptrlow->err_str; errptr->position = errptrlow->position; } errptr->err_str = err_str; errptr->position = position; ++errcount; ++toterr; } } /* list 1 line to list file if any errors or flags permit */ /* list line to console as well if any errors and list file is not console */ PUBLIC void listline() { if (!listpre && lineptr != 0) { if (errcount || (list.current && (!macflag || mcount != 0)) || (macflag && maclist.current) || list_force ) list1(lstfil); if (errcount) { if (lstfil != STDOUT) list1(STDOUT); errcount = 0; erroverflow = FALSE; } } } /* list 1 line unconditionally */ PRIVATE void list1(fd) fd_t fd; { outfd = fd; listcode(); write(outfd, linebuf, (unsigned) (lineptr - linebuf)); writenl(); if (errcount != 0) listerrors(); listpre = TRUE; list_force=FALSE; } /* list object code for 1 line */ PRIVATE void listcode() { unsigned char count; struct code_listing_s *listptr; unsigned numlength; char *numptr; listptr = (struct code_listing_s *) temp_buf(); memset((char *) listptr, ' ', sizeof *listptr); listptr->nullterm = 0; if (macflag) { listptr->linum_or_macro.macro.mark[0] = '+'; listptr->linum_or_macro.macro.level[0] = maclevel + ('a' - 1); } else { numlength = LINUM_LEN; numptr = listptr->linum_or_macro.linum; if (infiln != infil0) { *numptr++ = infiln - infil0 + ('a' - 1); numlength = LINUM_LEN - 1; } build_number(linum, numlength, numptr); } if ((count = mcount) != 0 || popflags & POPLC) build_2hex_number((u16_T) lc, listptr->lc); if (popflags & POPLO) { #if SIZEOF_OFFSET_T > 2 if (popflags & POPLONG) build_2hex_number((u16_T) (lastexp.offset / (offset_t) 0x10000L), listptr->displ4); #endif if (popflags & POPHI) build_2hex_number((u16_T) lastexp.offset, listptr->displ2); else build_1hex_number((opcode_pt) /* XXX */(u16_T) lastexp.offset, listptr->displ1); if (lastexp.data & RELBIT) listptr->reldispl[0] = '>'; } else if (count != 0) { #ifdef I80386 if (aprefix != 0) { --count; build_1hex_number(aprefix, listptr->aprefix); } if (oprefix != 0) { --count; build_1hex_number(oprefix, listptr->oprefix); } if (sprefix != 0) { --count; build_1hex_number(sprefix, listptr->sprefix); } #endif if (page != 0) { build_1hex_number(page, listptr->page); --count; } build_1hex_number(opcode, listptr->opcode); --count; if (postb != 0) { --count; build_1hex_number(postb, #ifdef MC6809 count == 0 ? listptr->displ1 : #endif listptr->postb); } #ifdef I80386 if (sib != NO_SIB) { --count; build_1hex_number(sib, listptr->sib); } #endif if (count > 0) { build_1hex_number((opcode_pt) lastexp.offset, listptr->displ1); if (lastexp.data & RELBIT) listptr->reldispl[0] = '>'; } if (count > 1) build_1hex_number((opcode_pt) (lastexp.offset >> 0x8), listptr->displ2); #if SIZEOF_OFFSET_T > 2 if (count > 2) { build_1hex_number((opcode_pt) (lastexp.offset >> 0x10), listptr->displ3); build_1hex_number((opcode_pt) (lastexp.offset >> 0x18), listptr->displ4); } #endif #ifdef I80386 if (immcount > 0) { build_1hex_number((opcode_pt) immadr.offset, listptr->imm1); if (immadr.data & RELBIT) listptr->relimm[0] = '>'; } if (immcount > 1) build_1hex_number((opcode_pt) (immadr.offset >> 0x8), listptr->imm2); if (immcount > 2) { build_1hex_number((opcode_pt) (immadr.offset >> 0x10), listptr->imm3); build_1hex_number((opcode_pt) (immadr.offset >> 0x18), listptr->imm4); } #endif } writes((char *) listptr); } /* list errors, assuming some */ PRIVATE void listerrors() { unsigned char column; unsigned char errcol; /* column # in error line */ unsigned char errcolw; /* working column in error line */ char *errmsg; struct error_s *errptr; char *linep; unsigned char remaining; #ifdef I80386 paderrorline(1); #else paderrorline(CODE_LIST_LENGTH - LINUM_LEN); #endif remaining = errcount; column = 0; /* column to match with error column */ errcolw = errcol = CODE_LIST_LENGTH; /* working & col number on err line */ errptr = errbuf; linep = linebuf; do { #ifdef I80386 if(errcol != CODE_LIST_LENGTH) { writenl(); paderrorline(1); } writes(errmsg = errptr->err_str); errcol = strlen(errmsg)+LINUM_LEN+1; column = 0; linep = linebuf; errcolw = CODE_LIST_LENGTH; while (errcolw > errcol) { writec('.'); ++errcol; } #endif while (errptr && errptr->position < 132 && column < errptr->position) { ++column; if (*linep++ == '\t') /* next tab (standard tabs only) */ errcolw = (errcolw + 8) & 0xf8; else ++errcolw; while (errcolw > errcol) { #ifdef I80386 writec('.'); #else writec(' '); #endif ++errcol; } } #ifdef I80386 writec('^'); ++errcol; #else if (errcolw < errcol) /* position under error on new line */ { writenl(); paderrorline((unsigned) errcolw - LINUM_LEN); } writec('^'); writes(errmsg = errptr->err_str); errcol += strlen(errmsg); #endif ++errptr; } while (--remaining != 0); writenl(); if (erroverflow) { #ifdef I80386 paderrorline(1); #else paderrorline(CODE_LIST_LENGTH - LINUM_LEN); #endif writesn(FURTHER); } } /* pad out error line to begin under 1st char of source listing */ PRIVATE void paderrorline(nspaces) unsigned nspaces; { int nstars = LINUM_LEN; while (nstars-- != 0) writec('*'); /* stars under line number */ while (nspaces-- != 0) writec(' '); /* spaces out to error position */ } /* write 1 character */ PUBLIC void writec(ch) char ch; { write(outfd, &ch, 1); } /* write newline */ PUBLIC void writenl() { writes(SOS_EOLSTR); } /* write 1 offset_t, order to suit target */ PUBLIC void writeoff(offset) offset_t offset; { char buf[sizeof offset]; #if SIZEOF_OFFSET_T > 2 u4c4(buf, offset); #else u2c2(buf, offset); #endif write(outfd, buf, sizeof buf); } /* write string */ PUBLIC void writes(s) char *s; { write(outfd, s, strlen(s)); } /* write string followed by newline */ PUBLIC void writesn(s) char *s; { writes(s); writenl(); } /* write 1 word, order to suit target */ PUBLIC void writew(word) unsigned word; { char buf[2]; u2c2(buf, (u16_T) word); write(outfd, buf, sizeof buf); } dev86-0.16.21/as/genobj.c000066400000000000000000000342401231050321700146250ustar00rootroot00000000000000/* genobj.c - object code generation routines for assembler */ #include "syshead.h" #include "const.h" #include "type.h" #include "address.h" #include "file.h" #include "globvar.h" #define OBJBUFSIZE 512 /* size of object code output buffer */ #define isge2byteoffset(offset) ((offset) >= 0x100) #define isge4byteoffset(offset) ((offset) >= 0x10000L) PRIVATE char hid_absbuf[OBJ_MAX_ABS_LEN]; /* absolute object code buf */ PRIVATE char *absbuf; /* start */ PRIVATE char *absbufend; /* last location + 1 */ PRIVATE char *absbufptr; /* current location */ PRIVATE struct sym_s **arrext; /* array of external symbol ptrs */ PRIVATE char hid_objbuf[OBJBUFSIZE]; /* object code buffer */ PRIVATE unsigned numext; /* number of external symbols */ PRIVATE char *objbuf; /* start */ PRIVATE char *objbufend; /* last location + 1 */ PRIVATE char *objbufptr; /* current location */ PRIVATE unsigned char relsize; /* current relocation size, 0 init */ /* local to genobjadr, but here */ /* because of static re-init bug */ PRIVATE offset_t rmbcount; /* accumulator for repeated RMB's */ FORWARD void flushabs P((void)); FORWARD void flushrmb P((void)); FORWARD void genobjadr P((struct address_s *adrptr, int size)); FORWARD void putobj1 P((opcode_pt ch)); FORWARD void putobj4 P((u32_T offset)); FORWARD void putobjoffset P((offset_t offset, count_t size)); FORWARD void putobjword P((unsigned word)); FORWARD void writeobj P((char *buf, unsigned count)); /* accumulate RMB requests into 1 (so + and - requests cancel) */ PUBLIC void accumulate_rmb(offset) offset_t offset; { if (objectc) { flushabs(); rmbcount += offset; } } /* flush absolute object code buffer to object code buffer if necessary */ PRIVATE void flushabs() { if (absbufptr > absbuf) { putobj1((absbufptr - absbuf) | OBJ_ABS); { register char *bufptr; bufptr = absbuf; do putobj1(*bufptr); while (++bufptr < absbufptr); absbufptr = absbuf; } } } /* flush object code buffer if necessary */ PUBLIC void flushobj() { int ntowrite; if ((ntowrite = objbufptr - objbuf) > 0) { if (write(objfil, objbuf, (unsigned) ntowrite) != ntowrite) { error(OBJOUT); listline(); finishup(); } objbufptr = objbuf; } } /* flush RMB count if necessary */ PRIVATE void flushrmb() { count_t size; if (rmbcount != 0) { #if SIZEOF_OFFSET_T > 2 if (isge4byteoffset(rmbcount)) { putobj1(OBJ_SKIP_4); size = 4; } else #endif if (isge2byteoffset(rmbcount)) { putobj1(OBJ_SKIP_2); size = 2; } else { putobj1(OBJ_SKIP_1); size = 1; } putobjoffset(rmbcount, size); rmbcount = 0; } } /* generate object code for current line */ /* any address parameter is (regrettably) in lastexp any immediate parameter is (corectly) in immadr */ PUBLIC void genobj() { struct address_s *adrptr; char *bufptr; unsigned char remaining; if (objectc && mcount != 0) { if (popflags) { if (fcflag) { bufptr = databuf.fcbuf; remaining = mcount; do putabs(*bufptr++); while (--remaining != 0); } if (fdflag) { adrptr = databuf.fdbuf; remaining = mcount; do genobjadr(adrptr++, 2); while ((remaining -= 2) != 0); } #if SIZEOF_OFFSET_T > 2 if (fqflag) { adrptr = databuf.fqbuf; remaining = mcount; do genobjadr(adrptr++, 4); while ((remaining -= 4) != 0); } #endif } else { remaining = mcount - 1; /* count opcode immediately */ #ifdef I80386 if (aprefix != 0) { putabs(aprefix); --remaining; } if (oprefix != 0) { putabs(oprefix); --remaining; } if (sprefix != 0) { putabs(sprefix); --remaining; } #endif if (page != 0) { putabs(page); --remaining; } putabs(opcode); if (remaining != 0) { if (postb != 0) { putabs(postb); --remaining; } #ifdef I80386 if (sib != NO_SIB) { putabs(sib); --remaining; } #endif if (remaining != 0) genobjadr(&lastexp, remaining); } } #ifdef I80386 if (immcount != 0) genobjadr(&immadr, immcount); #endif } } /* generate object code for current address */ PRIVATE void genobjadr(adrptr, size) struct address_s *adrptr; smallcount_t size; { unsigned char byte; unsigned symnum; if (!(adrptr->data & RELBIT)) { /* absolute address */ char buf[sizeof(offset_t)]; #if SIZEOF_OFFSET_T > 2 u4cn(buf, adrptr->offset, size); #else u2cn(buf, adrptr->offset, size); #endif putabs(buf[0]); if (size > 1) putabs(buf[1]); if (size > 2) { putabs(buf[2]); putabs(buf[3]); } } else { /* relocatable address */ if (size != relsize) /* set reloc size index |00|0000xx| */ putobj((relsize = size) == 4 ? 0x03 : relsize); if (!(adrptr->data & IMPBIT)) { /* offset relocation (known offset) */ putobj((adrptr->data & SEGM) | OBJ_OFFSET_REL | pcrflag); putobjoffset(adrptr->offset, size); } else { /* symbol relocation (imported symbol + offset) */ { register struct sym_s **copyptr; for (copyptr = arrext, symnum = 0; symnum < numext && *copyptr++ != adrptr->sym; ++symnum) ; } byte = OBJ_SYMBOL_REL; if (isge2byteoffset(symnum)) byte = OBJ_SYMBOL_REL | OBJ_S_MASK; #if SIZEOF_OFFSET_T > 2 if (isge4byteoffset(adrptr->offset)) { byte |= 0x03; /* 4 byte offset */ size = 4; } else #endif if (isge2byteoffset(adrptr->offset)) { byte |= 0x02; /* 2 byte offset */ size = 2; } else if (adrptr->offset != 0) { byte |= 0x01; /* 1 byte offset */ size = 1; } else size = 0; putobj(byte | pcrflag); if (isge2byteoffset(symnum)) putobjword(symnum); else putobj1((opcode_pt) symnum); if (adrptr->offset != 0) putobjoffset(adrptr->offset, size); } } } /* initialise private variables */ PUBLIC void initobj() { absbufend = (absbufptr = absbuf = hid_absbuf) + sizeof hid_absbuf; objbufend = (objbufptr = objbuf = hid_objbuf) + sizeof hid_objbuf; } /* write header to object file also build array of imported/exported symbols */ PUBLIC void objheader() { static char module_header[] = { #ifdef I80386 0xA3, 0x86, 1, 0, (char) (0xA3 + 0x86 + 1 + 0), #endif #ifdef MC6809 'S', '1', /* 2 byte magic number */ 0, 1, /* 2 byte number of modules in file */ 'S' + '1' + 0 + 1, /* 1 byte checksum */ #endif }; static char seg_max_sizes[] = { 0x55, /* all segments have maximum size 2^16 */ 0x55, /* this is encoded by 0b01 4 times per byte */ 0x55, /* other codes are 0b00 = max size 2^8 */ 0x55, /* 0b10 = max size 2^24, 0b11 = max 2^32 */ }; unsigned char byte; register struct sym_s **copyptr; struct sym_s **copytop; struct sym_s **hashptr; struct lc_s *lcp; char module_name[FILNAMLEN + 1]; char *nameptr; unsigned offset; unsigned segsizebytes; unsigned size; unsigned char sizebits; unsigned strsiz; /* size of object string table */ unsigned symosiz; /* size of object symbol table */ register struct sym_s *symptr; u32_T textlength; int symcount = 0; if ((objectc = objectg) == 0) return; writeobj(module_header, sizeof module_header); /* calculate number of imported/exported symbols */ /* and lengths of symbol and string tables */ /* build array of imported/exported symbols */ symosiz = 0; if (truefilename == NUL_PTR) truefilename = filnamptr; nameptr = strrchr(truefilename, DIRCHAR); strcpy(module_name, nameptr != NUL_PTR ? nameptr + 1 : truefilename); if ((nameptr = strrchr(module_name, '.')) != NUL_PTR) *nameptr = 0; strsiz = strlen(module_name) + 1; for (hashptr = spt; hashptr < spt_top;) if ((symptr = *hashptr++) != NUL_PTR) do { if ((symptr->type & EXPBIT || symptr->data & IMPBIT) || (!globals_only_in_obj && symptr->name[0] != '.' && !(symptr->type & (MNREGBIT | MACBIT | VARBIT)))) { symcount ++; } } while ((symptr = symptr->next) != NUL_PTR); arrext = copyptr = asalloc( sizeof(struct sym_s *) * symcount); for (hashptr = spt; hashptr < spt_top;) if ((symptr = *hashptr++) != NUL_PTR) do { if ((symptr->type & EXPBIT || symptr->data & IMPBIT) || (!globals_only_in_obj && symptr->name[0] != '.' && !(symptr->type & (MNREGBIT | MACBIT | VARBIT)))) { *copyptr++ = symptr; strsiz += symptr->length + 1; if (textseg>=0 && (symptr->data & SEGM) == textseg) strsiz+=2; #if SIZEOF_OFFSET_T > 2 if (isge4byteoffset(symptr->value_reg_or_op.value)) size = 4 + 4; /* 4 is size of offset into string table and flags */ /* 2nd 4 is for 4 byte offset */ else #endif if (isge2byteoffset(symptr->value_reg_or_op.value)) size = 4 + 2; else if (symptr->value_reg_or_op.value != 0) size = 4 + 1; else size = 4; symosiz += size; ++numext; } } while ((symptr = symptr->next) != NUL_PTR); copytop = copyptr; /* calculate length of text, and number of seg size bytes in header */ textlength = segsizebytes = 0; lcp = lctab; do if (lcp->lc != 0) { textlength += lcp->lc; /* assuming text starts at 0 */ #if SIZEOF_OFFSET_T > 2 if (isge4byteoffset(lcp->lc)) segsizebytes += 4; else #endif segsizebytes += 2; /* use 2 byte size if possible */ } while (++lcp < lctabtop); /* offset to text = length of header since only 1 module header consists of: module header sizeof module_header offset to start of text 4 length of text 4 length of string area 2 class 1 revision 1 seg max sizes sizeof seg_max_sizes seg size descriptors 4 seg sizes segsizebytes symbol count 2 symbol offsets and types symosiz strings strsiz */ /* offset to start of text */ putobj4((u32_T) (sizeof module_header + 4 + 4 + 2 + 1 + 1 + sizeof seg_max_sizes + 4 + segsizebytes + 2 + symosiz) + strsiz); /* length of text */ putobj4((u32_T) textlength); /* length of string area */ putobjword(strsiz); /* class and revision */ putobj1(0); putobj1(0); /* segment max sizes (constant) */ writeobj(seg_max_sizes, sizeof seg_max_sizes); /* segment size descriptors */ /* produce only 0 and 2 byte sizes */ lcp = lctabtop; byte = 0; sizebits = OBJ_SEGSZ_TWO << 6; do { --lcp; if (lcp->lc != 0) { byte |= sizebits; #if SIZEOF_OFFSET_T > 2 if (isge4byteoffset(lcp->lc)) byte |= sizebits >> 1; /* XXX - convert size 2 to size 4 */ #endif } if ((sizebits >>= 2) == 0) { putobj1(byte); byte = 0; sizebits = OBJ_SEGSZ_TWO << 6; } } while (lcp > lctab); /* segment sizes */ do /* lcp starts at lctab */ if (lcp->lc != 0) { #if SIZEOF_OFFSET_T > 2 if (isge4byteoffset(lcp->lc)) putobj4(lcp->lc); else #endif putobjword((unsigned) lcp->lc); } while (++lcp < lctabtop); /* symbol count */ putobjword(numext); /* symbol offsets and types */ offset = strlen(module_name) + 1; /* 1st symbol begins after name */ for (copyptr = arrext; copyptr < copytop;) { putobjword(offset); symptr = *copyptr++; byte = symptr->type & OBJ_N_MASK; #if SIZEOF_OFFSET_T > 2 if (isge4byteoffset(symptr->value_reg_or_op.value)) { byte |= OBJ_SZ_FOUR; size = 4; } else #endif if (isge2byteoffset(symptr->value_reg_or_op.value)) { byte |= OBJ_SZ_TWO; size = 2; } else if (symptr->value_reg_or_op.value != 0) { byte |= OBJ_SZ_ONE; size = 1; } else size = 0; if ((symptr->type & (COMMBIT | REDBIT)) == (COMMBIT | REDBIT)) { byte |= OBJ_SA_MASK; symptr->data &= ~OBJ_I_MASK; } putobjword((unsigned) (byte << 0x8) | (symptr->type & OBJ_E_MASK) | /* |E|0000000| */ ((symptr->data & (OBJ_I_MASK | OBJ_A_MASK | OBJ_SEGM_MASK)) ^ /* |0|I|0|A|SEGM| */ RELBIT)); /* RELBIT by negative logic */ if ((symptr->type & (COMMBIT | REDBIT)) == (COMMBIT | REDBIT)) symptr->data |= OBJ_I_MASK; if (size != 0) putobjoffset(symptr->value_reg_or_op.value, size); offset += symptr->length + 1; if (textseg>=0 && (symptr->data & SEGM) == textseg) offset+=2; } /* strings */ writeobj(module_name, strlen(module_name)); putobj1(0); for (copyptr = arrext; copyptr < copytop;) { symptr = *copyptr++; writeobj(symptr->name, symptr->length); if (textseg>=0 && (symptr->data & SEGM) == textseg) { putobj1('.'); putobj1(hexdigit[textseg]); } putobj1(0); } putobj1(OBJ_SET_SEG | 0); /* default segment 0, |0010|SEGM| */ } /* write trailer to object file */ PUBLIC void objtrailer() { if (objectc) { putobj(0); /* end of object file */ flushobj(); } } /* write char to absolute object code buffer, flush if necessary */ PUBLIC void putabs(ch) opcode_pt ch; { if (objectc) { if (rmbcount != 0) flushrmb(); if (absbufptr >= absbufend) flushabs(); *absbufptr++ = ch; } } /* write char to object code buffer, flush if necessary */ PUBLIC void putobj(ch) opcode_pt ch; { if (objectc) { flushabs(); flushrmb(); putobj1(ch); } } /* write char to object code buffer assuming nothing in absolute & rmb bufs */ PRIVATE void putobj1(ch) opcode_pt ch; { if (objbufptr >= objbufend) flushobj(); *objbufptr++ = ch; } /* write 32 bit offset to object code buffer assuming ... */ PRIVATE void putobj4(offset) u32_T offset; { char buf[sizeof offset]; u4c4(buf, offset); writeobj(buf, 4); } /* write sized offset to object code buffer assuming ... */ PRIVATE void putobjoffset(offset, size) offset_t offset; count_t size; { char buf[sizeof offset]; #if SIZEOF_OFFSET_T > 2 u4cn(buf, offset, size); #else u2cn(buf, offset, size); #endif putobj1(buf[0]); if (size > 1) putobj1(buf[1]); if (size > 2) { putobj1(buf[2]); putobj1(buf[3]); } } /* write word to object code buffer assuming ... */ PRIVATE void putobjword(word) unsigned word; { char buf[sizeof word]; u2c2(buf, word); putobj1(buf[0]); putobj1(buf[1]); } /* write several bytes to object code buffer assuming ... */ PRIVATE void writeobj(buf, count) char *buf; unsigned count; { do putobj1(*buf++); while (--count); } dev86-0.16.21/as/gensym.c000066400000000000000000000143371231050321700146700ustar00rootroot00000000000000/* gensym.c - generate symbol table for assembler */ #include "syshead.h" #include "const.h" #include "type.h" #include "flag.h" #include "file.h" #include "globvar.h" FORWARD int printsym P((register struct sym_s *symptr, unsigned column)); FORWARD void sort P((struct sym_s **array, struct sym_s **top, bool_pt nameflag)); /* sort labels in symbol table on name and value */ /* if listing, write human-readable table to list file */ /* if symbol file, write machine-readable tables to it */ /* pointers become relative to start of file */ PUBLIC void gensym() { unsigned column; struct sym_s **copyptr; struct sym_s **copytop; register struct sym_s **hashptr; unsigned label_count; /* number of labels */ unsigned labels_length; /* length of all label strings */ struct sym_s **symlptr; /* start of symbol output list */ register struct sym_s *symptr; #ifdef BINSYM unsigned label_stringptr; /* offset of label str from start of file */ #endif int symcount = 0; labels_length = label_count = 0; /* make copy of all relavant symbol ptrs on heap */ /* original ptrs can now be modified, but need to be an array for sort */ for (hashptr = spt; hashptr < spt_top;) if ((symptr = *hashptr++) != NUL_PTR) do if (!(symptr->type & (MACBIT | MNREGBIT | VARBIT))) symcount++; while ((symptr = symptr->next) != NUL_PTR); symlptr = copyptr = asalloc( sizeof(struct sym_s *) * symcount); for (hashptr = spt; hashptr < spt_top;) if ((symptr = *hashptr++) != NUL_PTR) do if (!(symptr->type & (MACBIT | MNREGBIT | VARBIT))) { *copyptr++ = symptr; ++label_count; labels_length += symptr->length + 3; /* 3 for type, value */ } while ((symptr = symptr->next) != NUL_PTR); sort(symlptr, copyptr, TRUE); /* sort on name */ copytop = copyptr; if (list.global) { outfd = lstfil; writenl(); writesn("Symbols:"); for (copyptr = symlptr, column = 0; copyptr < copytop;) column = printsym(*copyptr++, column); if (column != 0) writenl(); } if ((outfd = symfil) != 0) { #ifndef BINSYM for (copyptr = symlptr; copyptr < copytop;) /* for (copyptr = spt; copyptr < spt_top;) */ { int sft; if((symptr = *copyptr++) == NUL_PTR ) continue; if( globals_only_in_obj && !(symptr->type & EXPBIT)) continue; writec(hexdigit[symptr->data & SEGM]); writec(' '); for(sft=SIZEOF_OFFSET_T*8-4; sft >= 0; sft-=4) writec(hexdigit[(symptr->value_reg_or_op.value>>sft) & 0xF]); writec(' '); writec(symptr->type & EXPBIT ? 'E' : '-'); writec(symptr->type & ENTBIT ? 'N' : '-'); writec(symptr->data & IMPBIT ? 'I' : '-'); writec(symptr->data & RELBIT ? 'R' : 'A'); writec(symptr->type & COMMBIT ? 'C' : '-'); writec(' '); write(outfd, symptr->name, (unsigned) (symptr->length)); /* printsym(*copyptr++, 0); */ writenl(); } #else writew(mapnum); label_count *= 2; /* now length of ptr table (2 bytes per ptr) */ label_stringptr = label_count + 6; /* offset to current string in symbol file */ /* 6 is length of header */ labels_length += label_stringptr; /* offset to ptr table sorted on value */ writew(labels_length + label_count); /* total length of symbol file */ writew(label_count); for (copyptr = symlptr; copyptr < copytop;) { symptr = *copyptr++; writew((unsigned) (symptr->next = (struct sym_s *) label_stringptr)); /* reuse "next" to record string position */ label_stringptr += symptr->length + 3; } for (copyptr = symlptr; copyptr < copytop;) { symptr = *copyptr++; writew((unsigned) symptr->value_reg_or_op.value); writec(symptr->type); write(outfd, symptr->name, (unsigned) (symptr->length - 1)); writec(symptr->name[symptr->length - 1] | 0x80); } sort(symlptr, copyptr, FALSE); /* sort on value */ for (copyptr = symlptr; copyptr < copytop;) { symptr = *copyptr++; writew((unsigned) symptr->next); /* now has string position */ } #endif } } /* print symbol nicely formatted for given column */ PRIVATE int printsym(symptr, column) register struct sym_s *symptr; unsigned column; { unsigned char length; register struct sym_listing_s *listptr; char *outname; char *symname; listptr = (struct sym_listing_s *) temp_buf(); memset((char *) listptr, ' ', SYMLIS_LEN); listptr->nullterm = 0; if ((length = symptr->length) > SYMLIS_NAMELEN) { outname = listptr->name; outname[length = SYMLIS_NAMELEN] = '+'; } else outname = listptr->name; /*(listptr->name + SYMLIS_NAMELEN) - length;*/ symname = symptr->name; do *outname++ = *symname++; while (--length != 0); listptr->ar[0] = symptr->data & RELBIT ? 'R' : 'A'; listptr->segm[0] = hexdigit[symptr->data & SEGM]; if (symptr->type & COMMBIT) listptr->cein[0] = 'C'; else if (symptr->type & ENTBIT) listptr->cein[0] = 'N'; else if (symptr->type & EXPBIT) listptr->cein[0] = 'E'; else if (symptr->data & IMPBIT) listptr->cein[0] = 'I'; #if SIZEOF_OFFSET_T > 2 build_2hex_number((unsigned) (symptr->value_reg_or_op.value >> 16), listptr->value); #endif build_2hex_number((unsigned) symptr->value_reg_or_op.value, listptr->value); writes((char *) listptr); if ((column += SYMLIS_LEN) > (80 - SYMLIS_LEN)) { writenl(); column = 0; } return column; } /* shell sort symbols */ PRIVATE void sort(array, top, nameflag) struct sym_s **array; struct sym_s **top; bool_pt nameflag; { int gap; int i; int j; register struct sym_s **left; register struct sym_s **right; int size; struct sym_s *swap; size = top - array; /* choose gaps according to Knuth V3 p95 */ for (gap = 1, i = 4; (j = 3 * i + 1) < size; gap = i, i = j) ; do { for (j = gap; j < size; ++j) for (i = j - gap; i >= 0; i -= gap) { left = &array[i]; right = &array[i + gap]; if ((bool_t) nameflag) { if (strcmp((*left)->name, (*right)->name) <= 0) break; } else if ((unsigned) (*left)->value_reg_or_op.value <= (*right)->value_reg_or_op.value) break; swap = *left; *left = *right; *right = swap; } } while ((gap /= 3) != 0); } dev86-0.16.21/as/globvar.h000066400000000000000000000074201231050321700150220ustar00rootroot00000000000000/* globvar.h - global variables for assembler */ /* global control and bookkeeping */ EXTERN bool_t binaryc; /* current binary code flag */ EXTERN bool_t binaryg; /* global binary code flag */ EXTERN offset_t binmbuf; /* offset in binary code buffer for memory */ EXTERN bool_t binmbuf_set; /* set to 1 when binmbuf set by org */ EXTERN unsigned char dirpag; /* direct page */ EXTERN bool_t globals_only_in_obj; /* global symbols only in object file */ EXTERN bool_t jumps_long; /* make all jumps long */ EXTERN unsigned char mapnum; /* global map number */ EXTERN bool_t objectc; /* current object code flag */ EXTERN bool_t objectg; /* global object code flag */ EXTERN bool_t pass; /* pass, FALSE means 0, TRUE means 1 */ EXTERN offset_t progent; /* program entry point */ EXTERN bool_t symgen; /* generate symbol table flag */ EXTERN unsigned toterr; /* total errors */ EXTERN unsigned totwarn; /* total warnings */ EXTERN bool_t list_force; /* Force line to be listed - no error */ /* bookeeping for current line */ EXTERN char *linebuf; /* buffer */ /* for symbol table routines */ EXTERN unsigned char inidata; /* init sym entry data governed by "u" flag */ EXTERN struct sym_s **spt; /* symbol pointer table */ EXTERN struct sym_s **spt_top; /* top of symbol ptr table */ /* for translator */ EXTERN struct sym_s *label; /* non-null if valid label starts line */ EXTERN unsigned char pedata; /* shows how PROGENT bound, flags like LCDATA*/ EXTERN unsigned char popflags; /* pseudo-op flags */ /* for BLOCK stack */ EXTERN struct block_s *blockstak; /* stack ptr */ EXTERN unsigned char blocklevel; /* nesting level */ /* for IF stack */ EXTERN struct if_s *ifstak; /* stack ptr */ EXTERN unsigned char iflevel; /* nesting level */ EXTERN bool_t ifflag; /* set if assembling */ /* location counters for various segments */ EXTERN offset_t lc; /* location counter */ EXTERN unsigned char lcdata; /* shows how lc is bound */ /* FORBIT is set if lc is forward referenced */ /* RELBIT is is if lc is relocat. (not ASEG) */ EXTERN offset_t lcjump; /* lc jump between lines */ EXTERN offset_t oldlabel; /* Used for checking for moving labels */ #ifdef LOW_BYTE #define mcount (((unsigned char *) &lcjump)[LOW_BYTE]) /* low byte of lcjump */ #else #define mcount lcjump /* I think this is just a speed hack */ #endif EXTERN struct lc_s *lcptr; /* top of current spot in lctab */ EXTERN struct lc_s *lctab; /* start of lctab */ EXTERN struct lc_s *lctabtop; /* top of lctab */ /* for code generator */ EXTERN opsize_t mnsize; /* 1 if forced byte operand size, else 0 */ EXTERN opcode_t page; EXTERN opcode_t opcode; EXTERN opcode_t postb; /* postbyte, 0 if none */ EXTERN unsigned char pcrflag; /* OBJ_RMASK set if addressing is PC-relative */ EXTERN int last_pass; /* Pass number of last pass */ EXTERN int dirty_pass; /* Set if this pass had a label movement */ EXTERN int textseg; /* Text segment id */ #ifdef I80386 EXTERN opcode_t aprefix; /* address size prefix or 0 */ EXTERN bool_t asld_compatible; /* asld compatibility flag */ EXTERN opsize_t defsize; /* current default size */ EXTERN opsize_t idefsize; /* initial default size */ EXTERN opcode_t oprefix; /* operand size prefix or 0 */ EXTERN opcode_t sprefix; /* segment prefix or 0 */ EXTERN opcode_t sib; /* scale-index-base byte */ EXTERN int cpuid; /* Assembler instruction limit flag */ EXTERN int origcpuid; /* Assembler instruction limit flag */ #endif /* miscellaneous */ extern char hexdigit[]; /* cpuid functions */ #ifdef I80386 #ifndef __AS386_16__ #define iscpu(x) (cpuid>=(x)) #define needcpu(x) do{ if(cpuid<(x)) {warning(CPUCLASH); cpuid|=0x10;} }while(0) #define setcpu(x) (cpuid=(x)) #define cpuwarn() (cpuid&=0xF) #endif #endif #ifndef setcpu #define needcpu(x) #define setcpu(x) #define cpuwarn() #endif dev86-0.16.21/as/keywords.c000066400000000000000000000651261231050321700152370ustar00rootroot00000000000000/* keywords.c - keyword tables for assembler */ #include "syshead.h" #include "const.h" #include "type.h" #include "globvar.h" #include "opcode.h" /* --- start of keywords --- */ /* registers */ /* the register code (internal to assembler) is given in 1 byte */ /* the "opcode" field is not used */ PUBLIC char regs[] = { #ifdef I80386 2, 'B', 'P', BPREG, 0, 2, 'B', 'X', BXREG, 0, 2, 'D', 'I', DIREG, 0, 2, 'S', 'I', SIREG, 0, 3, 'E', 'A', 'X', EAXREG, 0, 3, 'E', 'B', 'P', EBPREG, 0, 3, 'E', 'B', 'X', EBXREG, 0, 3, 'E', 'C', 'X', ECXREG, 0, 3, 'E', 'D', 'I', EDIREG, 0, 3, 'E', 'D', 'X', EDXREG, 0, 3, 'E', 'S', 'I', ESIREG, 0, 3, 'E', 'S', 'P', ESPREG, 0, 2, 'A', 'X', AXREG, 0, 2, 'C', 'X', CXREG, 0, 2, 'D', 'X', DXREG, 0, 2, 'S', 'P', SPREG, 0, 2, 'A', 'H', AHREG, 0, 2, 'A', 'L', ALREG, 0, 2, 'B', 'H', BHREG, 0, 2, 'B', 'L', BLREG, 0, 2, 'C', 'H', CHREG, 0, 2, 'C', 'L', CLREG, 0, 2, 'D', 'H', DHREG, 0, 2, 'D', 'L', DLREG, 0, 2, 'C', 'S', CSREG, 0, 2, 'D', 'S', DSREG, 0, 2, 'E', 'S', ESREG, 0, 2, 'F', 'S', FSREG, 0, 2, 'G', 'S', GSREG, 0, 2, 'S', 'S', SSREG, 0, 3, 'C', 'R', '0', CR0REG, 0, 3, 'C', 'R', '2', CR2REG, 0, 3, 'C', 'R', '3', CR3REG, 0, 3, 'D', 'R', '0', DR0REG, 0, 3, 'D', 'R', '1', DR1REG, 0, 3, 'D', 'R', '2', DR2REG, 0, 3, 'D', 'R', '3', DR3REG, 0, 3, 'D', 'R', '6', DR6REG, 0, 3, 'D', 'R', '7', DR7REG, 0, 3, 'T', 'R', '3', TR3REG, 0, 3, 'T', 'R', '4', TR4REG, 0, 3, 'T', 'R', '5', TR5REG, 0, 3, 'T', 'R', '6', TR6REG, 0, 3, 'T', 'R', '7', TR7REG, 0, 2, 'S', 'T', ST0REG, 0, #endif /* I80386 */ #ifdef MC6809 1, 'A', AREG, 0, 1, 'B', BREG, 0, 2, 'C', 'C', CCREG, 0, 1, 'D', DREG, 0, 2, 'D', 'P', DPREG, 0, 2, 'P', 'C', PCREG, 0, 3, 'P', 'C', 'R', PCREG, 0, 1, 'S', SREG, 0, 1, 'U', UREG, 0, 1, 'X', XREG, 0, 1, 'Y', YREG, 0, #endif 0 /* end of register list */ }; #ifdef I80386 /* type sizes */ /* the "opcode" field gives the type size */ PUBLIC char typesizes[] = { 4, 'B', 'Y', 'T', 'E', BYTEOP, 1, 5, 'D', 'W', 'O', 'R', 'D', DWORDOP, 4, 5, 'F', 'W', 'O', 'R', 'D', FWORDOP, 6, 3, 'F', 'A', 'R', FAROP, 0, 4, 'N', 'E', 'A', 'R', WORDOP, 2, 3, 'P', 'T', 'R', PTROP, 0, 5, 'P', 'W', 'O', 'R', 'D', PWORDOP, 6, 5, 'Q', 'W', 'O', 'R', 'D', QWORDOP, 8, 5, 'T', 'B', 'Y', 'T', 'E', TBYTEOP, 10, 4, 'W', 'O', 'R', 'D', WORDOP, 2, 0 /* end of typesize list */ }; #endif /* ops */ /* the routine number is given in 1 byte */ /* the opcode is given in 1 byte (it is not used for pseudo-ops) */ PUBLIC char ops[] = { /* pseudo-ops. The "opcode" field is unused and padded with a null byte */ /* conditionals - must be first */ 4, 'E', 'L', 'S', 'E', ELSEOP, 0, 6, 'E', 'L', 'S', 'E', 'I', 'F', ELSEIFOP, 0, 7, 'E', 'L', 'S', 'E', 'I', 'F', 'C', ELSEIFCOP, 0, 5, 'E', 'N', 'D', 'I', 'F', ENDIFOP, 0, 2, 'I', 'F', IFOP, 0, 3, 'I', 'F', 'C', IFCOP, 0, /* unconditionals */ 6, '.', 'A', 'L', 'I', 'G', 'N', ALIGNOP, 0, 6, '.', 'A', 'S', 'C', 'I', 'I', FCCOP, 0, 6, '.', 'A', 'S', 'C', 'I', 'Z', ASCIZOP, 0, 5, '.', 'B', 'L', 'K', 'B', RMBOP, 0, 5, '.', 'B', 'L', 'K', 'W', BLKWOP, 0, 5, 'B', 'L', 'O', 'C', 'K', BLOCKOP, 0, 4, '.', 'B', 'S', 'S', BSSOP, 0, 5, '.', 'B', 'Y', 'T', 'E', FCBOP, 0, 4, 'C', 'O', 'M', 'M', COMMOP, 0, 5, '.', 'C', 'O', 'M', 'M', COMMOP1, 0, 5, '.', 'D', 'A', 'T', 'A', DATAOP, 0, 6, '.', 'D', 'A', 'T', 'A', '1', FCBOP, 0, 6, '.', 'D', 'A', 'T', 'A', '2', FDBOP, 0, #if SIZEOF_OFFSET_T > 2 6, '.', 'D', 'A', 'T', 'A', '4', FQBOP, 0, #endif 2, 'D', 'B', FCBOP, 0, #if SIZEOF_OFFSET_T > 2 2, 'D', 'D', FQBOP, 0, #endif 7, '.', 'D', 'E', 'F', 'I', 'N', 'E', EXPORTOP, 0, 2, 'D', 'W', FDBOP, 0, 3, 'E', 'N', 'D', PROCEOFOP, 0, 4, 'E', 'N', 'D', 'B', ENDBOP, 0, 6, '.', 'E', 'N', 'T', 'E', 'R', ENTEROP, 0, 5, 'E', 'N', 'T', 'R', 'Y', ENTRYOP, 0, 3, 'E', 'Q', 'U', EQUOP, 0, 5, '.', 'E', 'V', 'E', 'N', EVENOP, 0, 6, 'E', 'X', 'P', 'O', 'R', 'T', EXPORTOP, 0, 6, 'E', 'X', 'T', 'E', 'R', 'N', IMPORTOP, 0, 7, '.', 'E', 'X', 'T', 'E', 'R', 'N', IMPORTOP, 0, 5, 'E', 'X', 'T', 'R', 'N', IMPORTOP, 0, 4, 'F', 'A', 'I', 'L', FAILOP, 0, 5, '.', 'F', 'A', 'I', 'L', FAILOP, 0, 3, 'F', 'C', 'B', FCBOP, 0, 3, 'F', 'C', 'C', FCCOP, 0, 3, 'F', 'D', 'B', FDBOP, 0, 3, 'G', 'E', 'T', GETOP, 0, 7, '.', 'G', 'L', 'O', 'B', 'A', 'L', GLOBLOP, 0, 6, '.', 'G', 'L', 'O', 'B', 'L', GLOBLOP, 0, 5, 'I', 'D', 'E', 'N', 'T', IDENTOP, 0, 6, 'I', 'M', 'P', 'O', 'R', 'T', IMPORTOP, 0, 7, 'I', 'N', 'C', 'L', 'U', 'D', 'E', GETOP, 0, 5, 'L', 'C', 'O', 'M', 'M', LCOMMOP, 0, 6, '.', 'L', 'C', 'O', 'M', 'M', LCOMMOP1, 0, 5, '.', 'L', 'I', 'S', 'T', LISTOP, 0, 3, 'L', 'O', 'C', LOCOP, 0, #if SIZEOF_OFFSET_T > 2 5, '.', 'L', 'O', 'N', 'G', FQBOP, 0, #endif 8, '.', 'M', 'A', 'C', 'L', 'I', 'S', 'T', MACLISTOP, 0, 5, 'M', 'A', 'C', 'R', 'O', MACROOP, 0, 4, '.', 'M', 'A', 'P', MAPOP, 0, 3, 'O', 'R', 'G', ORGOP, 0, 4, '.', 'O', 'R', 'G', ORGOP, 0, 6, 'P', 'U', 'B', 'L', 'I', 'C', EXPORTOP, 0, 3, 'R', 'M', 'B', RMBOP, 0, 4, '.', 'R', 'O', 'M', DATAOP, 0, 5, '.', 'S', 'E', 'C', 'T', SECTOP, 0, 3, 'S', 'E', 'T', SETOP, 0, 5, 'S', 'E', 'T', 'D', 'P', SETDPOP, 0, 6, '.', 'S', 'H', 'O', 'R', 'T', FDBOP, 0, 6, '.', 'S', 'P', 'A', 'C', 'E', RMBOP, 0, 5, '.', 'T', 'E', 'X', 'T', TEXTOP, 0, #ifndef MC6809 5, 'U', 'S', 'E', '1', '6', USE16OP, 0, 5, 'U', 'S', 'E', '3', '2', USE32OP, 0, #endif 5, '.', 'W', 'A', 'R', 'N', WARNOP, 0, 5, '.', 'W', 'O', 'R', 'D', FDBOP, 0, 6, '.', 'Z', 'E', 'R', 'O', 'W', BLKWOP, 0, /* hardware ops. The opcode field is now used */ #ifdef I80386 3, 'A', 'A', 'A', INHER, 0x37, 3, 'A', 'A', 'D', INHER_A, 0xD5, 3, 'A', 'A', 'M', INHER_A, 0xD4, 3, 'A', 'A', 'S', INHER, 0x3F, 3, 'A', 'D', 'C', GROUP1, 0x10, 3, 'A', 'D', 'D', GROUP1, 0x00, 3, 'A', 'N', 'D', GROUP1, 0x20, 4, 'A', 'R', 'P', 'L', EwGw, 0x63, 3, 'B', 'C', 'C', BCC, 0x73, 3, 'B', 'C', 'S', BCC, 0x72, 3, 'B', 'E', 'Q', BCC, 0x74, 3, 'B', 'G', 'E', BCC, 0x7D, 3, 'B', 'G', 'T', BCC, 0x7F, 3, 'B', 'H', 'I', BCC, 0x77, 4, 'B', 'H', 'I', 'S', BCC, 0x73, 3, 'B', 'L', 'E', BCC, 0x7E, 3, 'B', 'L', 'O', BCC, 0x72, 4, 'B', 'L', 'O', 'S', BCC, 0x76, 3, 'B', 'L', 'T', BCC, 0x7C, 3, 'B', 'M', 'I', BCC, 0x78, 3, 'B', 'N', 'E', BCC, 0x75, 5, 'B', 'O', 'U', 'N', 'D', GvMa, 0x62, 3, 'B', 'P', 'C', BCC, 0x7B, 3, 'B', 'P', 'L', BCC, 0x79, 3, 'B', 'P', 'S', BCC, 0x7A, 2, 'B', 'R', CALL, JMP_OPCODE, 3, 'B', 'V', 'C', BCC, 0x71, 3, 'B', 'V', 'S', BCC, 0x70, 4, 'C', 'A', 'L', 'L', CALL, JSR_OPCODE, 5, 'C', 'A', 'L', 'L', 'F', CALLI, 0x9A, 5, 'C', 'A', 'L', 'L', 'I', CALLI, 0x9A, 3, 'C', 'B', 'W', INHER16, 0x98, 3, 'C', 'L', 'C', INHER, 0xF8, 3, 'C', 'L', 'D', INHER, 0xFC, 3, 'C', 'L', 'I', INHER, 0xFA, 3, 'C', 'M', 'C', INHER, 0xF5, 3, 'C', 'M', 'P', GROUP1, CMP_OPCODE_BASE, 4, 'C', 'M', 'P', 'S', INHER, CMPSW_OPCODE, 5, 'C', 'M', 'P', 'S', 'B', INHER, CMPSB_OPCODE, 5, 'C', 'M', 'P', 'S', 'D', INHER32, CMPSW_OPCODE, 5, 'C', 'M', 'P', 'S', 'W', INHER16, CMPSW_OPCODE, 4, 'C', 'M', 'P', 'W', INHER16, CMPSW_OPCODE, 4, 'C', 'S', 'E', 'G', INHER, 0x2E, 3, 'C', 'W', 'D', INHER16, 0x99, 4, 'C', 'W', 'D', 'E', INHER32, 0x98, 3, 'C', 'D', 'Q', INHER32, 0x99, 3, 'D', 'A', 'A', INHER, 0x27, 3, 'D', 'A', 'S', INHER, 0x2F, 4, 'D', 'S', 'E', 'G', INHER, 0x3E, 3, 'D', 'E', 'C', INCDEC, 0x08, 3, 'D', 'I', 'V', DIVMUL, 0x30, 5, 'E', 'N', 'T', 'E', 'R', ENTER, 0xC8, 4, 'E', 'S', 'E', 'G', INHER, 0x26, 4, 'F', 'S', 'E', 'G', INHER, 0x64, 4, 'G', 'S', 'E', 'G', INHER, 0x65, 3, 'H', 'L', 'T', INHER, 0xF4, 4, 'I', 'D', 'I', 'V', DIVMUL, 0x38, 4, 'I', 'M', 'U', 'L', IMUL, 0x28, 2, 'I', 'N', IN, 0xEC, 3, 'I', 'N', 'C', INCDEC, 0x00, 3, 'I', 'N', 'S', INHER, 0x6D, 4, 'I', 'N', 'S', 'B', INHER, 0x6C, 4, 'I', 'N', 'S', 'D', INHER32, 0x6D, 4, 'I', 'N', 'S', 'W', INHER16, 0x6D, 3, 'I', 'N', 'T', INT, 0xCD, 4, 'I', 'N', 'T', 'O', INHER, 0xCE, 3, 'I', 'N', 'W', IN, 0xED, 4, 'I', 'R', 'E', 'T', INHER16, 0xCF, 5, 'I', 'R', 'E', 'T', 'D', INHER32, 0xCF, 1, 'J', CALL, JMP_SHORT_OPCODE, 2, 'J', 'A', JCC, 0x77, 3, 'J', 'A', 'E', JCC, 0x73, 2, 'J', 'B', JCC, 0x72, 3, 'J', 'B', 'E', JCC, 0x76, 2, 'J', 'C', JCC, 0x72, 4, 'J', 'C', 'X', 'E', JCXZ, 0x2, 4, 'J', 'C', 'X', 'Z', JCXZ, 0x2, 5, 'J', 'E', 'C', 'X', 'E', JCXZ, 0x4, 5, 'J', 'E', 'C', 'X', 'Z', JCXZ, 0x4, 2, 'J', 'E', JCC, 0x74, 2, 'J', 'G', JCC, 0x7F, 3, 'J', 'G', 'E', JCC, 0x7D, 2, 'J', 'L', JCC, 0x7C, 3, 'J', 'L', 'E', JCC, 0x7E, 3, 'J', 'M', 'P', CALL, JMP_SHORT_OPCODE, 4, 'J', 'M', 'P', 'F', CALLI, 0xEA, 4, 'J', 'M', 'P', 'I', CALLI, 0xEA, 3, 'J', 'N', 'A', JCC, 0x76, 4, 'J', 'N', 'A', 'E', JCC, 0x72, 3, 'J', 'N', 'B', JCC, 0x73, 4, 'J', 'N', 'B', 'E', JCC, 0x77, 3, 'J', 'N', 'C', JCC, 0x73, 3, 'J', 'N', 'E', JCC, 0x75, 3, 'J', 'N', 'G', JCC, 0x7E, 4, 'J', 'N', 'G', 'E', JCC, 0x7C, 3, 'J', 'N', 'L', JCC, 0x7D, 4, 'J', 'N', 'L', 'E', JCC, 0x7F, 3, 'J', 'N', 'O', JCC, 0x71, 3, 'J', 'N', 'P', JCC, 0x7B, 3, 'J', 'N', 'S', JCC, 0x79, 3, 'J', 'N', 'Z', JCC, 0x75, 2, 'J', 'O', JCC, 0x70, 2, 'J', 'P', JCC, 0x7A, 3, 'J', 'P', 'E', JCC, 0x7A, 3, 'J', 'P', 'O', JCC, 0x7B, 2, 'J', 'S', JCC, 0x78, 2, 'J', 'Z', JCC, 0x74, 4, 'L', 'A', 'H', 'F', INHER, 0x9F, 3, 'L', 'D', 'S', GvMp, 0xC5, 3, 'L', 'E', 'A', LEA, 0x8D, 5, 'L', 'E', 'A', 'V', 'E', INHER, 0xC9, 3, 'L', 'E', 'S', GvMp, 0xC4, 4, 'L', 'O', 'C', 'K', INHER, 0xF0, 4, 'L', 'O', 'D', 'B', INHER, 0xAC, 4, 'L', 'O', 'D', 'S', INHER, 0xAD, 5, 'L', 'O', 'D', 'S', 'B', INHER, 0xAC, 5, 'L', 'O', 'D', 'S', 'D', INHER32, 0xAD, 5, 'L', 'O', 'D', 'S', 'W', INHER16, 0xAD, 4, 'L', 'O', 'D', 'W', INHER16, 0xAD, 4, 'L', 'O', 'O', 'P', JCC, 0xE2, 5, 'L', 'O', 'O', 'P', 'E', JCC, 0xE1, 6, 'L', 'O', 'O', 'P', 'N', 'E', JCC, 0xE0, 6, 'L', 'O', 'O', 'P', 'N', 'Z', JCC, 0xE0, 5, 'L', 'O', 'O', 'P', 'Z', JCC, 0xE1, 3, 'M', 'O', 'V', MOV, 0x88, 4, 'M', 'O', 'V', 'S', INHER, MOVSW_OPCODE, 5, 'M', 'O', 'V', 'S', 'B', INHER, MOVSB_OPCODE, 5, 'M', 'O', 'V', 'S', 'D', INHER32, MOVSW_OPCODE, 5, 'M', 'O', 'V', 'S', 'W', INHER16, MOVSW_OPCODE, 4, 'M', 'O', 'V', 'W', INHER16, MOVSW_OPCODE, 3, 'M', 'U', 'L', DIVMUL, 0x20, 3, 'N', 'E', 'G', NEGNOT, 0x18, 3, 'N', 'O', 'P', INHER, 0x90, 3, 'N', 'O', 'T', NEGNOT, 0x10, 2, 'O', 'R', GROUP1, 0x08, 3, 'O', 'U', 'T', OUT, 0xEE, 4, 'O', 'U', 'T', 'S', INHER, 0x6F, 5, 'O', 'U', 'T', 'S', 'B', INHER, 0x6E, 5, 'O', 'U', 'T', 'S', 'D', INHER32, 0x6F, 5, 'O', 'U', 'T', 'S', 'W', INHER16, 0x6F, 4, 'O', 'U', 'T', 'W', OUT, 0xEF, 3, 'P', 'O', 'P', PUSHPOP, POP_OPCODE, 4, 'P', 'O', 'P', 'A', INHER16, 0x61, 5, 'P', 'O', 'P', 'A', 'D', INHER32, 0x61, 4, 'P', 'O', 'P', 'F', INHER16, 0x9D, 5, 'P', 'O', 'P', 'F', 'D', INHER32, 0x9D, 4, 'P', 'U', 'S', 'H', PUSHPOP, PUSH_OPCODE, 5, 'P', 'U', 'S', 'H', 'A', INHER16, 0x60, 6, 'P', 'U', 'S', 'H', 'A', 'D', INHER32, 0x60, 5, 'P', 'U', 'S', 'H', 'F', INHER16, 0x9C, 6, 'P', 'U', 'S', 'H', 'F', 'D', INHER32, 0x9C, 3, 'R', 'C', 'L', GROUP2, 0x10, 3, 'R', 'C', 'R', GROUP2, 0x18, 3, 'R', 'O', 'L', GROUP2, 0x00, 3, 'R', 'O', 'R', GROUP2, 0x08, 3, 'R', 'E', 'P', INHER, 0xF3, 4, 'R', 'E', 'P', 'E', INHER, 0xF3, 5, 'R', 'E', 'P', 'N', 'E', INHER, 0xF2, 5, 'R', 'E', 'P', 'N', 'Z', INHER, 0xF2, 4, 'R', 'E', 'P', 'Z', INHER, 0xF3, 3, 'R', 'E', 'T', RET, 0xC3, 4, 'R', 'E', 'T', 'F', RET, 0xCB, 4, 'R', 'E', 'T', 'I', RET, 0xCB, 4, 'S', 'A', 'H', 'F', INHER, 0x9E, 3, 'S', 'A', 'L', GROUP2, 0x20, 3, 'S', 'A', 'R', GROUP2, 0x38, 3, 'S', 'B', 'B', GROUP1, 0x18, 4, 'S', 'C', 'A', 'B', INHER, 0xAE, 4, 'S', 'C', 'A', 'S', INHER, 0xAF, 5, 'S', 'C', 'A', 'S', 'B', INHER, 0xAE, 5, 'S', 'C', 'A', 'S', 'D', INHER32, 0xAF, 5, 'S', 'C', 'A', 'S', 'W', INHER16, 0xAF, 4, 'S', 'C', 'A', 'W', INHER16, 0xAF, 3, 'S', 'E', 'G', SEG, 0x06, 3, 'S', 'H', 'L', GROUP2, 0x20, 3, 'S', 'H', 'R', GROUP2, 0x28, 4, 'S', 'S', 'E', 'G', INHER, 0x36, 3, 'S', 'T', 'C', INHER, 0xF9, 3, 'S', 'T', 'D', INHER, 0xFD, 3, 'S', 'T', 'I', INHER, 0xFB, 4, 'S', 'T', 'O', 'B', INHER, 0xAA, 4, 'S', 'T', 'O', 'S', INHER, 0xAB, 5, 'S', 'T', 'O', 'S', 'B', INHER, 0xAA, 5, 'S', 'T', 'O', 'S', 'D', INHER32, 0xAB, 5, 'S', 'T', 'O', 'S', 'W', INHER16, 0xAB, 4, 'S', 'T', 'O', 'W', INHER16, 0xAB, 3, 'S', 'U', 'B', GROUP1, 0x28, 4, 'T', 'E', 'S', 'T', TEST, 0x84, 4, 'W', 'A', 'I', 'T', INHER, WAIT_OPCODE, 4, 'X', 'C', 'H', 'G', XCHG, 0x86, 4, 'X', 'L', 'A', 'T', INHER, 0xD7, 5, 'X', 'L', 'A', 'T', 'B', INHER, 0xD7, 3, 'X', 'O', 'R', GROUP1, 0x30, /* floating point */ 5, 'F', '2', 'X', 'M', '1', F_INHER, 0x70, 4, 'F', 'A', 'B', 'S', F_INHER, 0x61, 4, 'F', 'A', 'D', 'D', F_M4_M8_STST, 0x00, 5, 'F', 'A', 'D', 'D', 'P', F_STST, 0x60, 4, 'F', 'B', 'L', 'D', F_M10, 0x74, 5, 'F', 'B', 'S', 'T', 'P', F_M10, 0x76, 4, 'F', 'C', 'H', 'S', F_INHER, 0x60, 5, 'F', 'C', 'L', 'E', 'X', F_W_INHER, 0xE2, 4, 'F', 'C', 'O', 'M', F_M4_M8_OPTST, 0x02, 5, 'F', 'C', 'O', 'M', 'P', F_M4_M8_OPTST, 0x03, 6, 'F', 'C', 'O', 'M', 'P', 'P', F_INHER, 0x19, 4, 'F', 'C', 'O', 'S', F_INHER, 0x7F, 7, 'F', 'D', 'E', 'C', 'S', 'T', 'P', F_INHER, 0x76, 5, 'F', 'D', 'I', 'S', 'I', F_W_INHER, 0xE1, 4, 'F', 'D', 'I', 'V', F_M4_M8_STST, 0x06, 5, 'F', 'D', 'I', 'V', 'P', F_STST, 0x67, 5, 'F', 'D', 'I', 'V', 'R', F_M4_M8_STST, 0x07, 6, 'F', 'D', 'I', 'V', 'R', 'P', F_STST, 0x66, 4, 'F', 'E', 'N', 'I', F_W_INHER, 0xE0, 5, 'F', 'F', 'R', 'E', 'E', F_ST, 0x50, 5, 'F', 'I', 'A', 'D', 'D', F_M2_M4, 0x20, 5, 'F', 'I', 'C', 'O', 'M', F_M2_M4, 0x22, 6, 'F', 'I', 'C', 'O', 'M', 'P', F_M2_M4, 0x23, 5, 'F', 'I', 'D', 'I', 'V', F_M2_M4, 0x26, 6, 'F', 'I', 'D', 'I', 'V', 'R', F_M2_M4, 0x27, 4, 'F', 'I', 'L', 'D', F_M2_M4_M8, 0x30, 5, 'F', 'I', 'M', 'U', 'L', F_M2_M4, 0x21, 7, 'F', 'I', 'N', 'C', 'S', 'T', 'P', F_INHER, 0x77, 5, 'F', 'I', 'N', 'I', 'T', F_W_INHER, 0xE3, 4, 'F', 'I', 'S', 'T', F_M2_M4, 0x32, 5, 'F', 'I', 'S', 'T', 'P', F_M2_M4_M8, 0x33, 5, 'F', 'I', 'S', 'U', 'B', F_M2_M4, 0x24, 6, 'F', 'I', 'S', 'U', 'B', 'R', F_M2_M4, 0x25, 3, 'F', 'L', 'D', F_M4_M8_M10_ST, 0x10, 4, 'F', 'L', 'D', '1', F_INHER, 0x68, 6, 'F', 'L', 'D', 'L', '2', 'E', F_INHER, 0x6A, 6, 'F', 'L', 'D', 'L', '2', 'T', F_INHER, 0x69, 5, 'F', 'L', 'D', 'C', 'W', F_M2, 0x15, 6, 'F', 'L', 'D', 'E', 'N', 'V', F_M, 0x14, 6, 'F', 'L', 'D', 'L', 'G', '2', F_INHER, 0x6C, 6, 'F', 'L', 'D', 'L', 'N', '2', F_INHER, 0x6D, 5, 'F', 'L', 'D', 'P', 'I', F_INHER, 0x6B, 4, 'F', 'L', 'D', 'Z', F_INHER, 0x6E, 4, 'F', 'M', 'U', 'L', F_M4_M8_STST, 0x01, 5, 'F', 'M', 'U', 'L', 'P', F_STST, 0x61, 6, 'F', 'N', 'C', 'L', 'E', 'X', F_INHER, 0xE2, 6, 'F', 'N', 'D', 'I', 'S', 'I', F_INHER, 0xE1, 5, 'F', 'N', 'E', 'N', 'I', F_INHER, 0xE0, 6, 'F', 'N', 'I', 'N', 'I', 'T', F_INHER, 0xE3, 4, 'F', 'N', 'O', 'P', F_INHER, 0x50, 6, 'F', 'N', 'S', 'A', 'V', 'E', F_M, 0x56, 6, 'F', 'N', 'S', 'T', 'C', 'W', F_M2, 0x17, 7, 'F', 'N', 'S', 'T', 'E', 'N', 'V', F_M, 0x16, 6, 'F', 'N', 'S', 'T', 'S', 'W', F_M2_AX, 0x57, 6, 'F', 'P', 'A', 'T', 'A', 'N', F_INHER, 0x73, 5, 'F', 'P', 'R', 'E', 'M', F_INHER, 0x78, 6, 'F', 'P', 'R', 'E', 'M', '1', F_INHER, 0x75, 5, 'F', 'P', 'T', 'A', 'N', F_INHER, 0x72, 7, 'F', 'R', 'N', 'D', 'I', 'N', 'T', F_INHER, 0x7C, 6, 'F', 'R', 'S', 'T', 'O', 'R', F_M, 0x54, 5, 'F', 'S', 'A', 'V', 'E', F_W_M, 0x56, 6, 'F', 'S', 'C', 'A', 'L', 'E', F_INHER, 0x7D, 6, 'F', 'S', 'E', 'T', 'P', 'M', F_INHER, 0xE4, 4, 'F', 'S', 'I', 'N', F_INHER, 0x7E, 7, 'F', 'S', 'I', 'N', 'C', 'O', 'S', F_INHER, 0x7B, 5, 'F', 'S', 'Q', 'R', 'T', F_INHER, 0x7A, 3, 'F', 'S', 'T', F_M4_M8_ST, FST_ENCODED, 5, 'F', 'S', 'T', 'C', 'W', F_W_M2, 0x17, 6, 'F', 'S', 'T', 'E', 'N', 'V', F_W_M, 0x16, 4, 'F', 'S', 'T', 'P', F_M4_M8_M10_ST, FSTP_ENCODED, 5, 'F', 'S', 'T', 'S', 'W', F_W_M2_AX, 0x57, 4, 'F', 'S', 'U', 'B', F_M4_M8_STST, 0x04, 5, 'F', 'S', 'U', 'B', 'P', F_STST, 0x65, 5, 'F', 'S', 'U', 'B', 'R', F_M4_M8_STST, 0x05, 6, 'F', 'S', 'U', 'B', 'R', 'P', F_STST, 0x64, 4, 'F', 'T', 'S', 'T', F_INHER, 0x64, 5, 'F', 'U', 'C', 'O', 'M', F_OPTST, 0x54, 6, 'F', 'U', 'C', 'O', 'M', 'P', F_OPTST, 0x55, 7, 'F', 'U', 'C', 'O', 'M', 'P', 'P', F_INHER, 0xA9, 5, 'F', 'W', 'A', 'I', 'T', INHER, WAIT_OPCODE, 4, 'F', 'X', 'A', 'M', F_INHER, 0x65, 4, 'F', 'X', 'C', 'H', F_OPTST, 0x11, 7, 'F', 'X', 'T', 'R', 'A', 'C', 'T', F_INHER, 0x74, 5, 'F', 'Y', 'L', '2', 'X', F_INHER, 0x71, 7, 'F', 'Y', 'L', '2', 'X', 'P', '1', F_INHER, 0x79, #endif /* I80386 */ #ifdef MC6809 3, 'A', 'B', 'X', INHER, 0x3A, 4, 'A', 'D', 'C', 'A', ALL, 0x89, 4, 'A', 'D', 'C', 'B', ALL, 0xC9, 4, 'A', 'D', 'D', 'A', ALL, 0x8B, 4, 'A', 'D', 'D', 'B', ALL, 0xCB, 4, 'A', 'D', 'D', 'D', ALL, 0xC3, 4, 'A', 'N', 'D', 'A', ALL, 0x84, 4, 'A', 'N', 'D', 'B', ALL, 0xC4, 5, 'A', 'N', 'D', 'C', 'C', IMMED, 0x1C, 3, 'A', 'S', 'L', ALTER, 0x08, 4, 'A', 'S', 'L', 'A', INHER, 0x48, 4, 'A', 'S', 'L', 'B', INHER, 0x58, 3, 'A', 'S', 'R', ALTER, 0x07, 4, 'A', 'S', 'R', 'A', INHER, 0x47, 4, 'A', 'S', 'R', 'B', INHER, 0x57, 3, 'B', 'C', 'C', SHORT, 0x24, 3, 'B', 'C', 'S', SHORT, 0x25, 3, 'B', 'E', 'Q', SHORT, 0x27, 3, 'B', 'G', 'E', SHORT, 0x2C, 3, 'B', 'G', 'T', SHORT, 0x2E, 3, 'B', 'H', 'I', SHORT, 0x22, 3, 'B', 'H', 'S', SHORT, 0x24, 4, 'B', 'I', 'T', 'A', ALL, 0X85, 4, 'B', 'I', 'T', 'B', ALL, 0XC5, 3, 'B', 'L', 'E', SHORT, 0x2F, 3, 'B', 'L', 'O', SHORT, 0x25, 3, 'B', 'L', 'S', SHORT, 0x23, 3, 'B', 'L', 'T', SHORT, 0x2D, 3, 'B', 'M', 'I', SHORT, 0x2B, 3, 'B', 'N', 'E', SHORT, 0x26, 3, 'B', 'P', 'L', SHORT, 0x2A, 3, 'B', 'R', 'A', SHORT, 0x20, 4, 'L', 'B', 'R', 'A', LONG, 0x16, 3, 'B', 'R', 'N', SHORT, 0x21, 3, 'B', 'S', 'R', SHORT, 0x8D, 4, 'L', 'B', 'S', 'R', LONG, 0x17, 3, 'B', 'V', 'C', SHORT, 0x28, 3, 'B', 'V', 'S', SHORT, 0x29, 3, 'C', 'L', 'R', ALTER, 0x0F, 4, 'C', 'L', 'R', 'A', INHER, 0x4F, 4, 'C', 'L', 'R', 'B', INHER, 0x5F, 4, 'C', 'M', 'P', 'A', ALL, 0x81, 4, 'C', 'M', 'P', 'B', ALL, 0xC1, 4, 'C', 'M', 'P', 'X', ALL, 0x8C, 3, 'C', 'O', 'M', ALTER, 0x03, 4, 'C', 'O', 'M', 'A', INHER, 0x43, 4, 'C', 'O', 'M', 'B', INHER, 0x53, 4, 'C', 'W', 'A', 'I', IMMED, 0x3C, 3, 'D', 'A', 'A', INHER, 0x19, 3, 'D', 'E', 'C', ALTER, 0x0A, 4, 'D', 'E', 'C', 'A', INHER, 0x4A, 4, 'D', 'E', 'C', 'B', INHER, 0x5A, 4, 'E', 'O', 'R', 'A', ALL, 0x88, 4, 'E', 'O', 'R', 'B', ALL, 0xC8, 3, 'E', 'X', 'G', SWAP, 0x1E, 3, 'I', 'N', 'C', ALTER, 0x0C, 4, 'I', 'N', 'C', 'A', INHER, 0x4C, 4, 'I', 'N', 'C', 'B', INHER, 0x5C, 3, 'J', 'M', 'P', ALTER, 0x0E, 3, 'J', 'S', 'R', ALTER, 0x8D, 3, 'L', 'D', 'A', ALL, 0x86, 3, 'L', 'D', 'B', ALL, 0xC6, 3, 'L', 'D', 'D', ALL, 0xCC, 3, 'L', 'D', 'U', ALL, 0xCE, 3, 'L', 'D', 'X', ALL, 0x8E, 4, 'L', 'E', 'A', 'S', INDEXD, 0x32, 4, 'L', 'E', 'A', 'U', INDEXD, 0x33, 4, 'L', 'E', 'A', 'X', INDEXD, 0x30, 4, 'L', 'E', 'A', 'Y', INDEXD, 0x31, 3, 'L', 'S', 'L', ALTER, 0x08, 4, 'L', 'S', 'L', 'A', INHER, 0x48, 4, 'L', 'S', 'L', 'B', INHER, 0x58, 3, 'L', 'S', 'R', ALTER, 0x04, 4, 'L', 'S', 'R', 'A', INHER, 0x44, 4, 'L', 'S', 'R', 'B', INHER, 0x54, 3, 'M', 'U', 'L', INHER, 0x3D, 3, 'N', 'E', 'G', ALTER, 0x00, 4, 'N', 'E', 'G', 'A', INHER, 0x40, 4, 'N', 'E', 'G', 'B', INHER, 0x50, 3, 'N', 'O', 'P', INHER, 0x12, 3, 'O', 'R', 'A', ALL, 0x8A, 3, 'O', 'R', 'B', ALL, 0xCA, 4, 'O', 'R', 'C', 'C', IMMED, 0x1A, 4, 'P', 'S', 'H', 'S', SSTAK, 0x34, 4, 'P', 'S', 'H', 'U', USTAK, 0x36, 4, 'P', 'U', 'L', 'S', SSTAK, 0x35, 4, 'P', 'U', 'L', 'U', USTAK, 0x37, 3, 'R', 'O', 'L', ALTER, 0x09, 4, 'R', 'O', 'L', 'A', INHER, 0x49, 4, 'R', 'O', 'L', 'B', INHER, 0x59, 3, 'R', 'O', 'R', ALTER, 0x06, 4, 'R', 'O', 'R', 'A', INHER, 0x46, 4, 'R', 'O', 'R', 'B', INHER, 0x56, 3, 'R', 'T', 'I', INHER, 0x3B, 3, 'R', 'T', 'S', INHER, 0x39, 4, 'S', 'B', 'C', 'A', ALL, 0x82, 4, 'S', 'B', 'C', 'B', ALL, 0xC2, 3, 'S', 'E', 'X', INHER, 0x1D, 3, 'S', 'T', 'A', ALTER, 0x87, 3, 'S', 'T', 'B', ALTER, 0xC7, 3, 'S', 'T', 'D', ALTER, 0xCD, 3, 'S', 'T', 'U', ALTER, 0xCF, 3, 'S', 'T', 'X', ALTER, 0x8F, 4, 'S', 'U', 'B', 'A', ALL, 0x80, 4, 'S', 'U', 'B', 'B', ALL, 0xC0, 4, 'S', 'U', 'B', 'D', ALL, 0x83, 3, 'S', 'W', 'I', INHER, 0x3F, 4, 'S', 'Y', 'N', 'C', INHER, 0x13, 3, 'T', 'F', 'R', SWAP, 0x1F, 3, 'T', 'S', 'T', ALTER, 0x0D, 4, 'T', 'S', 'T', 'A', INHER, 0x4D, 4, 'T', 'S', 'T', 'B', INHER, 0x5D, #endif /* MC6809 */ 0 /* end of ops */ }; PUBLIC char page1ops[] = { #ifdef I80386 3, 'B', 'S', 'F', GvEv, 0xBC, 3, 'B', 'S', 'R', GvEv, 0xBD, 5, 'B', 'S', 'W', 'A', 'P', BSWAP, 0xC8, 2, 'B', 'T', GROUP8, 0x20, 3, 'B', 'T', 'C', GROUP8, 0x38, 3, 'B', 'T', 'R', GROUP8, 0x30, 3, 'B', 'T', 'S', GROUP8, 0x28, 4, 'C', 'L', 'T', 'S', INHER, 0x06, 7, 'C', 'M', 'P', 'X', 'C', 'H', 'G', ExGx, 0xA6, 4, 'I', 'N', 'V', 'D', INHER, 0x08, 6, 'I', 'N', 'V', 'L', 'P', 'G', GROUP7, 0x38, 3, 'L', 'A', 'R', GvEv, 0x02, 3, 'L', 'F', 'S', GvMp, 0xB4, 4, 'L', 'G', 'D', 'T', GROUP7, 0x10, 3, 'L', 'G', 'S', GvMp, 0xB5, 4, 'L', 'I', 'D', 'T', GROUP7, 0x18, 4, 'L', 'L', 'D', 'T', GROUP6, 0x10, 4, 'L', 'M', 'S', 'W', GROUP7, 0x30, 3, 'L', 'S', 'L', GvEv, 0x03, 3, 'L', 'S', 'S', GvMp, 0xB2, 3, 'L', 'T', 'R', GROUP6, 0x18, 5, 'M', 'O', 'V', 'S', 'X', MOVX, 0xBE, 5, 'M', 'O', 'V', 'Z', 'X', MOVX, 0xB6, 5, 'R', 'D', 'M', 'S', 'R', INHER, 0x32, 4, 'S', 'E', 'T', 'A', SETCC, 0x97, 5, 'S', 'E', 'T', 'A', 'E', SETCC, 0x93, 4, 'S', 'E', 'T', 'B', SETCC, 0x92, 5, 'S', 'E', 'T', 'B', 'E', SETCC, 0x96, 4, 'S', 'E', 'T', 'C', SETCC, 0x92, 4, 'S', 'E', 'T', 'E', SETCC, 0x94, 4, 'S', 'E', 'T', 'G', SETCC, 0x9F, 5, 'S', 'E', 'T', 'G', 'E', SETCC, 0x9D, 4, 'S', 'E', 'T', 'L', SETCC, 0x9C, 5, 'S', 'E', 'T', 'L', 'E', SETCC, 0x9E, 5, 'S', 'E', 'T', 'N', 'A', SETCC, 0x96, 6, 'S', 'E', 'T', 'N', 'A', 'E', SETCC, 0x92, 5, 'S', 'E', 'T', 'N', 'B', SETCC, 0x93, 6, 'S', 'E', 'T', 'N', 'B', 'E', SETCC, 0x97, 5, 'S', 'E', 'T', 'N', 'C', SETCC, 0x93, 5, 'S', 'E', 'T', 'N', 'E', SETCC, 0x95, 5, 'S', 'E', 'T', 'N', 'G', SETCC, 0x9E, 6, 'S', 'E', 'T', 'N', 'G', 'E', SETCC, 0x9C, 5, 'S', 'E', 'T', 'N', 'L', SETCC, 0x9D, 6, 'S', 'E', 'T', 'N', 'L', 'E', SETCC, 0x9F, 5, 'S', 'E', 'T', 'N', 'O', SETCC, 0x91, 5, 'S', 'E', 'T', 'N', 'P', SETCC, 0x9B, 5, 'S', 'E', 'T', 'N', 'S', SETCC, 0x99, 5, 'S', 'E', 'T', 'N', 'Z', SETCC, 0x95, 4, 'S', 'E', 'T', 'O', SETCC, 0x90, 4, 'S', 'E', 'T', 'P', SETCC, 0x9A, 5, 'S', 'E', 'T', 'P', 'E', SETCC, 0x9A, 5, 'S', 'E', 'T', 'P', 'O', SETCC, 0x9B, 4, 'S', 'E', 'T', 'S', SETCC, 0x98, 4, 'S', 'E', 'T', 'Z', SETCC, 0x94, 4, 'S', 'G', 'D', 'T', GROUP7, 0x00, 4, 'S', 'I', 'D', 'T', GROUP7, 0x08, 4, 'S', 'H', 'L', 'D', SH_DOUBLE, 0xA4, 4, 'S', 'H', 'R', 'D', SH_DOUBLE, 0xAC, 4, 'S', 'L', 'D', 'T', GROUP6, 0x00, 4, 'S', 'M', 'S', 'W', GROUP7, 0x20, 3, 'S', 'T', 'R', GROUP6, 0x08, 4, 'V', 'E', 'R', 'R', GROUP6, 0x20, 4, 'V', 'E', 'R', 'W', GROUP6, 0x28, 6, 'W', 'B', 'I', 'N', 'V', 'D', INHER, 0x09, 5, 'W', 'R', 'M', 'S', 'R', INHER, 0x30, 4, 'X', 'A', 'D', 'D', ExGx, 0xC0, #endif /* I80386 */ #ifdef MC6809 4, 'L', 'B', 'C', 'C', LONG, 0x24, 4, 'L', 'B', 'C', 'S', LONG, 0x25, 4, 'L', 'B', 'E', 'Q', LONG, 0x27, 4, 'L', 'B', 'G', 'E', LONG, 0x2C, 4, 'L', 'B', 'G', 'T', LONG, 0x2E, 4, 'L', 'B', 'H', 'I', LONG, 0x22, 4, 'L', 'B', 'H', 'S', LONG, 0x24, 4, 'L', 'B', 'L', 'E', LONG, 0x2F, 4, 'L', 'B', 'L', 'O', LONG, 0x25, 4, 'L', 'B', 'L', 'S', LONG, 0x23, 4, 'L', 'B', 'L', 'T', LONG, 0x2D, 4, 'L', 'B', 'M', 'I', LONG, 0x2B, 4, 'L', 'B', 'N', 'E', LONG, 0x26, 4, 'L', 'B', 'P', 'L', LONG, 0x2A, 4, 'L', 'B', 'R', 'N', LONG, 0x21, 4, 'L', 'B', 'V', 'C', LONG, 0x28, 4, 'L', 'B', 'V', 'S', LONG, 0x29, 4, 'C', 'M', 'P', 'D', ALL, 0x83, 4, 'C', 'M', 'P', 'Y', ALL, 0x8C, 3, 'L', 'D', 'S', ALL, 0xCE, 3, 'L', 'D', 'Y', ALL, 0x8E, 3, 'S', 'T', 'S', ALTER, 0xCF, 3, 'S', 'T', 'Y', ALTER, 0x8F, 4, 'S', 'W', 'I', '2', INHER, 0x3F, #endif /* MC6809 */ 0 /* end of page 1 ops */ }; PUBLIC char page2ops[] = { #ifdef MC6809 4, 'C', 'M', 'P', 'S', ALL, 0x8C, 4, 'C', 'M', 'P', 'U', ALL, 0x83, 4, 'S', 'W', 'I', '3', INHER, 0x3F, #endif 0 /* end of page 2 ops */ }; #ifdef I80386 # ifdef MNSIZE PUBLIC char bytesizeops[] = { 4, 'A', 'D', 'C', 'B', GROUP1, 0x10, 4, 'A', 'D', 'D', 'B', GROUP1, 0x00, 4, 'A', 'N', 'D', 'B', GROUP1, 0x20, 4, 'C', 'M', 'P', 'B', GROUP1, CMP_OPCODE_BASE, 4, 'D', 'E', 'C', 'B', INCDEC, 0x08, 4, 'D', 'I', 'V', 'B', DIVMUL, 0x30, 5, 'I', 'D', 'I', 'V', 'B', DIVMUL, 0x38, 5, 'I', 'M', 'U', 'L', 'B', IMUL, 0x28, 3, 'I', 'N', 'B', IN, 0xEC, 4, 'I', 'N', 'C', 'B', INCDEC, 0x00, 4, 'M', 'O', 'V', 'B', MOV, 0x88, 4, 'M', 'U', 'L', 'B', DIVMUL, 0x20, 4, 'N', 'E', 'G', 'B', NEGNOT, 0x18, 4, 'N', 'O', 'T', 'B', NEGNOT, 0x10, 3, 'O', 'R', 'B', GROUP1, 0x08, 4, 'O', 'U', 'T', 'B', OUT, 0xEE, 4, 'R', 'C', 'L', 'B', GROUP2, 0x10, 4, 'R', 'C', 'R', 'B', GROUP2, 0x18, 4, 'R', 'O', 'L', 'B', GROUP2, 0x00, 4, 'R', 'O', 'R', 'B', GROUP2, 0x08, 4, 'S', 'A', 'L', 'B', GROUP2, 0x20, 4, 'S', 'A', 'R', 'B', GROUP2, 0x38, 4, 'S', 'H', 'L', 'B', GROUP2, 0x20, 4, 'S', 'H', 'R', 'B', GROUP2, 0x28, 4, 'S', 'B', 'B', 'B', GROUP1, 0x18, 4, 'S', 'U', 'B', 'B', GROUP1, 0x28, 5, 'T', 'E', 'S', 'T', 'B', TEST, 0x84, 5, 'X', 'C', 'H', 'G', 'B', XCHG, 0x86, 4, 'X', 'O', 'R', 'B', GROUP1, 0x30, 0 /* end of byte size ops */ }; # endif /* MNSIZE */ #endif /* I80386 */ /* --- end of keywords --- */ dev86-0.16.21/as/macro.c000066400000000000000000000076231231050321700144670ustar00rootroot00000000000000/* macro.c - expand macros for assembler */ #include "syshead.h" #include "const.h" #include "type.h" #include "globvar.h" #include "scan.h" #undef EXTERN #define EXTERN #include "macro.h" /* Enter macro: stack macro and get its parameters. Parameters form a linked list of null-terminated strings of form next:string. The first string is the macro number in 4 bytes. */ PUBLIC void entermac(symptr) struct sym_s *symptr; { if (maclevel >= MAXMAC) error(MACOV); else if (macpar + 2 > macptop) error(PAROV); /* no room for 0th param */ /* (2 structs to fit it!) */ else { char ch; struct schain_s *param1; register char *reglineptr; register char *stringptr; ++maclevel; (--macstak)->text = (char *) symptr->value_reg_or_op.value; macstak->parameters = param1 = macpar; param1->next = NUL_PTR; *(stringptr = build_number(++macnum, 3, param1->string)) = 0; macpar = (struct schain_s *) (stringptr + 1); /* TODO: alignment */ getsym(); if (sym == EOLSYM) return; /* no other params */ if (sym != LPAREN) reglineptr = symname; else reglineptr = lineptr; stringptr = macpar->string; while (TRUE) { if (stringptr >= (char *) macptop) { symname = reglineptr; error(PAROV); return; } ch = *reglineptr++; if (ch == '\\') /* escaped means no special meaning for slash, comma, paren */ ch = *reglineptr++; else if (ch == ',' || ch == ')' || ch == '!' || ch == ';' || ch == '\n' || ch == 0) { if (stringptr >= (char *) macptop) { symname = reglineptr; error(PAROV); /* no room for null */ return; } *stringptr = 0; param1->next = macpar; /* ptr from previous */ (param1 = macpar)->next = NUL_PTR; /* this goes nowhere */ macpar = (struct schain_s *) (stringptr + 1); /* but is finished OK - TODO align */ stringptr = macpar->string; if (ch != ',') return; continue; } if ((*stringptr++ = ch) == 0) { symname = reglineptr; error(RPEXP); return; } } } } /* MACRO pseudo-op */ PUBLIC void pmacro() { bool_t saving; bool_t savingc; struct sym_s *symptr=0; int maclen = 8; int macoff = 0; char * macbuf = asalloc(8); saving = /* prepare for bad macro */ savingc = FALSE; /* normally don't save comments */ macload = TRUE; /* show loading */ if (label != NUL_PTR) error(ILLAB); else if (sym != IDENT) error(LABEXP); else { symptr = gsymptr; if (symptr->type & MNREGBIT) error(LABEXP); else if (symptr->type & LABIT || symptr->data & FORBIT) error(RELAB); else if (pass != last_pass || symptr->type & REDBIT) /* copy on pass 0, also pass 1 if redefined */ { saving = TRUE; if (symptr->type & MACBIT) symptr->type |= REDBIT; else symptr->type |= MACBIT; symptr->data = UNDBIT; /* undefined till end */ symptr->value_reg_or_op.value = (offset_t) macbuf; getsym_nolookup(); /* test for "C" */ if (sym == IDENT && lineptr == symname + 1 && *symname == 'C') savingc = TRUE; } } while (TRUE) { skipline(); listline(); readline(); if (!macload) break; /* macload cleared to show eof */ getsym_nolookup(); if (sym == IDENT) { if (lineptr == symname + 4 && ( strncmp(symname, "MEND", 4) == 0 || strncmp(symname, "mend", 4) == 0) ) { getsym(); break; } } else if (sym != MACROARG) { if (!savingc) continue; /* don't save comment */ } if (!saving) continue; { char * p = strchr(linebuf, EOLCHAR); int len = (p-linebuf+1); if ( macoff + len > maclen-4 ) { maclen = maclen * 2 + len; macbuf = asrealloc(macbuf, maclen); } memcpy(macbuf+macoff, linebuf, len); macoff += len; } } macload = FALSE; if (saving) { macbuf[macoff] = ETB; symptr->value_reg_or_op.value = (offset_t) macbuf; symptr->data = 0; } } dev86-0.16.21/as/macro.h000066400000000000000000000006671231050321700144750ustar00rootroot00000000000000/* macro.h - global variables for macro expansion for assembler */ EXTERN bool_t macflag; /* inside macro flag */ EXTERN bool_t macload; /* loading macro flag */ EXTERN unsigned macnum; /* macro call counter */ EXTERN unsigned char maclevel; /* nesting level */ EXTERN struct schain_s *macpar; /* parameter save buffer */ EXTERN struct schain_s *macptop; /* top of param buffer (+1) */ EXTERN struct macro_s *macstak; /* stack ptr */ dev86-0.16.21/as/mops.c000066400000000000000000001557661231050321700143600ustar00rootroot00000000000000/* mops.c - handle pseudo-ops */ #include "syshead.h" #include "const.h" #include "type.h" #include "globvar.h" #include "opcode.h" #include "scan.h" #undef EXTERN #define EXTERN #include "address.h" #define is8bitadr(offset) ((offset_t) offset < 0x100) #define is8bitsignedoffset(offset) ((offset_t) (offset) + 0x80 < 0x100) #define pass2 (pass==last_pass) FORWARD void mshort2 P((void)); FORWARD reg_pt regchk P((void)); FORWARD void reldata P((void)); FORWARD void segadj P((void)); #ifdef I80386 #define iswordadr(offset) ((offset_t) (offset) < 0x10000L) #define iswordoffset(offset) ((offset_t) (offset) + 0x8000L < 0x10000L) #define iswordorswordoffset(offset) ((offset_t) (offset) + 0xFFFFL < 0x1FFFEL) #define BYTE_SEGWORD 0x00 #define isspecreg(r) ((r) >= CR0REG && (r) <= TR7REG) #define BASE_MASK 0x07 #define BASE_SHIFT 0 #define INDEX_MASK 0x38 #define INDEX_SHIFT 3 #define MOD_MASK 0xC0 # define REG_MOD 0xC0 # define MEM0_MOD 0x00 # define MEM1_MOD 0x40 # define MEM2_MOD 0x80 #define REG_MASK 0x38 #define REG_SHIFT 3 #define RM_MASK 0x07 #define RM_SHIFT 0 # define D16_RM 0x06 # define D32_RM 0x05 # define SIB_NOBASE 0x05 # define SIB_RM 0x04 #define SREG_MASK 0x38 #define SREG_SHIFT 3 #define SS_MASK 0xC0 #define SS_SHIFT 6 #define SEGMOV 0x04 #define SIGNBIT 0x02 #define TOREGBIT 0x02 #define WORDBIT 0x01 PRIVATE opcode_t baseind16[] = { 0x00, /* BP + BP, illegal */ 0x00, /* BX + BP, illegal */ 0x03, /* DI + BP */ 0x02, /* SI + BP */ 0x00, /* BP + BX, illegal */ 0x00, /* BX + BX, illegal */ 0x01, /* DI + BX */ 0x00, /* SI + BX */ 0x03, /* BP + DI */ 0x01, /* BX + DI */ 0x00, /* DI + DI, illegal */ 0x00, /* SI + DI, illegal */ 0x02, /* BP + SI */ 0x00, /* BX + SI */ 0x00, /* DI + SI, illegal */ 0x00, /* SI + SI, illegal */ }; PRIVATE opcode_t regbits[] = { 0x05 << REG_SHIFT, /* BP */ 0x03 << REG_SHIFT, /* BX */ 0x07 << REG_SHIFT, /* DI */ 0x06 << REG_SHIFT, /* SI */ 0x00 << REG_SHIFT, /* EAX */ 0x05 << REG_SHIFT, /* EBP */ 0x03 << REG_SHIFT, /* EBX */ 0x01 << REG_SHIFT, /* ECX */ 0x07 << REG_SHIFT, /* EDI */ 0x02 << REG_SHIFT, /* EDX */ 0x06 << REG_SHIFT, /* ESI */ 0x04 << REG_SHIFT, /* ESP */ 0x00 << REG_SHIFT, /* AX */ 0x01 << REG_SHIFT, /* CX */ 0x02 << REG_SHIFT, /* DX */ 0x04 << REG_SHIFT, /* SP */ 0x04 << REG_SHIFT, /* AH */ 0x00 << REG_SHIFT, /* AL */ 0x07 << REG_SHIFT, /* BH */ 0x03 << REG_SHIFT, /* BL */ 0x05 << REG_SHIFT, /* CH */ 0x01 << REG_SHIFT, /* CL */ 0x06 << REG_SHIFT, /* DH */ 0x02 << REG_SHIFT, /* DL */ 0x01 << REG_SHIFT, /* CS */ 0x03 << REG_SHIFT, /* DS */ 0x00 << REG_SHIFT, /* ES */ 0x04 << REG_SHIFT, /* FS */ 0x05 << REG_SHIFT, /* GS */ 0x02 << REG_SHIFT, /* SS */ 0x00 << REG_SHIFT, /* CR0 */ 0x02 << REG_SHIFT, /* CR2 */ 0x03 << REG_SHIFT, /* CR3 */ 0x00 << REG_SHIFT, /* DR0 */ 0x01 << REG_SHIFT, /* DR1 */ 0x02 << REG_SHIFT, /* DR2 */ 0x03 << REG_SHIFT, /* DR3 */ 0x06 << REG_SHIFT, /* DR6 */ 0x07 << REG_SHIFT, /* DR7 */ 0x03 << REG_SHIFT, /* TR3 */ 0x04 << REG_SHIFT, /* TR4 */ 0x05 << REG_SHIFT, /* TR5 */ 0x06 << REG_SHIFT, /* TR6 */ 0x07 << REG_SHIFT, /* TR7 */ 0x00 << REG_SHIFT, /* ST(0) */ 0x01 << REG_SHIFT, /* ST(1) */ 0x02 << REG_SHIFT, /* ST(2) */ 0x03 << REG_SHIFT, /* ST(3) */ 0x04 << REG_SHIFT, /* ST(4) */ 0x05 << REG_SHIFT, /* ST(5) */ 0x06 << REG_SHIFT, /* ST(6) */ 0x07 << REG_SHIFT, /* ST(7) */ }; PRIVATE opsize_t regsize[] = { 2, /* BP */ 2, /* BX */ 2, /* DI */ 2, /* SI */ 4, /* EAX */ 4, /* EBP */ 4, /* EBX */ 4, /* ECX */ 4, /* EDI */ 4, /* EDX */ 4, /* ESI */ 4, /* ESP */ 2, /* AX */ 2, /* CX */ 2, /* DX */ 2, /* SP */ 1, /* AH */ 1, /* AL */ 1, /* BH */ 1, /* BL */ 1, /* CH */ 1, /* CL */ 1, /* DH */ 1, /* DL */ 2, /* CS */ 2, /* DS */ 2, /* ES */ 2, /* FS */ 2, /* GS */ 2, /* SS */ 4, /* CR0 */ 4, /* CR2 */ 4, /* CR3 */ 4, /* DR0 */ 4, /* DR1 */ 4, /* DR2 */ 4, /* DR3 */ 4, /* DR6 */ 4, /* DR7 */ 4, /* TR3 */ 4, /* TR4 */ 4, /* TR5 */ 4, /* TR6 */ 4, /* TR7 */ 10, /* ST(0) */ 10, /* ST(1) */ 10, /* ST(2) */ 10, /* ST(3) */ 10, /* ST(4) */ 10, /* ST(5) */ 10, /* ST(6) */ 10, /* ST(7) */ 0, /* NOREG */ }; PRIVATE opcode_t regsegword[] = { WORDBIT, /* BP */ WORDBIT, /* BX */ WORDBIT, /* DI */ WORDBIT, /* SI */ WORDBIT, /* EAX */ WORDBIT, /* EBP */ WORDBIT, /* EBX */ WORDBIT, /* ECX */ WORDBIT, /* EDI */ WORDBIT, /* EDX */ WORDBIT, /* ESI */ WORDBIT, /* ESP */ WORDBIT, /* AX */ WORDBIT, /* CX */ WORDBIT, /* DX */ WORDBIT, /* SP */ BYTE_SEGWORD, /* AH */ BYTE_SEGWORD, /* AL */ BYTE_SEGWORD, /* BH */ BYTE_SEGWORD, /* BL */ BYTE_SEGWORD, /* CH */ BYTE_SEGWORD, /* CL */ BYTE_SEGWORD, /* DH */ BYTE_SEGWORD, /* DL */ SEGMOV, /* CS */ SEGMOV, /* DS */ SEGMOV, /* ES */ SEGMOV, /* FS */ SEGMOV, /* GS */ SEGMOV, /* SS */ 0x20, /* CR0 */ 0x20, /* CR2 */ 0x20, /* CR3 */ 0x21, /* DR0 */ 0x21, /* DR1 */ 0x21, /* DR2 */ 0x21, /* DR3 */ 0x21, /* DR6 */ 0x21, /* DR7 */ 0x24, /* TR3 */ 0x24, /* TR4 */ 0x24, /* TR5 */ 0x24, /* TR6 */ 0x24, /* TR7 */ 0x00, /* ST(0) */ 0x00, /* ST(1) */ 0x00, /* ST(2) */ 0x00, /* ST(3) */ 0x00, /* ST(4) */ 0x00, /* ST(5) */ 0x00, /* ST(6) */ 0x00, /* ST(7) */ 0x00, /* NOREG */ }; PRIVATE opcode_t rm[] = { 0x05, /* BP */ 0x03, /* BX */ 0x07, /* DI */ 0x06, /* SI */ 0x00, /* EAX */ 0x05, /* EBP */ 0x03, /* EBX */ 0x01, /* ECX */ 0x07, /* EDI */ 0x02, /* EDX */ 0x06, /* ESI */ 0x04, /* ESP */ 0x00, /* AX */ 0x01, /* CX */ 0x02, /* DX */ 0x04, /* SP */ 0x04, /* AH */ 0x00, /* AL */ 0x07, /* BH */ 0x03, /* BL */ 0x05, /* CH */ 0x01, /* CL */ 0x06, /* DH */ 0x02, /* DL */ 0x01, /* CS */ 0x03, /* DS */ 0x00, /* ES */ 0x04, /* FS */ 0x05, /* GS */ 0x02, /* SS */ 0x00, /* CR0 */ 0x00, /* CR2 */ 0x00, /* CR3 */ 0x00, /* DR0 */ 0x00, /* DR1 */ 0x00, /* DR2 */ 0x00, /* DR3 */ 0x00, /* DR6 */ 0x00, /* DR7 */ 0x00, /* TR3 */ 0x00, /* TR4 */ 0x00, /* TR5 */ 0x00, /* TR6 */ 0x00, /* TR7 */ 0x00, /* ST(0) */ 0x00, /* ST(1) */ 0x00, /* ST(2) */ 0x00, /* ST(3) */ 0x00, /* ST(4) */ 0x00, /* ST(5) */ 0x00, /* ST(6) */ 0x00, /* ST(7) */ 0x04, /* null index reg for sib only */ }; PRIVATE opcode_t rmfunny[] = { 0x06, /* BP */ 0x07, /* BX */ 0x05, /* DI */ 0x04, /* SI */ }; PRIVATE opcode_t segoverride[] = { 0x2E, /* CS */ 0x3E, /* DS */ 0x26, /* ES */ 0x64, /* FS */ 0x65, /* GS */ 0x36, /* SS */ }; PRIVATE opcode_t ss[] = /* scale to ss bits */ { 0x00, /* x0, illegal */ 0x00 << SS_SHIFT, /* x1 */ 0x01 << SS_SHIFT, /* x2 */ 0x00, /* x3, illegal */ 0x02 << SS_SHIFT, /* x4 */ 0x00, /* x5, illegal */ 0x00, /* x6, illegal */ 0x00, /* x7, illegal */ 0x03 << SS_SHIFT, /* x8 */ }; PRIVATE unsigned char calljmp_kludge; PRIVATE opcode_t direction; PRIVATE bool_t fpreg_allowed; PRIVATE opcode_t segword; /* Values of segword: BYTE_SEGWORD for byte ea's. SEGMOV for segment registers opcode for special registers WORDBIT for other word and dword ea's */ PRIVATE struct ea_s source; PRIVATE struct ea_s source2; PRIVATE struct ea_s target; FORWARD void Eb P((struct ea_s *eap)); FORWARD void Ew P((struct ea_s *eap)); FORWARD void Ev P((struct ea_s *eap)); FORWARD void Ex P((struct ea_s *eap)); FORWARD void Gd P((struct ea_s *eap)); FORWARD void Gw P((struct ea_s *eap)); FORWARD void Gv P((struct ea_s *eap)); FORWARD void Gx P((struct ea_s *eap)); FORWARD void buildea P((struct ea_s *eap)); FORWARD void buildfloat P((void)); FORWARD void buildfreg P((void)); FORWARD void buildimm P((struct ea_s *eap, bool_pt signflag)); FORWARD void buildregular P((void)); FORWARD void buildsegword P((struct ea_s *eap)); FORWARD void buildunary P((opcode_pt opc)); FORWARD opsize_pt displsize P((struct ea_s *eap)); FORWARD reg_pt fpregchk P((void)); FORWARD bool_pt getaccumreg P((struct ea_s *eap)); FORWARD void getbinary P((void)); FORWARD bool_pt getdxreg P((struct ea_s *eap)); FORWARD void getea P((struct ea_s *eap)); FORWARD void getimmed P((struct ea_s *eap, count_t immed_count)); FORWARD void getindirect P((struct ea_s *eap)); FORWARD void getshift P((struct ea_s *eap)); FORWARD reg_pt indregchk P((reg_pt matchreg)); FORWARD void kgerror P((char * err_str)); FORWARD void lbranch P((int backamount)); FORWARD void notbytesize P((struct ea_s *eap)); FORWARD void notimmed P((struct ea_s *eap)); FORWARD void notindirect P((struct ea_s *eap)); FORWARD void notsegorspecreg P((struct ea_s *eap)); FORWARD void yesimmed P((struct ea_s *eap)); FORWARD void yes_samesize P((void)); PRIVATE void Eb(eap) register struct ea_s *eap; { Ex(eap); if (eap->size != 0x1) { #ifndef NODEFAULTSIZE if (eap->size == 0x0) eap->size = 0x1; else #endif kgerror(ILL_SIZE); } } PRIVATE void Ew(eap) register struct ea_s *eap; { Ex(eap); if (eap->size != 0x2) { #ifndef NODEFAULTSIZE if (eap->size == 0x0) eap->size = 0x2; else #endif kgerror(ILL_SIZE); } } PRIVATE void Ev(eap) register struct ea_s *eap; { Ex(eap); notbytesize(eap); } PRIVATE void Ex(eap) register struct ea_s *eap; { getea(eap); notimmed(eap); notsegorspecreg(eap); } PRIVATE void Gd(eap) register struct ea_s *eap; { Gx(eap); if (eap->size != 0x4) kgerror(ILL_SIZE); } PRIVATE void Gw(eap) register struct ea_s *eap; { Gx(eap); if (eap->size != 0x2) kgerror(ILL_SIZE); } PRIVATE void Gv(eap) register struct ea_s *eap; { Gx(eap); notbytesize(eap); } PRIVATE void Gx(eap) register struct ea_s *eap; { Ex(eap); notindirect(eap); } PRIVATE void buildea(eap) register struct ea_s *eap; { opsize_t asize; ++mcount; lastexp = eap->displ; if (eap->indcount == 0x0) postb = REG_MOD | rm[eap->base]; else { if (eap->base == NOREG) { if (eap->index == NOREG) { if ((asize = displsize(eap)) > 0x2) postb = D32_RM; else postb = D16_RM; } else { asize = 0x4; postb = SIB_NOBASE; /* for sib later */ } } else { if (eap->base > MAX16BITINDREG) { asize = 0x4; postb = rm[eap->base]; } else { asize = 0x2; if (!(lastexp.data & UNDBIT) && !iswordorswordoffset(lastexp.offset)) error(ABOUNDS); if (eap->index == NOREG) postb = rmfunny[eap->base]; else if (eap->base <= MAX16BITINDREG) postb = baseind16[eap->base + 0x4 * eap->index]; } } needcpu(asize==4?3:0); if (asize != defsize) aprefix = 0x67; if (eap->base == NOREG) mcount += asize; else if (lastexp.data & (FORBIT | RELBIT | UNDBIT) || !is8bitsignedoffset(lastexp.offset)) { postb |= MEM2_MOD; mcount += asize; } else if (lastexp.offset != 0x0 || (eap->base == BPREG && eap->index == NOREG) || eap->base == EBPREG) { postb |= MEM1_MOD; ++mcount; } if (asize > 0x2 && (eap->base == ESPREG || eap->index != NOREG)) { sib = ss[eap->scale] | (rm[eap->index] << INDEX_SHIFT) | (postb & RM_MASK); postb = (postb & MOD_MASK) | SIB_RM; ++mcount; } } } PRIVATE void buildfloat() { if (mcount != 0x0) { buildea(&source); oprefix = 0x0; postb |= (opcode & 0x07) << REG_SHIFT; opcode = ESCAPE_OPCODE_BASE | ((opcode & 0x70) >> 0x4); } } PRIVATE void buildfreg() { mcount += 0x2; oprefix = 0x0; postb = REG_MOD | ((opcode & 0x07) << REG_SHIFT) | (target.base - ST0REG); opcode = ESCAPE_OPCODE_BASE | ((opcode & 0x70) >> 0x4); } PRIVATE void buildimm(eap, signflag) register struct ea_s *eap; bool_pt signflag; { immadr = eap->displ; immcount = eap->size; if (!(immadr.data & (FORBIT | RELBIT | UNDBIT))) { if (immcount == 0x1) { if ((offset_t) (immadr.offset + 0x80) >= 0x180) datatoobig(); } else if (signflag && is8bitsignedoffset(immadr.offset)) { opcode |= SIGNBIT; immcount = 0x1; } else if (immcount == 0x2) { if ((offset_t) (immadr.offset + 0x8000L) >= 0x18000L) datatoobig(); } } } PRIVATE void buildregular() { if (mcount != 0x0) { buildea(&target); postb |= regbits[source.base]; } } /* Check size and build segword. */ PRIVATE void buildsegword(eap) register struct ea_s *eap; { if (eap->size == 0x0) #ifdef NODEFAULTSIZE kgerror(SIZE_UNK); #else eap->size = defsize; #endif if (eap->indcount != 0x0 || eap->base == NOREG) { segword = WORDBIT; if (eap->size == 0x1) segword = BYTE_SEGWORD; } else segword = regsegword[eap->base]; } PRIVATE void buildunary(opc) opcode_pt opc; { if (mcount != 0x0) { buildea(&target); postb |= opcode; opcode = opc; } } PRIVATE opsize_pt displsize(eap) register struct ea_s *eap; { opsize_t asize; asize = defsize; if (!(eap->displ.data & UNDBIT)) { if (asize > 0x2) { if (!(eap->displ.data & (FORBIT | RELBIT)) && iswordadr(eap->displ.offset)) asize = 0x2; } else if (!iswordorswordoffset(eap->displ.offset)) /* should really use iswordadr() */ /* but compiler generates signed offsets */ { if (!(eap->displ.data & (FORBIT | RELBIT))) asize = 0x4; else if (pass2) error(ABOUNDS); } } return asize; } PRIVATE reg_pt fpregchk() { reg_pt fpreg; fpreg_allowed = TRUE; fpreg = regchk(); fpreg_allowed = FALSE; if (fpreg != ST0REG) return NOREG; getsym(); if (sym == LPAREN) { getsym(); if (sym != INTCONST || (unsigned) number >= 0x8) error(ILL_FP_REG); else { fpreg += number; getsym(); if (sym != RPAREN) error(RPEXP); else getsym(); } } return fpreg; } PRIVATE bool_pt getaccumreg(eap) register struct ea_s *eap; { if ((eap->base = regchk()) != AXREG && eap->base != ALREG && eap->base != EAXREG) return FALSE; getsym(); if ((eap->size = regsize[eap->base]) > 0x1 && eap->size != defsize) oprefix = 0x66; return TRUE; } /* Get binary ea's in target & source (flipped if direction is set). Put size in source if not already. Initialise direction, segword, bump mcount. */ PRIVATE void getbinary() { ++mcount; getea(&target); if (target.indcount == 0x0 && target.base == NOREG) { error(ILL_IMM_MODE); target.base = AXREG; target.size = defsize; } getcomma(); getea(&source); if (source.size == 0x0) source.size = target.size; else if (target.size != 0x0 && target.size != source.size) { kgerror(MISMATCHED_SIZE); return; } if (source.indcount == 0x0 && regsegword[target.base] < SEGMOV) direction = 0x0; else if (target.indcount == 0x0 && regsegword[source.base] < SEGMOV) { struct ea_s swap; direction = TOREGBIT; swap = source; source = target; target = swap; } else if (target.indcount != 0x0) { kgerror(ILL_IND_TO_IND); return; } else { kgerror(ILL_SEG_REG); return; } buildsegword(&source); } PRIVATE bool_pt getdxreg(eap) register struct ea_s *eap; { if ((eap->base = regchk()) != DXREG) return FALSE; getsym(); return TRUE; } /* parse effective address */ /* Syntax is restrictive in that displacements must be in the right spots and will not be added up. optional size-type prefix, which is BYTE BYTE PTR WORD WORD PTR DWORD DWORD PTR PTR reg segreg [scaled index] where scaled index = indreg indreg*scale indreg+indreg indreg+indreg*scale [scaled index+displ] [scaled index-displ] optional-immediate-prefix displ[scaled index] [displ] optional-imediate-prefix displ (scaled index) -- anachronism optional-imediate-prefix displ(scaled index) -- anachronism */ PRIVATE void getea(eap) register struct ea_s *eap; { bool_t leading_displ; bool_t leading_immed; register struct sym_s *symptr; leading_immed = leading_displ = lastexp.data = eap->indcount = lastexp.offset = 0x0; eap->index = eap->base = NOREG; eap->scale = 0x1; eap->size = mnsize; /* 0x1 for byte ops, else 0x0 */ if (sym == IDENT) { if ((symptr = gsymptr)->type & MNREGBIT) { if (symptr->data & SIZEBIT) { getsym(); if (symptr->value_reg_or_op.op.opcode == 0x0) eap->indcount = 0x2 - calljmp_kludge; else { if (eap->size != 0x0) { if (eap->size != symptr->value_reg_or_op.op.opcode) error(MISMATCHED_SIZE); } else eap->size = symptr->value_reg_or_op.op.opcode; if (eap->size > 0x1 && eap->size != defsize) oprefix = 0x66; if (sym == IDENT && (symptr = gsymptr)->type & MNREGBIT && symptr->data & SIZEBIT && symptr->value_reg_or_op.op.routine == PTROP) { getsym(); eap->indcount = 0x2 - calljmp_kludge; } } } } if( last_pass == 1 ) if (!(symptr->type & (LABIT | MACBIT | MNREGBIT | VARBIT))) symptr->data |= FORBIT; /* show seen in advance */ } if ((eap->base = regchk()) != NOREG) { getsym(); if (eap->indcount != 0x0) { error(ILL_IND_PTR); eap->indcount = 0x0; } if (eap->size != 0x0 && eap->size != regsize[eap->base]) error(MISMATCHED_SIZE); if ((eap->size = regsize[eap->base]) > 0x1 && eap->size != defsize) oprefix = 0x66; eap->displ = lastexp; needcpu(eap->size==4?3:0); return; } if (sym != lindirect) { if (sym == IMMEDIATE || sym == STAR) { /* context-sensitive, STAR means signed immediate here */ leading_immed = TRUE; getsym(); } leading_displ = TRUE; expres(); eap->displ = lastexp; } if (sym == lindirect) { getsym(); eap->indcount = 0x2 - calljmp_kludge; if ((eap->base = indregchk((reg_pt) NOREG)) != NOREG) { if (eap->indcount == 0x0 && leading_displ) error(IND_REQ); getsym(); if (sym == ADDOP) { getsym(); if ((eap->index = indregchk(eap->base)) != NOREG) getsym(); else { if (eap->indcount == 0x0) error(IND_REQ); if (leading_displ) error(REPEATED_DISPL); expres(); /* this eats ADDOP, SUBOP, MULOP */ } } if (sym == STAR) { needcpu(3); /* context-sensitive, STAR means scaled here*/ if (eap->index == NOREG && eap->base == ESPREG) { error(INDEX_REG_EXP); eap->base = EAXREG; } getsym(); factor(); chkabs(); if (!(lastexp.data & UNDBIT) && lastexp.offset != 0x1) { if (eap->base <= MAX16BITINDREG || (lastexp.offset != 0x2 && lastexp.offset != 0x4 && lastexp.offset != 0x8)) error(ILL_SCALE); else { eap->scale = lastexp.offset; if (eap->index == NOREG) { eap->index = eap->base; eap->base = NOREG; } } } lastexp.data = lastexp.offset = 0x0; } if ((sym == ADDOP || sym == SUBOP)) { if (eap->indcount == 0x0) error(IND_REQ); if (leading_displ) error(REPEATED_DISPL); expres(); } } else { if (leading_displ) error(REPEATED_DISPL); expres(); } if (sym != rindirect) error(rindexp); else getsym(); } /* RDB */ else if (!leading_immed && defsize <= 0x2) eap->indcount = 0x1; /* compatibility kludge */ if (!leading_displ) eap->displ = lastexp; needcpu(eap->size==4?3:0); } PRIVATE void getimmed(eap, immed_count) struct ea_s *eap; count_t immed_count; { getea(eap); yesimmed(eap); if (mcount != 0x0) { eap->size = immed_count; buildimm(eap, FALSE); } } PRIVATE void getindirect(eap) register struct ea_s *eap; { getea(eap); if (eap->indcount == 0x0) kgerror(IND_REQ); } PRIVATE void getshift(eap) register struct ea_s *eap; { getcomma(); getea(eap); if (eap->base != CLREG) yesimmed(eap); } /* Check if current symbol is a compatible index register. Generate error if it is a reg but not a compatible index. Return register number (adjusted if necessary to a legal index) or NOREG. */ PRIVATE reg_pt indregchk(matchreg) reg_pt matchreg; { reg_pt reg; if ((reg = regchk()) != NOREG) { switch (matchreg) { case BPREG: case BXREG: if (reg != DIREG && reg != SIREG) { reg = SIREG; error(INDEX_REG_EXP); } break; case DIREG: case SIREG: if (reg != BPREG && reg != BXREG) { reg = BXREG; error(INDEX_REG_EXP); } break; case NOREG: break; default: if (reg <= MAX16BITINDREG || reg == ESPREG) { reg = EAXREG; error(INDEX_REG_EXP); } break; } if (reg > MAXINDREG && calljmp_kludge == 0x0) { if (matchreg != NOREG) reg = EAXREG; else reg = BXREG; error(INDEX_REG_EXP); } } return reg; } PRIVATE void kgerror(err_str) char * err_str; { error(err_str); sprefix = oprefix = aprefix = mcount = 0x0; } PRIVATE void lbranch(backamount) int backamount; { mcount += defsize + 0x1; segadj(); if (pass2) { reldata(); if (!(lastexp.data & (RELBIT | UNDBIT))) { lastexp.offset = lastexp.offset - lc - lcjump; if ( last_pass<2 && backamount != 0x0 && !(lastexp.data & IMPBIT) && lastexp.offset + backamount < 0x80 + backamount) warning(SHORTB); /* -0x8? to 0x7F, warning */ } } } /* BCC (long branches emulated by short branch over & long jump) */ PUBLIC void mbcc() { getea(&target); if (target.indcount >= 0x2 || target.base != NOREG) kgerror(REL_REQ); else { #ifdef iscpu if (iscpu(3)) #else if (defsize != 0x2) #endif { page = PAGE1_OPCODE; ++mcount; opcode += 0x10; lbranch(0x84); } else { aprefix = opcode ^ 0x1; /* kludged storage for short branch over */ oprefix = defsize + 0x1; mcount += 0x2; opcode = JMP_OPCODE; lbranch(0x83); mcount -= 0x2; } } } /* bswap r32 */ PUBLIC void mbswap() { needcpu(4); ++mcount; Gd(&target); opcode |= rm[target.base]; } /* BR, CALL, J, JMP */ PUBLIC void mcall() { opcode_pt far_diff; bool_t indirect; register struct sym_s *symptr; far_diff = 0x0; if (sym == IDENT && (symptr = gsymptr)->type & MNREGBIT && symptr->data & SIZEBIT ) { if(symptr->value_reg_or_op.op.routine == FAROP) { far_diff = 0x8; getsym(); } if(symptr->value_reg_or_op.op.routine == WORDOP && opcode == JMP_SHORT_OPCODE) { opcode = JMP_OPCODE; getsym(); } } indirect = FALSE; if (asld_compatible && defsize <= 0x2) { calljmp_kludge = 0x2; if (sym == INDIRECT) { calljmp_kludge = 0x0; indirect = TRUE; getsym(); } } getea(&target); if (indirect && target.indcount == 0x1) target.indcount = 0x2; calljmp_kludge = 0x0; if (sym == COLON) { int tsize = target.size?target.size:defsize; if (opcode == JMP_SHORT_OPCODE) opcode = JMP_OPCODE; ++mcount; yesimmed(&target); getsym(); getea(&source); yesimmed(&source); if (mcount != 0x0) { if (opcode == JMP_OPCODE) opcode = 0xEA; else opcode = 0x9A; lastexp = source.displ; if (!(lastexp.data & (FORBIT | RELBIT | UNDBIT)) && tsize == 0x2 && (offset_t) (lastexp.offset + 0x8000L) >= 0x18000L) datatoobig(); mcount += tsize; target.size = 0x2; buildimm(&target, FALSE); } } else if (target.indcount >= 0x2 || target.base != NOREG) { ++mcount; notsegorspecreg(&target); if (target.indcount == 0) notbytesize(&target); if (mcount != 0x0) { if (opcode == JMP_SHORT_OPCODE) opcode = JMP_OPCODE; buildea(&target); if (opcode == JMP_OPCODE) opcode = 0x20; else opcode = 0x10; postb |= opcode + far_diff; opcode = 0xFF; } } else if (opcode == JMP_SHORT_OPCODE) { if (jumps_long && ((pass!=0 && !is8bitsignedoffset(lastexp.offset - lc - 2)) || (last_pass==1))) { opcode = JMP_OPCODE; lbranch(0x83); } else { lastexp = target.displ; if (lastexp.data & IMPBIT) { error(NONIMPREQ); lastexp.data = FORBIT | UNDBIT; } mshort2(); } } else lbranch(opcode == JMP_OPCODE ? 0x83 : 0x0); } /* CALLI, JMPI */ PUBLIC void mcalli() { bool_t indirect; ++mcount; indirect = FALSE; if (sym == INDIRECT) { getsym(); indirect = TRUE; } getea(&target); if (target.indcount >= 0x2 || target.base != NOREG) indirect = TRUE; if (indirect) { buildea(&target); if (opcode == 0xEA) opcode = 0x28; else opcode = 0x18; postb |= opcode; opcode = 0xFF; } else { int tsize = target.size?target.size:defsize; getcomma(); getea(&source); yesimmed(&source); if (mcount != 0x0) { lastexp = target.displ; if (!(lastexp.data & (FORBIT | RELBIT | UNDBIT)) && tsize == 0x2 && (offset_t) (lastexp.offset + 0x8000L) >= 0x18000L) { tsize=4; if( tsize != defsize ) oprefix = 0x66; /* datatoobig(); */ } needcpu(tsize==4?3:0); mcount += tsize; source.size = 0x2; buildimm(&source, FALSE); } } } /* DIV, IDIV, MUL */ PUBLIC void mdivmul() { if (getaccumreg(&source)) { ++mcount; getcomma(); Ex(&target); yes_samesize(); buildunary(0xF6 | regsegword[source.base]); } else mnegnot(); } /* ENTER */ PUBLIC void menter() { ++mcount; getimmed(&target, 0x2); getcomma(); getimmed(&source, 0x1); if (mcount != 0x0) { mcount += 2; lastexp = target.displ; /* getimmed(&source) wiped it out */ } needcpu(1); } /* arpl r/m16,r16 (Intel manual opcode chart wrongly says EwRw) */ PUBLIC void mEwGw() { ++mcount; Ew(&target); getcomma(); Gw(&source); oprefix = 0x0; buildregular(); } /* [cmpxchg xadd] [r/m8,r8 r/m16,r16, r/m32,r32] */ PUBLIC void mExGx() { ++mcount; Ex(&target); getcomma(); Gx(&source); yes_samesize(); opcode |= segword; buildregular(); } PUBLIC void mf_inher() { mcount += 0x2; postb = REG_MOD | (opcode & ~REG_MOD); opcode = ESCAPE_OPCODE_BASE | (opcode >> 0x6); if (opcode == ESCAPE_OPCODE_BASE) opcode = ESCAPE_OPCODE_BASE | 0x6; /* fix up encoding of fcompp */ } /* [fldenv fnsave fnstenv frstor] mem */ PUBLIC void mf_m() { ++mcount; getindirect(&source); if (source.size != 0x0) kgerror(ILL_SIZE); buildfloat(); } /* [fldcw fnstcw] mem2i */ PUBLIC void mf_m2() { ++mcount; getindirect(&source); if (source.size != 0x0 && source.size != 0x2) kgerror(ILL_SIZE); buildfloat(); } /* fnstsw [mem2i ax] */ PUBLIC void mf_m2_ax() { if (getaccumreg(&target)) { if (target.base != AXREG) kgerror(ILLREG); else { opcode = 0x74; target.base = ST0REG; /* fake, really ax */ buildfreg(); } } else mf_m2(); } /* [fiadd ficom ficomp fidiv fidivr fimul fist fisub fisubr] [mem2i mem4i] */ PUBLIC void mf_m2_m4() { ++mcount; getindirect(&source); if (source.size == 0x0) kgerror(SIZE_UNK); else if (source.size == 0x2) opcode |= 0x40; else if (source.size != 0x4) kgerror(ILL_SIZE); buildfloat(); } /* [fild fistp] [mem2i mem4i mem8i] */ PUBLIC void mf_m2_m4_m8() { ++mcount; getindirect(&source); if (source.size == 0x0) kgerror(SIZE_UNK); else if (source.size == 0x2) opcode |= 0x40; else if (source.size == 0x8) opcode |= 0x45; /* low bits 0 -> 5 and 3 -> 7 */ else if (source.size != 0x4) kgerror(ILL_SIZE); buildfloat(); } /* [fcom fcomp] [mem4r mem8r optional-st(i)] */ PUBLIC void mf_m4_m8_optst() { if (sym == EOLSYM) { target.base = ST1REG; buildfreg(); } else mf_m4_m8_st(); } /* [fadd fdiv fdivr fmul fsub fsubr] [mem4r mem8r st,st(i) st(i),st] */ PUBLIC void mf_m4_m8_stst() { target.base = fpregchk(); if (target.base != NOREG) { getcomma(); source.base = fpregchk(); if (source.base == NOREG) { error(FP_REG_REQ); source.base = ST0REG; } if (target.base == ST0REG) target.base = source.base; else { if (source.base != ST0REG) error(ILL_FP_REG_PAIR); opcode |= 0x40; if ((opcode & 0x07) >= 0x4) opcode ^= 0x01; /* weird swap of fdiv/fdivr, fsub/fsubr */ } buildfreg(); } else { ++mcount; getindirect(&source); if (source.size == 0x0) kgerror(SIZE_UNK); else if (source.size == 0x8) opcode |= 0x40; else if (source.size != 0x4) kgerror(ILL_SIZE); buildfloat(); } } /* fst [mem4r mem8r st(i)] */ PUBLIC void mf_m4_m8_st() { target.base = fpregchk(); if (target.base != NOREG) { if (opcode == FST_ENCODED) opcode |= 0x40; buildfreg(); } else { ++mcount; getindirect(&source); if (source.size == 0x0) kgerror(SIZE_UNK); else if (source.size == 0x8) opcode |= 0x40; else if (source.size != 0x4) kgerror(ILL_SIZE); buildfloat(); } } /* [fld fstp] [mem4r mem8r mem10r st(i)] */ PUBLIC void mf_m4_m8_m10_st() { target.base = fpregchk(); if (target.base != NOREG) { if (opcode == FSTP_ENCODED) opcode |= 0x40; buildfreg(); } else { ++mcount; getindirect(&source); if (source.size == 0x0) kgerror(SIZE_UNK); else if (source.size == 0x8) opcode |= 0x40; else if (source.size == 0xA) opcode |= 0x25; /* low bits 0 -> 5 and 3 -> 7 */ else if (source.size != 0x4) kgerror(ILL_SIZE); buildfloat(); } } /* [fbld fbstp] mem10r */ PUBLIC void mf_m10() { ++mcount; getindirect(&source); if (source.size != 0xA) kgerror(ILL_SIZE); buildfloat(); } /* ffree st(i) */ PUBLIC void mf_st() { target.base = fpregchk(); if (target.base == NOREG) kgerror(FP_REG_REQ); buildfreg(); } /* [fucom fucomp fxch] optional-st(i) */ PUBLIC void mf_optst() { if (sym == EOLSYM) { target.base = ST1REG; buildfreg(); } else mf_st(); } /* [faddp fdivp fdivrp fmulp fsubp fsubrp] st(i),st */ PUBLIC void mf_stst() { target.base = fpregchk(); if (target.base == NOREG) { kgerror(FP_REG_REQ); return; } getcomma(); source.base = fpregchk(); if (source.base == NOREG) { kgerror(FP_REG_REQ); return; } if (source.base != ST0REG) { kgerror(ILL_FP_REG); return; } buildfreg(); } PUBLIC void mf_w_inher() { sprefix = WAIT_OPCODE; mf_inher(); } /* [fsave fstenv] mem */ PUBLIC void mf_w_m() { sprefix = WAIT_OPCODE; mf_m(); } /* fstcw mem2i */ PUBLIC void mf_w_m2() { sprefix = WAIT_OPCODE; mf_m2(); } /* fstsw [mem2i ax] */ PUBLIC void mf_w_m2_ax() { sprefix = WAIT_OPCODE; mf_m2_ax(); } /* ADC, ADD, AND, CMP, OR, SBB, SUB, XOR */ PUBLIC void mgroup1() { getbinary(); notsegorspecreg(&source); if (mcount != 0x0) { if (source.base == NOREG) { if (target.indcount == 0x0 && (target.base == ALREG || target.base == AXREG || (target.base == EAXREG && (source.displ.data & (FORBIT | RELBIT | UNDBIT) || !is8bitsignedoffset(source.displ.offset))))) { opcode |= 0x04 | segword; buildimm(&source, FALSE); } else { buildunary(0x80 | segword); buildimm(&source, TRUE); } } else { opcode |= direction | segword; buildregular(); } } } /* RCL, RCR, ROL, ROR, SAL, SAR, SHL, SHR */ PUBLIC void mgroup2() { ++mcount; Ex(&target); buildsegword(&target); getshift(&source); if (mcount != 0x0) { buildunary(0xD0 | segword); if (source.base == CLREG) opcode |= 0x2; else if (source.displ.offset != 0x1) { needcpu(1); opcode -= 0x10; source.size = 0x1; buildimm(&source, FALSE); } } } /* LLDT, LTR, SLDT, STR, VERR, VERW */ PUBLIC void mgroup6() { needcpu(2); ++mcount; Ew(&target); oprefix = 0x0; buildunary(0x0); } /* INVLPG, LGDT, LIDT, LMSW, SGDT, SIDT, SMSW */ PUBLIC void mgroup7() { needcpu(2); /* I think INVLPG is actually 386 */ ++mcount; if (opcode == 0x20 || opcode == 0x30) { Ew(&target); oprefix = 0x0; } else { getindirect(&target); oprefix = 0x0; if (target.size != 0x0 && target.size != 0x6) error(MISMATCHED_SIZE); /* XXX - size 6 wrong for INVLPG? */ } buildunary(0x1); } /* BT, BTR, BTS, BTC */ PUBLIC void mgroup8() { needcpu(3); ++mcount; Ev(&target); getcomma(); /* Gv or Ib */ getea(&source); notindirect(&source); notsegorspecreg(&source); if (mcount != 0x0) { if (source.base == NOREG) { buildunary(0xBA); source.size = 0x1; buildimm(&source, TRUE); } else { yes_samesize(); opcode += 0x83; buildregular(); } } } /* BSF, BSR, LAR, LSL (Intel manual opcode chart wrongly says GvEw for L*) */ PUBLIC void mGvEv() { needcpu(2); ++mcount; Gv(&source); getcomma(); Ev(&target); yes_samesize(); buildregular(); } /* bound [r16,m16&16 r32,m32&32] */ PUBLIC void mGvMa() { ++mcount; Gv(&source); getcomma(); getindirect(&target); yes_samesize(); buildregular(); } /* LDS, LES, LFS, LGS, LSS */ PUBLIC void mGvMp() { ++mcount; Gv(&source); getcomma(); getindirect(&target); if (target.size != 0x0 && target.size != 0x2 + source.size) error(MISMATCHED_SIZE); buildregular(); } /* IMUL */ PUBLIC void mimul() { ++mcount; Ex(&target); if (sym != COMMA) { buildsegword(&target); buildunary(0xF6 | segword); return; } getcomma(); notindirect(&target); source = target; /* direction is swapped */ getea(&target); notsegorspecreg(&target); yes_samesize(); if (sym != COMMA && (target.indcount != 0x0 || target.base != NOREG)) { needcpu(3); page = PAGE1_OPCODE; ++mcount; opcode = 0xAF; buildregular(); } else { if (sym == COMMA) { getsym(); getea(&source2); yesimmed(&source2); } else { source2 = target; target = source; } source2.size = target.size; if (is8bitsignedoffset(source2.displ.offset)) { source2.size = 0x1; opcode = 0x6B; } else { source2.size = target.size; opcode = 0x69; } buildregular(); if (mcount != 0x0) buildimm(&source2, FALSE); } } /* IN */ PUBLIC void min() { ++mcount; if (opcode & WORDBIT) /* inw; ind not supported */ mnsize = 0x2; if (sym == EOLSYM && mnsize != 0x0) target.size = mnsize; else { if (getaccumreg(&target)) { if (mnsize != 0x0 && regsize[target.base] != mnsize) error(MISMATCHED_SIZE); getcomma(); } else target.size = regsize[target.base = mnsize < 0x2 ? ALREG : AXREG]; opcode |= regsegword[target.base]; if (!getdxreg(&source)) { getimmed(&source, 0x1); opcode -= 0x8; } } if (target.size > 0x1 && target.size != defsize) oprefix = 0x66; } /* DEC, INC */ PUBLIC void mincdec() { ++mcount; Ex(&target); buildsegword(&target); if (target.indcount == 0x0 && segword == WORDBIT) opcode |= 0x40 | rm[target.base]; else buildunary(0xFE | segword); } /* CBW, CWD, CMPSW, INSW, IRET, LODSW, POPA, POPF, PUSHA, PUSHF */ /* MOVSW, OUTSW, SCASW, STOSW */ PUBLIC void minher16() { minher(); if (defsize != 0x2) oprefix = 0x66; } /* CWDE, CDQ, CMPSD, INSD, IRETD, LODSD, POPAD, POPFD, PUSHAD, PUSHFD */ /* MOVSD, OUTSD, SCASD, STOSD */ PUBLIC void minher32() { minher(); if (defsize != 0x4) oprefix = 0x66; needcpu(3); } /* AAD, AAM */ PUBLIC void minhera() { ++mcount; if (sym == EOLSYM) { target.displ.offset = 0xA; target.size = 0x1; buildimm(&target, FALSE); } else getimmed(&target, 0x1); } /* INT */ PUBLIC void mint() { ++mcount; getimmed(&target, 0x1); if (!(immadr.data & (FORBIT | RELBIT | UNDBIT)) && (opcode_t) immadr.offset == 0x3) { immcount = 0x0; opcode = 0xCC; } } /* JCC */ PUBLIC void mjcc() { /* First look for j* near */ if (sym == IDENT && gsymptr->type & MNREGBIT && gsymptr->data & SIZEBIT && gsymptr->value_reg_or_op.op.routine == WORDOP && opcode < 0x80) { getsym(); getea(&target); if (target.indcount >= 0x2 || target.base != NOREG) kgerror(REL_REQ); else { needcpu(3); page = PAGE1_OPCODE; ++mcount; opcode += 0x10; lbranch(0x84); } } else if (!jumps_long || opcode > 0x80) /* above 0x80 means loop, not long */ mshort(); else /* mbcc */ { getea(&target); lastexp = target.displ; if ( (pass!=0 && !is8bitsignedoffset(lastexp.offset - lc - 2)) || last_pass==1) { if (target.indcount >= 0x2 || target.base != NOREG) kgerror(REL_REQ); aprefix = opcode ^ 0x1; /* kludged storage for short branch over */ oprefix = defsize + 0x1; mcount += 0x2; opcode = JMP_OPCODE; lbranch(0x83); mcount -= 0x2; } else { /* 8 bit */ if (lastexp.data & IMPBIT) { error(NONIMPREQ); lastexp.data = FORBIT | UNDBIT; } mshort2(); } } } /* JCXZ, JECXZ */ PUBLIC void mjcxz() { if (opcode != defsize) { aprefix = 0x67; ++mcount; /* quick fix - mshort() needs to know */ } opcode = 0xE3; mshort(); if (aprefix != 0x0) --mcount; /* quick fix - main routine bumps it again */ } /* LEA */ PUBLIC void mlea() { Gv(&source); /* back to front */ getcomma(); ++mcount; getindirect(&target); yes_samesize(); buildregular(); } /* MOV */ PUBLIC void mmov() { getbinary(); if (segword >= SEGMOV) { oprefix = 0x0; notimmed(&target); /* target is actually the source */ if (segword > SEGMOV) /* special reg */ notindirect(&target); } if (mcount != 0x0) { if (target.base == NOREG && target.index == NOREG && (source.base == ALREG || source.base == AXREG || source.base == EAXREG)) { opcode = 0xA0 | (direction ^ TOREGBIT) | segword; lastexp = target.displ; if ((source.size = displsize(&target)) != defsize) aprefix = 0x67; mcount += source.size; needcpu(source.size==4?3:0); } else if (source.base == NOREG) { if (target.indcount == 0x0) opcode = 0xB0 | (segword << 0x3) | rm[target.base]; else { buildea(&target); opcode = 0xC6 | segword; } buildimm(&source, FALSE); } else { if (isspecreg(source.base)) { needcpu(3); page = PAGE1_OPCODE; ++mcount; opcode = 0x0; } opcode |= direction | segword; buildregular(); } } } /* MOVSX, MOVZX */ PUBLIC void mmovx() { ++mcount; Gv(&source); getcomma(); Ex(&target); if (target.size == 0x0) kgerror(SIZE_UNK); if (target.size > 0x2) kgerror(ILL_SIZE); oprefix = 0x0; if (source.size != defsize) oprefix = 0x66; buildsegword(&target); opcode |= segword; buildregular(); } /* NEG, NOT */ PUBLIC void mnegnot() { ++mcount; Ex(&target); buildsegword(&target); buildunary(0xF6 | segword); } /* OUT */ PUBLIC void mout() { ++mcount; if (opcode & WORDBIT) /* outw; outd not supported */ mnsize = 0x2; if (sym == EOLSYM && mnsize != 0x0) source.size = mnsize; else { if (!getdxreg(&target)) { getimmed(&target, 0x1); opcode -= 0x8; } if (sym == COMMA) { getsym(); if (!getaccumreg(&source)) kgerror(AL_AX_EAX_EXP); else if (mnsize != 0x0 && regsize[source.base] != mnsize) error(MISMATCHED_SIZE); } else source.size = regsize[source.base = mnsize < 0x2 ? ALREG : AXREG]; opcode |= regsegword[source.base]; } if (source.size > 0x1 && source.size != defsize) oprefix = 0x66; } /* POP, PUSH */ PUBLIC void mpushpop() { opcode_t oldopcode; ++mcount; getea(&target); buildsegword(&target); notbytesize(&target); if ((oldopcode = opcode) == POP_OPCODE) { notimmed(&target); if (target.base == CSREG) kgerror(ILL_SEG_REG); } if (mcount != 0x0) { if (target.indcount == 0x0) { if (segword == SEGMOV) { switch (target.base) { case CSREG: opcode = 0x0E; break; case DSREG: opcode = 0x1E; break; case ESREG: opcode = 0x06; break; case SSREG: opcode = 0x16; break; case FSREG: opcode = 0xA0; page = PAGE1_OPCODE; ++mcount; break; case GSREG: opcode = 0xA8; page = PAGE1_OPCODE; ++mcount; break; } if (oldopcode == POP_OPCODE) ++opcode; } else if (target.base != NOREG) { opcode = 0x50 | rm[target.base]; if (oldopcode == POP_OPCODE) opcode |= 0x8; } else { needcpu(1); /* On 8086 PUSH does not allow immediate */ opcode = 0x68; if (oldopcode == POP_OPCODE) ++opcode; buildimm(&target, TRUE); } } else { buildea(&target); if (oldopcode == PUSH_OPCODE) postb |= 0x6 << REG_SHIFT; } } } /* RET, RETF */ PUBLIC void mret() { ++mcount; if (sym != EOLSYM) { --opcode; getimmed(&target, 0x2); } } /* SEG CS/DS/ES/FS/GS/SS */ PUBLIC void mseg() { reg_pt reg; if (regsegword[reg = regchk()] != SEGMOV) error(SEG_REG_REQ); else { getsym(); ++mcount; opcode = (segoverride - CSREG)[reg]; } } /* SETCC */ PUBLIC void msetcc() { ++mcount; Eb(&target); if (mcount != 0x0) buildea(&target); } /* SHLD, SHRD */ PUBLIC void mshdouble() { needcpu(3); ++mcount; Ev(&target); getcomma(); Gv(&source); yes_samesize(); buildregular(); getshift(&source2); lastexp = target.displ; /* getshift() wiped it out */ if (mcount != 0x0) { if (source2.base == CLREG) opcode |= 0x1; else { source2.size = 0x1; buildimm(&source2, FALSE); } } } /* TEST Similar to the regular group1 operators. It does not allow the sign extended immediate byte forms and does not use the relevant direction bit. */ PUBLIC void mtest() { getbinary(); notsegorspecreg(&source); if (source.base == NOREG) { if (mcount != 0x0) { if (target.indcount == 0x0 && (target.base == ALREG || target.base == AXREG || target.base == EAXREG)) opcode = 0xA8 | segword; else { buildea(&target); opcode = 0xF6 | segword; } } buildimm(&source, FALSE); } else { opcode |= segword; buildregular(); } } /* XCHG Similar to the regular group1 operators. It does not allow any of the immediate forms and does not use the irrelevant direction bit. */ PUBLIC void mxchg() { getbinary(); notimmed(&source); notsegorspecreg(&source); if (target.indcount == 0x0) { if (target.base == AXREG || target.base == EAXREG) { opcode = 0x90 + rm[source.base]; return; } if (source.base == AXREG || source.base == EAXREG) { opcode = 0x90 + rm[target.base]; return; } } opcode |= segword; buildregular(); } PRIVATE void notbytesize(eap) register struct ea_s *eap; { if (eap->size == 0x1) kgerror(ILL_SIZE); } PRIVATE void notimmed(eap) register struct ea_s *eap; { if (eap->indcount == 0x0 && eap->base == NOREG) kgerror(ILL_IMM_MODE); } PRIVATE void notindirect(eap) register struct ea_s *eap; { if (eap->indcount != 0x0) kgerror(ILL_IND); } PRIVATE void notsegorspecreg(eap) register struct ea_s *eap; { if (regsegword[eap->base] >= SEGMOV) kgerror(ILLREG); } PRIVATE void yesimmed(eap) register struct ea_s *eap; { if (eap->indcount == 0x1) eap->indcount = 0x0; if (eap->indcount != 0x0 || eap->base != NOREG) kgerror(IMM_REQ); } PRIVATE void yes_samesize() { if (target.size == 0x0) target.size = source.size; else if (source.size != 0x0 && target.size != source.size) kgerror(MISMATCHED_SIZE); } #endif /* I80386 */ #ifdef MC6809 /* 6809 opcode constants */ /* bits for indexed addressing */ #define INDIRECTBIT 0x10 #define INDEXBIT 0x80 /* except 5 bit offset */ #define PCRELBIT 0x04 /* PC relative (in certain cases) */ #define RRBITS 0x60 /* register select bits */ PRIVATE opcode_t rrindex[] = /* register and index bits for indexed adr */ { 0x60 | INDEXBIT, /* S */ 0x40 | INDEXBIT, /* U */ 0x00 | INDEXBIT, /* X */ 0x20 | INDEXBIT, /* Y */ PCRELBIT | INDEXBIT, /* PC */ }; PRIVATE opcode_t pushpull[] = /* push/pull codes */ { 0x40, /* S */ 0x40, /* U */ 0x10, /* X */ 0x20, /* Y */ 0x80, /* PC */ 0x02, /* A */ 0x04, /* B */ 0x01, /* CC */ 0x08, /* DP */ 0x06, /* D */ }; PRIVATE opcode_t tfrexg1[] = /* transfer/exchange codes for source reg */ { 0x40, /* S */ 0x30, /* U */ 0x10, /* X */ 0x20, /* Y */ 0x50, /* PC */ 0x80, /* A */ 0x90, /* B */ 0xA0, /* CC */ 0xB0, /* DP */ 0x00, /* D */ }; PRIVATE opcode_t tfrexg2[] = /* transfer/exchange codes for target reg */ { 0x04, /* S */ 0x03, /* U */ 0x01, /* X */ 0x02, /* Y */ 0x05, /* PC */ 0x08, /* A */ 0x09, /* B */ 0x0A, /* CC */ 0x0B, /* DP */ 0x00, /* D */ }; FORWARD void checkpostinc P((void)); FORWARD void doaltind P((void)); FORWARD void do1altind P((void)); FORWARD void fixupind P((void)); FORWARD void getindexnopost P((void)); FORWARD void inderror P((char * err_str)); FORWARD reg_pt indreg P((reg_pt maxindex)); FORWARD void predec1 P((void)); FORWARD void sustack P((reg_pt stackreg)); PRIVATE void checkpostinc() { if (sym == ADDOP) { if (postb & INDIRECTBIT) inderror(ILLMOD); /* single-inc indirect illegal */ else { lastexp.offset &= 0xFF00; /* for printing if postbyte is 0: ,X+ */ getsym(); } } else if (sym == POSTINCOP) { postb |= 0x1; getsym(); } else postb |= 0x4; fixupind(); } /* common code for all-mode ops, alterable-mode ops, indexed ops */ PRIVATE void doaltind() { mcount += 0x2; if (sym == LBRACKET) { postb = INDIRECTBIT; getsym(); do1altind(); if (sym != RBRACKET) error(RBEXP); } else do1altind(); } PRIVATE void do1altind() { bool_t byteflag; /* set if direct or short indexed adr forced */ char *oldlineptr; char *oldsymname; reg_pt reg; bool_t wordflag; /* set if extended or long indexed adr forced*/ if ((reg = regchk()) != NOREG) { switch (reg) { case AREG: postb |= 0x86; break; case BREG: postb |= 0x85; break; case DREG: postb |= 0x8B; break; default: if (indreg(MAXINDREG) != NOREG) checkpostinc(); return; } getsym(); if (sym != COMMA) inderror(COMEXP); else getindexnopost(); return; } else if (sym == SUBOP) /* could be -R or - in expression */ { oldlineptr = lineptr; /* save state */ oldsymname = symname; getsym(); reg = regchk(); lineptr = oldlineptr; symname = oldsymname; if (reg != NOREG) { predec1(); /* it's -R */ return; } sym = SUBOP; } else if (sym == COMMA) { postb |= INDEXBIT; getsym(); if (sym == SUBOP) { predec1(); return; } else if (sym != PREDECOP) { if (indreg(MAXINDREG) != NOREG) checkpostinc(); return; } } if (sym == PREDECOP) { postb |= 0x83; getindexnopost(); return; } /* should have expression */ wordflag = byteflag = FALSE; if (sym == LESSTHAN) { /* context-sensitive, LESSTHAN means byte-sized here */ byteflag = TRUE; getsym(); } else if (sym == GREATERTHAN) { /* context-sensitive, GREATERTHAN means word-sized here */ wordflag = TRUE; getsym(); } expres(); if (sym == COMMA) { /* offset from register */ getsym(); if ((reg = indreg(PCREG)) == NOREG) return; postb |= 0x8; /* default 8 bit offset */ if (reg == PCREG) { reldata(); if (!(lastexp.data & (RELBIT | UNDBIT))) { lastexp.offset = lastexp.offset - lc; if (page != 0x0) lastexp.offset -= 0x4; /* extra for instruction */ else lastexp.offset -= 0x3; /* 3 byte instruction assuming 8 bit offset */ } } if (byteflag) { if (!(lastexp.data & (RELBIT | UNDBIT)) && !is8bitsignedoffset(lastexp.offset)) error(ABOUNDS); /* forced short form is impossible */ ++mcount; } else if (wordflag || lastexp.data & (FORBIT | RELBIT | UNDBIT) || !is8bitsignedoffset(lastexp.offset)) { /* 16 bit offset */ if (postb & PCRELBIT && !(lastexp.data & RELBIT)) --lastexp.offset; /* instruction 1 longer than already allowed */ postb |= 0x1; mcount += 0x2; } else if (!(postb & PCRELBIT) && (offset_t) (lastexp.offset + 0x10) < 0x20 && !(postb & INDIRECTBIT && lastexp.offset != 0x0)) { /* 5 bit offset */ postb &= RRBITS | INDIRECTBIT; if (lastexp.offset == 0x0) postb |= 0x84; /* index with zero offset */ else postb |= (lastexp.offset & 0x1F); } else /* 8 bit offset */ ++mcount; fixupind(); } else if (postb & INDIRECTBIT) { /* extended indirect */ postb = 0x9F; mcount += 0x2; fixupind(); } else if (postb & INDEXBIT) inderror(ILLMOD); /* e.g. LEAX $10 */ else { if (byteflag || (!wordflag && !(lastexp.data & (FORBIT | RELBIT)) && (lastexp.offset >> 0x8) == dirpag)) { /* direct addressing */ if (opcode >= 0x80) opcode |= 0x10; } else /* extended addressing */ { if (opcode < 0x80) opcode |= 0x70; else opcode |= 0x30; ++mcount; if (pass2 && (opcode == JSR_OPCODE || opcode == JMP_OPCODE) && !(lastexp.data & IMPBIT) && lastexp.offset + (0x81 - 0x3) < 0x101) /* JSR or JMP could be done with BSR or BRA */ warning(SHORTB); } } } PRIVATE void fixupind() { if ((opcode & 0x30) == 0x0) /* change all but LEA opcodes */ { if (opcode < 0x80) opcode |= 0x60; else opcode |= 0x20; } } PRIVATE void getindexnopost() { getsym(); if (indreg(MAXINDREG) != NOREG) fixupind(); } PRIVATE void inderror(err_str) char * err_str; { error(err_str); if (postb & INDIRECTBIT) sym = RBRACKET; /* fake right bracket to kill further errors */ fixupind(); } /* check current symbol is an index register (possibly excepting PC) */ /* if so, modify postbyte RR and INDEXBIT for it, get next sym, return TRUE */ /* otherwise generate error, return FALSE */ PRIVATE reg_pt indreg(maxindex) reg_pt maxindex; { reg_pt reg; if ((reg = regchk()) == NOREG) inderror(IREGEXP); else if (reg > maxindex) { inderror(ILLREG); reg = NOREG; } else { postb |= rrindex[reg]; getsym(); } return reg; } /* all-mode ops */ PUBLIC void mall() { if (sym == IMMEDIATE) mimmed(); else malter(); } /* alterable mode ops */ PUBLIC void malter() { postb = 0x0; /* not yet indexed or indirect */ doaltind(); } /* indexed mode ops */ PUBLIC void mindex() { postb = INDEXBIT; /* indexed but not yet indirect */ doaltind(); } /* immediate ops */ PUBLIC void mimmed() { opcode_t nybble; mcount += 0x2; if (sym != IMMEDIATE) error(ILLMOD); else { if (opcode >= 0x80 && ((nybble = opcode & 0xF) == 0x3 || nybble == 0xC || nybble >= 0xE)) ++mcount; /* magic for long immediate */ symexpres(); if (pass2 && mcount <= 0x2) { chkabs(); checkdatabounds(); } } } /* long branches */ PUBLIC void mlong() { mcount += 0x3; /* may be 0x0 or 0x1 here */ expres(); segadj(); if (pass2) { reldata(); if (!(lastexp.data & (RELBIT | UNDBIT))) { lastexp.offset = lastexp.offset - lc - lcjump; if ( last_pass<2 && !(lastexp.data & IMPBIT) && lastexp.offset + 0x81 < 0x101) warning(SHORTB); /* -0x81 to 0x7F, warning */ } } } /* PSHS and PULS */ PUBLIC void msstak() { sustack(SREG); } /* TFR and EXG */ PUBLIC void mswap() { reg_pt reg; mcount = 0x2; if ((reg = regchk()) == NOREG) error(REGEXP); else { postb = tfrexg1[reg]; getsym(); if (sym != COMMA) error(COMEXP); else { getsym(); if ((reg = regchk()) == NOREG) error(REGEXP); else if ((postb |= tfrexg2[reg]) & 0x88 && (postb & 0x88) != 0x88) error(ILLREG); /* registers not of same size */ } } } /* PSHU and PULU */ PUBLIC void mustak() { sustack(UREG); } PRIVATE void predec1() { if (postb & INDIRECTBIT) inderror(ILLMOD); /* single-dec indirect illegal */ else { postb |= 0x82; getindexnopost(); } } /* common routine for PSHS/PULS/PSHU/PULU */ PRIVATE void sustack(stackreg) reg_pt stackreg; { reg_pt reg; mcount = 0x2; while ((reg = regchk()) != NOREG) { if (reg == stackreg) { error(ILLREG); /* cannot stack self */ break; } postb |= pushpull[reg]; getsym(); if (sym != COMMA) break; getsym(); } } #endif /* MC6809 */ /* routines common to all processors */ PUBLIC void getcomma() { if (sym != COMMA) error(COMEXP); else getsym(); } /* inherent ops */ /* for I80386 */ /* AAA, AAS, CLC, CLD, CLI, CLTS, CMC, CMPSB, DAA, DAS, HLT, INTO, INSB, */ /* INVD, */ /* LAHF, LEAVE, LOCK, LODSB, MOVSB, NOP, OUTSB, REP, REPE, REPNE, REPNZ, */ /* REPZ, SAHF, SCASB, STC, STD, STI, STOSB, WAIT, WBINVD */ PUBLIC void minher() { ++mcount; } /* short branches */ PUBLIC void mshort() { nonimpexpres(); mshort2(); } PRIVATE void mshort2() { mcount += 0x2; if (pass2) { reldata(); if (lastexp.data & RELBIT) showrelbad(); else if (!(lastexp.data & UNDBIT)) { lastexp.offset = lastexp.offset - lc - mcount; if (!is8bitsignedoffset(lastexp.offset)) error(ABOUNDS); } } } /* check if current symbol is a register, return register number or NOREG */ PRIVATE reg_pt regchk() { register struct sym_s *symptr; if (sym == IDENT) { if ((symptr = gsymptr)->type & MNREGBIT) { if (symptr->data & REGBIT) { int regno = symptr->value_reg_or_op.reg; #ifdef I80386 if (regno == ST0REG && !fpreg_allowed) error(FP_REG_NOT_ALLOWED); /* Check cpu */ needcpu((regno==FSREG||regno==GSREG)?3:0); needcpu((regno>=EAXREG && regno<=ESPREG)?3:0); needcpu((regno>=CR0REG && regno<=TR7REG)?3:0); #endif return regno; } } else if( last_pass == 1 ) if (!(symptr->type & (LABIT | MACBIT | VARBIT))) symptr->data |= FORBIT; /* show seen in advance */ } return NOREG; } /* convert lastexp.data for PC relative */ PRIVATE void reldata() { if ((lastexp.data ^ lcdata) & (IMPBIT | RELBIT | SEGM)) { if ((lastexp.data ^ lcdata) & RELBIT) showrelbad(); /* rel - abs is weird, abs - rel is bad */ else { pcrflag = OBJ_R_MASK; lastexp.data = (lcdata & ~SEGM) | lastexp.data | RELBIT; /* segment is that of lastexp.data */ } } else /* same file, segment and relocation */ lastexp.data = (lastexp.data | lcdata) & ~(RELBIT | SEGM); } PRIVATE void segadj() { if ((lastexp.data & UNDBIT) && textseg >= 0 ) { lastexp.sym->data &= ~SEGM; lastexp.sym->data |= (lcdata & SEGM); } } dev86-0.16.21/as/obj1/000077500000000000000000000000001231050321700140455ustar00rootroot00000000000000dev86-0.16.21/as/obj1/calljmp.obj000066400000000000000000000003101231050321700161550ustar00rootroot00000000000000£†*;ˆUUUUˆ@ˆ@ˆcalljmpREL16REL32 @š è|fÿÐfÿÓfÿÑfÿÒfÿÔfÿÕfÿÖfÿ×gÿgÿgfÿèUfÿÐfÿÓfÿÑfÿÒf@ÿÔfÿÕfÿÖfÿ×fÿê ë3ÿàÿãÿáÿâÿäÿåÿæÿçÿ'ÿ'ÿ'ëfÿàfÿãfÿáfÿâfÿäfÿåfHÿæfÿçfÿ'dev86-0.16.21/as/obj1/ea.obj000066400000000000000000000007301231050321700151260ustar00rootroot00000000000000£†* ¯UUUU¯ea @gf‹gf‹gf‹gf‹gf‹gf‹gf¡4gf‹gf‹@gf‹Agf‹Bgf‹Cgf‹Dgf‹Eg@f‹Fgf‹Ggf‹€4gf‹4gf‹‚4gf‹ƒ4gf‹„4gf‹…4gf‹†4gf‹‡4ˆÀˆàˆØˆ@øˆÈˆèˆÐˆðf‰Àf‰Èf‰Ðf‰Øf‰àf‰èf‰ðf‰øf‹f‹f‹f‹f¡xV4f‹f‹f‹@f‹A@f‹Bf‹Cf‹Ef‹Ff‹Gf‹€xV4f‹xV4f‹‚xV4f‹ƒxV4f‹…xV4f‹†xV4f@‹‡xV4‰À‰È‰Ð‰Ø‰à‰è‰ð‰øf‹pf‹qf‹rf‹sf‹tf‹uxV4f‹vf‹wf‹Dpf@‹Dqf‹Drf‹Dsf‹Dtf‹D$f‹Duf‹Dvf‹Dwf‹„pxV4f‹„qxV4f‹„rxV4fo‹„sxV4f‹„txV4f‹„$xV4f‹„uxV4f‹„vxV4f‹„wxV4dev86-0.16.21/as/obj1/each.obj000066400000000000000000000013131231050321700154370ustar00rootroot00000000000000£†*7‡UUUU‡@Ï €;eachmanyalot @7Õ Ô ?fµfµf#µcµfbµf¼µf½µ@Ëf£µf»µf³µf«µÿµf˜˜øüúõf;µ¦f§@§f§µf™™'/ÿ µ÷4µÈô÷<µ÷,µä ÿµlfmmÍ Î@<µfÏÏuÿ$µŸfµfµÉµµfŵ@fĵf´µfµµf²µµ4µð¬f­­âfµ@µf‹µf‹µ"À¤f¥¥f¾µf¶µ÷$µ÷µ@÷µf µæ nfooµfaafÿ4µf``fœœÑµÑµ@ÑµÑ µóóóòòÃËžÑ$µÑ<µÑ$µÑ,µfµ®f¯¯@•µµ µf¤µf¬µµ$µùýûªf@«« µf+µf…µ$µ,µ› fÁµf‡µ×fG3µdev86-0.16.21/as/obj1/f.obj000066400000000000000000000003171231050321700147670ustar00rootroot00000000000000£†*«UUUU«f @ÜØØÁÜÁÜ3Ø3ØñÞÁß#ß3ØÜØÑØÑÝÁÝáÝáÞÚßÛß+ÙÝÛ+ÙÁÙ+Ù;Ù#Ý3Ù3Ý#@Ý;ßàÙÝÝÑ›Ù;›Ý;›ßà›Ý3›Ù3ÙÐÙàÙáÙäÙåÙèÙéÙêÙëÙìÙíÙîÙðÙñÙòÙóÙôÙõÙöÙk÷ÙøÙùÙúÙûÙüÙýÙþÙÿÚé›ÛàÛà›ÛáÛá›ÛâÛâ›ÛãÛãÛäÞÙdev86-0.16.21/as/obj1/fadd.obj000066400000000000000000000020551231050321700154410ustar00rootroot00000000000000£†*ÊSUUUUS@K €™€Æ)@ø1€!;€:D€EQ€)[@P`@µp€\{@º‰@æ@™™€ ž@°ª€Ä¶€u¿Å€¿Ð@.Ù€Oß@(è€Ëñ@®ú@¿€ €!faddSWAPSUBTRACT_BIGSHIFTTO_UNDERFLOWROUNDUPUNDERFLOWOVERFLOWADD_BIGSHIFTLOVERFLOWXBIGTO_ADD_BIGSHIFTNORMLITTLETO_NORMLITTLEROUNDNORMALIZEDONETO_SUBTRACTTO_OVERFLOWSUBTRACT_faddTO_ANSWER0faddfxfy_faccfsubfxfyfmulfxfyTO_DONE1NORMALIZE2DONE1ANSWER0 [fUf‰åg‹Fg‹Vg‹^ g‹N裀OB‰€S@f]Ãñ€UWV‰Ï‰Öæÿÿÿçÿÿÿ9þw r9Øs‡Ê‡þ“æÿÿçÿÿÎÏ@ÁéÁê‰Íf)Ñf÷Ùfƒù7s2f1Õfåu*€ù s*­Ý­ûÓïØþ)Ûf‰Ñfáÿ÷Æ@ té{ëbéÀé‹é¬÷½ÿtòfƒïf÷ßfQf‰ù¥Æ¥è¥ÝÓãfYf)ùr@;ý€w r…Ûu¨tƒÀƒÖ)í)Û÷Æ ufâf ÊÁâæÿÿ ò^_]Ã)Ò‰Ð@^_]ÃÑîÑØÑÝÑÛfAfùu¬ºàÿ)À^_]Àé ­Ý­ûÓïøƒÖ‡Ýé=ÿÿÿ¤Æ¤è@¤ÝÁã€ér±éJÿÿÿ)í€ù s­Ý­ûÓï÷ÝØþ)Ûf‰Ñfáÿé&ÿÿÿ€é ­Ý­ûÓï÷@Û÷݃ÛøƒÞ‡Ýf‰Ñfáÿéÿÿÿé]ÿÿÿëþéVÿÿÿUWV‰Ö‰ÏÁêÁéf‰Õf1Ífåf@âÿtÕfáÿtÎfÑférËfùÿwÂæÿÿçÿÿÎÏfQfU‰Á÷ã‰Õ“n÷æPR‰ð÷ç‰Ö‘÷çÅXЃÖZÕȃÖfZfYfƒÁ épþÿÿdev86-0.16.21/as/obj1/farcall.obj000066400000000000000000000001071231050321700161430ustar00rootroot00000000000000£†*%UUUUfarcall _šgÿgÿêÿ.gÿ.dev86-0.16.21/as/obj1/group1.obj000066400000000000000000000002211231050321700157510ustar00rootroot00000000000000£†*$iUUUUigroup1 @f4xV4€ÃfÃ4ÃxV4g€g€Gg€gf4gxV4g€gfƒýgƒýiÙfÙÙggfgggfgÙ Ù8ÙÙ(ÙÙ0Ùdev86-0.16.21/as/obj1/group6.obj000066400000000000000000000001031231050321700157550ustar00rootroot00000000000000£†*$UUUUgroup6 \ÐgÛgF ág,dev86-0.16.21/as/obj1/group7.obj000066400000000000000000000001221231050321700157570ustar00rootroot00000000000000£†*$+UUUU+group7 kgggg?gF ðg70ãdev86-0.16.21/as/obj1/imul.obj000066400000000000000000000002231231050321700155040ustar00rootroot00000000000000£†*"mUUUUmimul @öëö.f÷ëf÷.÷ë÷.f¯Ãf¯¯Ã¯fkÃfkkÃkgf¯g¯fkÀkÀfimÃ,fi,iÃà“ià“gf¯,¯à“fiÀ,iÀà“dev86-0.16.21/as/obj1/incdec.obj000066400000000000000000000002221231050321700157620ustar00rootroot00000000000000£†*$jUUUUjincdec @þÀþÄþÃþÇþÁþÅþÂþÆgÿgþf@fCfAfBfDfEfFfGgfÿ@CABDEFGgÿþÈþÌþËþÏþÉþjÍþÊþÎgÿgþfHfKfIfJfLfMfNfOgfÿHKIJLMNOgÿdev86-0.16.21/as/obj1/inher.obj000066400000000000000000000002361231050321700156470ustar00rootroot00000000000000£†*#wUUUUwinher @7?øüúõ¦'/ôÎlŸÉð¬¤nóóòž®ùýûª›˜™f˜f™§f§mfmÏfÏ­f­¥f¥ofoafaf`f`wœfœ¯f¯««××f˜f™˜™f§§fmmfÏÏf­­f¥¥foofaaff``fœœf¯¯f«f«××dev86-0.16.21/as/obj1/inout.obj000066400000000000000000000001221231050321700156720ustar00rootroot00000000000000£†*#,UUUU,inout líììfífííä äfå fåå åïîîfïfïïæ æfç fçeç çdev86-0.16.21/as/obj1/movspec.obj000066400000000000000000000013221231050321700162130ustar00rootroot00000000000000£†*% UUUU movspec @ À Ð Ø!À!È!Ð!Ø!ð!ø$Ø$à$è$ð$ø"À"Ð"Ø#À#È#Ð#Ø@#ð#ø&Ø&à&è&ð&ø Ã Ó Û!Ã!Ë!Ó!Û!ó!û$Û$ã$ë$ó$û"@Ã"Ó"Û#Ã#Ë#Ó#Û#ó#û&Û&ã&ë&ó&û Á Ñ Ù!Á!É!Ñ!Ù!ñ@!ù$Ù$á$é$ñ$ù"Á"Ñ"Ù#Á#É#Ñ#Ù#ñ#ù&Ù&á&é&ñ&ù Â@ Ò Ú!Â!Ê!Ò!Ú!ò!ú$Ú$â$ê$ò$ú"Â"Ò"Ú#Â#Ê#Ò#Ú#ò#@ú&Ú&â&ê&ò&ú Æ Ö Þ!Æ!Î!Ö!Þ!ö!þ$Þ$æ$î$ö$þ"Æ"Ö@"Þ#Æ#Î#Ö#Þ#ö#þ&Þ&æ&î&ö&þ Ç × ß!Ç!Ï!×!ß!÷!ÿ@$ß$ç$ï$÷$ÿ"Ç"×"ß#Ç#Ï#×#ß#÷#ÿ&ß&ç&ï&÷&ÿ Ä Ô @Ü!Ä!Ì!Ô!Ü!ô!ü$Ü$ä$ì$ô$ü"Ä"Ô"Ü#Ä#Ì#Ô#Ü#ô#ü&Ü@&ä&ì&ô&ü Å Õ Ý!Å!Í!Õ!Ý!õ!ý$Ý$å$í$õ$ý"Å"Õ"Ý`#Å#Í#Õ#Ý#õ#ý&Ý&å&í&õ&ýdev86-0.16.21/as/obj1/pushpop.obj000066400000000000000000000002371231050321700162410ustar00rootroot00000000000000£†*%vUUUUvpushpop @jgÿ7fjÿfPfSfQfRfTfUfVfWffff f¨fh4fh4gfÿ7PSQRTUVWhxV4vhxV4gÿ7gfXf[fYfZf\f]f^f_fff¡f©fgfX[YZ\]^_gdev86-0.16.21/as/obj1/seg.obj000066400000000000000000000000521231050321700153140ustar00rootroot00000000000000£†*!UUUUseg F.>&de6dev86-0.16.21/as/obj1/shdouble.obj000066400000000000000000000001521231050321700163440ustar00rootroot00000000000000£†*43UUUU3 @shdoubleILLEGALS sf¤Øf¤Ë¤òf¥Ù¤Ögf¤g¤gf¥g¥f¬Ëf­Ùdev86-0.16.21/as/obj1/shift.obj000066400000000000000000000004641231050321700156620ustar00rootroot00000000000000£†*# UUUU shift @ÒÐÒÔÒÓÒ×ÒÑÒÕÒÒÒÖgÓgÒfÓÐfÓÓfÓÑfÓÒfÓÔfÓÕfÓÖfÓ×gfÓÓÐÓÓÓÑÓÒÓÔÓÕÓÖ@Ó×gÓÐÐÐÔÐÓÐ×ÐÑÐÕÐÒÐÖgÑgÐfÑÐfÑÓfÑÑfÑÒfÑÔfÑÕfÑÖfÑ×gfÑÑÐÑÓÑÑÑÒÑ@ÔÑÕÑÖÑ×gÑÀÐÀÔÀÓÀ×ÀÑÀÕÀÒÀÖgÁgÀÀÐfÁÐfÁÓfÁÑfÁÒfÁÔ@fÁÕfÁÖfÁ×gfÁÁÐÁÓÁÑÁÒÁÔÁÕÁÖÁ×gÁfÁØfÁÀfÁÈfÁàfÁJøfÁàfÁèdev86-0.16.21/as/obj1/xchg.obj000066400000000000000000000004101231050321700154650ustar00rootroot00000000000000£†*"àUUUUàxchg @ff“f‘f’f”f•f–f—ff“f‘f’f”f•f–f—“‘’”•–—“‘’”•–—†À†à†Ø†ø†Ë†ë†Ó†ó@g†g†'g†g†?g†g†/g†g†7g†g†'g†g†?g†g†/g†g†7gf‡gf‡gf‡gf‡@gf‡'gf‡/gf‡7gf‡?gf‡gf‡gf‡gf‡gf‡'gf‡/gf‡7gf‡?g‡g‡g‡g‡g‡'g`‡/g‡7g‡?f‡f‡f‡ f‡f‡#f‡+f‡3f‡;dev86-0.16.21/as/opcode.h000066400000000000000000000050361231050321700146400ustar00rootroot00000000000000/* opcode.h - routine numbers and special opcodes for assembler */ enum { /* Pseudo-op routine numbers. * Conditionals are first - this is used to test if op is a conditional. */ ELSEOP, ELSEIFOP, ELSEIFCOP, ENDIFOP, IFOP, IFCOP, #define MIN_NONCOND ALIGNOP ALIGNOP, ASCIZOP, BLKWOP, BLOCKOP, BSSOP, COMMOP, COMMOP1, DATAOP, ENDBOP, ENTEROP, ENTRYOP, EQUOP, EVENOP, EXPORTOP, FAILOP, FCBOP, FCCOP, FDBOP, #if SIZEOF_OFFSET_T > 2 FQBOP, #endif GETOP, GLOBLOP, IDENTOP, IMPORTOP, LCOMMOP, LCOMMOP1, LISTOP, LOCOP, MACLISTOP, MACROOP, MAPOP, ORGOP, PROCEOFOP, RMBOP, SECTOP, SETOP, SETDPOP, TEXTOP, #ifdef I80386 USE16OP, USE32OP, #endif WARNOP, /* Machine-op routine numbers. */ #ifdef I80386 BCC, BSWAP, CALL, CALLI, DIVMUL, ENTER, EwGw, ExGx, F_INHER, F_M, F_M2, F_M2_AX, F_M2_M4, F_M2_M4_M8, F_M4_M8_OPTST, F_M4_M8_ST, F_M4_M8_STST, F_M4_M8_M10_ST, F_M10, F_OPTST, F_ST, F_STST, F_W_INHER, F_W_M, F_W_M2, F_W_M2_AX, GROUP1, GROUP2, GROUP6, GROUP7, GROUP8, GvEv, GvMa, GvMp, IMUL, IN, INCDEC, INHER, INHER16, INHER32, INHER_A, INT, JCC, JCXZ, LEA, MOV, MOVX, NEGNOT, OUT, PUSHPOP, RET, SEG, SETCC, SH_DOUBLE, TEST, XCHG #endif /* I80386 */ #ifdef MC6809 ALL, /* all address modes allowed, like LDA */ ALTER, /* all but immediate, like STA */ IMMED, /* immediate only (ANDCC, ORCC) */ INDEXD, /* indexed (LEA's) */ INHER, /* inherent, like CLC or CLRA */ LONG, /* long branches */ SHORT, /* short branches */ SSTAK, /* S-stack (PSHS, PULS) */ SWAP, /* TFR, EXG */ USTAK /* U-stack (PSHU,PULU) */ #endif /* MC6809 */ }; /* Special opcodes. */ #ifdef I80386 # define CMP_OPCODE_BASE 0x38 # define CMPSB_OPCODE 0xA6 # define CMPSW_OPCODE 0xA7 # define ESCAPE_OPCODE_BASE 0xD8 # define FST_ENCODED 0x12 # define FSTP_ENCODED 0x13 # define JMP_OPCODE 0xE9 # define JMP_SHORT_OPCODE 0xEB # define JSR_OPCODE 0xE8 # define MOVSB_OPCODE 0xA4 # define MOVSW_OPCODE 0xA5 # define PAGE1_OPCODE 0x0F # define POP_OPCODE 0x8F # define PUSH_OPCODE 0xFF # define WAIT_OPCODE 0x9B #endif #ifdef MC6809 # define JMP_OPCODE 0x7E # define JSR_OPCODE 0xBD # define PAGE1_OPCODE 0x10 # define PAGE2_OPCODE 0x11 #endif dev86-0.16.21/as/pops.c000066400000000000000000000471331231050321700143470ustar00rootroot00000000000000/* pops.c - handle pseudo-ops for assembler */ #include "syshead.h" #include "const.h" #include "type.h" #include "address.h" #include "flag.h" #include "globvar.h" #include "opcode.h" #include "scan.h" PRIVATE bool_t elseflag; /* set if ELSE/ELSEIF are enabled */ /* depends on zero = FALSE init */ PRIVATE bool_t lcommflag; FORWARD void bumpsem P((struct flags_s *flagptr, int defval)); FORWARD void constdata P((unsigned size)); FORWARD void docomm P((void)); FORWARD void doelseif P((pfv func)); FORWARD void doequset P((int labits)); FORWARD void doentexp P((int entbits, int impbits)); FORWARD void dofcc P((void)); FORWARD void doif P((pfv func)); FORWARD struct sym_s *needlabel P((void)); FORWARD void showredefinedlabel P((void)); FORWARD void setloc P((unsigned seg)); PRIVATE void bumpsem(flagptr, defval) register struct flags_s *flagptr; int defval; { int newcount; if (flagptr->global && pass == last_pass) { /* bump semaphore count by an expression (default 1), */ /* then set currentflag iff semaphore count is plus */ if (sym == EOLSYM) lastexp.offset = defval; else { absexpres(); if (lastexp.data & UNDBIT) return; } newcount = (int) lastexp.offset; #ifdef I80386 /* really sizeof (offset_t) != sizeof (int) */ if (newcount != lastexp.offset) datatoobig(); #endif newcount += flagptr->semaphore; if ((int) lastexp.offset >= 0) { if (newcount < flagptr->semaphore) { error(COUNTOV); newcount = 0x7fff; } } else if (newcount >= flagptr->semaphore) { error(COUNTUN); newcount = -0x8000; } flagptr->semaphore = newcount; flagptr->current = newcount >= 0; } } /* check symbol is either undefined */ /* or has the same segment & relocatability as lc */ PUBLIC bool_pt checksegrel(symptr) register struct sym_s *symptr; { if ((symptr->type & LABIT || (symptr->data & IMPBIT && !(symptr->data & UNDBIT))) && ((symptr->data ^ lcdata) & (RELBIT | SEGM))) { error(SEGREL); return FALSE; } return TRUE; } /* check address fits in 1 byte (possibly with sign truncated) */ PUBLIC void checkdatabounds() { if (!(lastexp.data & UNDBIT) && (offset_t) (lastexp.offset + 0x80) >= 0x180) datatoobig(); } /* allocate constant data (zero except for size 1), default zero for size 1 */ PRIVATE void constdata(size) unsigned size; { offset_t remaining; absexpres(); if (!((lcdata |= lastexp.data) & UNDBIT)) { lcjump = lastexp.offset * size; popflags = POPLONG | POPHI | POPLO | POPLC; if (size == 1 && sym == COMMA) { symabsexpres(); checkdatabounds(); for (remaining = lcjump; remaining != 0; --remaining) { putbin((opcode_pt) lastexp.offset); /* fill byte */ putabs((opcode_pt) lastexp.offset); } lastexp.offset = lcjump; } else accumulate_rmb(lastexp.offset * size); } } PUBLIC void datatoobig() { error(DBOUNDS); } /* common routine for COMM/.COMM */ PRIVATE void docomm() { register struct sym_s *labptr; absexpres(); /* if undefined, value 0 and size unchanged */ labptr = label; if (checksegrel(labptr)) { if (labptr->type & (EXPBIT | LABIT)) labelerror(ALREADY); else { if (!(labptr->type & COMMBIT) || lastexp.offset > labptr->value_reg_or_op.value) labptr->value_reg_or_op.value = lastexp.offset; labptr->type |= COMMBIT; if (lcommflag) labptr->type |= REDBIT; /* kludge - COMMBIT | REDBIT => SA */ if( last_pass == 1 ) labptr->data = (lcdata & SEGM) | (FORBIT | IMPBIT | RELBIT); else labptr->data = (lcdata & SEGM) | (IMPBIT | RELBIT); showlabel(); } } lcommflag = FALSE; } /* common routine for ELSEIF/ELSEIFC */ PRIVATE void doelseif(func) pfv func; { if (iflevel == 0) error(ELSEIFBAD); else { ifflag = FALSE; if (elseflag) { (*func) (); if (!(lastexp.data & UNDBIT) && lastexp.offset != 0) /* expression valid and TRUE, enable assembling */ { ifflag = TRUE; elseflag = FALSE; } } else { /* Skip to EOL */ while (sym != EOLSYM) getsym(); } } } /* common routine for EQU/SET */ PRIVATE void doequset(labits) unsigned char labits; { register struct sym_s *labptr; unsigned char olddata; unsigned char oldtype; labptr = label; /* set up new label flags in case labe isl used in expression */ labptr->type = (oldtype = labptr->type) | labits; labptr->data = (olddata = labptr->data) & ~IMPBIT; /* non-imported now */ nonimpexpres(); lastexp.data |= olddata & FORBIT; /* take all but FORBIT from expression */ if (oldtype & LABIT && !(olddata & UNDBIT) && !pass) /* this is a previously defined label */ /* redefinition only allowed if same relocatability, segment and value */ { if ((olddata ^ lastexp.data) & (RELBIT | UNDBIT) || labptr->value_reg_or_op.value != lastexp.offset) { showredefinedlabel(); return; } } labptr->data = lastexp.data; labptr->value_reg_or_op.value = lastexp.offset; showlabel(); if(pass && !(labits & VARBIT) && labptr->value_reg_or_op.value != oldlabel) { dirty_pass = TRUE; if( pass == last_pass ) error(UNSTABLE_LABEL); } } /* common routine for ENTRY/EXPORT */ PRIVATE void doentexp(entbits, impbits) unsigned char entbits; unsigned char impbits; { struct sym_s *symptr; while (TRUE) { if ((symptr = needlabel()) != NUL_PTR) { if (symptr->type & COMMBIT) error(ALREADY); else if (impbits != 0) { if (pass == last_pass) ; else if (symptr->type & (EXPBIT | LABIT)) symptr->type |= EXPBIT; else { symptr->type |= REDBIT; if (!(symptr->data & IMPBIT)) symptr->data |= IMPBIT | SEGM; } } else { if (pass == last_pass) { if (!(symptr->type & LABIT)) error(UNLAB); } else { symptr->type |= entbits | EXPBIT; symptr->data &= ~IMPBIT; } } } getsym(); if (sym != COMMA) break; getsym(); } } /* common routine for FCC (== .ASCII) and .ASCIZ */ PRIVATE void dofcc() { register char *bufptr; char byte; char delimiter; register char *reglineptr; bufptr = databuf.fcbuf; reglineptr = symname; if ((delimiter = *reglineptr) != EOLCHAR) ++reglineptr; while (TRUE) { if ((byte = *reglineptr) == EOLCHAR) { symname = reglineptr; error(DELEXP); break; } if (byte == delimiter) { if ((byte = *++reglineptr) != delimiter) break; } else if (byte == '\\') { switch (byte = *++reglineptr) { case '"': case '\'': case '\\': case '?': break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': byte -= '0'; if (*(reglineptr + 1) >= '0' && *(reglineptr + 1) < '8') { byte = 8 * byte + *++reglineptr - '0'; if (*(reglineptr + 1) >= '0' && *(reglineptr + 1) < '8') byte = 8 * byte + *++reglineptr - '0'; } break; case 'a': byte = 7; break; case 'b': byte = 8; break; case 'f': byte = 12; break; case 'n': byte = 10; break; case 'r': byte = 13; break; case 't': byte = 9; break; case 'v': byte = 11; break; case 'x': byte = '0'; while (TRUE) { ++reglineptr; if (*reglineptr >= '0' && *reglineptr <= '9') byte = 16 * byte + *reglineptr - '0'; else if (*reglineptr >= 'F' && *reglineptr <= 'F') byte = 16 * byte + *reglineptr - 'A'; else if (*reglineptr >= 'a' && *reglineptr <= 'f') byte = 16 * byte + *reglineptr - 'F'; else break; } --reglineptr; break; default: symname = reglineptr; error(UNKNOWN_ESCAPE_SEQUENCE); break; } } else if (byte < ' ' && byte >= 0) { symname = reglineptr; error(CTLINS); byte = ' '; } ++reglineptr; *bufptr++ = byte; } lineptr = reglineptr; getsym(); lastexp.offset = databuf.fcbuf[0]; /* show only 1st char (if any) */ mcount = bufptr - databuf.fcbuf; /* won't overflow, line length limits it */ /* XXX - but now line length is unlimited */ } /* common routine for IF/IFC */ PRIVATE void doif(func) pfv func; { if (iflevel >= MAXIF) error(IFOV); else { ++iflevel; --ifstak; ifstak->elseflag = elseflag; elseflag = FALSE; /* prepare */ if ((ifstak->ifflag = ifflag) != FALSE) /* else not assembling before, so not now & no ELSE's */ { (*func) (); if (!(lastexp.data & UNDBIT) && lastexp.offset == 0) /* else expression invalid or FALSE, don't change flags */ { ifflag = FALSE; /* not assembling */ elseflag = TRUE;/* but ELSE will change that */ } } else { /* Skip to EOL */ while (sym != EOLSYM) getsym(); } } } PUBLIC void fatalerror(err_str) char * err_str; { error(err_str); skipline(); listline(); finishup(); } /* swap position with label position, do error, put back posn */ /* also clear label ptr */ PUBLIC void labelerror(err_str) char * err_str; { struct sym_s *oldgsymptr; char *oldlineptr; unsigned char oldsym; char *oldsymname; oldgsymptr = gsymptr; oldlineptr = lineptr; oldsym = sym; oldsymname = symname; lineptr = linebuf; getsym(); /* 1st symbol is label or symbol after * missing one */ error(err_str); gsymptr = oldgsymptr; lineptr = oldlineptr; sym = oldsym; symname = oldsymname; label = NUL_PTR; } PRIVATE struct sym_s *needlabel() { register struct sym_s *symptr; if (sym != IDENT || (symptr = gsymptr)->type & (MACBIT | MNREGBIT | VARBIT)) { error(LABEXP); return NUL_PTR; } return symptr; } /* .ALIGN pseudo-op */ PUBLIC void palign() { absexpres(); if (!((lcdata |= lastexp.data) & UNDBIT)) { popflags = POPLONG | POPHI | POPLO | POPLC; if (lastexp.offset != 0 && (lcjump = lc % lastexp.offset) != 0) accumulate_rmb(lcjump = lastexp.offset - lcjump); } } /* .ASCIZ pseudo-op */ PUBLIC void pasciz() { dofcc(); databuf.fcbuf[mcount++] = 0; fcflag = TRUE; popflags = POPLO | POPLC; } /* .BLKW pseudo-op */ PUBLIC void pblkw() { constdata(2); } /* BLOCK pseudo-op */ PUBLIC void pblock() { if (blocklevel >= MAXBLOCK) error(BLOCKOV); else { register struct block_s *blockp; ++blocklevel; blockp = blockstak; blockstak = --blockp; blockp->data = lcdata; blockp->dp = dirpag; blockp->lc = lc; porg(); /* same as ORG apart from stacking */ } } /* .BSS pseudo-op */ PUBLIC void pbss() { setloc(BSSLOC); } /* COMM pseudo-op */ PUBLIC void pcomm() { if (label == NUL_PTR) labelerror(MISLAB); else if (label->type & VARBIT) labelerror(VARLAB); /* variable cannot be COMM'd */ else docomm(); } /* .COMM pseudo-op */ PUBLIC void pcomm1() { unsigned oldseg; if (label != NUL_PTR) labelerror(ILLAB); oldseg = lcdata & SEGM; setloc(BSSLOC); if ((label = needlabel()) != NUL_PTR && checksegrel(label)) { /* Like import. */ if (label->type & (EXPBIT | LABIT)) error(ALREADY); else if( last_pass == 1 ) label->data = lcdata | (FORBIT | IMPBIT | RELBIT); else label->data = lcdata | (IMPBIT | RELBIT); getsym(); getcomma(); if (label->type & (EXPBIT | LABIT)) absexpres(); /* just to check it */ else docomm(); } setloc(oldseg); } /* .DATA pseudo-op */ PUBLIC void pdata() { setloc(DATALOC); } /* ELSE pseudo-op */ PUBLIC void pelse() { if (iflevel == 0) error(ELSEBAD); else { ifflag = FALSE; /* assume ELSE disabled */ if (elseflag) { ifflag = TRUE; /* ELSE enabled */ elseflag = FALSE; } } } /* ELSEIF pseudo-op */ PUBLIC void pelseif() { doelseif(absexpres); } /* ELSEIFC pseudo-op */ PUBLIC void pelsifc() { doelseif(scompare); } /* ENDB pseudo-op */ PUBLIC void pendb() { if (label != NUL_PTR) labelerror(ILLAB); if (blocklevel == 0) error(ENDBBAD); else { register struct block_s *blockp; blockp = blockstak; lcdata = blockp->data; dirpag = blockp->dp; accumulate_rmb(blockp->lc - lc); lc = blockp->lc; --blocklevel; blockstak = blockp + 1; } } /* ENDIF pseudo-op */ PUBLIC void pendif() { if (iflevel == 0) error(ENDIFBAD); else { ifflag = ifstak->ifflag; elseflag = ifstak->elseflag; ++ifstak; --iflevel; } } /* ENTER pseudo-op */ PUBLIC void penter() { if (!(pedata & UNDBIT)) error(REENTER); else { if (!((pedata = (pedata & ~UNDBIT) | lcdata) & UNDBIT)) { progent = lc; popflags = POPLC; } } } /* ENTRY pseudo-op */ PUBLIC void pentry() { doentexp(ENTBIT, 0); } /* EQU pseudo-op */ PUBLIC void pequ() { register struct sym_s *labptr; if ((labptr = label) == NUL_PTR) labelerror(MISLAB); else if (labptr->type & COMMBIT) showredefinedlabel(); /* common cannot be EQU'd */ else if (labptr->type & VARBIT) labelerror(VARLAB); /* variable cannot be EQU'd */ else doequset(LABIT); } /* .EVEN pseudo-op */ PUBLIC void peven() { popflags = POPLONG | POPHI | POPLO | POPLC; accumulate_rmb(lcjump = lastexp.data = lc & 1); } /* EXPORT pseudo-op */ PUBLIC void pexport() { doentexp(0, 0); } /* FAIL pseudo-op */ PUBLIC void pfail() { if(pass==last_pass) error(FAILERR); } /* FCB pseudo-op */ PUBLIC void pfcb() { char *bufptr; offset_t firstbyte; bufptr = databuf.fcbuf; absexpres(); firstbyte = lastexp.offset; while (TRUE) { checkdatabounds(); *bufptr++ = lastexp.offset; ++mcount; /* won't overflow, line length limits it */ if (sym != COMMA) break; symabsexpres(); } lastexp.offset = firstbyte; popflags = POPLO | POPLC; fcflag = TRUE; } /* FCC pseudo-op */ PUBLIC void pfcc() { dofcc(); if (mcount != 0) { fcflag = TRUE; popflags = POPLO | POPLC; } } /* FDB pseudo-op */ PUBLIC void pfdb() { struct address_s *adrptr; unsigned firstdata; offset_t firstword; adrptr = databuf.fdbuf; expres(); firstword = lastexp.offset; firstdata = lastexp.data; while (TRUE) { *adrptr++ = lastexp; mcount += 2; /* won't overflow, line length limits it */ if (sym != COMMA) break; symexpres(); } lastexp.offset = firstword; lastexp.data = firstdata; popflags = POPHI | POPLO | POPLC; fdflag = TRUE; } #if SIZEOF_OFFSET_T > 2 /* FQB pseudo-op */ PUBLIC void pfqb() { struct address_s *adrptr; offset_t firstdata; offset_t firstword; adrptr = databuf.fqbuf; expres(); firstword = lastexp.offset; firstdata = lastexp.data; while (TRUE) { *adrptr++ = lastexp; mcount += 4; /* won't overflow, line length limits it */ if (sym != COMMA) break; symexpres(); } lastexp.offset = firstword; lastexp.data = firstdata; popflags = POPLONG | POPHI | POPLO | POPLC; fqflag = TRUE; } #endif /* SIZEOF_OFFSET_T > 2 */ /* .GLOBL pseudo-op */ PUBLIC void pglobl() { if (binaryg) error(NOIMPORT); doentexp(0, IMPBIT); } /* IDENT pseudo-op (not complete) */ PUBLIC void pident() { if (sym != IDENT) error(LABEXP); else getsym_nolookup(); /* should save ident string */ } /* IF pseudo-op */ PUBLIC void pif() { doif(absexpres); } /* IFC pseudo-op */ PUBLIC void pifc() { doif(scompare); } /* IMPORT pseudo-op */ PUBLIC void pimport() { struct sym_s *symptr; if (binaryg) error(NOIMPORT); while (TRUE) { if ((symptr = needlabel()) != NUL_PTR && checksegrel(symptr)) { if (symptr->type & (COMMBIT | EXPBIT | LABIT)) /* IMPORT is null if label (to be) declared */ error(ALREADY); else if( last_pass == 1 ) /* get current segment from lcdata, no need to mask rest */ symptr->data = lcdata | (FORBIT | IMPBIT | RELBIT); else symptr->data = lcdata | (IMPBIT | RELBIT); } getsym(); if (sym != COMMA) break; getsym(); } } /* LCOMM pseudo-op */ PUBLIC void plcomm() { lcommflag = TRUE; pcomm(); } /* .LCOMM pseudo-op */ PUBLIC void plcomm1() { lcommflag = TRUE; pcomm1(); } /* .LIST pseudo-op */ PUBLIC void plist() { bumpsem(&list, 1); } /* .NOLIST pseudo-op */ PUBLIC void pnolist() { bumpsem(&list, -1); } /* LOC pseudo-op */ PUBLIC void ploc() { if (label != NUL_PTR) labelerror(ILLAB); absexpres(); if (!(lastexp.data & UNDBIT)) { if (lastexp.offset >= NLOC) datatoobig(); else setloc((unsigned) lastexp.offset); } } /* .MACLIST pseudo-op */ PUBLIC void pmaclist() { bumpsem(&maclist, 1); } /* .MAP pseudo-op */ PUBLIC void pmap() { absexpres(); if (!(lastexp.data & UNDBIT)) { mapnum = lastexp.offset; popflags = POPLO; if (lastexp.offset >= 0x100) datatoobig(); } } /* ORG pseudo-op */ PUBLIC void porg() { if (label != NUL_PTR) labelerror(ILLAB); absexpres(); if (!((lcdata = lastexp.data) & UNDBIT)) { accumulate_rmb(lastexp.offset - lc); binmbuf = lc = lastexp.offset; binmbuf_set = 1; popflags = POPLC; } } /* RMB pseudo-op */ PUBLIC void prmb() { constdata(1); } /* .SECT pseudo-op */ PUBLIC void psect() { if (label != NUL_PTR) labelerror(ILLAB); while (sym == IDENT) { if (!(gsymptr->type & MNREGBIT)) error(ILL_SECTION); else switch (gsymptr->value_reg_or_op.op.routine) { case BSSOP: pbss(); break; case DATAOP: pdata(); break; case TEXTOP: ptext(); break; default: error(ILL_SECTION); break; } getsym(); if (sym == COMMA) getsym(); } } /* SET pseudo-op */ PUBLIC void pset() { register struct sym_s *labptr; if ((labptr = label) == NUL_PTR) labelerror(MISLAB); else if (labptr->type & COMMBIT) labelerror(RELAB); /* common cannot be SET'd */ else doequset(labptr->type & LABIT ? 0 : VARBIT); } /* SETDP pseudo-op */ PUBLIC void psetdp() { absexpres(); if (!(lastexp.data & UNDBIT)) { dirpag = lastexp.offset; popflags = POPLO; if (lastexp.offset >= 0x100) datatoobig(); } } /* .TEXT pseudo-op */ PUBLIC void ptext() { if( textseg <= 0 ) setloc(TEXTLOC); else setloc(textseg); } /* .WARN pseudo-op */ PUBLIC void pwarn() { bumpsem(&as_warn, -1); } #ifdef I80386 /* USE16 pseudo-op */ PUBLIC void puse16() { defsize = 2; #ifdef iscpu if( sym != EOLSYM ) { absexpres(); if (lastexp.data & UNDBIT) return; if( lastexp.offset > 8000 ) setcpu((int) lastexp.offset / 100 % 10); else if( lastexp.offset > 15 ) setcpu((int) lastexp.offset / 100); else setcpu((int) lastexp.offset); } #endif } /* USE16 pseudo-op */ PUBLIC void puse32() { defsize = 4; #ifdef iscpu if(!iscpu(3)) setcpu(3); if( sym != EOLSYM ) { absexpres(); if (lastexp.data & UNDBIT) return; if( lastexp.offset > 15 ) setcpu((int) lastexp.offset / 100); else setcpu((int) lastexp.offset); } #endif } #endif /* show redefined label and error, and set REDBIT */ PRIVATE void showredefinedlabel() { register struct sym_s *labptr; labptr = label; /* showlabel() will kill label prematurely */ showlabel(); if (!(labptr->type & REDBIT)) { labptr->type |= REDBIT; labelerror(RELAB); } } PUBLIC void showlabel() { register struct sym_s *labptr; labptr = label; lastexp.data = labptr->data; lastexp.offset = labptr->value_reg_or_op.value; popflags = POPLONG | POPHI | POPLO; label = NUL_PTR; /* show handled by COMM, EQU or SET */ } /* set location segment */ PRIVATE void setloc(seg) unsigned seg; { if (pass == last_pass && seg != (lcdata & SEGM)) putobj((opcode_pt) (seg | OBJ_SET_SEG)); { register struct lc_s *lcp; lcp = lcptr; lcp->data = lcdata; lcp->lc = lc; lcptr = lcp = lctab + (unsigned char) seg; lcdata = (lcp->data & ~SEGM) | (unsigned char) seg; binmbuf = lc = lcp->lc; popflags = POPLC; } } dev86-0.16.21/as/proto.h000066400000000000000000000122221231050321700145250ustar00rootroot00000000000000/* extern functions */ /* as.c */ int main P((int argc, char **argv)); void as_abort P((char *message)); void finishup P((void)); void initp1p2 P((void)); void line_zero P((void)); /* assemble.c */ void assemble P((void)); /* express.c */ void absexpres P((void)); void chkabs P((void)); void nonimpexpres P((void)); void showrelbad P((void)); void symabsexpres P((void)); void symexpres P((void)); void expres P((void)); void factor P((void)); void scompare P((void)); /* genbin.c */ void binheader P((void)); void bintrailer P((void)); void genbin P((void)); void initbin P((void)); void putbin P((int ch)); /* genlist.c */ char *build_2hex_number P((unsigned num, char *where)); char *build_number P((unsigned num, unsigned width, char *where)); void warning P((char * errorstr)); void error P((char * errorstr)); void listline P((void)); void writec P((int ch)); void writenl P((void)); void writeoff P((offset_t offset)); void writes P((char *s)); void writesn P((char *s)); void writew P((unsigned word)); /* genobj.c */ void accumulate_rmb P((offset_t offset)); void flushobj P((void)); void genobj P((void)); void initobj P((void)); void objheader P((void)); void objtrailer P((void)); void putabs P((opcode_pt ch)); void putobj P((opcode_pt ch)); /* gensym.c */ void gensym P((void)); /* macro.c */ void entermac P((struct sym_s *symptr)); void pmacro P((void)); /* mops.c */ #ifdef I80386 void mbcc P((void)); void mbswap P((void)); void mcall P((void)); void mcalli P((void)); void mdivmul P((void)); void menter P((void)); void mEwGw P((void)); void mExGx P((void)); void mf_inher P((void)); void mf_m P((void)); void mf_m2 P((void)); void mf_m2_ax P((void)); void mf_m2_m4 P((void)); void mf_m2_m4_m8 P((void)); void mf_m4_m8_optst P((void)); void mf_m4_m8_st P((void)); void mf_m4_m8_stst P((void)); void mf_m4_m8_m10_st P((void)); void mf_m10 P((void)); void mf_optst P((void)); void mf_st P((void)); void mf_stst P((void)); void mf_w_inher P((void)); void mf_w_m P((void)); void mf_w_m2 P((void)); void mf_w_m2_ax P((void)); void mgroup1 P((void)); void mgroup2 P((void)); void mgroup6 P((void)); void mgroup7 P((void)); void mgroup8 P((void)); void mGvEv P((void)); void mGvMa P((void)); void mGvMp P((void)); void mimul P((void)); void min P((void)); void mincdec P((void)); void minher P((void)); void minher16 P((void)); void minher32 P((void)); void minhera P((void)); void mint P((void)); void mjcc P((void)); void mjcxz P((void)); void mlea P((void)); void mmov P((void)); void mmovx P((void)); void mnegnot P((void)); void mout P((void)); void mpushpop P((void)); void mret P((void)); void mseg P((void)); void msetcc P((void)); void mshdouble P((void)); void mtest P((void)); void mxchg P((void)); #endif /* I80386 */ #ifdef MC6809 void mall P((void)); void malter P((void)); void mimmed P((void)); void mindex P((void)); void minher P((void)); void mlong P((void)); void msstak P((void)); void mswap P((void)); void mustak P((void)); #endif /* MC6809 */ void getcomma P((void)); void mshort P((void)); /* pops.c */ bool_pt checksegrel P((struct sym_s *symptr)); void checkdatabounds P((void)); void datatoobig P((void)); void fatalerror P((char * errorstr)); void labelerror P((char * errorstr)); void palign P((void)); void pasciz P((void)); void pblkw P((void)); void pblock P((void)); void pbss P((void)); void pcomm P((void)); void pcomm1 P((void)); void pdata P((void)); void pelse P((void)); void pelseif P((void)); void pelsifc P((void)); void pendb P((void)); void pendif P((void)); void penter P((void)); void pentry P((void)); void pequ P((void)); void peven P((void)); void pexport P((void)); void pfail P((void)); void pfcb P((void)); void pfcc P((void)); void pfdb P((void)); #if SIZEOF_OFFSET_T > 2 void pfqb P((void)); #endif void pglobl P((void)); void pident P((void)); void pif P((void)); void pifc P((void)); void pimport P((void)); void plcomm P((void)); void plcomm1 P((void)); void plist P((void)); void pnolist P((void)); void ploc P((void)); void pmaclist P((void)); void pmap P((void)); void porg P((void)); void prmb P((void)); void psect P((void)); void pset P((void)); void psetdp P((void)); void ptext P((void)); void puse16 P((void)); void puse32 P((void)); void pwarn P((void)); void showlabel P((void)); /* readsrc.c */ void initsource P((void)); fd_t open_input P((char *name)); void pget P((void)); void pproceof P((void)); void readline P((void)); void skipline P((void)); /* scan.c */ void context_hexconst P((void)); void getsym P((void)); void getsym_nolookup P((void)); void initscan P((void)); /* table.c */ void inst_keywords P((void)); struct sym_s *lookup P((void)); void statistics P((void)); /* type.c */ u2_pt c2u2 P((char *buf)); u4_t c4u4 P((char *buf)); u2_pt cnu2 P((char *buf, unsigned count)); u4_t cnu4 P((char *buf, unsigned count)); void u2c2 P((char *buf, u16_pt offset)); void u4c4 P((char *buf, u32_T offset)); void u2cn P((char *buf, u16_pt offset, unsigned count)); void u4cn P((char *buf, u32_T offset, unsigned count)); bool_pt typeconv_init P((bool_pt big_endian, bool_pt long_big_endian)); /* alloc.c */ void * asalloc P((unsigned int size)); void * asrealloc P((void * oldptr, unsigned int size)); void * temp_buf P((void)); void init_heap P((void)); dev86-0.16.21/as/readsrc.c000066400000000000000000000253221231050321700150050ustar00rootroot00000000000000/* readsrc.c - read source files for assembler */ #include "syshead.h" #include "const.h" #include "type.h" #include "flag.h" #include "file.h" #include "globvar.h" #include "macro.h" #include "scan.h" #undef EXTERN #define EXTERN #include "source.h" /* * Ok, lots of hack & slash here. * 1) Added BIG buffer to load entire _primary_ file into memory. * 2) This means the primary file can be standard input. * 3) Fixed so 'get/include' processing now works. * 4) Altered for a 'normal' style buffer otherwise (MINIBUF) * 5) Have the option of completely unbuffered if you need the last Kb. * * RDB. */ #ifndef __AS386_16__ #ifndef BIGBUFFER #define BIGBUFFER 1 /* For most machines we have the memory */ #endif #endif #ifdef MSDOS #define off_t long /* Not a typedef! */ #endif #ifndef MINIBUF #define MINIBUF 1 /* Add in a reasonable buffer */ #endif struct get_s /* to record included files */ { fd_t fd; unsigned line; off_t position; }; PRIVATE char hid_filnambuf[FILNAMLEN + 1]; /* buffer for file name */ PRIVATE struct get_s hid_getstak[MAXGET]; /* GET stack */ PRIVATE struct get_s *getstak; /* ptr */ #if BIGBUFFER == 1 PRIVATE char *mem_start = 0, *mem_end; #endif PRIVATE char hid_linebuf[LINLEN]; /* line buffer */ PRIVATE char *eol_ptr; PRIVATE char *maclinebuf; PRIVATE char *maclineptr; #if MINIBUF == 1 PRIVATE void inp_seek P((int fd, long posn)); PRIVATE long inp_tell P((int fd)); PRIVATE int inp_line P((int fd, char * buf, int size)); #endif FORWARD void clearsource P((void)); FORWARD void line_too_long P((void)); PRIVATE void clearsource() { } PRIVATE void line_too_long() { symname = linebuf + (LINLEN - 1); /* spot for the error */ error(LINLONG); /* so error is shown in column LINLEN - 1 */ } /* initialise private variables */ PUBLIC void initsource() { filnamptr = hid_filnambuf; getstak = hid_getstak; clearsource(); /* sentinel to invoke blank skipping */ } PUBLIC fd_t open_input(name) char *name; { fd_t fd; #if BIGBUFFER == 1 off_t filelength = -1; if( mem_start == 0 && strcmp(name, "-") == 0 ) fd = 0; else #endif #ifdef O_BINARY if ((unsigned) (fd = open(name, O_RDONLY|O_BINARY)) > 255) as_abort("error opening input file"); #else if ((unsigned) (fd = open(name, O_RDONLY)) > 255) as_abort("error opening input file"); #endif #if BIGBUFFER == 1 if( mem_start == 0 ) { size_t memsize = 0; int cc; if(fd) { struct stat st; if( fstat(fd, &st) >= 0 ) filelength = st.st_size; if( filelength > (((unsigned)-1)>>1)-3 ) { mem_end = mem_start = "\n\n"; goto cant_do_this; } } if (filelength > 0) { if( (mem_start = malloc(filelength+4)) == 0 ) { mem_end = mem_start = "\n\n"; goto cant_do_this; } memsize = filelength; filelength = read(fd, mem_start, filelength); } else filelength = 0; for(;;) { if( filelength >= memsize ) { if (memsize > 16000) mem_start = asrealloc(mem_start, (memsize+=16384)+4); else mem_start = asrealloc(mem_start, (memsize+=memsize+32)+4); } cc = read(fd, mem_start+filelength, (size_t)(memsize-filelength)); if( cc <= 0 ) break; filelength+=cc; } *(mem_end=mem_start+filelength) = '\n'; mem_end[1] = '\0'; infiln = infil0 = 0; /* Assemble from memory */ if(fd) close(fd); fd = -1; } cant_do_this: #endif clearsource(); return fd; } /* handle GET pseudo_op stack state of current file, open new file and reset global state vars file must be seekable for the buffer discard/restore method to work */ PUBLIC void pget() { if (infiln >= MAXGET) error(GETOV); else { char save; skipline(); listline(); getstak->fd = infil; getstak->line = linum; if (infiln != 0) #if MINIBUF == 1 getstak->position = inp_tell(infil); #else getstak->position = lseek(infil, 0L, 1); #endif else getstak->position = (off_t)eol_ptr; ++getstak; ++infiln; linum = 0; for(lineptr=symname; *lineptr != EOLCHAR; lineptr++) if( *lineptr <= ' ' ) break; save = *lineptr; *lineptr = '\0'; infil = open_input(symname); *lineptr = save; getsym(); } } /* process end of file */ /* close file, unstack old file if current one is included */ /* otherwise switch pass 0 to pass 1 or exit on pass 2 */ /* end of file may be from phyical end of file or an END statement */ PUBLIC void pproceof() { if (infiln != 0) close(infil); if (infiln == infil0) /* all conditionals must be closed before end of main file (not GETs) */ { if (blocklevel != 0) error(EOFBLOCK); if (iflevel != 0) error(EOFIF); if (pass && (lcdata & UNDBIT)) error(EOFLC); lcptr->data = lcdata; lcptr->lc = lc; } /* macros must be closed before end of all files */ if (macload) error(EOFMAC); if (linebuf != lineptr) listline(); /* last line or line after last if error */ if (infiln != infil0) { --getstak; infil = getstak->fd; linum = getstak->line; if (--infiln == 0) eol_ptr = (void*)getstak->position; else #if MINIBUF == 1 inp_seek(infil, getstak->position); #else lseek(infil, getstak->position, 0); #endif } else if (pass!=last_pass) { pass++; if( last_pass>1 && last_pass<30 && dirty_pass && pass==last_pass ) last_pass++; if( pass==last_pass ) objheader(); /* while pass 1 data all valid */ binmbuf = 0; /* reset zero variables */ maclevel = iflevel = blocklevel = totwarn = toterr = linum = macnum = 0; initp1p2(); /* reset other varaiables */ if(pass==last_pass) binaryc = binaryg; #ifdef I80386 defsize = idefsize; cpuid = origcpuid; #endif if(pass==last_pass) { list.current = list.global; maclist.current = maclist.global; as_warn.current = TRUE; if (as_warn.semaphore < 0) as_warn.current = FALSE; } if (infiln != 0) infil = open_input(filnamptr); else eol_ptr=0; if(pass==last_pass) binheader(); line_zero(); } else finishup(); } /* read 1 line of source. Source line ends with '\n', line returned is null terminated without '\n'. Control characters other than blank, tab and newline are discarded. Long lines (length > LINLEN) are truncated, and an error is generated. On EOF, calls pproceof(), and gets next line unless loading a macro. This is where macro lines are recursively expanded. */ PUBLIC void readline() { int cc = 0; listpre = FALSE; /* not listed yet */ if (maclevel != 0) { register char *bufptr; /* hold *bufptr in a reg char variable */ register char *reglineptr; /* if possible (not done here) */ char *oldbufptr; struct schain_s *parameters; char paramnum; unsigned int remaining; /* space remaining in line + 2 */ /* value 0 not used except for temp predec */ /* value 1 means error already gen */ /* values 1 and 2 mean no space */ for (; maclevel != 0; macpar = macstak->parameters, ++macstak, --maclevel) if (*(bufptr = macstak->text) != ETB) /* nonempty macro, process it and return without continuing the for loop */ { if (!macflag) { maclinebuf = linebuf; maclineptr = lineptr; macflag = TRUE; } remaining = LINLEN + 2; lineptr = linebuf = reglineptr = hid_linebuf; while (*bufptr++ != EOLCHAR) { if (bufptr[-1] == MACROCHAR && *bufptr >= '0' && *bufptr <= '9') { parameters = macstak->parameters; for (paramnum = *bufptr++; paramnum-- != '0';) if ((parameters = parameters->next) == NUL_PTR) break; if (parameters != NUL_PTR) { for (oldbufptr = bufptr, bufptr = parameters->string; *bufptr++ != 0;) { if (--remaining <= 1) { if (remaining != 0) line_too_long(); remaining = 1; break; /* forget rest, param on 1 line */ } *reglineptr++ = bufptr[-1]; } bufptr = oldbufptr; } } else { if (--remaining <= 1) { if (remaining != 0) line_too_long(); remaining = 1; } else *reglineptr++ = bufptr[-1]; } } macstak->text = bufptr; #if 0 *reglineptr = 0; printf("MLINE:%s.\n", lineptr); #endif *reglineptr = EOLCHAR; return; } } if (macflag) { linebuf = maclinebuf; lineptr = maclineptr; macflag = FALSE; } /* End of macro expansion processing */ again: /* On EOF for main or included files */ ++linum; #if BIGBUFFER == 1 if( infiln == 0 ) { if( eol_ptr == 0 ) eol_ptr = mem_start-1; else *eol_ptr = '\n'; linebuf = lineptr = eol_ptr + 1; cc = (mem_end - linebuf); /* memchr not strchr 'cause some implementations of strchr are like: memchr(x,y,strlen(x)); this is _BAD_ with BIGBUFFER */ if((eol_ptr = memchr(linebuf, '\n', cc)) == 0 && cc > 0) cc = -1; } else #endif { lineptr = linebuf = hid_linebuf; *(hid_linebuf+sizeof(hid_linebuf)-2) = '\0'; /* Term */ #if MINIBUF == 1 cc = inp_line(infil, linebuf, sizeof(hid_linebuf)-2); if( cc >= 0 ) eol_ptr = linebuf+cc-1; #else cc = read(infil, linebuf, sizeof(hid_linebuf)-2); if( cc > 0 ) { eol_ptr = memchr(linebuf, '\n', cc); if( eol_ptr == 0 ) eol_ptr = hid_linebuf+sizeof(hid_linebuf)-2; else lseek(infil, (long)(eol_ptr+1-hid_linebuf)-cc, 1); } #endif } if( cc <= 0 ) { if( cc < 0 ) as_abort("error reading input"); clearsource(); pproceof(); listpre = FALSE; if (macload) { symname = lineptr; return; /* macro not allowed across eof */ } goto again; } #if 0 *eol_ptr = 0; printf("LINE:%s.\n", lineptr); #endif *eol_ptr = EOLCHAR; } PUBLIC void skipline() { if(macflag) lineptr = strchr(hid_linebuf, EOLCHAR); else lineptr = eol_ptr; } #if MINIBUF == 1 PRIVATE char input_buf[1024]; /* input buffer */ PRIVATE int in_start=0, in_end=0; PRIVATE long ftpos = 0; PRIVATE int lastfd = -1; PRIVATE int inp_line(fd, buf, size) int fd; char * buf; int size; { int offt = 0; if( fd!=lastfd ) inp_seek(-1, 0L); for(;;) { if(in_start >= in_end) { lastfd = -1; ftpos = lseek(fd, 0L, 1); in_start = 0; in_end = read(fd, input_buf, sizeof(input_buf)); if( in_end <=0 ) return in_end; lastfd = fd; } if( (buf[offt++] = input_buf[in_start++]) == '\n' || offt >= size ) break; } return offt; } PRIVATE long inp_tell(fd) int fd; { if( fd != lastfd ) return lseek(fd, 0L, 1); else return ftpos + in_start; } PRIVATE void inp_seek(fd, posn) int fd; long posn; { if( lastfd != -1 ) lseek(lastfd, ftpos+in_start, 0); lastfd = -1; in_end = 0; if( fd >= 0 ) lseek(fd, posn, 0); } #endif dev86-0.16.21/as/scan.c000066400000000000000000000143531231050321700143100ustar00rootroot00000000000000/* scan.c - lexical analyser for assembler */ #include "syshead.h" #include "const.h" #include "type.h" #include "globvar.h" #undef EXTERN #define EXTERN #include "scan.h" PRIVATE int numbase; /* base for number */ PRIVATE char symofchar[256] = /* table to convert chars to their symbols */ { EOLSYM, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, EOLSYM, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, EOLSYM, STRINGCONST, IMMEDIATE, /* !"# */ HEXCONST, BINCONST, ANDOP, CHARCONST, /* $%&' */ LPAREN, RPAREN, STAR, ADDOP, /* ()*+ */ COMMA, SUBOP, IDENT, SLASH, /* ,-./ */ INTCONST, INTCONST, INTCONST, INTCONST, /* 0123 */ INTCONST, INTCONST, INTCONST, INTCONST, /* 4567 */ INTCONST, INTCONST, COLON, EOLSYM, /* 89:; */ LESSTHAN, EQOP, GREATERTHAN, MACROARG, /* <=>? */ INDIRECT, IDENT, IDENT, IDENT, /* @ABC */ IDENT, IDENT, IDENT, IDENT, /* DEFG */ IDENT, IDENT, IDENT, IDENT, /* HIJK */ IDENT, IDENT, IDENT, IDENT, /* LMNO */ IDENT, IDENT, IDENT, IDENT, /* PQRS */ IDENT, IDENT, IDENT, IDENT, /* TUVW */ IDENT, IDENT, IDENT, LBRACKET, /* XYZ[ */ OTHERSYM, RBRACKET, OTHERSYM, IDENT, /* \]^_ */ OTHERSYM, IDENT, IDENT, IDENT, /* `abc */ IDENT, IDENT, IDENT, IDENT, /* defg */ IDENT, IDENT, IDENT, IDENT, /* hijk */ IDENT, IDENT, IDENT, IDENT, /* lmno */ IDENT, IDENT, IDENT, IDENT, /* pqrs */ IDENT, IDENT, IDENT, IDENT, /* tuvw */ IDENT, IDENT, IDENT, OTHERSYM, /* xyz{ */ OROP, OTHERSYM, NOTOP, OTHERSYM, /* |}~ */ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE }; FORWARD void intconst P((void)); PUBLIC void context_hexconst() { numbase = 16; intconst(); } PUBLIC void getsym() { register char *reglineptr; reglineptr = lineptr; advance: symname = reglineptr; switch (sym = symofchar[(unsigned char) *reglineptr++]) { case WHITESPACE: goto advance; case ADDOP: if (*reglineptr == '+') { sym = POSTINCOP; ++reglineptr; } break; case BINCONST: numbase = 2; lineptr = reglineptr; intconst(); return; case CHARCONST: if ((number = *reglineptr) < ' ') number = ' '; if (*reglineptr != EOL) ++reglineptr; sym = INTCONST; break; case GREATERTHAN: /* context-sensitive */ if (*reglineptr == '>') { sym = SROP; ++reglineptr; } break; case HEXCONST: numbase = 16; lineptr = reglineptr; intconst(); return; case IDENT: /* walk to end of identifier - magic INTCONST is max of INT, IDENT */ while (symofchar[(unsigned char) *reglineptr] <= INTCONST) ++reglineptr; lineptr = reglineptr; gsymptr = lookup(); return; case INTCONST: if (*(reglineptr - 1) == '0') { if (*reglineptr != 'x' && *reglineptr != 'X') numbase = 8; else { numbase = 16; ++reglineptr; } } else { --reglineptr; numbase = 10; } lineptr = reglineptr; intconst(); return; case LESSTHAN: /* context-sensitive */ if (*reglineptr == '<') { sym = SLOP; ++reglineptr; } break; case SUBOP: if (*reglineptr == '-') { sym = PREDECOP; ++reglineptr; } break; } lineptr = reglineptr; return; } PUBLIC void getsym_nolookup() { bool_t old_ifflag; old_ifflag = ifflag; ifflag = FALSE; getsym(); ifflag = old_ifflag; } PRIVATE void intconst() { register char *reglineptr; number = 0; reglineptr = lineptr; for (; *reglineptr >= '0'; ++reglineptr) { if (*reglineptr > '9') { if (numbase != 16) break; if (*reglineptr >= 'a' && *reglineptr <= 'f') { if (number != 0) number = numbase * number + (*reglineptr - 'a' + 10); else number = *reglineptr - 'a' + 10; } else if (*reglineptr >= 'A' && *reglineptr <= 'F') { if (number != 0) number = numbase * number + (*reglineptr - 'A' + 10); else number = *reglineptr - 'A' + 10; } else break; } else if (number != 0) number = numbase * number + (*reglineptr - '0'); else number = *reglineptr - '0'; } if (*reglineptr == 'L' || *reglineptr == 'l') ++reglineptr; sym = INTCONST; lineptr = reglineptr; } PUBLIC void initscan() { #ifndef MC6809 if (asld_compatible) { lindirect = LPAREN; rindexp = RPEXP; rindirect = RPAREN; } else { #endif lindirect = LBRACKET; rindexp = RBEXP; rindirect = RBRACKET; #ifndef MC6809 } #endif } dev86-0.16.21/as/scan.h000066400000000000000000000010051231050321700143030ustar00rootroot00000000000000/* scan.h - global variables for scanner for assembler */ #define EOLCHAR '\n' EXTERN struct sym_s *gsymptr; /* global symbol ptr */ EXTERN char lindirect; /* left symbol for indirect addressing */ EXTERN char *lineptr; /* current line position */ EXTERN offset_t number; /* constant number */ EXTERN char * rindexp; /* error code for missing rindirect */ EXTERN char rindirect; /* right symbol for indirect addressing */ EXTERN char sym; /* current symbol */ EXTERN char *symname; /* current symbol name */ dev86-0.16.21/as/source.h000066400000000000000000000002621231050321700146630ustar00rootroot00000000000000/* source.h - global variables for source handlers for assembler */ EXTERN unsigned linum; /* line # */ EXTERN bool_t listpre; /* flag to show line has already been listed */ dev86-0.16.21/as/syshead.h000066400000000000000000000026111231050321700150230ustar00rootroot00000000000000 #ifndef POSIX_HEADERS_MISSING #include #include #include #include #endif #ifndef STDC_HEADERS_MISSING #include #include #include #endif #ifdef MSDOS #include #include #include #include #undef min #undef POSIX_HEADERS_MISSING #define VERSION "MSDOS Compile" #endif #if __STDC__ && !defined(__minix) #define P(x) x #else #define P(x) () #endif #ifdef STDC_HEADERS_MISSING char *strcpy P((char *s1, const char *s2)); char *strrchr P((const char *s, int c)); int memcmp P((const void *s1, const void *s2, unsigned n)); int strcmp P((const char *s1, const char *s2)); int strncmp P((const char *s1, const char *s2, unsigned n)); unsigned strlen P((const char *s)); void *malloc P((unsigned size)); void *memset P((void *s, int c, unsigned n)); void exit P((int status)); #endif #ifdef POSIX_HEADERS_MISSING int close P((int fd)); int creat P((const char *path, int mode)); int open P((const char *path, int oflag, ...)); int read P((int fd, void *buf, unsigned nbytes)); int write P((int fd, const void *buf, unsigned nbytes)); typedef long off_t; off_t lseek P((int fd, off_t offset, int whence)); #define BIGBUFFER 0 /* Can't use a big buffer ... sorry */ #endif #ifndef O_RDONLY #define O_RDONLY 0 #endif #ifndef O_WRONLY #define O_WRONLY 1 #endif #ifndef O_RDWR #define O_RDWR 2 #endif dev86-0.16.21/as/table.c000066400000000000000000000121461231050321700144510ustar00rootroot00000000000000/* table.c - keyword tables and symbol table lookup for assembler */ #include "syshead.h" #include "const.h" #include "type.h" #include "globvar.h" #include "opcode.h" #include "scan.h" #define hconv(ch) ((unsigned char) (ch) - 0x41) /* better form for hashing */ #ifdef I80386 # ifdef MNSIZE EXTERN char bytesizeops[]; # endif #endif EXTERN char ops[]; EXTERN char page1ops[]; EXTERN char page2ops[]; EXTERN char regs[]; #ifdef I80386 EXTERN char typesizes[]; #endif #ifdef DEBUG_HASH unsigned nhash; unsigned nlookup; unsigned nsym; unsigned nx[30]; FORWARD void printchain P((void)); #endif FORWARD void install P((register char *keyptr, int data)); PUBLIC void inst_keywords() { install(regs, REGBIT); #ifdef I80386 install(typesizes, SIZEBIT); #endif install(ops, 0); install(page1ops, PAGE1); install(page2ops, PAGE2); #ifdef I80386 # ifdef MNSIZE install(bytesizeops, PAGE1 | PAGE2); # endif #endif } PRIVATE void install(keyptr, data) register char *keyptr; unsigned char data; { char lowcasebuf[20]; unsigned namelength; char *nameptr; char *namend; register struct sym_s *symptr; while (*keyptr != 0) { namelength = *keyptr++; lineptr = (symname = keyptr) + namelength; for (nameptr = lowcasebuf, namend = lowcasebuf + namelength; nameptr < namend;) { if (*keyptr < 'A' || *keyptr > 'Z') *nameptr++ = *keyptr++; else *nameptr++ = *keyptr++ + ('a' - 'A'); } symptr = lookup(); symptr->type = MNREGBIT; symptr->data = data; symptr->value_reg_or_op.op.routine = *keyptr; symptr->value_reg_or_op.op.opcode = keyptr[1]; lineptr = (symname = lowcasebuf) + namelength; symptr = lookup(); symptr->type = MNREGBIT; symptr->data = data; symptr->value_reg_or_op.op.routine = *keyptr; symptr->value_reg_or_op.op.opcode = keyptr[1]; keyptr += 2; } } /* Lookup() searches symbol table for the string from symname to lineptr - 1. * If string is not found and ifflag is TRUE, string is added to table, with * type = 0 * data = inidata (RELBIT | UNDBIT, possibly with IMPBIT | SEGM) * Returns pointer to symbol entry (NUL_PTR if not found and not installed) * unless symbol table overflows, when routine aborts. */ PUBLIC struct sym_s *lookup() { struct sym_s **hashptr; register char *nameptr; register struct sym_s *symptr; register unsigned hashval; register unsigned length; #ifdef DEBUG_HASH int tries; ++nlookup; tries = 0; #endif /* Hash function is a weighted xor of 1 to 4 chars in the string. * This works seems to work better than looking at all the chars. * It is important that the function be fast. * The string comparision function should also be fast and it helps * if it is optimized for mostly identical comparisions. * The multiplication by MULTIPLIER should compile as a shift. */ #define MULTIPLIER (SPTSIZ / (1 << USEFUL_BITS_IN_ASCII)) #define USEFUL_BITS_IN_ASCII 6 nameptr = lineptr; length = nameptr - symname; if (length <= 3) { if (length <= 2) hashval = hconv(nameptr[-1]) * MULTIPLIER; else hashval = hconv(nameptr[-2]) * MULTIPLIER, hashval ^= hconv(nameptr[-1]); } else hashval = hconv(symname[length-(length / 2)]) * MULTIPLIER, hashval ^= hconv(nameptr[-2]) << 2, hashval ^= hconv(nameptr[-1]); nameptr = symname; if ((symptr = *(hashptr = spt + (hashval ^ (hconv(nameptr[0]) << 1)) % SPTSIZ)) != NUL_PTR) { do { #ifdef DEBUG_HASH if (tries != 0) --nx[tries]; ++tries; if (tries < sizeof nx / sizeof nx[0]) ++nx[tries]; if (tries >= 5) printchain(hashptr - spt); #endif if ((unsigned char) length != symptr->length) continue; if (memcmp(symptr->name, nameptr, length) == 0) return symptr; } while ((symptr = symptr->next) != NUL_PTR); /* Calculate last non-NUL_PTR hash ptr. * This is faster than keeping hashptr up to date in previous loop * since most lookups are successful and hash ptr is not needed. */ do { symptr = *hashptr; hashptr = &symptr->next; } while (symptr->next != NUL_PTR); } if (!ifflag) return NUL_PTR; #ifdef DEBUG_HASH ++nsym; if (hashptr >= spt && hashptr < spt + SPTSIZ) ++nhash; #endif *hashptr = symptr = asalloc(sizeof(struct sym_s) + length); symptr->type = 0; symptr->data = inidata; symptr->length = length; symptr->value_reg_or_op.value = (offset_t) (symptr->next = NUL_PTR); memcpy(symptr->name, nameptr, length); symptr->name[length] = 0; return symptr; } #ifdef DEBUG_HASH static void printchain(hashval) unsigned hashval; { register struct sym_s *symptr; printf("%04x ", hashval); for (symptr = spt[hashval]; symptr != NUL_PTR; symptr = symptr->next) printf("%s ", symptr->name); printf("\n"); } #endif PUBLIC void statistics() { #ifdef DEBUG_HASH int i; int weight; for (i = 0; i < SPTSIZ; ++i) printchain(i); printf("nhash = %d, nsym = %d, nlookup = %d nx =\n", nhash, nsym, nlookup); weight = 0; for (i = 0; i < 30; ++i) { printf("%5d", nx[i]); weight += nx[i] * i; } printf("\n"); printf("weight = %d%d\n", weight); #endif } dev86-0.16.21/as/type.h000066400000000000000000000060721231050321700143510ustar00rootroot00000000000000/* type.h - types for assembler */ typedef unsigned short u2_t; typedef unsigned u2_pt; typedef unsigned long u4_t; typedef unsigned long u4_pt; /* redefine foo_t's because their use has become non-portable */ #define bool_t bool_T #define count_t count_T #define fd_t fd_T #define indcount_t indcount_T #define offset_t offset_T #define opcode_t opcode_T #define opsize_t opsize_T #define scale_t scale_T #define sem_t sem_T #define smallcount_t smallcount_T #define soffset_t soffset_T typedef unsigned char bool_t; typedef int bool_pt; typedef unsigned count_t; typedef int fd_t; typedef unsigned char indcount_t; #ifdef I80386 typedef unsigned long offset_t; typedef long soffset_t; # define SIZEOF_OFFSET_T 4 /* non-portable */ #endif #ifdef MC6809 typedef unsigned offset_t; typedef int soffset_t; # define SIZEOF_OFFSET_T 2 /* but sizeof (offset_t) often breaks cpp */ #endif typedef int opcode_pt; typedef unsigned char opcode_t; typedef int opsize_pt; typedef unsigned char opsize_t; typedef unsigned reg_pt; typedef unsigned char scale_t; typedef unsigned char smallcount_t; typedef /* signed */ char sem_t; typedef unsigned u16_pt; typedef unsigned short u16_T; typedef unsigned long u32_T; /* symbol table entry */ struct sym_s { struct sym_s *next; /* next symbol in hash chain (NUL_PTR if none) */ /* zero offset because it is accessed most */ unsigned char type; unsigned char data; /* flags valid for expressions as well as syms*/ union { offset_t value; /* value, if sym is a label */ unsigned char reg; /* register code, if sym is a register */ struct { unsigned char routine; /* routine number */ opcode_t opcode; /* opcode, if sym is a hardware op */ } op; /* if sym is pseudo-op or hardware op */ } value_reg_or_op; unsigned char length; /* length of symbol string */ char name[1]; /* string of variable length */ }; /* address */ struct address_s { offset_t offset; unsigned char data; struct sym_s *sym; }; #ifdef I80386 /* effective address */ struct ea_s { indcount_t indcount; opsize_t size; reg_pt base; reg_pt index; scale_t scale; struct address_s displ; }; #endif /* flags */ struct flags_s { bool_t global; bool_t current; int semaphore; }; /* location counter */ struct lc_s { unsigned char data; offset_t lc; }; /* string chain */ struct schain_s { struct schain_s *next; char string[2]; /* variable length */ }; /* block stack */ struct block_s { unsigned char data; unsigned char dp; offset_t lc; }; /* if stack */ struct if_s { bool_t ifflag; bool_t elseflag; }; /* macro stack */ struct macro_s { char *text; struct schain_s *parameters; }; /* symbol listing format */ struct sym_listing_s { char name[SYMLIS_NAMELEN]; char zname[2]; char segm[1]; char pad1[1]; char value[4]; char pad2[1]; char ar[1]; char pad3[1]; char cein[1]; char pad4[1]; char nullterm; }; #if __STDC__ typedef void (*pfv)(void); #else typedef void (*pfv)(); #endif #include "proto.h" dev86-0.16.21/as/typeconv.c000066400000000000000000000066421231050321700152350ustar00rootroot00000000000000 /* * Type conversion routines, these have been rewritten for portability. * * The only requirement is now that the u2_t and u4_t must be big enough. */ #include "syshead.h" #include "const.h" #include "type.h" #include "globvar.h" void xxerr P((char *)); void xxerr(x) char * x; { write(2, x, strlen(x)); } #ifdef __AS386_16__ static int no_swap = 1; #endif static int long_off[4] = {0,1,2,3}; static int int_off[2] = {0,1}; PUBLIC bool_pt typeconv_init(big_endian, long_big_endian) bool_pt big_endian; bool_pt long_big_endian; { int i; #ifdef __AS386_16__ no_swap = (!big_endian && !long_big_endian); #endif for(i=0; i<4; i++) long_off[i] = i; for(i=0; i<2; i++) int_off[i] = i; if( long_big_endian ) { i = long_off[0]; long_off[0] = long_off[2]; long_off[2] = i; i = long_off[1]; long_off[1] = long_off[3]; long_off[3] = i; } if( big_endian ) { i = long_off[2]; long_off[2] = long_off[3]; long_off[3] = i; i = long_off[0]; long_off[0] = long_off[1]; long_off[1] = i; i = int_off[0]; int_off[0] = int_off[1]; int_off[1] = i; } return 1; } PUBLIC void u2c2(buf, offset) char *buf; u2_pt offset; { #ifdef __AS386_16__ if( no_swap ) { *((unsigned short*)buf) = offset; /* UNALIGNED ACCESS! */ return; } #endif buf[int_off[0]] = offset; buf[int_off[1]] = (offset>>8); } PUBLIC void u4c4(buf, offset) char *buf; u4_t offset; { int i; #ifdef __AS386_16__ if( no_swap ) { *((unsigned long*)buf) = offset; /* UNALIGNED ACCESS! */ return; } #endif for(i=0; i<4; i++) { buf[long_off[i]] = offset; offset >>= 8; } } PUBLIC void u4cn(buf, offset, count) char *buf; u4_t offset; unsigned count; { switch(count) { case 1: buf[0] = (char) offset; return; case 2: u2c2(buf, (u2_pt) offset); return; case 4: u4c4(buf, (u4_t) offset); return; default: xxerr("WARNING: typeconv.c(u4cn) illegal count\n"); return; } } PUBLIC void u2cn(buf, offset, count) char *buf; u2_pt offset; unsigned count; { switch(count) { case 1: buf[0] = (char) offset; return; case 2: u2c2(buf, (u2_pt) offset); return; case 4: u4c4(buf, (u4_t) offset); return; default: xxerr("WARNING: typeconv.c(u2cn) illegal count\n"); return; } } PUBLIC u2_pt c2u2(buf) char *buf; { u2_pt res; #ifdef __AS386_16__ if( no_swap ) return *((u2_pt *)buf); /* UNALIGNED ACCESS! */ #endif res = ((unsigned char *)buf) [int_off[0]] + ((((unsigned char *)buf) [int_off[1]]) << 8); return res; } PUBLIC u4_t c4u4(buf) char *buf; { u4_t res; int i; #ifdef __AS386_16__ if( no_swap ) return *((u4_t *)buf); /* UNALIGNED ACCESS! */ #endif res = 0; for(i=3; i>=0; i--) { res = (res<<8) + ((unsigned char *)buf) [long_off[i]]; } return res; } PUBLIC u4_t cnu4(buf, count) char *buf; unsigned count; { switch (count) { case 0: return 0; case 1: return buf[0] & 0xFF; case 2: return c2u2(buf); case 4: return c4u4(buf); default: xxerr("WARNING: typeconv.c(cnu4) illegal count\n"); return 0; } } PUBLIC u2_pt cnu2(buf, count) char *buf; unsigned count; { switch (count) { case 0: return 0; case 1: return buf[0] & 0xFF; case 2: return c2u2(buf); case 4: return (u2_pt) c4u4(buf); default: xxerr("WARNING: typeconv.c(cnu2) illegal count\n"); return 0; } } dev86-0.16.21/bcc/000077500000000000000000000000001231050321700133365ustar00rootroot00000000000000dev86-0.16.21/bcc/6809/000077500000000000000000000000001231050321700137445ustar00rootroot00000000000000dev86-0.16.21/bcc/6809/const.h000066400000000000000000000027031231050321700152450ustar00rootroot00000000000000/* const.h - constants for bcc */ /* Copyright (C) 1992 Bruce Evans */ /* switches for code generation */ #define DEBUG /* generate compiler-debugging code */ /*#define I8088*/ /* target processor is Intel 8088 thru 80386 */ #define MC6809 /* target processor is Motorola 6809 */ #define SELFTYPECHECK /* check calculated type = runtime type */ #ifdef I8088 # define DYNAMIC_LONG_ORDER 1 /* long word order spec. at compile time */ # define FRAMEPOINTER /* index locals off frame ptr, not stack ptr */ # define HOLDSTRINGS /* hold strings for dumping at end * since assembler has only 1 data seg */ #endif #ifdef MC6809 # define DYNAMIC_LONG_ORDER 0 /* have to define it so it works in #if's */ # define OP1 /* logical operators only use 1 byte */ # define POSINDEPENDENT /* position indep code can (also) be gen */ #endif /* switches for source and target operating system dependencies */ /*#define SOS_EDOS*/ /* source O/S is EDOS */ /*#define SOS_MSDOS*/ /* source O/S is MSDOS */ #define TOS_EDOS /* target O/S is EDOS */ /* switches for source machine dependencies */ #ifndef SOS_EDOS # define S_ALIGNMENT (sizeof(int)) /* source memory alignment, power of 2 */ #endif #ifndef SOS_MSDOS /* need portable alignment for large model */ # define UNPORTABLE_ALIGNMENT #endif /* local style */ #define FALSE 0 #ifndef NULL #define NULL 0 #endif #define TRUE 1 #define EXTERN extern #define FORWARD static #define PRIVATE static #define PUBLIC dev86-0.16.21/bcc/Makefile000066400000000000000000000025661231050321700150070ustar00rootroot00000000000000# # bcc Makefile # $Id$ # PREFIX=/usr CFLAGS =-O LDFLAGS =-s BINDIR =$(PREFIX)/bin LIBDIR =$(PREFIX)/lib/bcc BCCDEFS =-DLOCALPREFIX=$(PREFIX) -DBINDIR=$(BINDIR) -DDEFARCH=0 BCFLAGS=$(ANSI) $(CFLAGS) $(LDFLAGS) OBJS = bcc-cc1.o codefrag.o dbnode.o declare.o express.o exptree.o floatop.o \ function.o gencode.o genloads.o glogcode.o hardop.o input.o label.o \ loadexp.o longop.o output.o preproc.o preserve.o scan.o softop.o \ state.o table.o type.o assign.o hashcmd.o debug.o dbprintf.o all: bcc-cc1 bcc install: all install -d $(BINDIR) install -m 755 bcc $(BINDIR)/bcc install -d $(LIBDIR) install -m 755 bcc-cc1 $(LIBDIR)/bcc-cc1 bcc: bcc.c $(CC) $(BCFLAGS) $(BCCDEFS) bcc.c -o $@ ncc: bcc.c $(CC) $(BCFLAGS) -DLOCALPREFIX= -DDEFARCH=0 bcc.c -o $@ bcc09: bcc.c $(CC) $(BCFLAGS) -DMC6809 $(BCCDEFS) bcc.c -o $@ ccc: bcc.c $(CC) $(BCFLAGS) -DCCC $(BCCDEFS) bcc.c -o $@ bcc-cc1: $(OBJS) $(CC) $(BCCARCH) $(LDFLAGS) $(OBJS) -o bcc-cc1 debug.o: debug.c debug.h $(CC) $(ANSI) $(BCCARCH) $(CFLAGS) -c debug.c dbprintf.o: dbprintf.c $(CC) $(ANSI) $(BCCARCH) $(CFLAGS) -c dbprintf.c clean realclean: rm -f bcc bcc-cc1 ncc bcc09 ccc bcc.o $(OBJS) $(OBJS): bcc.h align.h const.h types.h \ byteord.h condcode.h gencode.h \ input.h label.h os.h output.h \ parse.h proto.h reg.h sc.h scan.h \ sizes.h table.h type.h .c.o: $(CC) $(BCCARCH) $(CFLAGS) -c $< dev86-0.16.21/bcc/align.h000066400000000000000000000006351231050321700146050ustar00rootroot00000000000000/* align.h - memory alignment requirements for bcc */ /* Copyright (C) 1992 Bruce Evans */ #ifndef S_ALIGNMENT # define align(x) (x) #else # if defined(__STDC__) && defined(_POSIX_SOURCE) # define align(x) (((ssize_t) (x) + (S_ALIGNMENT-1)) & ~(S_ALIGNMENT-1)) # else # define align(x) ((char *) (x) + (- (char) (x) & (S_ALIGNMENT-1))) # endif #endif extern uoffset_T alignmask; /* general alignment mask */ dev86-0.16.21/bcc/assign.c000066400000000000000000000231321231050321700147670ustar00rootroot00000000000000/* assign.c - assignment and casting operations for bcc */ /* Copyright (C) 1992 Bruce Evans */ #include "bcc.h" #include "byteord.h" #include "gencode.h" #include "reg.h" #include "sc.h" #include "sizes.h" #include "type.h" FORWARD void blockmove P((struct symstruct *source, struct symstruct *target)); FORWARD void call3 P((char *funcname, struct symstruct *target, struct symstruct *source, uoffset_T size)); FORWARD void fconvert P((struct symstruct *source, struct typestruct *type)); PUBLIC void assign(source, target) struct symstruct *source; struct symstruct *target; { store_pt regpushed; store_pt sourcereg; scalar_t tscalar; if (target->type->constructor & (ARRAY | FUNCTION) || target->flags == TEMP || target->flags == (LABELLED | STRING) || (target->indcount == 0 && target->flags != REGVAR)) { bugerror("botched lvalue"); return; } if (source->storage != target->storage || source->indcount != target->indcount || source->level != target->level || source->offset.offi != target->offset.offi /* kludge union cmp */ || source->type != target->type || ((source->storage & (LOCAL | GLOBAL) || source->level == OFFKLUDGELEVEL) && ((source->flags ^ target->flags) & LABELLED || (source->flags & LABELLED && source->name.label != target->name.label) || (!(source->flags & LABELLED) && strcmp(source->name.namep, target->name.namep) != 0)))) { tscalar = target->type->scalar; if (tscalar & CHAR && source->storage == CONSTANT) { source->offset.offv &= CHMASKTO; source->type = target->type; } regpushed = preslval(source, target); if (!(tscalar & CHAR) || source->flags != TEMP || source->offset.offi != sp || source->type->typesize > itypesize) cast(target->type, source); if (tscalar & RSCALAR) { if (source->storage == CONSTANT && (!reguse & doubleregs)) load(source, doubleregs & ~DREG); if (source->storage != CONSTANT && source->indcount == 0) { /* XXX - 386 only */ storereg(DREG, target); #ifdef I80386 if (i386_32) { if (tscalar & DOUBLE) { target->indcount = 1; /* XXX outnnadr clobbers this */ target->offset.offi += accregsize; storereg(doubleregs & ~DREG, target); } } else #endif if (tscalar & DOUBLE) { int i; for(i=1; i; i<<=1) if( i!= DREG && (doubleregs & i) ) { target->indcount = 1; /* XXX outnnadr clobbers this */ target->offset.offi += accregsize; storereg(i, target); } } #ifdef I8088 else if (tscalar & FLOAT) { target->indcount = 1; /* XXX outnnadr clobbers this */ target->offset.offi += accregsize; storereg(DATREG2, target); } #endif target->storage = source->storage; target->offset.offi = 0; } else if (f_indirect(source) && tscalar & DOUBLE && (!(reguse & OPREG) || target->storage == OPREG)) { struct symstruct temptarg; temptarg = *target; pointat(&temptarg); call("Fpull"); outntypechar(temptarg.type); sp += dtypesize; } else blockmove(source, target); } else if (target->type->constructor & STRUCTU) blockmove(source, target); else { if (tscalar & CHAR) load(source, DREG); else if (target->indcount == 0 && target->storage & regregs) load(source, target->storage); else loadany(source); if (tscalar & DLONG) { storereg(DREG, target); target->indcount = 1; target->offset.offi += accregsize; } if ((store_t) (sourcereg = source->storage) == DREG && target->type->scalar & CHAR) sourcereg = BREG; storereg(sourcereg, target); if ((store_t) regpushed != 0) { /* DLONG */ target->indcount = 1; target->offset.offi -= accregsize; recovlist(regpushed); } else { target->storage = sourcereg; target->offset.offi = 0; if (target->level == OFFKLUDGELEVEL) target->level = EXPRLEVEL; } } } } /* block move assumes itypesize == accregsize && BREG size == 1 */ PRIVATE void blockmove(source, target) struct symstruct *source; struct symstruct *target; { struct symstruct oldtarget; uoffset_T typesize; struct symstruct worksource; oldtarget = *target; if ((typesize = target->type->typesize) >= 8 * itypesize || source->indcount + target->indcount != 2) { address(source); address(target); call3("_memcpy", target, source, typesize); } else { if (source->level == OFFKLUDGELEVEL) addoffset(source); /* else kludge is lost and offsets big */ if (target->level == OFFKLUDGELEVEL) addoffset(target); worksource = *source; for (; typesize >= itypesize; typesize -= itypesize) { loadreg(source, DREG); worksource.offset.offi += itypesize; *source = worksource; storereg(DREG, target); target->indcount = 1; target->offset.offi += accregsize; } while (typesize-- != 0) { outload(); outregname(BREG); outopsep(); outadr(source); worksource.offset.offi += 1; *source = worksource; storereg(BREG, target); target->indcount = 1; target->offset.offi += 1; } } *target = oldtarget; } PRIVATE void call3(funcname, target, source, size) char *funcname; struct symstruct *target; struct symstruct *source; uoffset_T size; { store_pt regpushed; offset_T spmark; struct symstruct *length; pushlist(regpushed = reguse & ~calleemask); spmark = sp; length = constsym((value_t) size); length->type = uitype; push(length); push(source); push(target); call(funcname); outnl(); if (regpushed) { modstk(spmark); recovlist(regpushed); } } PUBLIC void cast(type, target) struct typestruct *type; struct symstruct *target; { scalar_t newscalar; uoffset_T newsize; scalar_t oldscalar; uoffset_T oldsize; store_pt targreg; if (type->constructor & (ARRAY | FUNCTION) || (type->constructor & STRUCTU && target->type != type)) { bugerror("botched implicit cast"); return; } if (target->type == type) return; if (target->type->constructor == ARRAY) oldsize = ptypesize; else oldsize = target->type->typesize; newscalar = type->scalar; oldscalar = target->type->scalar; if ((newsize = type->typesize) == oldsize && !((newscalar | oldscalar) & RSCALAR)) ; else if (newsize == ctypesize) /* char only */ { if (oldscalar & RSCALAR) fconvert(target, type); else if (target->indcount == 1) { #if DYNAMIC_LONG_ORDER if (long_big_endian) #endif #if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN # if INT_BIG_ENDIAN target->offset.offi += oldsize - ctypesize; # else { if (oldscalar & DLONG) target->offset.offi += itypesize; /* discard msword */ } # endif #endif #if DYNAMIC_LONG_ORDER else #endif #if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN == 0 # if INT_BIG_ENDIAN target->offset.offi += ctypesize; # else ; # endif #endif } else if (target->storage != CONSTANT) { load(target, DREG); target->storage = BREG; } } else if ((newscalar & (SHORT | INT | LONG) && !(newscalar & DLONG)) || type->constructor & POINTER) { if (oldscalar & RSCALAR) fconvert(target, type); else if (oldsize < newsize) extend(target); else if (target->indcount == 1) { #if DYNAMIC_LONG_ORDER if (long_big_endian) #endif #if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN { if (oldscalar & DLONG) target->offset.offi += itypesize; /* discard msword */ } #endif } else load(target, DREG); } else if (newscalar & DLONG) { if (oldscalar & RSCALAR) fconvert(target, type); else if (target->storage != CONSTANT) { extend(target); load(target, DREG); target->storage = targreg = getindexreg(); if (oldscalar & UNSIGNED || target->type->constructor & (ARRAY | FUNCTION | POINTER)) uitol(targreg); else itol(targreg); } } else if (newscalar & RSCALAR) { saveopreg(); /* XXX */ if (oldscalar & (ISCALAR | FLOAT)) fpush(target); if (newscalar & FLOAT) { pointat(target); call("dto"); outntypechar(type); justpushed(target); /* XXX - sets dtype wrong (harmless) and * wastes (dtypesize - ftypesize) stack */ } restoreopreg(); } target->type = type; } /* extend char or short to int (unsigned if from unsigned) */ PUBLIC void extend(target) struct symstruct *target; { scalar_t tscalar; if ((tscalar = target->type->scalar) & (CHAR | SHORT)) { if (target->storage != CONSTANT && target->type->typesize < itypesize) { load(target, DREG); if (target->type == sctype) sctoi(); #if defined(I8088) && defined(I80386) else if (tscalar & SHORT) { if (tscalar & UNSIGNED) ustoi(); else stoi(); } #endif else ctoi(); target->storage = DREG; } if (tscalar & UNSIGNED) target->type = uitype; else target->type = itype; } } PRIVATE void fconvert(source, type) struct symstruct *source; struct typestruct *type; { offset_T spmark; pushlist(reguse & OPREG); spmark = sp; pointat(source); if (source->type->scalar & DOUBLE) call("dto"); else call("fto"); if (type->scalar & UNSIGNED) outbyte('u'); outntypechar(type); if (type->scalar & DLONG) { if (reguse & OPREG) bugerror("loading long into used reg"); source->storage = OPREG; } else if (type->scalar & CHAR) source->storage = BREG; else source->storage = DREG; source->offset.offi = source->flags = source->indcount = 0; modstk(spmark); /* could adjust later (load instead of pop) */ poplist(reguse & OPREG); } dev86-0.16.21/bcc/bcc-cc1.c000066400000000000000000000006561231050321700147040ustar00rootroot00000000000000/* bcc-cc1.c - "pass 1" for bcc */ /* Copyright (C) 1992 Bruce Evans */ #include "bcc.h" PUBLIC int main(argc, argv) int argc; char **argv; { debug(1, "Start"); growheap(0); /* init order is important */ syminit(); etreeinit(); #ifdef BUILTIN_CPP ifinit(); predefine(); #endif openio(argc, argv); codeinit(); typeinit(); program(); finishup(); /* NOTREACHED */ return 0; } dev86-0.16.21/bcc/bcc.c000066400000000000000000000762771231050321700142540ustar00rootroot00000000000000/* * bcc.c Version 2001.1 * Complete rewrite because the old one was just too confusing! * * There are no significant compile time options (MC6809 and CCC * just change defaults) but you should set LOCALPREFIX. * * Personality flags are: * * -Mn Normal ELKS * -Md MSDOS * -Ms PC Standalone. * -Ml i386 Linux * -M8 CvW's c386 * -M9 MC6809 with bcc * -M0 A framework for the -B option. */ #include #ifdef __STDC__ #include #include #ifndef MSDOS #include #endif #else #include #endif #include #include #include #include #include #ifndef MSDOS #include #include #endif #include "version.h" #ifdef MSDOS #define LOCALPREFIX /linux86 #define EXESUF ".exe" #define R_OK 4 /* Test for read permission. */ #define W_OK 2 /* Test for write permission. */ #define X_OK 1 /* Test for execute permission. */ #define F_OK 0 /* Test for existence. */ #define DEFARCH 0 /* Default to 8086 code */ #include "version.h" #else #define EXESUF #endif #define AS "as" EXESUF #define LD "ld" EXESUF #define CPP "cpp" EXESUF #define CC1 "cc1" EXESUF #define OPT "opt" EXESUF #define CC1C386 "c386" EXESUF #define AS09 "as09" EXESUF #define LD09 "ld09" EXESUF #define CPPBCC "bcc-cpp" EXESUF #define CC1BCC "bcc-cc1" EXESUF #define AS86 "as86" EXESUF #define LD86 "ld86" EXESUF #define GCC "gcc" #define UNPROTO "unproto" EXESUF #define OPTIM "copt" EXESUF #if __STDC__ == 1 #define P(x) x #define HASHIT(x) #x #define QUOT(x) HASHIT(x) #else #define P(x) () /* Well you find something that works! */ #define QUOT(x) "x" #endif struct command { char * cmd; char * altcmd; char * fullpath; int numargs; int maxargs; char ** arglist; } command = { 0,0,0,0,0,0 }; struct file_list { struct file_list * next; char * file; char * oldfile; char * name; int filetype; /* Char, notional extention of file. */ } * files; struct opt_list { struct opt_list * next; char * opt; int opttype; /* Where the option should go */ } * options; int opt_v, opt_V, opt_e, opt_x, opt_I, opt_L, opt_W, opt_i, opt_O, opt_M, opt_f #ifndef VERY_SMALL_MEMORY , opt_7 #endif ; #ifdef DEFARCH int opt_arch = (DEFARCH != 0); #else int opt_arch = sizeof (char *) >= 4; #endif int do_preproc = 1; /* c -> i */ int do_unproto = 0; /* i -> i */ int do_compile = 1; /* i -> s */ int do_optim = 0; /* s -> s */ int do_as = 1; /* s -> o */ int do_link = 1; /* o -> done */ char * executable_name = 0; int file_count = 0; int dyn_count = 0; int error_count = 0; char * progname = "C"; #ifdef MSDOS char * tmpdir = ""; #else char * tmpdir = "/tmp/"; #endif int main P((int argc, char **argv)); void add_prefix P((char * path)); void build_prefix P((char * path1, char * path2, char * path3)); void run_aspreproc P((struct file_list * file)); void run_preproc P((struct file_list * file)); void run_unproto P((struct file_list * file)); void run_compile P((struct file_list * file)); void run_optim P((struct file_list * file)); void run_as P((struct file_list * file)); void run_link P((void)); void command_reset P((void)); void command_opt P((char * option)); void command_arch P((void)); void command_opts P((int opykey)); void newfilename P((struct file_list * file, int last_stage, int new_extn, int use_o)); void run_unlink P((void)); void validate_link_opt P((char * option)); void validate_link_opts P((void)); void append_file P((char * filename, int ftype)); void append_option P((char * option, int otype)); void prepend_option P((char * option, int otype)); char * build_libpath P((char * opt, char * str, char * suffix)); void * xalloc P((int size)); void Usage P((void)); void fatal P((char * why)); char * copystr P((char * str)); char * catstr P((char * str, char * str2)); void reset_prefix_path P((void)); void run_command P((struct file_list * file)); void getargs P((int argc, char ** argv)); char * prefix_path = ""; #ifdef LOCALPREFIX char * localprefix = QUOT(LOCALPREFIX); #else char * localprefix = "/"; #endif /* These paths are NATIVE install paths, change others below */ char * default_include = "/usr/include"; char * optim_rules = "/lib"; #ifdef LIBDIR char * default_libdir = QUOT(LIBDIR); #else char * default_libdir = "/lib"; #endif char * libdir_suffix = ""; char devnull[] = "/dev/null"; char * exec_prefixs[16] = { 0 /* Last chance is contents of $PATH */ }; char * libc = "-lc"; int main(argc, argv) int argc; char ** argv; { struct file_list * next_file; char * temp; progname = argv[0]; if ((temp = getenv("BCC_PREFIX")) != 0 ) localprefix = copystr(temp); getargs(argc, argv); validate_link_opts(); reset_prefix_path(); if (!*localprefix || !localprefix[1]) { if (*localprefix == '/') { /* Paths for full NATIVE install "-M/" */ build_prefix(default_libdir, libdir_suffix, ""); build_prefix(default_libdir, "", ""); default_include = build_libpath("-I", "/usr/include", ""); default_libdir = build_libpath("-L", default_libdir, libdir_suffix); optim_rules = build_libpath("-d", optim_rules, libdir_suffix); #if 0 } else if (*localprefix == '+') { /* Paths for a special */ #endif } else { /* Relative paths to a build dir "-M-" */ build_prefix("/lib", libdir_suffix, ""); build_prefix("/lib", "", ""); default_include = build_libpath("-I", "/include", ""); default_libdir = build_libpath("-L", "/lib", libdir_suffix); optim_rules = build_libpath("-d", "/lib", libdir_suffix); } } else { /* Relative paths to normal PREFIX directory */ default_include = build_libpath("-I", "/lib/bcc/include", ""); default_libdir = build_libpath("-L", "/lib/bcc", libdir_suffix); optim_rules = build_libpath("-d", "/lib/bcc", libdir_suffix); build_prefix("/lib/bcc", libdir_suffix, ""); build_prefix("/lib/bcc", "", ""); } build_prefix("/bin", "", ""); #ifdef BINDIR add_prefix(QUOT(BINDIR) "/"); #endif if (opt_v>1) { command.cmd = ""; command_reset(); } for(next_file = files; next_file && !error_count; next_file = next_file->next) { if (next_file->filetype == 'o') continue; if (opt_V) fprintf(stderr, "%s:\n", next_file->file); /* Assembler that's not to be optimised. */ if (do_preproc && next_file->filetype == 'x') run_aspreproc(next_file); if (do_preproc && next_file->filetype == 'S') run_aspreproc(next_file); if (do_as && next_file->filetype == 's') run_as(next_file); /* C source */ if (do_preproc && next_file->filetype == 'c') run_preproc(next_file); if (do_unproto && do_compile && next_file->filetype == 'i') run_unproto(next_file); if (do_compile && next_file->filetype == 'i') run_compile(next_file); if (do_optim && next_file->filetype == 's') run_optim(next_file); if (do_as && next_file->filetype == 's') run_as(next_file); } if (do_link && !error_count) run_link(); run_unlink(); exit(error_count>0); } char * copystr(str) char * str; { return strcpy(xalloc(strlen(str)+1), str); } char * catstr(str, str2) char * str, * str2; { return strcat(strcpy(xalloc(strlen(str)+strlen(str2)+1), str), str2); } void run_aspreproc(file) struct file_list * file; { static char cc1bcc[] = CC1BCC; if (opt_arch<5) { if (opt_e) command.cmd = cc1bcc; else { command.cmd = CPPBCC; command.altcmd = cc1bcc; } } else command.cmd = CPP; command_reset(); newfilename(file, (!do_as && !do_optim), (do_compile?'s':'i'), (opt_arch<5)); if (opt_arch<5 && command.cmd == cc1bcc) command_opt("-E"); else if (opt_arch<5 && do_unproto) command_opt("-A"); command_opts('p'); command_opt("-D__ASSEMBLER__"); command_arch(); run_command(file); } void run_preproc(file) struct file_list * file; { int last_stage = 0; int combined_cpp; static char cc1bcc[] = CC1BCC; if (opt_arch<5) { if (opt_e) command.cmd = cc1bcc; else { command.cmd = CPPBCC; command.altcmd = cc1bcc; } } else command.cmd = CPP; command_reset(); combined_cpp = (command.cmd == cc1bcc && opt_arch != 3 && opt_e < 2 && !do_unproto && do_compile); if (combined_cpp && !do_optim && !do_as ) last_stage =1; if (!combined_cpp && !do_compile ) last_stage =1; newfilename(file, last_stage, (combined_cpp?'s':'i'), (opt_arch<5)); if (!combined_cpp && opt_arch<5) { if (command.cmd == cc1bcc) command_opt("-E"); else if (do_unproto) command_opt("-A"); } command_opts('p'); command_opts('C'); if (combined_cpp) { if (opt_arch<5 && !do_as) command_opt("-t"); command_opts('c'); } if (!opt_I) command_opt(default_include); command_arch(); run_command(file); } void run_unproto(file) struct file_list * file; { command.cmd = UNPROTO; command_reset(); newfilename(file, !do_compile, 'i', 0); command_opts('u'); run_command(file); } void run_compile(file) struct file_list * file; { if (opt_arch == 3) command.cmd = CC1C386; else if (opt_arch<5) command.cmd = CC1BCC; else command.cmd = CC1; command_reset(); newfilename(file, !(do_optim || do_as), 's', (opt_arch != 3 && opt_arch<5)); if (opt_arch<5 && !do_as) command_opt("-t"); #ifndef VERY_SMALL_MEMORY if (opt_7) command_opt("-7"); #endif command_opts('c'); command_opts('C'); command_arch(); run_command(file); } void run_optim(file) struct file_list * file; { char buf[32]; if (opt_arch<5) command.cmd = OPTIM; else command.cmd = OPT; command_reset(); newfilename(file, !do_as, 's', 1); command_opt("-c!"); if (opt_O && opt_arch == 0) { sprintf(buf, "-huse16 %c86", opt_O); command_opt(buf); } command_opt(optim_rules); command_opt("rules.start"); command_opts('o'); if (opt_O) { if (opt_arch == 0) sprintf(buf, "rules.%c86", opt_O); else sprintf(buf, "rules.lv_%c", opt_O); command_opt(buf); } switch(opt_arch) { case 0: command_opt("rules.86"); break; case 1: case 2: command_opt("rules.i386"); break; case 4: command_opt("rules.6809"); break; default:command_opt("rules.mid"); break; } command_opt("rules.end"); run_command(file); } void run_as(file) struct file_list * file; { char * buf; switch(opt_arch) { case 0: case 1: case 2: command.cmd = AS86; break; case 4: command.cmd = AS09; break; default: command.cmd = AS; break; } command_reset(); newfilename(file, (!do_link && opt_arch!=2), 'o', 1); if (opt_arch==3) command_opt("-j"); if (opt_arch<5) command_opt("-u"); command_opts('a'); if (opt_W) command_opt("-w-"); else command_opt("-w"); command_arch(); command_opt("-n"); buf = catstr(file->name, ".s"); command_opt(buf); free(buf); run_command(file); if (opt_arch == 2) { command.cmd = LD86; command_reset(); command_opt("-r"); command_opt("-N"); newfilename(file, !do_link, 'o', 1); run_command(file); } } void run_link() { struct file_list * next_file; switch(opt_arch) { case 0: case 1: command.cmd = LD86; break; case 2: command.cmd = GCC; break; case 4: command.cmd = LD09; break; default: command.cmd = LD; break; } command_reset(); if (executable_name) { command_opt("-o"); command_opt(executable_name); } if (opt_arch < 2) command_opt("-y"); command_opts('l'); if (opt_arch != 2) { if (opt_arch == 0 && !opt_i) command_opt("-i"); if (!opt_L) command_opt(default_libdir); command_arch(); if (!opt_x) command_opt("-C0"); } /* Current Debian compilers only work in with this: */ else command_opt("--static"); for(next_file = files; next_file; next_file = next_file->next) command_opt(next_file->file); if (opt_arch != 2) command_opt(libc); run_command(0); } void validate_link_opt(option) char * option; { int err = 0; if (option[0] != '-') return; switch(option[1]) { default: err = 1; break; case '0': /* use 16-bit libraries */ case '3': /* use 32-bit libraries */ case 'M': /* print symbols linked */ case 'i': /* separate I & D output */ case 'm': /* print modules linked */ case 's': /* strip symbols */ case 't': /* trace modules linked */ case 'z': /* unmapped zero page */ case 'N': /* Native format a.out */ case 'd': /* Make a headerless outfile */ case 'c': /* Write header in CP/M-86 format */ case 'y': /* Use a newer symbol table */ if (option[2] != 0 && option[2] != '-') err = 1; break; case 'C': /* startfile name */ case 'L': /* library path */ case 'O': /* library file name */ case 'T': /* text base address */ case 'D': /* data base address */ case 'H': /* heap top address */ case 'l': /* library name */ case 'o': /* output file name */ break; } if (err) { if (do_link) fprintf(stderr, "warning: unknown option %s passed to linker.\n", option); else fprintf(stderr, "warning: option %s not recognised.\n", option); } else if (!do_link) fprintf(stderr, "warning: linker option %s unused.\n", option); } void validate_link_opts() { struct opt_list * ol; struct file_list * next_file; if (opt_arch>1) return; /* Only check ld86 options */ for(ol=options; ol; ol=ol->next) if (ol->opttype == 'l') validate_link_opt(ol->opt); for(next_file = files; next_file; next_file = next_file->next) validate_link_opt(next_file->file); if (!do_link) { if (opt_i) fprintf(stderr, "warning: linker option -i unused.\n"); if (opt_x) fprintf(stderr, "warning: linker option -x unused.\n"); if (opt_L) fprintf(stderr, "warning: linker option -L unused.\n"); } } void command_reset() { #ifndef MAXPATHLEN #define MAXPATHLEN 1024 #endif char buf[MAXPATHLEN]; char ** prefix; char * saved_cmd; if (command.arglist) { int i; for(i=0; inext) if (ol->opttype == optkey) command_opt(ol->opt); } void newfilename(file, last_stage, new_extn, use_o) struct file_list * file; int last_stage; int new_extn; int use_o; { file->filetype = new_extn; if (file->oldfile) free(file->oldfile); file->oldfile = file->file; file->file = 0; if (last_stage) { if (executable_name) file->file = copystr(executable_name); else { char buf[4]; buf[0] = '.'; buf[1] = file->filetype; buf[2] = 0; file->file = catstr(file->name, buf); } } else { char buf[16]; #ifdef MSDOS sprintf(buf, "$$%05d$", dyn_count++); #else sprintf(buf, "$$%04d%05d", dyn_count++, getpid()); #endif file->file = catstr(tmpdir, buf); } command_opt(file->oldfile); /* *.i files go to the stdout */ if (last_stage && file->filetype == 'i') return; if (use_o) command_opt("-o"); command_opt(file->file); } void run_unlink() { int i; for(i=0; i1) fprintf(stderr, "rm %s\n", p); if (opt_v>2) continue; if (unlink(p) < 0) { if (error_count==0 || opt_v>1) fprintf(stderr, "Error unlinking %s\n", p); error_count++; } free(p); } } void getargs(argc, argv) int argc; char ** argv; { int ar; char * pflag = 0; int control_count = 0; int exe_count = 0; for(ar=1; ar= '1' && opt_arg[0] <= '9' )) opt_O = opt_arg[0]; else if (opt_arg[0] == '-') append_option(opt_arg, 'o'); else { char * p = xalloc(strlen(opt_arg)+8); strcpy(p, "rules."); strcat(p, opt_arg); append_option(p, 'o'); free(p); } break; case 'o': exe_count++; executable_name = opt_arg; break; case 'B': add_prefix(opt_arg); break; case 'I': case 'D': case 'U': append_option(argv[ar], 'p'); break; case 'T': tmpdir = catstr(opt_arg, "/"); break; case 'M': if (opt_arg[0] == '/') { localprefix = copystr(opt_arg); break; } if (opt_arg[1]) Usage(); if (opt_arg[0] == '-') { localprefix = ""; break; } opt_M = *opt_arg; break; default: pflag = argv[ar]+1; used_arg = 0; break; } /* Singleton flags */ if(pflag) switch(opt = *pflag++) { case 'P': append_option("-P", 'p'); /*FALLTHROUGH*/ case 'E': control_count++; do_compile = do_link = do_as = 0; break; case 'S': control_count++; do_as = do_link = 0; break; case 'c': control_count++; do_link = 0; break; case 'O': do_optim=1; break; case 'G': opt_M = 'g'; break; case 'v': opt_v++; break; case 'V': opt_V++; break; case 'e': opt_e++; break; case 'x': opt_x++; break; case 'I': opt_I++; break; case 'L': opt_L++; break; case 'i': opt_i++; break; case 'f': opt_f++; break; #ifndef VERY_SMALL_MEMORY case '7': opt_7++; break; #endif case 'W': opt_W++; break; case '0': opt_arch=0; break; case '3': opt_arch=1; break; case 'w': /*IGNORED*/ break; case 'g': /*IGNORED*/ break; case 'p': /*IGNORED*/ break; default: if (pflag == argv[ar]+2) { /* Special; unknown options saved as flags for the linker */ append_file(argv[ar], 'o'); pflag = 0; } else Usage(); } if (!pflag || !*pflag) { ar++; pflag = 0; } if (used_arg && inc_ar) ar++; if (used_arg && inc_ar==2) fatal("Last option requires an argument"); } if (control_count>1) fatal("only one option from -E -P -S -c allowed"); if (exe_count>1) fatal("only one -o option allowed"); if (file_count==0) Usage(); if (exe_count && file_count != 1 && !do_link) fatal("only one input file for each non-linked output"); add_prefix(getenv("BCC_EXEC_PREFIX")); #ifdef MC6809 if (opt_M==0) opt_M = '9'; #endif #ifdef CCC if (opt_M==0) opt_M = '8'; #endif #ifdef MSDOS if (opt_M==0) opt_M = 'd'; #endif #ifdef __CYGWIN__ if (opt_M==0) opt_M = 'd'; #endif if (opt_M==0) opt_M = (opt_arch==1 ?'l':'n'); switch(opt_M) { case 'n': /* Normal Elks */ prepend_option("-D__unix__", 'p'); prepend_option("-D__ELKS__", 'p'); libc="-lc"; break; case 'f': /* Fast Call Elks */ prepend_option("-D__unix__", 'p'); prepend_option("-D__ELKS__", 'p'); append_option("-c", 'C'); append_option("-f", 'C'); libc="-lc_f"; break; case 'c': /* Caller saves Elks */ prepend_option("-D__unix__", 'p'); prepend_option("-D__ELKS__", 'p'); append_option("-c", 'C'); libc="-lc"; break; case 's': /* Standalone 8086 */ prepend_option("-D__STANDALONE__", 'p'); libc="-lc_s"; break; case 'd': /* DOS COM file */ prepend_option("-D__MSDOS__", 'p'); if (do_link) { libc="-ldos"; append_option("-d", 'l'); append_option("-T100", 'l'); } break; case 'l': /* 386 Linux a.out */ opt_arch=1; prepend_option("-D__unix__", 'p'); prepend_option("-D__linux__", 'p'); if (do_link) { libc="-lc"; append_option("-N", 'l'); } break; case 'g': /* 386 Linux object using gcc as linker */ opt_arch = 2; prepend_option("-D__unix__", 'p'); prepend_option("-D__linux__", 'p'); /* This is a more traditional libc, it also gives a 20k executable * for hello world vs. 400k with glibc2 and --static. * NB: DLL libc no longer seems to work. */ add_prefix("/usr/bin/i386-uclibc-"); break; case '8': /* Use 'c386' program as compiler */ opt_arch = 3; prepend_option("-D__unix__", 'p'); prepend_option("-D__c386__", 'p'); break; case '9': /* 6809 compiler */ opt_arch = 4; prepend_option("-D__6809__", 'p'); break; case '0': /* Plain old Unix V7 style */ opt_arch = 5; opt_I = 1; opt_L = 1; opt_x = 1; append_option("/lib/crt0.o", 'l'); break; default: fatal("Unknown model specifier for -M valid are: n,f,c,s,d,l,g,8,9,0"); } if (do_optim) { append_option("-O", 'C'); append_option("-O", 'a'); } if (opt_arch == 0) { if (opt_f) { /* append_option("--enable-floats", 'c'); */ libc = catstr(libc, "+f"); } else append_option("-D__HAS_NO_FLOATS__", 'p'); } if (opt_arch == 1) libdir_suffix = "/i386"; if (opt_arch == 4) libdir_suffix = "/m09"; #ifdef VERSION { char verbuf[64]; sprintf(verbuf, "-D__BCC_VERSION__=0x%02x%02x%02xL", VER_MAJ, VER_MIN, VER_PAT); append_option(verbuf, 'p'); } #endif } void build_prefix(path1, path2, path3) char * path1, * path2, * path3; { char * newstr; int l; newstr = xalloc(strlen(path1)+strlen(path2)+strlen(path3) + strlen(prefix_path)+2); strcpy(newstr, prefix_path); strcat(newstr, path1); strcat(newstr, path2); strcat(newstr, path3); l = strlen(newstr); if (l>1 && newstr[l-1] != '/') strcat(newstr, "/"); add_prefix(newstr); } void add_prefix(path) char * path; { char ** p; if (!path || !*path) return; for( p=exec_prefixs; pfile = copystr(filename); name = copystr(filename); s = strrchr(name, '.'); if (ftype) { newfile->name = copystr(name); newfile->filetype = ftype; } else if (s && s == name + strlen(name) - 2) { newfile->filetype = s[1]; *s = 0; newfile->name = copystr(name); } else newfile->name = copystr(name); free(name); if (newfile->filetype == 0) newfile->filetype = 'o'; /* Objects */ if (files==0) files = newfile; else { struct file_list * fptr; for(fptr=files; fptr->next; fptr=fptr->next); fptr->next = newfile; } } void append_option (option, otype) char * option; int otype; { struct opt_list * newopt = xalloc(sizeof(struct opt_list)); newopt->opt = copystr(option); newopt->opttype = otype; if (options==0) options = newopt; else { struct opt_list * optr; for(optr=options; optr->next; optr=optr->next); optr->next = newopt; } } void prepend_option (option, otype) char * option; int otype; { struct opt_list * newopt = xalloc(sizeof(struct opt_list)); newopt->opt = copystr(option); newopt->opttype = otype; newopt->next = options; options = newopt; } char * build_libpath(opt, str, suffix) char * opt, * str, * suffix; { char * newstr; newstr = xalloc(strlen(opt)+strlen(str)+strlen(prefix_path)+strlen(suffix)+1); strcpy(newstr, opt); strcat(newstr, prefix_path); strcat(newstr, str); strcat(newstr, suffix); return newstr; } void * xalloc (size) int size; { void * p = malloc(size); if (!p) fatal("Out of memory"); memset(p, '\0', size); return p; } void Usage() { #ifdef VERSION #ifdef __AS386_16__ if (opt_v) fprintf(stderr, "%s: version %s (16bit)\n", progname, VERSION); #else if (opt_v) fprintf(stderr, "%s: version %s\n", progname, VERSION); #endif #endif fprintf(stderr, "Usage: %s [-ansi] [-options] [-o output] file [files].\n", progname); exit(1); } void fatal(str) char * str; { fprintf(stderr, "%s: Fatal error: %s.\n", progname, str); exit(1); } #ifdef MSDOS void reset_prefix_path() { char *ptr, *temp; if (*localprefix && localprefix[1]) { prefix_path = localprefix; return; } temp = copystr(progname); if( (ptr = strrchr(temp, '\\')) != 0 && temp2) return; } #ifdef MSDOS status = spawnv(0, command.fullpath, command.arglist); if (status<0) { fprintf(stderr, "Unable to execute %s\n", command.fullpath); } #else oqsig = signal(SIGQUIT, SIG_IGN); oisig = signal(SIGINT, SIG_IGN); otsig = signal(SIGTERM, SIG_IGN); ocsig = signal(SIGCHLD, SIG_DFL); switch(fork()) { case -1: fatal("Forking failure"); case 0: (void) signal(SIGQUIT, SIG_DFL); (void) signal(SIGINT, SIG_DFL); (void) signal(SIGTERM, SIG_DFL); (void) signal(SIGCHLD, SIG_DFL); #ifdef __BCC__ execve(command.fullpath, command.arglist, minienviron); #else if (command.fullpath[0] =='/') execv(command.fullpath, command.arglist); else execvp(command.fullpath, command.arglist); #endif fprintf(stderr, "Unable to execute %s.\n", command.fullpath); exit(1); default: wait(&status); if (status&0xFF) { fprintf(stderr, "%s: killed by signal %d\n", command.fullpath, (status&0xFF)); } } (void) signal(SIGQUIT, oqsig); (void) signal(SIGINT, oisig); (void) signal(SIGTERM, otsig); (void) signal(SIGCHLD, ocsig); #endif if (status) { if (file) file->filetype = '~'; error_count++; } } dev86-0.16.21/bcc/bcc.doc000066400000000000000000000156701231050321700145650ustar00rootroot00000000000000WARNING: This document bis out of date; it's kept mainly for the 6809 notes. bcc options ----------- bcc [-03EGOPSVcegv] [-Aas_option] [-Bexecutable_prefix] [-Ccc1_option] [-Ddefine] [-Iinclude_dir] [-Lld_option] [-Qc386_option] [-Ttmpdir] [-Uundef] [-o outfile] [-fpt error] [ld_options] [infiles] The 6809 version does not support -0, -3 or -G. Only the c386 version supports -Q. defaults (off or none except for these): -03 native outfile stdout for preprocessor output somewhere/file.[ci] -> file.s for compiler output somewhere/file.[cis] -> file.o for assembler output a.out for ld output -ansi Pass the source through 'unproto' first -0 8086 target (works even on 80386 host) -3 80386 target (works even on 8086 host) -A pass remainder of option to assembler (e.g. -A-l -Alistfile for a listing) -B prefix for executable search path (as usual; the search order is all paths specified using -B, in order, then the path given in the environment variable BCC_EXEC_PREFIX if that is set, then the compiled-in defaults (something like /usr/libexec/i386/bcc/ followed by /usr/bin/)) -C pass remainder of option to cc1 (e.g. -C-c for caller-saves) -D define (as usual) -E produce preprocessor output (as usual) -G produce gnu-Minix objects (link with gnu ld) -Ix include search path (as usual) -I don't add default include to search list -Lx add dir name x to the head of the list of library dirs searched -L don't add default library to search list -X pass remainder of option to linker -O optimize (does nothing) -P produce preprocessor output with no line numbers (as usual) -Q pass full option to c386 -S produce assembler file (as usual) -T temporary directory (overrides previous value and default; default is from the environment variable TMPDIR if that is set, otherwise /tmp) -U undefine (as usual) -V print names of files being compiled -c produce object file (as usual) -e run the preprocess pass separately. This takes less memory, and may help or harm by giving more traditional semantics like token pasting with /**/. -f error (float emulation not supported) -g produce debugging info (does nothing) -o output file name follows (assembler, object or executable) (as usual) -p error (profiling not supported) -t error (substitution of some cc passes not supported) -v print names and args of subprocesses being run. Two or more -v's: print names of files being unlinked. Three or more -v's: print names of paths being searched. Other options are passed to the linker, in particular -i-, -lx, -M, -m, -s. The -i option is always passed to the linker but can be cancelled using -i-. This is supposed to match the V7 manual except for -0, -3, -A, -C, -G, -L, -T, -V, -e, -v and where not supported. cc1 options ---------- cc1 [-03EPcdfltw[-]] [-Ddefine] [-Iinclude_dir] [-Uundef] [-o outfile] [infile] The 6809 version does not support -0 or -3 but it supports -p. defaults (off or none except for these): -03 native -c on for 6809 -f on for 6809 outfile stdout infile stdin -0 8086 target (works even on 80386 host) -3 80386 target (works even on 8086 host) -D define (as usual) -E produce preprocessor output (as usual) -I include search path (as usual) -P produce preprocessor output with no line numbers (as usual) -c produce code with caller saving regs before function calls -d print debugging information in assembly output -f produce code with 1st argument passed in a register -l produce code for 2 3 1 0 long byte order (only works in 16-bit versions) -o assembler output file name follows -p produce (almost) position-independent code -t print source code in assemby output -w print what cc1 thinks is the location counter in assembly output All the options except -D, -I and -o may be turned off by following the option letter by a '-'. Options are processed left to right so the last setting has precedence. The following is defined before option processing: __BCC__ 1 The following may be defined after option processing: __AS09__ 1 if 6809 version __AS386_16__ 1 if -0 option on 80*86 __AS386_32__ 1 if -3 option on 80*86 __CALLER_SAVES__ 1 if -c option __FIRST_ARG_IN_AX__ 1 if -f option on 80*86 __FIRST_ARG_IN_X__ 1 if -f option on 6809 __LONG_BIG_ENDIAN__ 1 if -l option __POS_INDEPENDENT__ 1 if -p option on 6809 The following are standard builtins: __FILE__ stringized name of current input file __LINE__ current line number as options ---------- as [-03agjuw] [-b [bin]] [-lm [list]] [-n name] [-o obj] [-s sym] src The 6809 version does not support -0, -3, -a or -j. defaults (off or none except for these; no output is produced without a flag): -03 native list stdout (beware of clobbering next arg) name basename of the source name -0 start with 16-bit code segment -3 start with 32-bit code segment -a enable partial compatibility with asld -g only put global symbols in object file -j force all jumps to be long -l produce list file, filename may follow -m print macro expansions in listing -n name of module follows (goes in object instead of source name) -o produce object file, filename follows -b produce binary file, filename may follow -s produce symbol file, filename follows -u take undefined symbols as imported-with-unspecified segment -w don't print warnings The -u and -w options are perhaps back to front because they are needed for cc1 output and Minix's make does the wrong thing with .s files left around. However, all assembler code not written by compilers should assemble with them turned off. The -b flag now produces a 'raw' binary file with no header, if there's no -s flag the file starts at location 0. The -s generates an ASCII symbol table, if a binary file doesn't start at location zero the first two items are the start and end addresses of the binary file. ld options ---------- ld [-03Mimrstz[-]] [-llib_extension] [-o outfile] [-Ccrtfile] [-Llibdir] [-Olibfile] [-T textaddr] infile... The version that produces old Minix a.out format does not support -r. The 6809 version does not support -i or -r. defaults (off or none except for these): -03 native -L/usr/local/lib/m/ (m is machine-dependent) outfile a.out -0 produce header with 16-bit magic and use library subdir i86 for -lx -3 produce header with 32-bit magic and use library subdir i386 for -lx -Cx add file libdir-from-search/crtx.o to list of files linked -Lx add dir name x to the head of the list of library dirs searched -M print symbols linked on stdout -Ox add library libdir-from-search/x to list of files linked -T text base address follows (in format suitable for strtoul) -i separate I&D output -lx add library libdir-from-search/libx.a to list of files linked -m print modules linked on stdout -o output file name follows -r produce output suitable for further relocation -s strip symbols -t trace modules being looked at on stdout -z produce "unmapped zero page" executables All the options not taking an argument may be turned off by following the option letter by a '-', as for cc1. dev86-0.16.21/bcc/bcc.h000066400000000000000000000011661231050321700142420ustar00rootroot00000000000000/* Copyright (C) 1997 Robert de Bath * This file is part of the Linux-8086 Development environment and is * distributed under the GNU General Public License. */ #ifdef _AIX #include /* AIX 4.1 + GCC seems to need this */ #endif /* Ansi C has certain guarentees ... except under MSdross :-( */ #ifdef __STDC__ #ifndef MSDOS #include #include #include #include #endif #define P(x) x #else #define P(x) () #endif #include "const.h" #include "types.h" #include "proto.h" #if !defined(__STDC__) || defined(MSDOS) #include "sysproto.h" #endif dev86-0.16.21/bcc/byteord.h000066400000000000000000000005411231050321700151570ustar00rootroot00000000000000/* byteord.h - byte order dependencies for bcc */ /* Copyright (C) 1992 Bruce Evans */ #ifdef I8088 # define INT_BIG_ENDIAN 0 # define LONG_BIG_ENDIAN 1 /* longs are back to front for Xenix */ #endif #ifdef MC6809 # define INT_BIG_ENDIAN 1 /* byte order in words is high-low */ # define LONG_BIG_ENDIAN 1 /* byte order in longs is high-low */ #endif dev86-0.16.21/bcc/codefrag.c000066400000000000000000000776511231050321700152740ustar00rootroot00000000000000/* codefrag.c - code fragments for bcc */ /* Copyright (C) 1992 Bruce Evans */ #include "bcc.h" #include "byteord.h" #include "condcode.h" #include "gencode.h" #include "label.h" #include "output.h" #include "reg.h" #include "scan.h" #include "sizes.h" #define DEFSTR_BYTEMAX 10 #define DEFSTR_DELIMITER '"' #define DEFSTR_STRINGMAX 40 #define EOS_TEXT '0' #define MAXPRINTCHAR '~' #define MINPRINTCHAR ' ' /* segment numbers */ #ifdef I8088 # define CSEG 0 # define outcseg() outop0str(".text\n") # define DSEG 1 # define outdseg() outop0str(".data\n") # define BSSSEG 2 # define outbssseg() outop0str(".bss\n") #endif #ifdef MC6809 # define CSEG 0 # define outcseg() outop0str("LOC\t0\n") # define DPSEG 2 # define outdpseg() outop0str("LOC\t2\n") # define DSEG 3 # define outdseg() outop0str("LOC\t3\n") # define STRSEG 1 # define outstrseg() outop0str("LOC\t1\n") #endif #ifdef I8088 FORWARD void adjcarry P((void)); #endif FORWARD void clr P((store_pt reg)); FORWARD bool_pt lowregisDreg P((void)); #ifdef I8088 FORWARD void outand P((void)); FORWARD void outequate P((void)); # ifdef XENIX_AS FORWARD void outexport P((void)); # endif FORWARD void outmovsx P((void)); FORWARD void outmovzx P((void)); FORWARD void tfrhilo P((void)); FORWARD void tfrlohi P((void)); #endif #ifdef MC6809 FORWARD void negBsbcA P((void)); #endif FORWARD void outaccum P((void)); FORWARD void outstackreg P((void)); FORWARD void opregadr P((void)); /* operator and miscellaneous strings */ #ifdef I8088 # define ACCHISTR "ah" # define ANDSTRING "and\t" # define DEFSTR_QUOTER '\\' # define EORSTRING "xor\t" # define MAX_INLINE_SHIFT 2 /* better 3 for 88, 1 for 186 and above */ # define ORSTRING "or\t" # define TARGET_FIRST # define addfactor(reg) (outadd(), outregname(reg), outncregname(DXREG)) # define defstorage() outop0str(".blkb\t") # define extBnegD() (ctoi(), negDreg()) # define finishfactor() /* save/add/subfactor() ended already */ # define outadc() outop3str("adc\t") # define outandac() (outand(), outaccum(), bumplc()) # define outandlo() (outand(), outstr(acclostr)) # define outbimmed() outbyte('*') # define outcommon() outop0str(".comm\t") # define outcwd() outnop1str("cwd") # define outdefstr() outop0str(".ascii\t\"") # define outexchange() outop1str("xchg\t") # define outglobl() outop0str(".globl\t") # ifdef XENIX_AS # define outimport() outexport() # else # define outexport() outop0str("export\t") # define outimport() outop0str("import\t") # endif # ifdef XENIX_AS # define outj1switch() outop3str("seg\tcs\nbr\t@"); # else # define outj1switch() outop3str("seg\tcs\nbr\t"); # endif # define outj2switch() \ (outindleft(), outstr(ireg0str), outindright(), bumplc2(), outnl()) # define outlcommon() outop0str("\tlcomm\t") # define outlswitch() (outload(), outstr(ireg0str), outncregname(DREG)) # define outnc1() outnstr(",*1") # define outsbc() outop3str("sbb\t") # define outset() outstr ("\tset\t") # define outsl() outop2str("shl\t") # define outsr() outop2str("sar\t") # define outtransfer() outload() # define outusr() outop2str("shr\t") # define outxor() outop2str(EORSTRING) # define reclaimfactor() /* factor in DXREG, DXREG now junk */ # define savefactor(reg) regtransfer((reg), DXREG) # define smiDreg() (outcwd(), regexchange(DREG, DXREG)) # define sr1() (outsr(), outaccum(), outnc1()) # define subfactor(reg) (outsub(), outregname(reg), outncregname(DXREG)) # define usr1() (outusr(), outaccum(), outnc1()) PRIVATE void adjcarry() { outop3str("rcl\t"); outregname(DXREG); outncimmadr((offset_T) 9); outand(); bumplc2(); bumplc2(); outregname(DXREG); outncimmadr((offset_T) 0x100); } PUBLIC void clrBreg() { outxor(); outstr(acclostr); outncregname(BREG); } PUBLIC void comment() { outstr("! "); } PUBLIC void ctoi() { #ifdef I80386 if (i386_32) { outmovzx(); outaccum(); outncregname(BREG); } else #endif { outxor(); outhiaccum(); outcomma(); outhiaccum(); outnl(); } } PUBLIC void defbyte() { outop0str(".byte\t"); } #ifdef XENIX_AS PUBLIC void defword() { } /* don't have to print ".word\t" */ #else PUBLIC void defword() { outop0str(".word\t"); } #endif PUBLIC void defdword() { outop0str("dd\t"); } PUBLIC void even() { outop0str(".even\n"); } PUBLIC void negDreg() { outop2str("neg\t"); outnregname(DREG); } PUBLIC void comDreg() { outop2str("not\t"); outnregname(DREG); } PUBLIC void outadd() { outop2str("add\t"); } PUBLIC void outaddsp() { outadd(); outstackreg(); outcomma(); outimmed(); bumplc2(); } PRIVATE void outand() { outop2str(ANDSTRING); } #ifdef XENIX_AS PUBLIC void outcalladr() { outop2str("call\t@"); } #else PUBLIC void outcalladr() { outop2str("call\t"); } #endif PUBLIC void outcmp() { outop2str("cmp\t"); } PUBLIC void outdec() { outop1str("dec\t"); } PUBLIC void outdword() { outstr("dword "); } PRIVATE void outequate() { outop0str("\t=\t"); } #ifdef XENIX_AS PRIVATE void outexport() { outop0str(".globl\t"); } #endif PUBLIC void outfail() { outop0str(".fail\t"); } PUBLIC void outinc() { outop1str("inc\t"); } #ifdef XENIX_AS PUBLIC void outindleft() { outbyte('('); } PUBLIC void outindright() { outbyte(')'); } #else PUBLIC void outindleft() { outbyte('['); } PUBLIC void outindright() { outbyte(']'); } #endif #ifndef FRAMEPOINTER PUBLIC void outindstackreg() { outindleft(); outregname(STACKREG); outindright(); } #endif PUBLIC void outldaccum() { outload(); outaccum(); outcomma(); } PUBLIC void outldmulreg() { outload(); outregname(MULREG); outcomma(); } PUBLIC void outlea() { outop2str("lea\t"); } PUBLIC void outleasp() { outlea(); outstackreg(); outcomma(); } PUBLIC void outload() { outop2str("mov\t"); } PRIVATE void outmovsx() { outop3str("movsx\t"); } PRIVATE void outmovzx() { outop3str("movzx\t"); } PUBLIC void outmulmulreg() { outop2str("mul\t"); outnregname(MULREG); } PUBLIC void outopsep() { outcomma(); } PUBLIC void outpshs() { outop1str("push"); } PUBLIC void outpuls() { outop1str("pop"); } PUBLIC void outreturn() { outnop1str("ret"); } PUBLIC void outstore() { outload(); } PUBLIC void outsub() { outop2str("sub\t"); } PUBLIC void outtest() { outop2str("test\t"); } PUBLIC void outword() { outstr("word "); } PUBLIC void sctoi() { #ifdef I80386 if (i386_32) { outmovsx(); outaccum(); outncregname(BREG); } else #endif outnop1str("cbw"); } PUBLIC void stoi() { outnop1str("cwde"); } PRIVATE void tfrhilo() { outload(); outstr(acclostr); outcomma(); outhiaccum(); outnl(); } PRIVATE void tfrlohi() { outload(); outhiaccum(); outncregname(BREG); } #ifdef I80386 PUBLIC void ustoi() { outmovzx(); outaccum(); outcomma(); outshortregname(DREG); outnl(); } #endif /* I80386 */ #endif /* I8088 */ #ifdef MC6809 # define ACCHISTR "A" # define ANDSTRING "AND" # define DEFSTR_QUOTER '"' # define EORSTRING "EOR" # define MAX_INLINE_SHIFT 16 # define ORSTRING "OR" # define addfactor(reg) outop2str("ADDD\t,S") # define defstorage() outop0str("RMB\t") # define extBnegD() (ctoi(), negBsbcA()) # define finishfactor() outnl() # define outadc() outop2str("ADC") # define outandhi() outop2str("ANDA") # define outandlo() outop2str("ANDB") # define outcommon() outop0str("\tCOMM\t") # define outdefstr() outop0str("FCC\t\"") # define outequate() outop0str("\tEQU\t") # define outexchange() outop2str("EXG\t") # define outexport() outop0str("EXPORT\t") # define outglobl() outop0str("GLOBL\t") # define outimport() outop0str("IMPORT\t") # define outjswitch() outnop2str("JMP\t[D,X]") # define outlcommon() outop0str("\tLCOMM\t") # define outlswitch() outop3str("LDX\t#") # define outpijswitch() outnop2str("JMP\tD,X") # define outpil1switch() outop3str("LEAX\t<") # define outpil2switch() outnop2str("LDD\tD,X") # define outrolhi() outnop1str("ROLA"); # define outsbc() outop2str("SBC") # define outset() outstr ("\tSET\t") # define outsl() outop1str("LSL") # define outtransfer() outop2str("TFR\t") # define reclaimfactor() outnstr ("++") /* discard factor from stack */ # define savefactor(reg) outop2str("PSHS\tD") # define smiDreg() (clrBreg(), outnop1str("ROLA"), \ outnop2str("SBCB\t#0"), sctoi()) /* this tricky sequence is twice as fast as TFR A,B; SEX; TFR A,B */ /* it gets the sign bit of A in the carry */ /* then subtracts it from 0 in D (effectively) */ # define sr1() (outnop1str("ASRA"), outnop1str("RORB")) # define stackregstr "S" # define subfactor(reg) outop2str("SUBD\t,S") # define testhi() outnop1str("TSTA") # define tfrhilo() outnop2str("TFR\tA,B") # define tfrlohi() outnop2str("TFR\tB,A") # define usr1() (outnop1str("LSRA"), outnop1str("RORB")) PUBLIC void clrBreg() { outnop1str("CLRB"); } PUBLIC void comment() { outstr("| "); } PUBLIC void defbyte() { outop0str("FCB\t"); } PUBLIC void defword() { outop0str("FDB\t"); } PUBLIC void negDreg() { outnop1str("NEGA"); negBsbcA(); } PRIVATE void negBsbcA() { outnop1str("NEGB"); sbc0(); } PUBLIC void comDreg() { outnop1str("COMA"); outnop1str("COMB"); } PUBLIC void outABX() { outnop1str("ABX"); } PUBLIC void outadd() { outop2str("ADD"); } PUBLIC void outaddsp() { outleasp(); bumplc2(); } PUBLIC void outcalladr() { outop2str("JSR"); } PUBLIC void outcmp() { outop2str("CMP"); } PUBLIC void outdec() { outop1str("DEC"); } PUBLIC void outdirectpage() { outbyte('<'); } PUBLIC void outextended() { outbyte('>'); } PUBLIC void outfail() { outop0str("FAIL\t"); } PUBLIC void outinc() { outop1str("INC"); } PUBLIC void outindleft() { outbyte('['); } PUBLIC void outindright() { outbyte(']'); } PUBLIC void outldaccum() { outload(); outaccum(); } PUBLIC void outldmulreg() { outop2str("LDA"); } PUBLIC void outlea() { outop2str("LEA"); } PUBLIC void outleasp() { outop2str("LEAS\t"); } PUBLIC void outload() { outop2str("LD"); } PUBLIC void outmulmulreg() { outnop1str("MUL"); } PUBLIC void outncspregname() { outcomma(); outstackreg(); outnl(); } PUBLIC void outopsep() { } /* is tab, but already done by outadr() */ PUBLIC void outpshs() { outop2str("PSHS"); } PUBLIC void outpuls() { outop2str("PULS"); } PUBLIC void outreturn() { outnop1str("RTS"); } PUBLIC void outstore() { outop2str("ST"); } PUBLIC void outsub() { outop2str("SUB"); } PUBLIC void outtest() { outop1str("TST"); } PUBLIC void sctoi() { outnop1str("SEX"); } PUBLIC void ctoi() { outnop1str("CLRA"); } #endif /* MC6809 */ #ifdef FRAMEREG PUBLIC void outindframereg() { outindleft(); outregname(FRAMEREG); outindright(); } #endif typedef fastin_t seg_t; /* range 0..3 */ PRIVATE seg_t segment; /* current seg, depends on init to CSEG = 0 */ /* add carry resulting from char addition */ PUBLIC void adc0() { #ifdef I80386 if (i386_32) { adjcarry(); outadd(); outaccum(); outncregname(DXREG); } else #endif { outadc(); outhiaccum(); outncimmadr((offset_T) 0); } } /* add constant to register */ PUBLIC void addconst(offset, reg) offset_T offset; store_pt reg; { #ifdef I8088 #ifdef I80386 if ((i386_32 && (uoffset_T) offset + 1 <= 2) /* do -1 to 1 by dec/inc */ || (!i386_32 && (uoffset_T) offset + 2 <= 4)) /* do -2 to 2 */ #else if ((uoffset_T) offset + 2 <= 4) /* do -2 to 2 */ #endif { if (reg == ALREG) reg = AXREG; /* shorter and faster */ do { if (offset < 0) { outdec(); ++offset; } else /* if offset == 0, do inc + dec */ { outinc(); --offset; /* shouldn't happen and harmless */ } outnregname(reg); } while (offset); } else #endif #ifdef MC6809 if (!(reg & ALLDATREGS)) lea(offset, reg, reg); else if (reg == BREG && (offset == 1 || offset == -1)) { if (offset < 0) outdec(); else outinc(); outnregname(reg); } else #endif { outadd(); outimadj(offset, reg); } } /* adjust lc for signed offset */ PUBLIC void adjlc(offset, reg) offset_T offset; store_pt reg; { if (!(reg & CHARREGS)) { bumplc(); if (!isbyteoffset(offset)) { #ifdef I8088 if ((store_t) reg != AXREG) #endif bumplc(); #ifdef I80386 if (i386_32) bumplc2(); #endif } } } /* adjust stack ptr by adding a labelled constant less current sp */ PUBLIC void adjsp(label) label_no label; { outaddsp(); outbyte(LOCALSTARTCHAR); outlabel(label); if (switchnow != NULL) { outminus(); outswstacklab(); } else { outplus(); outhex((uoffset_T) - sp); } #ifdef MC6809 outcregname(LOCAL); #endif #ifdef I80386 if (i386_32) bumplc2(); #endif outnl(); } /* and accumulator with constant */ PUBLIC void andconst(offset) offset_T offset; { char_t botbits; uoffset_T topbits; if ((topbits = offset & ~(uoffset_T) CHMASKTO & intmaskto) != 0 && topbits != (~(uoffset_T) CHMASKTO & intmaskto)) /* if topbits == 0, callers reduce the type */ { #ifdef OP1 outandhi(); outncimmadr((offset_T) (topbits >> (INT16BITSTO - CHBITSTO))); #else outandac(); #ifdef I80386 if (i386_32) bumplc2(); #endif outncimmadr(offset); return; #endif } if ((botbits = (char_t) offset & CHMASKTO) == 0) clrBreg(); else if (botbits != CHMASKTO) { outandlo(); outncimmadr((offset_T) botbits); } } #ifdef I8088 /* set bss segment */ PUBLIC void bssseg() { if (segment != BSSSEG) { segment = BSSSEG; outbssseg(); } } #endif /* jump to case of switch */ PUBLIC label_no casejump() { label_no jtablelab; #ifdef I8088 outlswitch(); outj1switch(); outlabel(jtablelab = getlabel()); outj2switch(); #ifdef I80386 if (i386_32) bumplc2(); #endif #endif #ifdef MC6809 if (posindependent) { outpil1switch(); outlabel(jtablelab = getlabel()); outncregname(GLOBAL); outpil2switch(); outpijswitch(); } else { outlswitch(); outnlabel(jtablelab = getlabel()); outjswitch(); } #endif return jtablelab; } /* clear register to 0 */ PRIVATE void clr(reg) store_pt reg; { loadconst((offset_T) 0, reg); } /* define common storage */ PUBLIC void common(name) char *name; { #ifdef I8088 outcommon(); outccname(name); outcomma(); #endif #ifdef MC6809 outccname(name); outcommon(); #endif } /* set code segment */ PUBLIC void cseg() { if (segment != CSEG) { segment = CSEG; outcseg(); } } /* define long */ PUBLIC void deflong(value) uoffset_T value; { uoffset_T longhigh; uoffset_T longlow; longlow = value & (uoffset_T) intmaskto; #ifdef I80386 if (i386_32) defdword(); else #endif { longhigh = (value >> INT16BITSTO) & (uoffset_T) intmaskto; defword(); #if DYNAMIC_LONG_ORDER if (long_big_endian) #endif #if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN outnhex(longhigh); #endif #if DYNAMIC_LONG_ORDER else #endif #if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN == 0 { outnhex(longlow); longlow = longhigh; } #endif defword(); } outnhex(longlow); } /* define null storage */ PUBLIC void defnulls(nullcount) uoffset_T nullcount; { if (nullcount != 0) { defstorage(); outnhex(nullcount); } } /* define string */ PUBLIC label_no defstr(sptr, stop, dataflag) char *sptr; char *stop; bool_pt dataflag; { int byte; /* promoted char for output */ label_no strlab; seg_t oldsegment; fastin_t count; /* range 0..max(DEFSTR_BYTEMAX,DEFSTR_STRMAX) */ #ifdef HOLDSTRINGS if (!(bool_t) dataflag) return holdstr(sptr, stop); #endif oldsegment = segment; #ifdef I8088 dseg(); #endif #ifdef MC6809 if (dataflag) dseg(); else { segment = STRSEG; /* could use dseg() */ outstrseg(); /* this brings strings together */ } #endif outnlabel(strlab = getlabel()); byte = (unsigned char) *sptr++; while (sptr <= stop) { if ((unsigned char) byte >= MINPRINTCHAR && (unsigned char) byte <= MAXPRINTCHAR) { outdefstr(); count = DEFSTR_STRINGMAX; while (count-- > 0 && (unsigned char) byte >= MINPRINTCHAR && (unsigned char) byte <= MAXPRINTCHAR && sptr <= stop) { #if DEFSTR_DELIMITER - DEFSTR_QUOTER if ((unsigned char) byte == DEFSTR_DELIMITER || (unsigned char) byte == DEFSTR_QUOTER) #else if ((unsigned char) byte == DEFSTR_DELIMITER) #endif outbyte(DEFSTR_QUOTER); outbyte(byte); byte = (unsigned char) *sptr++; } outnbyte(DEFSTR_DELIMITER); } else { defbyte(); count = DEFSTR_BYTEMAX; while (count-- > 0 && ((unsigned char) byte < MINPRINTCHAR || (unsigned char) byte > MAXPRINTCHAR) && sptr <= stop) { if (count < DEFSTR_BYTEMAX - 1) outcomma(); /* byte separator */ outhex((uoffset_T) byte); byte = (unsigned char) *sptr++; } outnl(); } } defbyte(); outnbyte(EOS_TEXT); switch (oldsegment) { case CSEG: cseg(); break; case DSEG: dseg(); break; #ifdef I8088 case BSSSEG: bssseg(); break; #endif #ifdef MC6809 case DPSEG: dpseg(); break; #endif } return strlab; } /* divide D register by a constant if it is easy to do with shifts */ PUBLIC bool_pt diveasy(divisor, uflag) value_t divisor; bool_pt uflag; { bool_t sign; sign = FALSE; if (divisor < 0 && !(bool_t) uflag) { sign = TRUE; divisor = -divisor; } if (bitcount((uvalue_t) divisor) > 1) return FALSE; if (divisor == 0) clr(DREG); else { if (sign) negDreg(); srconst((value_t) highbit((uvalue_t) divisor), uflag); } return TRUE; } #ifdef MC6809 /* set direct page segment */ PUBLIC void dpseg() { if (segment != DPSEG) { segment = DPSEG; outdpseg(); } } #endif /* set data segment */ PUBLIC void dseg() { if (segment != DSEG) { segment = DSEG; outdseg(); } } /* equate a name to an EOL-terminated string */ PUBLIC void equ(name, string) char *name; char *string; { outstr(name); outequate(); outline(string); } /* equate a local label to a value */ PUBLIC void equlab(label, offset) label_no label; offset_T offset; { outbyte(LOCALSTARTCHAR); outlabel(label); outequate(); outshex(offset); outnl(); } /* import or export a variable */ PUBLIC void globl(name) char *name; { outglobl(); outnccname(name); } /* import a variable */ PUBLIC void import(name) char *name; { outimport(); outnccname(name); } /* extend an int to a long */ PUBLIC void itol(reg) store_pt reg; { #define TEMP_LABEL_FOR_REGRESSION_TESTS #ifdef TEMP_LABEL_FOR_REGRESSION_TESTS getlabel(); #endif if (lowregisDreg()) { #ifdef I8088 outcwd(); regtransfer(DXREG, reg); #else label_no exitlab; clr(reg); testhi(); sbranch(GE, exitlab = getlabel()); loadconst((offset_T) - 1, reg); outnlabel(exitlab); #endif } else { regtransfer(DREG, reg); smiDreg(); } } /* define local common storage */ PUBLIC void lcommlab(label) label_no label; { outlabel(label); outlcommon(); } PUBLIC void lcommon(name) char *name; { outccname(name); outlcommon(); } #ifdef MC6809 /* load effective address */ PUBLIC void lea(offset, sourcereg, targreg) offset_T offset; store_pt sourcereg; store_pt targreg; { outlea(); outregname(targreg); outtab(); outshex(offset); outncregname(sourcereg); } #endif /* load constant into given register */ PUBLIC void loadconst(offset, reg) offset_T offset; store_pt reg; { #ifdef I8088 if (offset == 0) { outxor(); outregname(reg); outncregname(reg); } else #endif #ifdef MC6809 if (offset == 0 && reg == BREG) clrBreg(); else #endif { outload(); outregname(reg); #ifdef MC6809 if (reg == YREG) bumplc2(); else #endif if (reg != BREG) { bumplc(); #ifdef I80386 if (i386_32) bumplc2(); #endif } outncimmadr(offset); } } /* convert index half of long reg pair into low half of pair */ PRIVATE bool_pt lowregisDreg() { #if DYNAMIC_LONG_ORDER if (long_big_endian) #endif # if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN return FALSE; #endif #if DYNAMIC_LONG_ORDER else #endif #if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN == 0 return TRUE; #endif } /* partially long shift left register by a constant (negative = infinity) */ PUBLIC int lslconst(shift, reg) value_t shift; store_pt reg; { if ((uvalue_t) shift >= INT16BITSTO) { slconst(shift - INT16BITSTO, lowregisDreg() ? DREG : reg); regexchange(reg, DREG); clr(lowregisDreg() ? DREG : reg); return 0; } #ifdef I8088 if (shift >= CHBITSTO) { if (long_big_endian) { tfrlohi(); outnop2str("mov\tal,bh"); outnop2str("mov\tbh,bl"); outnop2str("sub\tbl,bl"); } else { outnop2str("mov\tbh,bl"); outnop2str("mov\tbl,ah"); tfrlohi(); clrBreg(); } return (int) shift - CHBITSTO; } #endif return (int) shift; } /* partially long shift right register by a constant (negative = infinity) */ PUBLIC int lsrconst(shift, reg, uflag) value_t shift; store_pt reg; bool_pt uflag; { if ((uvalue_t) shift >= INT16BITSTO) { if (lowregisDreg()) regexchange(reg, DREG); srconst(shift - INT16BITSTO, uflag); if ((bool_t) uflag) uitol(reg); else itol(reg); return 0; } #ifdef I8088 if (shift >= CHBITSTO) { if (long_big_endian) { outnop2str("mov\tbl,bh"); outnop2str("mov\tbh,al"); tfrhilo(); if ((bool_t) uflag) ctoi(); else sctoi(); } else { tfrhilo(); outnop2str("mov\tah,bl"); outnop2str("mov\tbl,bh"); if ((bool_t) uflag) outnop2str("sub\tbh,bh"); else { regexchange(reg, DREG); sctoi(); regexchange(reg, DREG); } } return (int) shift - CHBITSTO; } #endif return (int) shift; } /* take D register modulo a constant if it is easy to do with a mask */ PUBLIC bool_pt modeasy(divisor, uflag) value_t divisor; bool_pt uflag; { bool_t sign; sign = FALSE; if (divisor < 0 && !(bool_t) uflag) { sign = TRUE; divisor = -divisor; } if (bitcount((uvalue_t) divisor) > 1) return FALSE; if (--divisor == 0) clrBreg(); /* original divisor 1 or -1 yields 0 */ else { if (sign) negDreg(); andconst((offset_T) divisor); /* if original divisor 0, this is null */ if (sign) negDreg(); } return TRUE; } /* multiply register by a constant if it is easy to do with shifts */ PUBLIC bool_pt muleasy(factor, reg) uvalue_t factor; store_pt reg; { int mulstack[MAXINTBITSTO / 2 + 1]; /* must be signed, not a fastin_t */ fastin_pt count; fastin_t single1skip; fastin_t lastcount; fastin_t mulsp; int stackentry; /* signed */ #ifdef I8088 /* Now using imul directly so don't be so keen to shift */ if( factor > 16 && factor != 32 && factor != 64 && factor != 0xFFFFFFFFL ) return FALSE; #endif if (factor == 0) { clr(reg); return TRUE; } single1skip = 0; mulsp = -1; /* may be unsigned, but bumps to 0 */ while (factor != 0) { for (lastcount = single1skip; (factor & 1) == 0; factor >>= 1) ++lastcount; mulstack[(int)++mulsp] = lastcount; /* first time bumps mulsp to 0 even if an unsigned char */ for (count = 0; (factor & 1) != 0; factor >>= 1) ++count; single1skip = 1; if (count == 2 && factor == 0) /* 3 = 2 + 1 better than 3 = 4 - 1 */ /* but rest of algorithm messed up unless factor now 0 */ mulstack[(int)++mulsp] = 1; else if (count > 1) { single1skip = 0; if (lastcount == 1 && mulsp != 0) mulstack[(int)mulsp] = -1 - count; else mulstack[(int)++mulsp] = -count; } } if (mulsp > 3) return FALSE; if (mulsp != 0) { savefactor(reg); /* on stack or in reg as nec */ do { finishfactor(); /* finish save/add/subfactor() if nec */ stackentry = mulstack[(int)mulsp--]; if (stackentry < 0) { #ifdef I8088 if (stackentry == -INT32BITSTO) clr(reg); /* shifting would do nothing */ else #endif slconst((value_t) - stackentry, reg); subfactor(reg); /* from wherever put by savefactor() */ } else { slconst((value_t) stackentry, reg); addfactor(reg); /* from wherever put by savefactor() */ } } while (mulsp != 0); reclaimfactor(); /* reclaim storage if nec */ } slconst((value_t) mulstack[0], reg); return TRUE; } /* negate a register */ PUBLIC void negreg(reg) store_pt reg; { if ((store_t) reg == BREG) extBnegD(); else negDreg(); } /* return string of operator */ PUBLIC char *opstring(op) op_pt op; { switch (op) { case ANDOP: return ANDSTRING; case EOROP: return EORSTRING; case OROP: return ORSTRING; } return "badop"; } /* print DREG (accumulator) */ PRIVATE void outaccum() { outstr(accumstr); } /* print a c compiler name with leading CCNAMEPREXFIX */ PUBLIC void outccname(name) char *name; { outbyte(CCNAMEPREFIX); outstr(name); } /* print high byte of word accumulator */ PUBLIC void outhiaccum() { outstr(ACCHISTR); } /* print immediate address */ PUBLIC void outimmadr(offset) offset_T offset; { #ifdef I8088 if (!isbyteoffset(offset)) outimmed(); else outbimmed(); #else outimmed(); #endif outshex(offset); } /* print register, comma, immediate address and adjust lc */ PUBLIC void outimadj(offset, targreg) offset_T offset; store_pt targreg; { outregname(targreg); adjlc(offset, targreg); outncimmadr(offset); } /* print immediate address designator */ PUBLIC void outimmed() { outbyte('#'); } PUBLIC void outjumpstring() { outop3str(jumpstring); #ifdef I80386 if (i386_32) bumplc2(); #endif } /* print cc name, then newline */ PUBLIC void outnccname(name) char *name; { outccname(name); outnl(); } /* print separator, immediate address, newline */ PUBLIC void outncimmadr(offset) offset_T offset; { #ifdef I8088 outcomma(); #endif #ifdef MC6809 outtab(); #endif outimmadr(offset); outnl(); } /* print signed offset and adjust lc */ PUBLIC void outoffset(offset) offset_T offset; { #ifdef MC6809 if (!is5bitoffset(offset)) #endif adjlc(offset, INDREG0); outshex(offset); } /* print stack register */ PRIVATE void outstackreg() { outstr(stackregstr); } PUBLIC void public(name) char *name; { #ifndef AS09 outexport(); outnccname(name); #endif outccname(name); outnbyte(PUBLICENDCHAR); } /* print cc name as a private label */ PUBLIC void private(name) char *name; { #ifdef LABELENDCHAR outccname(name); outnbyte(LABELENDCHAR); #else outnccname(name); #endif } /* exchange registers */ PUBLIC void regexchange(sourcereg, targreg) store_pt sourcereg; store_pt targreg; { outexchange(); outregname(sourcereg); outncregname(targreg); #ifdef I8088 if (!((sourcereg | targreg) & AXREG)) bumplc(); #endif } /* transfer a register */ PUBLIC void regtransfer(sourcereg, targreg) store_pt sourcereg; store_pt targreg; { outtransfer(); #ifdef TARGET_FIRST outregname(targreg); outncregname(sourcereg); #else outregname(sourcereg); outncregname(targreg); #endif } /* subtract carry resulting from char addition */ PUBLIC void sbc0() { #ifdef I80386 if (i386_32) { adjcarry(); outsub(); outaccum(); outncregname(DXREG); } else #endif { outsbc(); outhiaccum(); outncimmadr((offset_T) 0); } } /* set a name to a value */ PUBLIC void set(name, value) char *name; offset_T value; { outccname(funcname); outbyte(LOCALSTARTCHAR); outstr(name); outset(); outshex(value); #ifdef FRAMEPOINTER #ifdef I8088 #ifndef NO_DEL_PUSH if (framep && optimise && !callersaves && value+sp-framep >= 0 && !(regfuse & callee1mask)) { outbyte('-'); outstr(funcname); outstr(".off"); } #endif #endif #endif outnl(); #ifdef FRAMEPOINTER if (framep) { outbyte(LOCALSTARTCHAR); outstr(funcname); outbyte(LOCALSTARTCHAR); outstr(name); outset(); outshex(value+sp-framep); #ifdef I8088 #ifndef NO_DEL_PUSH if (optimise && !callersaves && value+sp-framep < 0 && !(regfuse & callee1mask)) { outbyte('+'); outstr(funcname); outstr(".off"); } #endif #endif outnl(); } #endif } /* shift left register by 1 */ PUBLIC void sl1(reg) store_pt reg; { outsl(); #ifdef I8088 outregname(reg); outnc1(); #endif #ifdef MC6809 outnregname(BREG); outrolhi(); #endif } /* shift left register by a constant (negative = infinity) */ PUBLIC void slconst(shift, reg) value_t shift; store_pt reg; { #ifdef I80386 if (i386_32) { if ((shift = (uvalue_t) shift % INT32BITSTO) != 0) { outsl(); if (shift != 1) bumplc(); outregname(reg); outncimmadr((offset_T) shift); } return; } #endif if ((uvalue_t) shift >= INT16BITSTO) clr(reg); else { if (shift >= CHBITSTO && reg == DREG) { tfrlohi(); clrBreg(); shift -= CHBITSTO; } #ifdef I8088 # if MAX_INLINE_SHIFT < INT16BITSTO if (shift > MAX_INLINE_SHIFT) { outload(); outregname(SHIFTREG); outcomma(); outimmadr((offset_T) shift); outnl(); outsl(); outregname(reg); outncregname(SHIFTREG); } else # endif #endif while (shift--) sl1(reg); } } /* shift right D register by a constant (negative = infinity) */ PUBLIC void srconst(shift, uflag) value_t shift; bool_pt uflag; { #ifdef I80386 if (i386_32) { if ((shift = (uvalue_t) shift % INT32BITSTO) != 0) { if (uflag) outusr(); else outsr(); if (shift != 1) bumplc(); outaccum(); outncimmadr((offset_T) shift); } return; } #endif if ((uvalue_t) shift >= INT16BITSTO) /* covers negatives too */ { if ((bool_t) uflag) clr(DREG); else /* make D == 0 if D >= 0, else D == -1 */ smiDreg(); /* special case of 68020 Scc instruction */ } else { if (shift >= CHBITSTO) { tfrhilo(); if ((bool_t) uflag) ctoi(); else sctoi(); shift -= CHBITSTO; } #ifdef I8088 # if MAX_INLINE_SHIFT < INT16BITSTO if (shift > MAX_INLINE_SHIFT) { outload(); outregname(SHIFTREG); outcomma(); outimmadr((offset_T) shift); outnl(); if ((bool_t) uflag) outusr(); else outsr(); outaccum(); outncregname(SHIFTREG); } else # endif #endif while (shift--) { if ((bool_t) uflag) usr1(); else sr1(); } } } /* extend an unsigned in DREG to a long */ PUBLIC void uitol(reg) store_pt reg; { if (lowregisDreg()) clr(reg); else { regexchange(DREG, reg); clr(DREG); } } PRIVATE char opregstr[] = "_opreg"; /*----------------------------------------------------------------------------- opregadr() outputs address of variable opreg where OPREG is saved -----------------------------------------------------------------------------*/ PRIVATE void opregadr() { #ifdef I8088 outindleft(); outccname(opregstr); outindright(); bumplc2(); #ifdef I80386 if (i386_32) bumplc2(); #endif #endif #ifdef MC6809 outregname(OPREG); outtab(); if (posindependent) { outccname(opregstr); outncregname(GLOBAL); bumplc(); } else { outextended(); outnccname(opregstr); } bumplc(); #endif } /*----------------------------------------------------------------------------- restoreopreg() restores register OPREG from static location >opreg if it is was use -----------------------------------------------------------------------------*/ PUBLIC void restoreopreg() { if (reguse & OPREG) { #ifdef I8088 outload(); outregname(OPREG); outopsep(); opregadr(); outnl(); #endif #ifdef MC6809 outload(); opregadr(); #endif } } /*----------------------------------------------------------------------------- saveopreg() saves register OPREG to static location >opreg if it is in use this makes the flop routines non-reentrant. It is too messy to push it because the flop routines leave results on the stack -----------------------------------------------------------------------------*/ PUBLIC void saveopreg() { if (reguse & OPREG) { #ifdef I8088 bssseg(); common(opregstr); outnhex(opregsize); cseg(); outstore(); opregadr(); outncregname(OPREG); #endif #ifdef MC6809 dseg(); common(opregstr); outnhex(opregsize); cseg(); outstore(); opregadr(); #endif } } dev86-0.16.21/bcc/condcode.h000066400000000000000000000003601231050321700152640ustar00rootroot00000000000000/* condcode.h - condition codes for bcc */ /* Copyright (C) 1992 Bruce Evans */ #define EQ 0 #define NE 1 #define RA 2 #define RN 3 #define LT 4 #define GE 5 #define LE 6 #define GT 7 #define LO 8 #define HS 9 #define LS 10 #define HI 11 dev86-0.16.21/bcc/const.h000066400000000000000000000042631231050321700146420ustar00rootroot00000000000000/* const.h - constants for bcc */ /* Copyright (C) 1992 Bruce Evans */ #ifdef __STDC__ #include #else #include #endif #include "debug.h" /* switches for code generation */ #if !defined(I8088) && !defined(MC6809) /* The default compiler type ... */ #define I8088 /* target processor is Intel 8088 thru 80386 */ #undef MC6809 /* target processor is Motorola 6809 */ #endif #ifdef __AS386_16__ #define VERY_SMALL_MEMORY #endif #ifndef VERY_SMALL_MEMORY #define SELFTYPECHECK /* check calculated type = runtime type */ #define OPTIMISE /* include optimisation code */ #ifndef MSDOS #define DBNODE /* generate compiler node debugging code */ #endif #endif #ifndef __BCC__ #define BUILTIN_CPP /* Remove the built in C preprocessor */ #endif #ifdef I8088 # define FRAMEPOINTER /* index locals off frame ptr, not stack ptr */ # define HOLDSTRINGS /* hold strings for dumping at end * since assembler has only 1 data seg */ # define DYNAMIC_LONG_ORDER 1 /* long word order spec. at compile time */ #ifdef __HAS_NO_FLOATS__ /* Humm, now this is nasty :-) */ #define float no_hope #define double no_hope #define atof atol #define NOFLOAT typedef long no_hope; #endif #ifndef VERY_SMALL_MEMORY #ifndef NO_I80386 # define I80386 /* Little BCC doesn't need 386 */ #endif #endif #endif #ifdef MC6809 # define DYNAMIC_LONG_ORDER 0 /* have to define it so it works in #if's */ # define OP1 /* logical operators only use 1 byte */ # define POSINDEPENDENT /* position indep code can (also) be gen */ #endif /* switches for source and target operating system dependencies */ /*#define SOS_EDOS*/ /* source O/S is EDOS */ /*#define SOS_MSDOS*/ /* source O/S is MSDOS */ /*#define TOS_EDOS*/ /* target O/S is EDOS */ #ifdef MSDOS #define SOS_MSDOS #endif /* switches for source machine dependencies */ /* Unportable alignment needed for specific compilers */ #ifndef VERY_SMALL_MEMORY # define S_ALIGNMENT (sizeof(long)) /* A little safer */ #endif /* local style */ #ifndef NULL #define NULL 0 #endif #define FALSE 0 #define TRUE 1 #define EXTERN extern #define FORWARD static #define PRIVATE static #define PUBLIC /* #define C_CODE * Don't use assembler outstr() function. */ dev86-0.16.21/bcc/dbnode.c000066400000000000000000000074561231050321700147510ustar00rootroot00000000000000/* dbnode.c - print debug messages for operators for bcc */ /* Copyright (C) 1992 Bruce Evans */ #include "bcc.h" #ifdef DBNODE #include "gencode.h" #include "reg.h" #include "sc.h" #include "scan.h" #include "type.h" PRIVATE char *opname[LASTOP - FIRSTOP + 1] = /* operator names */ { /* order must agree with op.h */ "cond?", "or", "eor", "and", "gt", "lt", "add", "div", "mod", "lognot", "not", "strucelt", "strucptr", "eq", "addab", "andab", "divab", "eorab", "modab", "mulab", "orab", "slab", "srab", "subab", "comma", "cond:", "logor", "logand", "logeq", "ne", "ge", "le", "sl", "sr", "sub", "mul", "address", "cast", "indirect", "neg", "predec", "preinc", "postdec", "postinc", "func", "list", "rootlist", "leaf", "ptraddab", "ptradd", "ptrsub", }; FORWARD void outindchars P((int byte, indn_pt count)); PUBLIC void dbitem(item) struct symstruct *item; { dbtype(item->type); if (item->storage == NOSTORAGE) { outbyte(' '); outstr(item->name.namep + 2); outstr(" (offset "); outshex(item->offset.offi); outbyte(')'); return; } if (item->storage == LOCAL) { outbyte(' '); if (item->flags == TEMP) outstr("(temp)"); else outstr(item->name.namep); } outstr(" = "); outindchars('[', item->indcount); switch (item->storage) { case CONSTANT: outstr("const "); if (item->type->scalar & RSCALAR) outstr("(whatever)"); else if (item->type->scalar & UNSIGNED) outuvalue((uvalue_t) item->offset.offv); else outvalue(item->offset.offv); break; case BREG: case DREG: case INDREG0: case INDREG1: case INDREG2: #ifdef DATREG1 case DATREG1: #endif #ifdef DATREG2 case DATREG2: #endif outregname(item->storage); if (item->level == OFFKLUDGELEVEL) { outplus(); if (item->flags & LABELLED) outlabel(item->name.label); else outccname(item->name.namep); } break; case LOCAL: outbyte('S'); if (sp <= 0) outplus(); outshex(-sp); break; case GLOBAL: if (item->flags & LABELLED) outlabel(item->name.label); else outstr(item->name.namep); break; default: outstr("bad storage ("); outhex((uoffset_T) item->storage); outbyte(')'); outstr(" offset "); } if (item->storage != CONSTANT) { if (item->offset.offi >= 0) outplus(); outshex(item->offset.offi); } outindchars(']', item->indcount); } PUBLIC void dbtype(type) struct typestruct *type; { for ( ; type != NULL; type = type->nexttype) { outbyte(' '); switch (type->constructor) { case ARRAY: outbyte('['); outhex(type->typesize / type->nexttype->typesize); outbyte(']'); break; case FUNCTION: outstr("()"); break; case POINTER: outbyte('*'); break; case STRUCTU: outstr("struct "); default: if (type->scalar & UNSIGNED) outstr("unsigned "); outstr(type->tname); break; } } } PUBLIC void dbnode(exp) /* sub-nodes must be leaves */ struct nodestruct *exp; { if (!dbnodeon) return; outstr("! Debug: "); if (exp->tag < FIRSTOP && exp->tag > LASTOP) outstr("unknown op"); else outstr(opname[exp->tag - FIRSTOP]); if (exp->right != NULL && exp->tag != FUNCOP && exp->tag != LISTOP && exp->tag != ROOTLISTOP) { dbitem(exp->right->left.symptr); outstr(" to"); } dbitem(exp->left.nodeptr->left.symptr); outstr(" (used reg = "); if (reguse & INDREG0) outregname(INDREG0); if (reguse & INDREG1) outregname(INDREG1); if (reguse & INDREG2) outregname(INDREG2); outnstr(")"); } PUBLIC void dbnodeswap() { if (dbnodeon) outnstr("! Debug: expression subtree swapping"); } PRIVATE void outindchars(byte, count) int byte; indn_pt count; { while (count--) outbyte(byte); } #endif /* DBNODE */ dev86-0.16.21/bcc/dbprintf.c000066400000000000000000000104361231050321700153160ustar00rootroot00000000000000 #include #include #if defined(__STDC__) && !defined(__FIRST_ARG_IN_AX__) #include #define va_strt va_start #else #include #define va_strt(p,i) va_start(p) #endif #if defined(__STDC__) && !defined(__FIRST_ARG_IN_AX__) int dbprintf(const char * fmt, ...) #else int dbprintf(fmt, va_alist) __const char *fmt; va_dcl #endif { va_list ptr; int rv; va_strt(ptr, fmt); rv = vdbprintf(fmt,ptr); va_end(ptr); return rv; } static unsigned char * __numout (long i, int base); static void putch(int ch) { static char buf[2]; *buf = ch; write(2,buf,1); } int vdbprintf(fmt, ap) register __const char *fmt; register va_list ap; { int c; int count = 0; int type, base; long val; char * cp; char padch=' '; int minsize, maxsize; while(c=*fmt++) { count++; if(c!='%') putch(c); else { type=1; padch = *fmt; maxsize=minsize=0; if(padch == '-') fmt++; for(;;) { c=*fmt++; if( c<'0' || c>'9' ) break; minsize*=10; minsize+=c-'0'; } if( c == '.' ) for(;;) { c=*fmt++; if( c<'0' || c>'9' ) break; maxsize*=10; maxsize+=c-'0'; } if( padch == '-' ) minsize = -minsize; else if( padch != '0' ) padch=' '; if( c == 0 ) break; if(c=='h') { c=*fmt++; type = 0; } else if(c=='l') { c=*fmt++; type = 2; } switch(c) { case 'x': base=16; type |= 4; if(0) { case 'o': base= 8; type |= 4; } if(0) { case 'u': base=10; type |= 4; } if(0) { case 'd': base=-10; } switch(type) { case 0: /* Promoted: val=va_arg(ap, short); break; */ case 1: val=va_arg(ap, int); break; case 2: val=va_arg(ap, long); break; case 4: /* Promoted: val=va_arg(ap, unsigned short); break; */ case 5: val=va_arg(ap, unsigned int); break; case 6: val=va_arg(ap, unsigned long); break; default:val=0; break; } cp = __numout(val,base); if(0) { case 's': cp=va_arg(ap, char *); } count--; c = strlen(cp); if( !maxsize ) maxsize = c; if( minsize > 0 ) { minsize -= c; while(minsize>0) { putch(padch); count++; minsize--; } minsize=0; } if( minsize < 0 ) minsize= -minsize-c; while(*cp && maxsize-->0 ) { putch(*cp++); count++; } while(minsize>0) { putch(' '); count++; minsize--; } break; case 'c': putch(va_arg(ap, int)); break; case 'C': c = va_arg(ap, int); if (c>0x7F) { c &=0x7F; putch('M'); putch('-'); } if (c<' ' || c == '\177') { putch('^'); putch(c^'@'); } else putch(c); break; default: putch(c); break; } } } return count; } static char nstring[]="0123456789ABCDEF"; #ifndef __AS386_16__ #define NUMLTH 11 static unsigned char * __numout(long i, int base) { static unsigned char out[NUMLTH+1]; int n; int flg = 0; unsigned long val; if (base<0) { base = -base; if (i<0) { flg = 1; i = -i; } } val = i; out[NUMLTH] = '\0'; n = NUMLTH-1; do { out[n--] = nstring[val % base]; val /= base; } while(val); if(flg) out[n--] = '-'; return &out[n+1]; } #else #asm ! numout.s ! .bss ___out lcomm $C .text ___numout: push bp mov bp,sp push di push si add sp,*-4 mov byte ptr -8[bp],*$0 ! flg = 0 mov si,4[bp] ; i or val.lo mov di,6[bp] ; i or val.hi mov cx,8[bp] ; base test cx,cx ! base < 0 ? jge .3num neg cx ! base = -base or di,di ! i < 0 ? jns .5num mov byte ptr -8[bp],*1 ! flg = 1 neg di ! i = -i neg si sbb di,0 .5num: .3num: mov byte ptr [___out+$B],*$0 ! out[11] = nul mov -6[bp],*$A ! n = 10 .9num: !!! out[n--] = nstring[val % base]; xor dx,dx xchg ax,di div cx xchg ax,di xchg ax,si div cx xchg ax,si ! val(new) = val / base mov bx,dx ! dx = val % base mov al,_nstring[bx] mov bx,-6[bp] dec word ptr -6[bp] mov ___out[bx],al mov ax,si or ax,di ! while (val) jne .9num cmp byte ptr -8[bp],*$0 ! flg == 0 ? je .Dnum mov bx,-6[bp] dec word ptr -6[bp] mov byte ptr ___out[bx],*$2D ! out[n--] = minus .Dnum: mov ax,-6[bp] add ax,#___out+1 add sp,*4 pop si pop di pop bp ret #endasm #endif dev86-0.16.21/bcc/debug.c000066400000000000000000000132021231050321700145660ustar00rootroot00000000000000/* * debug.c: a generic debugging facility for unix programs. * * The calling program is required to call debug_setlevel(lvl) to set * which messages will be displayed. The level is a two part value * where the least significant (decimal) digit is a level as described * below. The most significant digits are a class code. For a message * to be displayed the class code must either be zero or match the * class code of the debug(...) message. * * The 'debug(lvl, fmt, ...)' function displays debugging messages * complete with source and line number. The function can be used * as a normal one in if() smt else smt constructs. It returns the * actual number of bytes printed so it's return value can be used * inside an if(debug(...)) to enable more debugging code. This code * will be removed by the compiler (as dead code) if debugging is * not enabled. * * The level on the debug() statment also consists of a level and class * code where the class code must be zero or match the setlevel's class * code for the message to be displayed. * * Level 0 * Always displayed if the debugging is enabled. * You probably shouldn't use this. * * Level 1 * Important state changes and errors that cause a significant change * in program flow. * * Level 2 * Rare things that cause a minor program flow adjustment. * * Level 3 * Errors and useful messages that are slightly too verbose or common * for 0-2 or don't quite fit in the classifications. * * Level 4 * All remote responses or major results. (Trace results) * * Level 5 * All remote commands or major tasks. (Trace jobs) * * Level 6 * General information that will not be too verbose but is normally a * little less important. (Trace state) * * Level 7 * Similar to level 3 but verbose or not as useful. * * Level 8 * Very verbose information that'll probably be useful sometime. * * Level 9 * Anything and everything else, debugs that probably won't be useful * ever again. (unclassified) * * Notes: * If the programmer doesn't set the debug level this is not an important * debug message or is only important right now. * => default debug level == 9 * * If something fits in one of the lower levels but is very verbose * it should nevertheless be moved upto level 3 or levels 7-9. * (Possibly leaving a single line 'oops' at the lower level) * * The general idea is that debug levels 0-3 should not scroll too fast * to read and nothing below level 7 should be much more verbose than * levels 4 or 5. * ***************************************************************************** * * 2004-06-20: Added __STDC__ to debug.h so it can be called from non-ansi * compiler. This file still needs ansi or unproto. * * 2004-06-20: Added check of DEBUG environment variable if setlevel isn't * called before a debug(). * * 2004-06-20: Added #define VARARG_MACROS so the preprocessor can remove * all the debugging 'stuff'. * */ #include #include #include #include "debug.h" #define USE_DBPRINTF #ifndef DEBUG static char ident[] = "$Id: debug.c: (c) 1995-2004 Robert de Bath. Debugging disabled. $"; #else static char ident[] = "$Id: debug.c: (c) 1995-2004 Robert de Bath. Debugging enabled. $"; static char * db_file = 0; static int db_lineno = 0; static int disp_state = 0; static int disp_pos(void); static void debug_envvar(void); int debug_level = -1; void debug_do_setlevel(char * fname, int lineno, int level) { if(level || !debug_level) debug_level = level; debug_pos(fname, lineno); debug_msg(1, "Debug level now %d", level); debug_level = level; } int debug_pos(char * file, int lineno) { db_file = file; db_lineno = lineno; disp_state |= 1; return disp_pos(); } int debug_msg(int level, char * fmt, ...) { va_list ap; int rv = 0; int disp = 0; if (debug_level == -1) debug_envvar(); if (level == -1) { level = 0; disp_state |= 1; db_lineno = -1; } disp_state |= 2; if (level>9 || debug_level>9) { disp = (level%10 <= debug_level%10); if (disp && level>9 && debug_level>9 && level/10 != debug_level/10) disp = 0; } else disp = (level <= debug_level); if (disp) { disp_state |= 4; va_start(ap, fmt); #ifdef USE_DBPRINTF rv = vdbprintf(fmt, ap); #else rv = vfprintf(stderr, fmt, ap); #endif va_end(ap); } return rv + disp_pos(); } int disp_pos() { int rv = 0; if (disp_state == 7 && db_lineno != -1) #ifdef USE_DBPRINTF rv = dbprintf(" at %s:%d\n", db_file, db_lineno); #else rv = fprintf(stderr, " at %s:%d\n", db_file, db_lineno); #endif if ((disp_state&3) == 3) { db_file = 0; db_lineno = disp_state = 0; } return rv; } /* If setlevel isn't called check the environment */ static void debug_envvar(void) { char * p = getenv("DEBUG"); if (!p || !*p) debug_level = 0; else debug_level = atoi(p); if (debug_level) #ifdef USE_DBPRINTF dbprintf("Debug level now %d from environment.\n", debug_level); #else fprintf(stderr, "Debug level now %d from environment.\n", debug_level); #endif } #endif #ifndef VARARG_MACROS /* * This function should never be called. * * If ident sees the message in a binary then your compiler is wasting * space by allocating it for unused strings. * * We know GNU-C is ok, but it complains. */ int debug_never(int level, char * name, ...) { #ifndef __GNUC__ 1?0:debug_never(0, "$Warning: Debugging strings exist in non-debug binary $"); #endif return 0; } #endif dev86-0.16.21/bcc/debug.h000066400000000000000000000014721231050321700146010ustar00rootroot00000000000000 #ifndef _DEBUG_H_ #define _DEBUG_H_ #if __STDC__ void debug_do_setlevel(char * fname, int lineno, int level); int debug_pos(char * file, int lineno); int debug_msg(int level, char * name, ...); int debug_never(int level, char * name, ...); #else void debug_do_setlevel(); int debug_pos(); int debug_msg(); int debug_never(); #endif /* __STDC__ */ /* The new CPP has these. */ #if defined(__BCC__) && (__BCC_VERSION__ >= 0x001011L) #define VARARG_MACROS #endif #ifdef DEBUG extern int debug_level; #define debug !debug_level?0:debug_pos(__FILE__,__LINE__)+debug_msg #define debug_setlevel(lvl) debug_do_setlevel(__FILE__, __LINE__, lvl) #else /* !DEBUG */ #ifdef VARARG_MACROS # define debug(junk ...) 0 #else # define debug 1?0:debug_never #endif # define debug_setlevel(lvl) #endif /* DEBUG */ #endif /* _DEBUG_H_ */ dev86-0.16.21/bcc/declare.c000066400000000000000000000672551231050321700151200ustar00rootroot00000000000000/* declare.c - declaration routines for bcc */ /* Copyright (C) 1992 Bruce Evans */ #ifndef VERY_SMALL_MEMORY #include #endif #include "bcc.h" #include "align.h" #include "byteord.h" #include "gencode.h" #include "input.h" /* just for orig_cppmode */ #include "reg.h" #include "sc.h" #include "scan.h" #include "sizes.h" #include "table.h" #include "type.h" #undef EXTERN #define EXTERN #include "parse.h" PRIVATE bool_t argsallowed; /* nonzero to allow args in declarator */ PRIVATE sym_t gvarsc; /* sc flags of last identifier declared */ PRIVATE char gvar2name[2 + NAMESIZE]; /* space for structure keys and .. */ #define gvarname (gvar2name + 2) /* last identifier declared */ PRIVATE struct typestruct *gvartype; /* type of last identifier declared */ PRIVATE bool_t initlistflag; /* remembers whether initializer is a list */ #ifndef VERY_SMALL_MEMORY PRIVATE int anons = 0; /* number of anonymous structures/unions seen */ #endif FORWARD struct typestruct *chainprefix P((struct typestruct *pretype, struct typestruct *sufftype)); FORWARD void declaf P((void)); FORWARD void declarator P((void)); FORWARD void declarg P((void)); FORWARD struct typestruct *declenum P((void)); FORWARD void declfunc P((void)); FORWARD void declselt P((struct typestruct *structype, offset_T *psoffset, struct typelist ** ptypelist)); FORWARD bool_pt declspec P((void)); FORWARD struct typestruct *declsu P((void)); FORWARD void idecllist P((void)); FORWARD void initarray P((struct typestruct *type)); FORWARD void inititem P((struct typestruct *type)); FORWARD void initstruct P((struct typestruct *type)); FORWARD void lbrace P((void)); FORWARD void multidecl P((char *sname)); FORWARD void need P((int charneeded)); FORWARD void rdeclarator P((void)); FORWARD bool_pt regdecl P((void)); PRIVATE struct typestruct *chainprefix(pretype, sufftype) struct typestruct *pretype; struct typestruct *sufftype; { if (pretype->nexttype != NULL) { sufftype = chainprefix(pretype->nexttype, sufftype); if (pretype->constructor != ARRAY) return prefix(pretype->constructor, pretype->typesize, sufftype); else return prefix(ARRAY, pretype->typesize / pretype->nexttype->typesize * sufftype->typesize, sufftype); } return sufftype; } PUBLIC void colon() { if (sym != COLON) need(':'); else nextsym(); } /* decllist() - list of local declarations */ /* this does the non-terminal symbols declaration-list, type-declaration */ /* list and declaration */ /* the different cases are and ";" at the end are decided by idecllist() */ PUBLIC void decllist() { while (declspec()) { if (gvarsc == NULLDECL) gvarsc = AUTODECL; idecllist(); } } PRIVATE void declaf() { uoffset_T asize; bool_t levelnew; #ifdef TESTING_PROTOTYPES char ogvarname[NAMESIZE]; sym_t ogvarsc; struct symstruct *ogvarsymptr; struct typestruct *ogvartype; #endif if (sym == LPAREN) /* function */ { nextsym(); if (argsallowed && level == GLBLEVEL) { newlevel(); levelnew = TRUE; } else levelnew = FALSE; #ifdef TESTING_PROTOTYPES strcpy(ogvarname, gvarname); ogvarsc = gvarsc; ogvarsymptr = gvarsymptr; ogvartype = gvartype; if (declspec()) { if (level == ARGLEVEL) outstr(gvarname); outbyte('('); do { declarator(); dbtype(gvartype); outbyte(' '); #if 0 if (gvarname[0] != 0 && gsymptr != NULL && gsymptr->level == level) error("repeated argument"); #endif outstr(gvarname); if (levelnew) addloc(gsname, gvartype); /* adjust offsets later */ if (sym != COMMA) break; outcomma(); nextsym(); } while (declspec()); if (sym == STRUCELTOP) { /* ... should be lexed. */ nextsym(); if (sym == STRUCELTOP) { nextsym(); if (sym == STRUCELTOP) { nextsym(); outstr(" ..."); } } } outbyte(')'); if (level == ARGLEVEL) outnl(); } else { #endif /* TESTING_PROTOTYPES */ while (sym == IDENT) { if (gsymptr != NULL && gsymptr->level == level) error("repeated argument"); if (levelnew) addloc(gsname, itype); /* adjust types and offsets later */ nextsym(); if (sym != COMMA) break; nextsym(); } #ifdef TESTING_PROTOTYPES } strcpy(gvarname, ogvarname); gvarsc = ogvarsc; gvarsymptr = ogvarsymptr; gvartype = ogvartype; #endif /* TESTING_PROTOTYPES */ rparen(); declaf(); switch (gvartype->constructor) { case ARRAY: error("function returning array is illegal"); break; case FUNCTION: error("function returning function is illegal"); break; } gvartype = prefix(FUNCTION, ftypesize, gvartype); } else if (sym == LBRACKET) { nextsym(); if (sym == RBRACKET) asize = 0; else asize = constexpression() & intmaskto; /* FIXME: warn overflow */ rbracket(); declaf(); if (gvartype->typesize == 0) switch (gvartype->constructor) { case FUNCTION: error("array of functions is illegal"); break; case STRUCTU: error("undefined structure"); break; default: /* array */ error("null dimension"); gvartype->typesize = 1; } gvartype = prefix(ARRAY, asize * gvartype->typesize, gvartype); } } PRIVATE void declarator() { rdeclarator(); if (gvartype->constructor == STRUCTU && gvartype->typesize == 0 && /* We don't do the anonymous union/structure trickery on low mem machines */ #ifdef VERY_SMALL_MEMORY gvarsc != TYPEDEFDECL && gvarsc != EXTERNDECL) #else gvarsc != TYPEDEFDECL && gvarsc != EXTERNDECL && gvarsc != NULLDECL) #endif error("undefined structure"); } PRIVATE void declarg() { if (gvarsymptr->level != ARGLEVEL) error2error(gvarname, " not in argument list"); else if (gvarsymptr->flags & INITIALIZED && gvarsymptr->type != gvartype) multidecl(gvarname); else { gvarsymptr->flags = INITIALIZED; /* flag otherwise unused for locals */ if (gvartype->constructor & (ARRAY | POINTER)) gvartype = pointype(gvartype->nexttype); gvarsymptr->type = gvartype; if (gvarsc == REGDECL && regdecl()) regarg = TRUE; } } /* enum-specifier = "enum" [identifier] "{" enumerator {, enumerator} "}" | "enum" identifier. enumerator = identifier | identifier = constant-expression. */ PRIVATE struct typestruct *declenum() { register struct symstruct *esymptr; register struct typestruct *enumtype; offset_T ordinal; nextsym(); if (sym != IDENT && sym != TYPEDEFNAME) enumtype = addstruct(""); else if ((esymptr = findstruct(gsname)) == NULL) { enumtype = addstruct(gsname); nextsym(); } else { nextsym(); enumtype = esymptr->type; if (sym != LBRACE) return enumtype; if (esymptr->level != level) enumtype = addstruct(esymptr->name.namea); } lbrace(); if (enumtype->typesize != 0) multidecl(enumtype->tname); else { enumtype->typesize = itypesize; enumtype->alignmask = itype->alignmask; } if (sym != IDENT) error("empty enumerator list"); ordinal = 0; while (sym == IDENT) { if ((esymptr = gsymptr) != NULL && esymptr->level == level) multidecl(gsname); else { (esymptr = addlorg(gsname, itype))->storage = CONSTANT; esymptr->indcount = 0; } nextsym(); if (sym == ASSIGNOP) { nextsym(); ordinal = constexpression() & intmaskto; /* FIXME: warn ovflo */ if (ordinal > maxintto) ordinal -= (maxuintto + 1); } if (esymptr->storage == CONSTANT) esymptr->offset.offv = ordinal++; if (sym != COMMA) break; nextsym(); } rbrace(); return enumtype; } /* declselt - get list of declarations for a structure/union member */ PRIVATE void declselt(structype, psoffset, ptypelist) struct typestruct *structype; offset_T *psoffset; struct typelist **ptypelist; { struct typestruct *basetype; value_t fieldwidth; value_t fwidth; offset_T offset; scalar_t scalar=0; offset = *psoffset; declspec(); if (gvarsc != NULLDECL) error("illegal type name"); basetype = gvartype; #ifndef VERY_SMALL_MEMORY if (sym == SEMICOLON || sym == EOFSYM) { /* Generate a fake structure if none specified... */ anonstruct (); /* ....and pretend it was regularly present in source */ goto anonstr; } #endif while (sym != SEMICOLON && sym != EOFSYM) { gvartype = basetype; declarator(); anonstr: fieldwidth = -1; if (sym == COLON) { scalar = gvartype->scalar; if (!(scalar & ISCALAR)) error("bitfield has non-integral type"); nextsym(); fwidth = constexpression(); if (fwidth < 0) error("bitfield has negative width"); else if (fwidth > INT32BITSTO) /* XXX */ error("bitfield is too wide"); else fieldwidth = fwidth; } if (gvarname[0] == 0) { if (fieldwidth == 0) offset = (offset + ~gvartype->alignmask) & gvartype->alignmask; else /* XXX - should really align to fieldwidth'th bit. */ offset = (offset + ~gvartype->alignmask) & gvartype->alignmask; } else { if (fieldwidth == 0) error("bitfield has zero width"); else if (fieldwidth > 0 && scalar & ISCALAR) { if (fieldwidth <= CHBITSTO) /* XXX! */ gvartype = ctype; else if (fieldwidth <= INT32BITSTO) /* XXX */ gvartype = itype; else gvartype = ltype; if (scalar & UNSIGNED) gvartype = tounsigned(gvartype); } gvar2name[0] = structype->structkey[0]; gvar2name[1] = structype->structkey[1]; /* key provides unique name space */ if (findlorg(gvar2name) != NULL) multidecl(gvarname); else { (gvarsymptr = addlorg(gvar2name, gvartype))->storage = NOSTORAGE; structype->alignmask &= gvartype->alignmask; offset = (gvarsymptr->offset.offi = (offset+ ~gvartype->alignmask) & gvartype->alignmask) + gvartype->typesize; { register struct typelist *newtypelist; newtypelist = qmalloc(sizeof *newtypelist); #ifdef TS ++ts_n_newtypelist; ts_s_newtypelist += sizeof *newtypelist; #endif newtypelist->tlnext = NULL; newtypelist->tltype = gvartype; if (*ptypelist == NULL) structype->listtype = newtypelist; else (*ptypelist)->tlnext = newtypelist; *ptypelist = newtypelist; } } } if (sym != COMMA) break; nextsym(); } semicolon(); *psoffset = offset; } PRIVATE bool_pt declspec() { unsigned nsc; unsigned nsigned; unsigned ntype; unsigned nunsigned; gvarsc = NULLDECL; gvartype = itype; nsigned = nunsigned = ntype = nsc = 0; while (TRUE) { switch (sym) { case AUTODECL: ++nsc; gvarsc = sym; nextsym(); break; case ENUMDECL: ++ntype; declenum(); gvartype = itype; /* kludge - ignore type of enum */ break; case EXTERNDECL: ++nsc; gvarsc = sym; nextsym(); break; case REGDECL: ++nsc; gvarsc = sym; nextsym(); break; case STATICDECL: ++nsc; gvarsc = sym; nextsym(); break; case STRUCTDECL: case UNIONDECL: ++ntype; gvartype = declsu(); break; case TYPEDECL: if (ntype == 1) { /* allow short int and long int */ if (gvartype == itype && (gsymptr->type == stype || gsymptr->type == ltype)) ntype = 0; /* Allow long double and long float */ if (gvartype == ltype && (gsymptr->type == fltype || gsymptr->type == dtype)) { gvartype = dtype; nextsym(); break; } /* allow int short and int long, blech */ if (gsymptr->type == itype && (gvartype == stype || gvartype == ltype)) { nextsym(); break; } } ++ntype; gvartype = gsymptr->type; nextsym(); break; case TYPEDEFDECL: ++nsc; gvarsc = sym; nextsym(); break; case TYPEDEFNAME: if (ntype != 0) goto break2; ++ntype; gvartype = gsymptr->type; nextsym(); break; case SIGNDECL: ++nsigned; nextsym(); break; case UNSIGNDECL: ++nunsigned; nextsym(); break; case ASMSYM: nextsym(); doasm(); break; default: goto break2; } } break2: if (nsigned > 0) { if (ntype == 0) { gvartype = itype; ntype = 1; } gvartype = tosigned(gvartype); if (nsigned > 1 || nunsigned > 0) ntype = 2; } if (nunsigned > 0) { if (ntype == 0) { gvartype = uitype; ntype = 1; } gvartype = tounsigned(gvartype); if (nunsigned > 1 || nsigned > 0) ntype = 2; } if (nsc > 0) { if (ntype == 0) ntype = 1; if (nsc > 1) error("multiple storage classes in declaration"); } if (ntype > 1) error("multiple types in declaration"); return nsc > 0 || ntype > 0; } /* declsu - get structure or union name and/or declaration, return type */ PRIVATE struct typestruct *declsu() { sym_t ogvarsc; offset_T soffset; offset_T struclength; sym_t susym; struct typelist *typelist; struct typestruct *structype; susym = sym; nextsym(); if (sym != IDENT && sym != TYPEDEFNAME) structype = addstruct(""); else if ((gvarsymptr = findstruct(gsname)) == NULL) { structype = addstruct(gsname); nextsym(); } else { nextsym(); if (sym == LBRACE && gvarsymptr->level != level) structype = addstruct(gvarsymptr->name.namea); else structype = gvarsymptr->type; } if (sym != LBRACE) return structype; if (structype->typesize != 0) multidecl(structype->tname); nextsym(); ogvarsc = gvarsc; struclength = soffset = 0; typelist = NULL; while (sym != RBRACE && sym != EOFSYM) { declselt(structype, &soffset, &typelist); if (susym == STRUCTDECL) struclength = soffset; else { if (struclength < soffset) struclength = soffset; soffset = 0; } } structype->typesize = (struclength + ~structype->alignmask) & structype->alignmask; rbrace(); gvarsc = ogvarsc; return structype; } /* declfunc() - function name and parameter list */ PRIVATE void declfunc() { offset_T argsp; uoffset_T argsize; struct symstruct *symptr; int main_flag = 0; strcpy(funcname, gvarname); if( strcmp(funcname, "main") != 0 ) main_flag = -1; if (gvarsymptr == NULL) gvarsymptr = addglb(gvarname, gvartype); /* No ancient switch on small memory systems */ #ifndef VERY_SMALL_MEMORY else if (ancient) {} /* Full declaration type different from the prior implicit * one. Even gcc allows this, just comes up with a warning */ #endif else if (gvarsymptr->type != gvartype || (gvarsymptr->flags & INITIALIZED)) multidecl(gvarname); /* different type or full declare */ gvarsymptr->flags = INITIALIZED; /* show full declare */ cseg(); if (gvarsc == STATICDECL) private(gvarname); /* don't need to put STATIC in flags */ else public(gvarname); callee1mask = calleemask; #ifdef FRAMEPOINTER frame1list = framelist; #endif func1saveregsize = funcsaveregsize; #if 0 if ((returntype = gvartype->nexttype)->scalar & RSCALAR) #else if ((returntype = gvartype->nexttype)->scalar & DOUBLE) #endif { callee1mask &= ~doublreturnregs; #ifdef FRAMEPOINTER frame1list &= ~doublreturnregs; #endif func1saveregsize = funcdsaveregsize; } arg1size = /* would already be 0 unless last function empty */ #ifdef FRAMEPOINTER framep = stackarg = #endif reguse = 0; /* would already be 0 unless last f had reg vars */ decllist(); argsp = returnadrsize; if (returntype->constructor & STRUCTU) argsp += ptypesize; softsp = -func1saveregsize; for (symptr = &locsyms[0]; symptr < locptr && symptr->flags != STRUCTNAME && *symptr->name.namea >= 'A'; symptr = (struct symstruct *) align(&symptr->name.namea[strlen(symptr->name.namea) + 1])) { if( main_flag >= 0 ) main_flag++; /* convert arg sizes to offsets */ if (symptr->type == fltype) symptr->type = dtype; argsize = symptr->type->typesize; #ifdef FRAMEPOINTER if (!arg1inreg || symptr != &locsyms[0] || symptr->flags != REGVAR) stackarg = TRUE; #endif if (arg1inreg && symptr == &locsyms[0] && symptr->flags != REGVAR) { if ((arg1size = argsize) < itypesize) arg1size = itypesize; argsp = softsp -= arg1size; } #if INT_BIG_ENDIAN if (argsize < itypesize) argsp += itypesize - argsize; symptr->offset.offi = argsp; argsp += argsize; #else symptr->offset.offi = argsp; if (argsize > itypesize) argsp += argsize; else argsp += itypesize; #endif if (arg1inreg && symptr == &locsyms[0]) argsp = returnadrsize; /* skip return adr after 1st arg */ } if( main_flag > 0 ) { globl("__mkargv"); if( main_flag > 2 ) globl("environ"); } #ifdef I8088 regfuse = 0; #endif lbrace(); compound(); #ifdef I8088 if (regfuse & (callee1mask | INDREG0)) { outstr("! Register"); if (regfuse & INDREG0 ) outstr(" BX"); if (regfuse & INDREG1 & callee1mask) outstr(" SI"); if (regfuse & INDREG2 & callee1mask) outstr(" DI"); if (regfuse & LOCAL & callee1mask) outstr(" BP"); outstr(" used in function "); outnstr(funcname); if (optimise && !callersaves) { outstr(funcname); outnstr(".off = 0"); } } else if (optimise && !callersaves) { outstr(funcname); outstr(".off = "); #ifndef I80386 outnhex(4); #else outnhex(i386_32?12:4); #endif } #endif clearfunclabels(); } /* idecllist() - list of init-declarations with a given base type */ /* this does the non-terminal symbols list( init-declarator ) ";" */ /* and list( type-declaration ) ";" */ /* and complete declarations of functions */ PRIVATE void idecllist() { struct typestruct *basetype; struct typestruct *inittype; scopelev_t levelmark; uoffset_T newoffset; argsallowed = level == GLBLEVEL; levelmark = level; basetype = gvartype; while (sym != SEMICOLON) { gvartype = basetype; declarator(); if (gvarname[0] == 0) needvarname(); if (gvartype->constructor == FUNCTION) { if (sym != COMMA && sym != SEMICOLON) { if (level == ARGLEVEL && gvarsc != TYPEDEFDECL) declfunc(); else error("illegal non-external function"); if (level != levelmark) { oldlevel(); locptr = &locsyms[0]; } argsallowed = FALSE; return; } } if (level != levelmark) { oldlevel(); locptr = &locsyms[0]; } argsallowed = FALSE; if (level == ARGLEVEL) { if (gvarsymptr == NULL) gvarsymptr = addglb(gvarname, gvartype); /* error soon */ declarg(); } else if (gvarsymptr != NULL && (gvarsymptr->level == level || gvartype->constructor == FUNCTION || (gvarsc == EXTERNDECL && gvarsymptr->level == GLBLEVEL))) { if (gvarsymptr->level != GLBLEVEL || gvarsymptr->flags == KEYWORD) multidecl(gvarname); else if (gvarsymptr->type != gvartype) { if (gvartype->constructor != ARRAY || gvarsymptr->type->constructor != ARRAY || gvartype->nexttype != gvarsymptr->type->nexttype || (gvartype->typesize != 0 && gvarsymptr->type->typesize != 0)) multidecl(gvarname); else if (gvartype->typesize != 0) gvarsymptr->type = gvartype; } if (gvarsc == NULLDECL) gvarsymptr->flags &= ~EXTERNAL; } else if (level == GLBLEVEL || gvartype->constructor == FUNCTION || gvarsc == EXTERNDECL) { gvarsymptr = addglb(gvarname, gvartype); #ifdef DIRECTPAGE /* make all global scalar and pointer variables DIRECTPAGE */ if (!(gvartype->constructor & ~POINTER)) gvarsymptr->flags = DIRECTPAGE; #endif if (gvarsc == EXTERNDECL) gvarsymptr->flags |= EXTERNAL; } else { gvarsymptr = addloc(gvarname, gvartype); if ((gvarsc != REGDECL || !regdecl()) && gvartype->constructor != FUNCTION && gvarsc != STATICDECL && gvarsc != TYPEDEFDECL) gvarsymptr->offset.offi = softsp = (softsp & gvartype->alignmask) - gvartype->typesize; } if (gvarsc == STATICDECL) { gvarsymptr->flags &= ~EXTERNAL; gvarsymptr->flags |= STATIC; if (gvarsymptr->level != GLBLEVEL) { gvarsymptr->storage = GLOBAL; gvarsymptr->offset.offlabel = getlabel(); /* must leave gvarsymptr->name.label alone */ /* since name is required for findlorg() */ /* label is activated by expression() */ } } if (gvarsc == TYPEDEFDECL) { gvarsymptr->flags = KEYWORD; gvarsymptr->offset.offsym = TYPEDEFNAME; } #ifndef VERY_SMALL_MEMORY if (sym == ASSIGNOP || (ancient && sym == LBRACE)) #else if (sym == ASSIGNOP) #endif { /* This is always false for low-memory environments given */ /* there's no ancient switch there. */ int oldstyle = (sym == LBRACE); if (gvarsymptr->flags & INITIALIZED) multidecl(gvarname); /* If we're initializing an array, let's pretend there */ /* was a new-fashioned initializer with an equal sign */ if (oldstyle && gvartype->constructor == ARRAY) oldstyle = 0; else nextsym(); if (level == GLBLEVEL || gvarsc == STATICDECL) { #ifndef DIRECTPAGE dseg(); #else if (gvarsymptr->flags & DIRECTPAGE) dpseg(); else dseg(); #endif if ((inittype = gvartype)->constructor == ARRAY) inittype = inittype->nexttype; newoffset = (dataoffset + ~inittype->alignmask) & inittype->alignmask; defnulls(newoffset - dataoffset); dataoffset = newoffset; if (gvarsc == STATICDECL) { if (level == GLBLEVEL) private(gvarname); else outnlabel(gvarsymptr->offset.offlabel); } else public(gvarname); initlistflag = TRUE; if (sym != LBRACE) initlistflag = FALSE; inititem(gvartype); dataoffset += (gvarsymptr->type = gvartype)->typesize; if (gvarsymptr->level == GLBLEVEL) gvarsymptr->flags |= INITIALIZED; if (level != GLBLEVEL) cseg(); } else { if (gvarsc == EXTERNDECL) error("initialization of externs is illegal"); switch (gvartype->constructor) { case ARRAY: error("initialization of auto arrays is illegal"); break; case FUNCTION: error("initialization of functions is illegal"); break; default: initexpression(gvartype); break; } } if (oldstyle) rbrace(); } else if (level != GLBLEVEL && gvarsc == STATICDECL && gvartype->constructor != FUNCTION) { #ifndef DIRECTPAGE bssseg(); #else if (gvarsymptr->flags & DIRECTPAGE) dpseg(); else dseg(); #endif lcommlab(gvarsymptr->offset.offlabel); outnhex(gvartype->typesize); cseg(); } if (sym != COMMA) break; nextsym(); } semicolon(); argsallowed = FALSE; } PRIVATE void initarray(type) struct typestruct *type; { uoffset_T basesize; struct typestruct *basetype; uoffset_T dimension; char *stringend; uoffset_T stringlength; uoffset_T remaining; if ((basesize = (basetype = type->nexttype)->typesize) == 0) dimension = remaining = 0; else dimension = remaining = type->typesize / basesize; if (sym == STRINGCONST && (basetype->scalar & CHAR)) { stringlength = (stringend = charptr) - constant.value.s; if (remaining != 0 && stringlength >= remaining) /* same dim should be allowed but defstr always nullterms */ { error("string longer than dimension"); stringend = constant.value.s + (/* size_t */ unsigned) (stringlength = remaining - 1); } defstr(constant.value.s, stringend, TRUE); remaining -= (stringlength + 1); nextsym(); } else do inititem(basetype); while (--remaining != 0 && sym == COMMA && initlistflag && (nextsym(), sym != RBRACE)); if (dimension == 0) { if (type == gvartype) gvartype = prefix(ARRAY, -remaining * basesize, basetype); } else defnulls(remaining * basesize); } PRIVATE void inititem(type) struct typestruct *type; { sym_t startsym; if ((startsym = sym) == LBRACE) nextsym(); switch (type->constructor) { case ARRAY: initarray(type); break; case STRUCTU: initstruct(type); break; case FUNCTION: error("initialization of functions is illegal"); break; default: initexpression(type); } if (startsym == LBRACE) { if (sym == COMMA) { nextsym(); if (sym != RBRACE) error("too many initializers"); } rbrace(); } } PRIVATE void initstruct(type) struct typestruct *type; { struct typestruct *memtype; uoffset_T newoffset; uoffset_T offset; struct typelist *typelist; offset = 0; if ((typelist = type->listtype) != NULL) do { memtype = typelist->tltype; newoffset = (offset + ~memtype->alignmask) & memtype->alignmask; defnulls(newoffset - offset); offset = newoffset + memtype->typesize; inititem(memtype); } while ((typelist = typelist->tlnext) != NULL && sym == COMMA && initlistflag && (nextsym(), sym != RBRACE)); /* eof here will break next time */ defnulls(type->typesize - offset); } PRIVATE void lbrace() { if (sym != LBRACE) need('{'); else nextsym(); } PUBLIC void lparen() { if (sym != LPAREN) need('('); else nextsym(); } PRIVATE void multidecl(sname) char *sname; { error2error(sname, " already declared"); } PRIVATE void need(charneeded) int charneeded; { static char message[] = "need 'x'"; message[6] = charneeded; error(message); } PUBLIC void needvarname() { error("need variable name"); nextsym(); } PUBLIC void program() { #ifdef BUILTIN_CPP if (orig_cppmode) cppscan(0); else #endif { nextsym(); while (sym != EOFSYM) { declspec(); idecllist(); } } } PUBLIC void rbrace() { if (sym != RBRACE) need('}'); else nextsym(); } PUBLIC void rbracket() { if (sym != RBRACKET) need(']'); else nextsym(); } PRIVATE void rdeclarator() { while (sym == STAR) { nextsym(); gvartype = pointype(gvartype); } if (sym == LPAREN) { struct typestruct *pretype; struct typestruct *sufftype; nextsym(); sufftype = gvartype; gvartype = ctype; rdeclarator(); rparen(); pretype = gvartype; gvartype = sufftype; declaf(); gvartype = chainprefix(pretype, gvartype); } else if (sym == IDENT || sym == TYPEDEFNAME) { strcpy(gvarname, gsname); gvarsymptr = gsymptr; nextsym(); } else { gvarname[0] = 0; gvarsymptr = NULL; } declaf(); } PRIVATE bool_pt regdecl() { store_t regavail; #if !NOTFINISHED if (gvarsymptr->type->constructor != POINTER) return FALSE; #endif #ifdef MC6809 if (gvarsymptr->type->constructor != POINTER) return FALSE; #endif if (!(regavail = regregs & ~reguse)) return FALSE; gvarsymptr->flags = REGVAR; gvarsymptr->indcount = 0; #define LOWBITMASK(bits) (bits - (bits & (bits - 1))) /* & chops low bit */ reguse |= gvarsymptr->storage = LOWBITMASK(regavail); return TRUE; } PUBLIC void rparen() { if (sym != RPAREN) need(')'); else nextsym(); } PUBLIC void semicolon() { outnstr("!BCC_EOS"); if (sym != SEMICOLON) need(';'); else nextsym(); } PUBLIC struct typestruct *typename() { char ogvarname[NAMESIZE]; sym_t ogvarsc; struct symstruct *ogvarsymptr; struct typestruct *ogvartype; struct typestruct *type; /* the global variable data must be preserved */ /* although this is only called for casts and sizeof, */ /* the casts can be in initialisers */ /* and the sizeof in an array size expression */ strcpy(ogvarname, gvarname); ogvarsc = gvarsc; ogvarsymptr = gvarsymptr; ogvartype = gvartype; if (declspec()) { declarator(); if (gvarsc != NULLDECL || gvarname[0] != 0) error("illegal type name"); type = gvartype; } else type = NULL; strcpy(gvarname, ogvarname); gvarsc = ogvarsc; gvarsymptr = ogvarsymptr; gvartype = ogvartype; return type; } #ifndef VERY_SMALL_MEMORY PUBLIC int lastanon() { return anons; } PUBLIC void anonname(name, i) char *name; int i; { if (i == 0xfff) fatalerror("Too many anonymous structs/unions"); sprintf (name, "__an%03x", i); } PUBLIC void anonstruct() { anonname (gvarname, anons++); } #endif dev86-0.16.21/bcc/express.c000066400000000000000000000244121231050321700151760ustar00rootroot00000000000000/* express.c - expression parsing routines for bcc */ /* Copyright (C) 1992 Bruce Evans */ #include "bcc.h" #include "gencode.h" #include "parse.h" #include "reg.h" #include "sc.h" #include "scan.h" #include "table.h" /* just for charptr for string constant */ #include "type.h" PRIVATE unsigned insizeof; /* nest level for getsizeof */ /* used to avoid aborting undefined idents */ /* to 0 when they appear in a cpp expression */ /* under sizeof */ /* names of expression functions are related to the 15 precedence levels */ /* on p49 of K & R */ FORWARD struct nodestruct *cast_exp P((void)); FORWARD struct nodestruct *expr2 P((void)); FORWARD struct nodestruct *exp3to12 P((fastin_pt lprecedence)); FORWARD struct nodestruct *listargs P((void)); FORWARD struct nodestruct *postfix_exp P((bool_pt seenlp)); FORWARD struct nodestruct *primary_exp P((void)); FORWARD struct nodestruct *unary_exp P((void)); PRIVATE struct nodestruct *cast_exp() { struct nodestruct *nodeptr; scalar_t scalar; struct typestruct *vartype; if (sym != LPAREN) return unary_exp(); nextsym(); if ((vartype = typename()) == NULL) return postfix_exp(TRUE); rparen(); scalar = (nodeptr = cast_exp())->nodetype->scalar; if (vartype->scalar & INT && scalar & (CHAR | SHORT | INT) && !((vartype->scalar ^ scalar) & UNSIGNED)) { /* No ancient switch on low mem systems */ #ifndef VERY_SMALL_MEMORY /* In ancient UNIX C, casts remain lvalues */ if (!ancient) #endif nodeptr->flags &= ~LVALUE; return nodeptr; /* skip casts that are default promotions */ } return castnode(vartype, nodeptr); } PUBLIC struct nodestruct *assignment_exp() { struct nodestruct *lhs; op_pt op; lhs = expr2(); if (sym >= ASSIGNOP && sym <= SUBABOP) /* assign-op syms in order! */ { op = sym; nextsym(); lhs = node(op, lhs, assignment_exp()); } return lhs; } PUBLIC struct nodestruct *expression() { struct nodestruct *lhs; lhs = assignment_exp(); while (sym == COMMA) { nextsym(); lhs = node(COMMAOP, lhs, assignment_exp()); } return lhs; } PRIVATE struct nodestruct *expr2() { struct nodestruct *lhs; struct nodestruct *rhs; lhs = exp3to12(0); if (sym == CONDOP) { nextsym(); rhs = expression(); colon(); lhs = node(CONDOP, lhs, node(COLONOP, rhs, expr2())); } return lhs; } PRIVATE struct nodestruct *exp3to12(lprecedence) fastin_pt lprecedence; { struct nodestruct *lhs; op_pt op; fastin_t rprecedence; lhs = cast_exp(); while (TRUE) { rprecedence = 0; switch (sym) { case LOGOROP: if ((fastin_t) lprecedence <= 1) rprecedence = 2; break; case LOGANDOP: if ((fastin_t) lprecedence <= 3) rprecedence = 4; break; case OROP: if ((fastin_t) lprecedence <= 5) rprecedence = 6; break; case EOROP: if ((fastin_t) lprecedence <= 7) rprecedence = 8; break; case AMPERSAND: if ((fastin_t) lprecedence <= 9) { sym = ANDOP; rprecedence = 10; } break; case EQOP: case NEOP: if ((fastin_t) lprecedence <= 11) rprecedence = 12; break; case GEOP: case GTOP: case LEOP: case LTOP: if ((fastin_t) lprecedence <= 13) rprecedence = 14; break; case SLOP: case SROP: if ((fastin_t) lprecedence <= 15) rprecedence = 16; break; case HYPHEN: if ((fastin_t) lprecedence <= 17) { sym = SUBOP; rprecedence = 18; } break; case ADDOP: if ((fastin_t) lprecedence <= 17) rprecedence = 18; break; case STAR: if ((fastin_t) lprecedence <= 19) { sym = MULOP; rprecedence = 20; } break; case DIVOP: case MODOP: if ((fastin_t) lprecedence <= 19) rprecedence = 20; break; } if (rprecedence == 0) break; op = sym; nextsym(); lhs = node(op, lhs, exp3to12(rprecedence)); } return lhs; } PRIVATE struct nodestruct *listargs() { struct nodestruct *parent; struct nodestruct *nextright; if (sym == RPAREN) { nextsym(); return NULLNODE; } parent = node(arg1op, assignment_exp(), NULLNODE); nextright = parent; while (sym == COMMA) { nextsym(); nextright = nextright->right = node(LISTOP, assignment_exp(), NULLNODE); } rparen(); return parent; } PRIVATE struct nodestruct *postfix_exp(seenlp) bool_pt seenlp; { struct nodestruct *nodeptr; struct symstruct *symptr; if (seenlp) { nodeptr = expression(); rparen(); } else nodeptr = primary_exp(); while (TRUE) { switch (sym) { case DECSYM: nextsym(); nodeptr = node(POSTDECOP, nodeptr, NULLNODE); continue; case INCSYM: nextsym(); nodeptr = node(POSTINCOP, nodeptr, NULLNODE); continue; case LBRACKET: nextsym(); nodeptr = node(INDIRECTOP, node(ADDOP, nodeptr, expression()), NULLNODE); rbracket(); continue; case LPAREN: nextsym(); nodeptr = node(FUNCOP, nodeptr, listargs()); { register struct nodestruct *np; for (np = nodeptr->right; np != NULL; np = np->right) { if (np->nodetype->scalar & RSCALAR) { np = nodeptr->left.nodeptr; if (np->tag != LEAF) printf_fp = TRUE; else { unsigned len; register char *name; name = np->left.symptr->name.namep; if ((len = strlen(name)) >= 6 && strcmp(name + len - 6, "printf") == 0) printf_fp = TRUE; } break; } } for (np = nodeptr->right; np != NULL; np = np->right) { if (np->nodetype->constructor & POINTER && np->nodetype->nexttype->scalar & RSCALAR) { np = nodeptr->left.nodeptr; if (np->tag != LEAF) scanf_fp = TRUE; else { unsigned len; register char *name; name = np->left.symptr->name.namep; if ((len = strlen(name)) >= 5 && strcmp(name + len - 5, "scanf") == 0) scanf_fp = TRUE; } break; } } } continue; case STRUCPTROP: nodeptr = node(INDIRECTOP, nodeptr, NULLNODE); case STRUCELTOP: nextsym(); /* On memory constrained systems we save space that would be needed to keep */ /* track of anonymous structure members by not implementing lookup in them */ /* at all. */ #ifdef VERY_SMALL_MEMORY gs2name[0] = nodeptr->nodetype->structkey[0]; gs2name[1] = nodeptr->nodetype->structkey[1]; if ((gsymptr = findlorg(gs2name)) == NULL) #else if ((gsymptr = findstrm(nodeptr->nodetype, gs2name)) == NULL) #endif { error("undefined structure element"); gsymptr = addglb(gs2name, itype); } symptr = exprsym(gsymptr); nextsym(); nodeptr = node(STRUCELTOP, nodeptr, leafnode(symptr)); continue; default: return nodeptr; } } } PRIVATE struct nodestruct *primary_exp() { bool_t isdefined; struct nodestruct *nodeptr; uoffset_T stringlen; struct symstruct *symptr; struct symstruct *symptr1; bool_t waslparen; switch (sym) { case IDENT: if (incppexpr && !insizeof) { cpp_ident: nextsym(); return leafnode(constsym((value_t) 0)); } if ((symptr = gsymptr) != NULL) nextsym(); else { symptr = addglb(gsname, fitype); nextsym(); if (sym != LPAREN) { error2error(symptr->name.namea, " undeclared"); symptr->indcount = 1; symptr->type = itype; } } symptr1 = exprsym(symptr); if (symptr->flags & STATIC && symptr->level != GLBLEVEL) { symptr1->flags |= LABELLED; symptr1->offset.offi = 0; symptr1->name.label = symptr->offset.offlabel; } nodeptr = leafnode(symptr1); if (!(nodeptr->nodetype->constructor & (ARRAY | FUNCTION | VOID))) nodeptr->flags = LVALUE; return nodeptr; case TYPEDEFNAME: if (incppexpr && !insizeof) goto cpp_ident; /* else fall through */ default: error("bad expression"); constant.value.v = 0; constant.type = itype; case CHARCONST: case INTCONST: /* this includes enumeration-constants */ symptr = constsym(constant.value.v); symptr->type = constant.type; if (!(ltype->scalar & LONG)) { if (symptr->type == ltype) symptr->type = itype; else if (symptr->type == ultype) symptr->type = uitype; } nextsym(); return leafnode(symptr); case DEFINEDSYM: waslparen = isdefined = FALSE; if (!blanksident()) { nextsym(); if (sym != LPAREN) lparen(); else waslparen = TRUE; } if (waslparen && !blanksident()) needvarname(); else { if ((symptr = findlorg(gsname)) != NULL && symptr->flags == DEFINITION) isdefined = TRUE; nextsym(); } if (waslparen) rparen(); return leafnode(constsym((value_t) isdefined)); case FLOATCONST: symptr = constsym((value_t) 0); symptr->type = constant.type; symptr->offset.offd = qmalloc(sizeof *symptr->offset.offd); *symptr->offset.offd = constant.value.d; nextsym(); return leafnode(symptr); case LPAREN: nextsym(); nodeptr = expression(); rparen(); return nodeptr; case STRINGCONST: symptr = constsym((value_t) 0); symptr->storage = GLOBAL; symptr->flags = LABELLED | STRING; /* string length before defstr() or prefix() updates charptr */ stringlen = charptr - constant.value.s + 1; symptr->name.label = defstr(constant.value.s, charptr, FALSE); symptr->type = prefix(ARRAY, stringlen, ctype); nextsym(); return leafnode(symptr); } } PRIVATE struct nodestruct *unary_exp() { value_t size; struct typestruct *vartype; switch (sym) { case ADDOP: nextsym(); return cast_exp(); case AMPERSAND: nextsym(); return node(ADDRESSOP, cast_exp(), NULLNODE); /* maybe unary_exp */ case DECSYM: nextsym(); return node(PREDECOP, unary_exp(), NULLNODE); case HYPHEN: nextsym(); return node(NEGOP, cast_exp(), NULLNODE); case INCSYM: nextsym(); return node(PREINCOP, unary_exp(), NULLNODE); case LOGNOTOP: nextsym(); return node(LOGNOTOP, cast_exp(), NULLNODE); case NOTOP: nextsym(); return node(NOTOP, cast_exp(), NULLNODE); case SIZEOFSYM: nextsym(); ++insizeof; if (sym != LPAREN) size = unary_exp()->nodetype->typesize; else { nextsym(); if ((vartype = typename()) != NULL) { rparen(); size = vartype->typesize; } else size = postfix_exp(TRUE)->nodetype->typesize; } --insizeof; return leafnode(constsym(size)); case STAR: nextsym(); return node(INDIRECTOP, cast_exp(), NULLNODE); /* maybe unary_exp */ } return postfix_exp(FALSE); } dev86-0.16.21/bcc/exptree.c000066400000000000000000000653431231050321700151710ustar00rootroot00000000000000/* exptree.c - expression tree routines for bcc */ /* Copyright (C) 1992 Bruce Evans */ #include "bcc.h" #include "byteord.h" #include "gencode.h" #include "parse.h" #include "reg.h" #include "sc.h" #include "scan.h" #include "sizes.h" #include "type.h" #ifdef VERY_SMALL_MEMORY #define ETREESIZE 300 #else #define ETREESIZE 1200 #endif #define errtype itype #define redtype ctype #define uredtype uctype PRIVATE struct nodestruct etree[ETREESIZE]; /* expression tree */ PRIVATE struct nodestruct *ettop; FORWARD void badlvalue P((struct nodestruct *nodeptr)); FORWARD void binconvert P((struct nodestruct *nodeptr)); FORWARD void castiright P((struct nodestruct *nodeptr)); FORWARD void etreefull P((void)); FORWARD void fixnode P((struct nodestruct *nodeptr)); FORWARD bool_pt isconst0 P((struct nodestruct *nodeptr)); FORWARD bool_pt isnodecharconst P((struct nodestruct *nodeptr)); FORWARD void needint P((struct nodestruct *nodeptr)); FORWARD void neednonstruct P((struct nodestruct *nodeptr)); FORWARD void needscalar P((struct nodestruct *nodeptr)); FORWARD void needspv P((struct nodestruct *nodeptr)); FORWARD struct typestruct *nodetype P((struct nodestruct *nodeptr)); FORWARD int redscalar P((struct nodestruct *nodeptr)); FORWARD struct nodestruct *unconvert P((struct nodestruct *nodeptr)); PRIVATE void badlvalue(nodeptr) struct nodestruct *nodeptr; { error("invalid lvalue"); fixnode(nodeptr); } PRIVATE void binconvert(nodeptr) register struct nodestruct *nodeptr; { bool_t bothscalar; value_t divisor; scalar_t lscalar; register struct nodestruct *right; scalar_t rscalar; rscalar = (right = nodeptr->right)->nodetype->scalar; lscalar = nodeptr->left.nodeptr->nodetype->scalar; if ((bothscalar = lscalar | rscalar) & RSCALAR) { nodeptr->nodetype = dtype; if (!(lscalar & DOUBLE)) nodeptr->left.nodeptr = castnode(dtype, nodeptr->left.nodeptr); if (!(rscalar & DOUBLE)) nodeptr->right = castnode(dtype, right); } else if (!(bothscalar & DLONG) && ((nodeptr->tag == ANDOP && (redscalar(nodeptr->left.nodeptr) | redscalar(right)) & CHAR) || ((nodeptr->tag == EOROP || nodeptr->tag == OROP) && redscalar(nodeptr->left.nodeptr) & redscalar(right) & CHAR) || (nodeptr->tag == MODOP && right->tag == LEAF && right->left.symptr->storage == CONSTANT && (divisor = right->left.symptr->offset.offv, (uvalue_t) divisor <= MAXUCHTO + 1) && bitcount((uvalue_t) divisor) <= 1))) { /* result fits in char and extends correctly */ if (bothscalar & UNSIGNED) nodeptr->nodetype = uredtype; else nodeptr->nodetype = redtype; } else if (bothscalar & LONG) { nodeptr->nodetype = ltype; if (bothscalar & UNSIGNED) nodeptr->nodetype = ultype; if (bothscalar & (DLONG | SHORT | INT)) { /* XXX - otherwise both are long, or one is long with the same * size as int and the other is char, and we want the lower level * routines to handle the char. */ if (!(lscalar & LONG)) nodeptr->left.nodeptr = castnode(nodeptr->nodetype, nodeptr->left.nodeptr); if (!(rscalar & LONG)) nodeptr->right = castnode(nodeptr->nodetype, right); } } #ifdef I80386 else if (i386_32 && bothscalar & SHORT) { nodeptr->nodetype = itype; if (bothscalar & UNSIGNED) nodeptr->nodetype = uitype; if (lscalar & SHORT) nodeptr->left.nodeptr = castnode(nodeptr->nodetype, nodeptr->left.nodeptr); if (rscalar & SHORT) nodeptr->right = castnode(nodeptr->nodetype, right); } #endif else if (bothscalar & UNSIGNED) nodeptr->nodetype = uitype; else nodeptr->nodetype = itype; } PRIVATE void castiright(nodeptr) struct nodestruct *nodeptr; { nodeptr->right = castnode(itype, nodeptr->right); } PUBLIC struct nodestruct *castnode(type, nodeptr) struct typestruct *type; struct nodestruct *nodeptr; { struct symstruct *symptr; (symptr = constsym((value_t) 0))->type = type; return node(CASTOP, nodeptr, leafnode(symptr)); } PRIVATE void etreefull() { #if ETREESIZE == 1200 limiterror("expression too complex (1201 nodes)"); #else limiterror("expression too complex (ETREESIZE)"); #endif } PUBLIC void etreeinit() { ettop = (etptr = etree) + ETREESIZE; } PRIVATE void fixnode(nodeptr) register struct nodestruct *nodeptr; { nodeptr->tag = LEAF; nodeptr->flags = nodeptr->weight = 0; nodeptr->left.symptr = constsym((value_t) 0); /* this has type errtype */ nodeptr->nodetype = errtype; } PRIVATE bool_pt isconst0(nodeptr) register struct nodestruct *nodeptr; { register struct symstruct *symptr; return nodeptr->tag == LEAF && (symptr = nodeptr->left.symptr)->storage == CONSTANT && symptr->offset.offv == 0 && symptr->type->scalar & ISCALAR; } PRIVATE bool_pt isnodecharconst(nodeptr) register struct nodestruct *nodeptr; { register struct symstruct *symptr; if (nodeptr->tag == LEAF && (symptr = nodeptr->left.symptr)->storage == CONSTANT && ischarconst(symptr->offset.offv) && symptr->type->scalar & ISCALAR) return TRUE; return FALSE; } PUBLIC struct nodestruct *leafnode(source) struct symstruct *source; { register struct nodestruct *leafptr; if ((leafptr = etptr++) >= ettop) etreefull(); leafptr->tag = LEAF; leafptr->flags = leafptr->weight = 0; leafptr->nodetype = source->type; leafptr->left.symptr = source; leafptr->right = NULL; return leafptr; } PRIVATE void needint(nodeptr) struct nodestruct *nodeptr; { if (!(nodeptr->nodetype->scalar & ISCALAR)) { error("need integral type"); fixnode(nodeptr); } } PRIVATE void neednonstruct(nodeptr) struct nodestruct *nodeptr; { if (nodeptr->nodetype->constructor & STRUCTU) { error("need non-structure type"); fixnode(nodeptr); } } PRIVATE void needscalar(nodeptr) struct nodestruct *nodeptr; { if (!nodeptr->nodetype->scalar) { error("need scalar"); fixnode(nodeptr); } } PRIVATE void needspv(nodeptr) struct nodestruct *nodeptr; { if (nodeptr->nodetype->constructor & (ARRAY | FUNCTION | STRUCTU)) { error("need scalar or pointer or void"); fixnode(nodeptr); } } PUBLIC struct nodestruct *node(t, p1, p2) op_pt t; struct nodestruct *p1; struct nodestruct *p2; { #if MAXREGS != 1 weight_t rightweight; #endif double dsourceval = 0; /* for -Wall */ double dtargval = 0 ; /* for -Wall */ bool_t lflag; scalar_t lscalar; struct nodestruct *pswap; struct symstruct *source = NULL; /* for -Wall */ value_t sourceval = 0 ; /* for -Wall */ struct symstruct *target; offset_T targszdelta; value_t targval = 0; /* for -Wall */ scalar_t rscalar = 0; /* for -Wall */ bool_t uflag; switch ((op_t) t) { case ADDABOP: if (p1->nodetype->constructor & (ARRAY | POINTER)) t = PTRADDABOP; break; case ADDOP: if (p2->nodetype->constructor & (ARRAY | POINTER)) { pswap = p1; p1 = p2; p2 = pswap; } if (p1->nodetype->constructor & (ARRAY | POINTER)) t = PTRADDOP; break; case CONDOP: /* Change structs to struct pointers so condop() doesn't have to know * about structs. */ if (p2->nodetype->constructor & STRUCTU) { p2 = node(COLONOP, node(ADDRESSOP, p2->left.nodeptr, NULLNODE), node(ADDRESSOP, p2->right, NULLNODE)); return node(INDIRECTOP, node(CONDOP, p1, p2), NULLNODE); } break; case FUNCOP: if (p1->nodetype->constructor & (ARRAY | POINTER)) p1 = node(INDIRECTOP, p1, NULLNODE); break; case SUBABOP: if (p1->nodetype->constructor & (ARRAY | POINTER)) { t = PTRADDABOP; p2 = node(NEGOP, p2, NULLNODE); break; } case SUBOP: #if 0 /* This works but sometimes pessimizes the code by converting small * constants into large negative constants. It makes the most * difference for longs by avoiding stack tangles. longop could be * more careful. Only the case (regpair) - constant is naturally * tangled. */ if (p2->tag == LEAF && p2->nodetype->scalar && (source = p2->left.symptr)->storage == CONSTANT) { if (source->type->scalar & RSCALAR) *source->offset.offd = -*source->offset.offd; else source->offset.offv = -source->offset.offv; return node((op_t) t == SUBOP ? ADDOP : ADDABOP, p1, p2); } #endif if (p1->nodetype->constructor & (ARRAY | POINTER)) { if (p2->nodetype->nexttype == p1->nodetype->nexttype) t = PTRSUBOP; else { t = PTRADDOP; p2 = node(NEGOP, p2, NULLNODE); } } break; } if (((op_t) t == PTRADDABOP || (op_t) t == PTRADDOP) && p1->nodetype->nexttype->constructor & (FUNCTION | VOID)) error("arithmetic on pointer to function or void"); if (p1->tag != LEAF) goto node1; target = p1->left.symptr; switch ((op_t) t) { case ADDRESSOP: if (target->indcount == 0 && target->flags == REGVAR) error("register variable addressed"); else if (target->type->constructor & ARRAY) { if (target->indcount != 0) bugerror("botched array indirection count"); target->type = pointype(target->type); } else if (!(p1->flags & LVALUE)) badlvalue(p1); else { address(target); /* change p1, no code generated */ if (target->indcount == 2) /* XXX - MAXINDIRECT? */ /* just became direct enough */ p1->weight = 1; } p1->flags &= ~LVALUE; p1->nodetype = target->type; return p1; case CASTOP: needspv(p2); if (p1->nodetype == p2->nodetype) { /* No ancient switch on low mem systems */ #ifndef VERY_SMALL_MEMORY /* In ancient UNIX C, casts remain lvalues */ if (!ancient) #endif p1->flags &= ~LVALUE; return p1; } if ((rscalar = p2->nodetype->scalar) & ISCALAR) neednonstruct(p1); else if (rscalar & RSCALAR) needscalar(p1); else /* POINTER */ neednonstruct(p1); /* H & S say functions & arrays must match */ if (((lscalar = p1->nodetype->scalar) | rscalar) & RSCALAR) { if (target->storage != CONSTANT) goto node1; if (lscalar & RSCALAR && !(rscalar & RSCALAR)) { double val; /* XXX: Gcc warns about ansi vs k&r problem with this */ static double MAXULONG = (double)0xFFFFFFFFL +1; val = *target->offset.offd; if (val > maxlongto) val -= MAXULONG; target->offset.offv = (value_t) val; } if (!(lscalar & RSCALAR) && rscalar & RSCALAR) { value_t val; val = target->offset.offv; target->offset.offd = qmalloc(sizeof *target->offset.offd); if (lscalar & UNSIGNED) *target->offset.offd = (uvalue_t) val; else *target->offset.offd = val; } } if (target->storage == CONSTANT) { if (rscalar & CHAR) { target->offset.offv &= CHMASKTO; if (p2->nodetype == sctype && target->offset.offv&((~CHMASKTO)>>1)) target->offset.offv |= ~CHMASKTO; } else if (rscalar & SHORT) { target->offset.offv &= shortmaskto; if (!(rscalar & UNSIGNED) && target->offset.offv > maxshortto) target->offset.offv -= (maxushortto + 1); } else if (rscalar & INT) { target->offset.offv &= intmaskto; if (!(rscalar & UNSIGNED) && target->offset.offv > maxintto) target->offset.offv -= (maxuintto + 1); } else if (rscalar & FLOAT) *target->offset.offd = (float) *target->offset.offd; } else if ((targszdelta = ((p1->nodetype->constructor & (ARRAY | POINTER)) ? ptypesize : p1->nodetype->typesize) - p2->nodetype->typesize) == 0) ; else if (target->indcount == 1 && targszdelta > 0 && target->flags != REGVAR) { #if DYNAMIC_LONG_ORDER if (long_big_endian) #endif #if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN # if INT_BIG_ENDIAN target->offset.offi += targszdelta; # else { if (lscalar & DLONG) target->offset.offi += itypesize; /* discard msword */ } # endif #endif #if DYNAMIC_LONG_ORDER else #endif #if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN == 0 # if INT_BIG_ENDIAN { if (rscalar & CHAR) target->offset.offi += ctypesize; } # else ; # endif #endif } else goto node1; /* No ancient switch on low mem systems */ #ifndef VERY_SMALL_MEMORY /* In ancient UNIX C, casts remain lvalues */ if (!ancient) #endif p1->flags &= ~LVALUE; p1->nodetype = target->type = p2->nodetype; return p1; case INDIRECTOP: if (!(target->type->constructor & (ARRAY | POINTER))) error("illegal indirection"); else { indirec(target); if (target->indcount == 3) /* XXX - MAXINDIRECT + 1? */ /* just became too indirect */ p1->weight = 1; p1->flags |= LVALUE; p1->nodetype = target->type; } return p1; case STRUCELTOP: /* p2 known leaf */ if (target->indcount != 1) break; /* struc() would generate code */ struc(p2->left.symptr, target); p1->flags |= LVALUE; p1->nodetype = target->type; return p1; } if (target->indcount != 0) goto node1; lscalar = target->type->scalar; if (target->storage == CONSTANT) { if (lscalar & RSCALAR) dtargval = *target->offset.offd; else targval = target->offset.offv; switch ((op_t) t) { case COMMAOP: return p2; case CONDOP: if ((lscalar & RSCALAR && dtargval != FALSE) || (!(lscalar & RSCALAR) && targval != FALSE)) { p2->left.nodeptr->nodetype = p2->nodetype; return p2->left.nodeptr; } p2->right->nodetype = p2->nodetype; return p2->right; case LOGANDOP: if ((lscalar & RSCALAR && dtargval != FALSE) || (!(lscalar & RSCALAR) && targval != FALSE)) break; p1->nodetype = target->type = itype; return p1; case LOGOROP: if ((lscalar & RSCALAR && dtargval == FALSE) || (!(lscalar & RSCALAR) && targval == FALSE)) break; target->offset.offv = TRUE; p1->nodetype = target->type = itype; return p1; } } switch ((op_t) t) { case COLONOP: case FUNCOP: case LISTOP: case ROOTLISTOP: goto node1; case PTRADDOP: if (p2->tag == LEAF && (source = p2->left.symptr)->storage == CONSTANT && source->type->scalar & ISCALAR) { indexadr(source, target); p1->flags &= ~LVALUE; p1->nodetype = target->type; return p1; } } if (target->storage != CONSTANT || !((lscalar & (ISCALAR | RSCALAR)) && (op_t) t != PTRSUBOP) || (p2 != NULL && (p2->tag != LEAF || (source = p2->left.symptr)->storage != CONSTANT || (!((rscalar = source->type->scalar) & (ISCALAR | RSCALAR)) && (op_t) t != PTRSUBOP)))) goto node1; lflag = lscalar & LONG; uflag = lscalar & UNSIGNED; if (p2 != NULL) { if (rscalar & RSCALAR) dsourceval = *source->offset.offd; else { sourceval = source->offset.offv; lflag |= rscalar & LONG; uflag |= rscalar & UNSIGNED; } } if (lscalar & RSCALAR || (p2 != NULL && rscalar & RSCALAR)) { if (!(lscalar & RSCALAR)) { if (uflag) dtargval = (uvalue_t) targval; else dtargval = targval; } if (p2 != NULL && !(rscalar & RSCALAR)) { if (rscalar & UNSIGNED) dsourceval = (uvalue_t) sourceval; else dsourceval = sourceval; } switch ((op_t) t) { case ADDOP: dtargval += dsourceval; break; case DIVOP: if (dsourceval == 0) { error("divison by 0"); dsourceval = 1; } dtargval /= dsourceval; break; case EQOP: targval = dtargval == dsourceval; goto intconst; case GEOP: targval = dtargval >= dsourceval; goto intconst; case GTOP: targval = dtargval > dsourceval; goto intconst; case LEOP: targval = dtargval <= dsourceval; goto intconst; case LOGANDOP: targval = dtargval && dsourceval; goto intconst; case LOGNOTOP: targval = !dtargval; goto intconst; case LOGOROP: targval = dtargval || dsourceval; goto intconst; case LTOP: targval = dtargval < dsourceval; goto intconst; case MULOP: dtargval *= dsourceval; break; case NEGOP: dtargval = -dtargval; break; case NEOP: targval = dtargval != dsourceval; goto intconst; case SUBOP: dtargval -= dsourceval; break; } /* XXX - leaks memory */ target->offset.offd = qmalloc(sizeof *target->offset.offd); *target->offset.offd = dtargval; p1->nodetype = target->type = dtype; return p1; } switch ((op_t) t) { case ADDOP: targval += sourceval; break; case ANDOP: targval &= sourceval; break; case DIVOP: if (sourceval == 0) { error("divison by 0"); sourceval = 1; } if (uflag) targval = (uvalue_t) targval / sourceval; else targval /= sourceval; break; case EOROP: targval ^= sourceval; break; case EQOP: targval = targval == sourceval; break; case GEOP: if (uflag) targval = (uvalue_t) targval >= sourceval; else targval = targval >= sourceval; goto intconst; case GTOP: if (uflag) targval = (uvalue_t) targval > sourceval; else targval = targval > sourceval; goto intconst; case LEOP: if (uflag) targval = (uvalue_t) targval <= sourceval; else targval = targval <= sourceval; goto intconst; case LOGANDOP: targval = targval && sourceval; goto intconst; case LOGNOTOP: targval = !targval; goto intconst; case LOGOROP: targval = targval || sourceval; goto intconst; case LTOP: if (uflag) targval = (uvalue_t) targval < sourceval; else targval = targval < sourceval; goto intconst; break; case MODOP: if (sourceval == 0) { error("modulo by 0"); sourceval = 1; } if (uflag) targval = (uvalue_t) targval % sourceval; else targval %= sourceval; break; case MULOP: targval *= sourceval; break; case NEGOP: targval = -targval; break; case NEOP: targval = targval != sourceval; goto intconst; case NOTOP: targval = ~targval; break; case OROP: targval |= sourceval; break; case PTRSUBOP: if (targval < sourceval) targval = -((uvalue_t) (sourceval - targval) / target->type->nexttype->typesize); else targval = (uvalue_t) (targval - sourceval) / target->type->nexttype->typesize; uflag = FALSE; break; case SLOP: targval <<= sourceval; /* assume shiftcount treated as unsigned */ lflag = lscalar & LONG; uflag = lscalar & UNSIGNED; break; case SROP: if (uflag) targval = (uvalue_t) targval >> sourceval; else targval >>= sourceval; lflag = lscalar & LONG; uflag = lscalar & UNSIGNED; break; case SUBOP: targval -= sourceval; break; } if (lflag) { target->type = ltype; if (uflag) target->type = ultype; } else { targval &= intmaskto; if (uflag) target->type = uitype; else { target->type = itype; if (targval > maxintto) targval -= (maxuintto + 1); } } target->offset.offv = targval; p1->nodetype = target->type; return p1; intconst: target->offset.offv = targval; p1->nodetype = target->type = itype; return p1; node1: { register struct nodestruct *nodeptr; register struct nodestruct *regp2; if ((nodeptr = etptr++) >= ettop) etreefull(); regp2 = p2; nodeptr->tag = t; nodeptr->left.nodeptr = p1; nodeptr->right = regp2; if ((op_t) t == FUNCOP) nodeptr->weight = MAXREGS + 1; else { #if MAXREGS == 1 if ((nodeptr->weight = p1->weight) <= MAXREGS && (regp2 == NULL || (nodeptr->weight = regp2->weight) < MAXREGS)) nodeptr->weight = MAXREGS; #else nodeptr->weight = p1->weight; if (regp2 == NULL) rightweight = 1; /* could do POST-ops with 0 */ else /* 0 more approp for LIST-ops but 1 OK */ rightweight = regp2->weight; if (nodeptr->weight < rightweight) nodeptr->weight = rightweight; else if (nodeptr->weight == rightweight && nodeptr->weight < MAXREGS) ++nodeptr->weight; #endif } nodeptr->nodetype = nodetype(nodeptr); return nodeptr; } } PRIVATE struct typestruct *nodetype(nodeptr) struct nodestruct *nodeptr; { scalar_t bothscalar; scalar_t lscalar; scalar_t rscalar; struct nodestruct *left; struct nodestruct *right; struct typestruct *targtype; if (nodeptr->tag == LEAF) return nodeptr->left.symptr->type; targtype = (left = nodeptr->left.nodeptr)->nodetype; right = nodeptr->right; switch (nodeptr->tag) { case FUNCOP: if (!(targtype->constructor & FUNCTION)) { error("call of non-function"); fixnode(nodeptr); return errtype; } return targtype->nexttype; case INDIRECTOP: if (!(targtype->constructor & (ARRAY | POINTER))) { error("illegal indirection"); fixnode(nodeptr); return errtype; } nodeptr->flags |= LVALUE; return targtype->nexttype; case LISTOP: case ROOTLISTOP: nodeptr->left.nodeptr = unconvert(left); return promote(targtype); case CASTOP: needspv(right); case COMMAOP: case CONDOP: return right->nodetype; case STRUCELTOP: nodeptr->flags |= LVALUE; return right->nodetype; case ADDRESSOP: if (!(left->flags & LVALUE)) { badlvalue(nodeptr); return errtype; } return pointype(targtype); case LOGNOTOP: neednonstruct(left); return redtype; case NEGOP: needscalar(left); return promote(left->nodetype); case NOTOP: needint(left); return promote(left->nodetype); case PREDECOP: case PREINCOP: case POSTDECOP: case POSTINCOP: neednonstruct(left); if (!(left->flags & LVALUE)) { badlvalue(nodeptr); return errtype; } break; case ANDOP: case EOROP: case MODOP: case OROP: needint(left); needint(right); /* fall through to redundant check and code to cast to same types */ case ADDOP: case DIVOP: case MULOP: case SUBOP: needscalar(left); needscalar(right); binconvert(nodeptr); return nodeptr->nodetype; case PTRADDABOP: if (!(left->flags & LVALUE)) { badlvalue(nodeptr); return errtype; } case PTRADDOP: /* right type conversion to same size as ptr */ needint(right); if (right->nodetype->scalar & LONG) castiright(nodeptr); break; case PTRSUBOP: /* already checked */ return itype; case SLOP: /* right type conversion always to int */ case SROP: /* ulong strictly to unsigned but no matter */ needint(left); needint(right); if (right->nodetype->scalar & LONG) castiright(nodeptr); return promote(left->nodetype); case LTOP: case LEOP: case GTOP: case GEOP: case EQOP: case LOGOROP: case LOGANDOP: case NEOP: neednonstruct(left); neednonstruct(right); nodeptr->left.nodeptr = left = unconvert(left); nodeptr->right = right = unconvert(right); #ifdef MAYBE_DO_LATER /* OK if pointers fit in uitype */ if (left->nodetype->constructor & POINTER) nodeptr->left.nodeptr = left = castnode(uitype, left); if (right->nodetype->constructor & POINTER) nodeptr->right = right = castnode(uitype, right); #endif binconvert(nodeptr); return redtype; case COLONOP: if (isnodecharconst(left) && isnodecharconst(right)) { targtype = (targtype->scalar | right->nodetype->scalar) & UNSIGNED ? uctype : ctype; left = castnode(targtype, left); right = castnode(targtype, right); } nodeptr->left.nodeptr = left = unconvert(left); nodeptr->right = right = unconvert(right); targtype = left->nodetype; if ( #ifdef I80386 i386_32 || #endif ( targtype->scalar & FLOAT ) == 0) if (targtype == right->nodetype) return targtype; /* XXX - reduced from promote(targtype) */ if ((lscalar = targtype->scalar) != 0 && (rscalar = right->nodetype->scalar) != 0) { /* promote minimally without using binconvert for char/short */ if ((bothscalar = lscalar | rscalar) & (LONG | RSCALAR)) { binconvert(nodeptr); return nodeptr->nodetype; } if (bothscalar & INT || (lscalar ^ rscalar) & UNSIGNED) targtype = itype; else if (bothscalar & SHORT) targtype = stype; else targtype = ctype; if (bothscalar & UNSIGNED) targtype = tounsigned(targtype); if ((!(bothscalar & INT) || (left->tag == LEAF && lscalar & INT)) || (right->tag == LEAF && rscalar & INT)) { /* this is correct even when the if fails (the casts have to */ /* be considered at a lower level) but gives worse code */ if (left->nodetype != targtype) nodeptr->left.nodeptr = castnode(targtype, left); if (right->nodetype != targtype) nodeptr->right = castnode(targtype, right); } return targtype; /* XXX - reduced from promote(targtype) */ } if (targtype->constructor & POINTER && (isconst0(right) || (right->nodetype->constructor & POINTER && right->nodetype->nexttype->constructor & VOID))) return targtype; if (right->nodetype->constructor & POINTER && (isconst0(left) || (targtype->constructor & POINTER && targtype->nexttype->constructor & VOID))) return right->nodetype; error("mismatched types"); fixnode(left); /* XXX - better to fix the CONDOP */ fixnode(right); return errtype; case ASSIGNOP: if (right->nodetype->constructor & VOID) { error("assignment of void"); fixnode(right); } if (targtype->constructor & (ARRAY | FUNCTION | VOID)) { error("assignment to array, function or void"); fixnode(nodeptr); return errtype; } if ((targtype->constructor | right->nodetype->constructor) & STRUCTU && targtype != right->nodetype) { error("assignment to/from struct/union of a different type"); fixnode(nodeptr); return errtype; } if (!(left->flags & LVALUE)) { badlvalue(nodeptr); return errtype; } #if 0 /* XXX - this is done at the lowest levels, with too many chances for * errors. */ if (targtype != right->nodetype) nodeptr->right = castnode(left->nodetype, right); #endif break; case ANDABOP: case EORABOP: case MODABOP: case ORABOP: needint(right); needint(left); if (!(left->flags & LVALUE)) { badlvalue(nodeptr); return errtype; } /* fall through to redundant check and code to cast to same types */ case ADDABOP: case SUBABOP: case DIVABOP: case MULABOP: needscalar(right); needscalar(left); if (!(left->flags & LVALUE)) { badlvalue(nodeptr); return errtype; } rscalar = right->nodetype->scalar; if ((lscalar = (targtype = left->nodetype)->scalar) & RSCALAR) { if (!(rscalar & DOUBLE)) nodeptr->right = castnode(dtype, right); } else if (lscalar & LONG) { if (!(rscalar & LONG)) nodeptr->right = castnode(rscalar & UNSIGNED ? ultype : targtype, right); } #ifdef I80386 else if (i386_32 && lscalar & INT) { if (rscalar & SHORT) nodeptr->right = castnode(rscalar & UNSIGNED ? uitype : targtype, right); } #endif break; case SLABOP: case SRABOP: needint(right); needint(left); if (!(left->flags & LVALUE)) { badlvalue(nodeptr); return errtype; } if (!(right->nodetype->scalar & INT)) castiright(nodeptr); break; } return left->nodetype; } PRIVATE int redscalar(nodeptr) register struct nodestruct *nodeptr; { if (isnodecharconst(nodeptr)) return CHAR; return nodeptr->nodetype->scalar; } PRIVATE struct nodestruct *unconvert(nodeptr) struct nodestruct *nodeptr; { if (nodeptr->nodetype->constructor & (ARRAY | FUNCTION)) return castnode(pointype(nodeptr->nodetype->constructor & ARRAY ? nodeptr->nodetype->nexttype : nodeptr->nodetype), nodeptr); return nodeptr; } dev86-0.16.21/bcc/floatop.c000066400000000000000000000112721231050321700151510ustar00rootroot00000000000000/* floatop.c - software operations on floats and doubles for bcc */ /* Copyright (C) 1992 Bruce Evans */ #include "bcc.h" #include "gencode.h" #include "reg.h" #include "sc.h" #include "scan.h" #include "type.h" /*----------------------------------------------------------------------------- f_indirect(target leaf) make the float or double target indirect if it is not already return nonzero iff the result is a temp double on the base of the stack -----------------------------------------------------------------------------*/ PUBLIC bool_pt f_indirect(target) struct symstruct *target; { if (target->indcount == 0) { if (target->storage == CONSTANT) { #ifdef I80386 if (i386_32) { if (target->type->scalar & FLOAT) { float val; val = *target->offset.offd; push(constsym(((value_t *) &val)[0])); } else { push(constsym(((value_t *) target->offset.offd)[1])); push(constsym(((value_t *) target->offset.offd)[0])); } } else #endif { if (target->type->scalar & FLOAT) { float val = *target->offset.offd; push(constsym( ((unsigned short*) &val)[1] )); push(constsym( ((unsigned short*) &val)[0] )); } else { push(constsym(((unsigned short*) target->offset.offd)[3])); push(constsym(((unsigned short*) target->offset.offd)[2])); push(constsym(((unsigned short*) target->offset.offd)[1])); push(constsym(((unsigned short*) target->offset.offd)[0])); } } } else if (target->type->scalar & FLOAT) pushlist(target->storage); /* XXX - floatregs */ else pushlist(doubleregs); onstack(target); } return target->flags == TEMP && target->type->scalar & DOUBLE && target->offset.offi == sp; } /*----------------------------------------------------------------------------- float1op(operation code, source leaf) handles all flop unary operations except inc/dec result is double on stack (or in condition codes for EQOP) -----------------------------------------------------------------------------*/ PUBLIC void float1op(op, source) op_pt op; struct symstruct *source; { saveopreg(); pointat(source); if ((op_t) op == NEGOP) call("Fneg"); else /* op == EQOP */ call("Ftst"); outntypechar(source->type); if ((op_t) op != EQOP) justpushed(source); restoreopreg(); } /*----------------------------------------------------------------------------- floatop(operation code, source leaf, target leaf) handles all flop binary operations result is double on stack (or in condition codes for EQOP) ----------------------------------------------------------------------------*/ PUBLIC void floatop(op, source, target) op_pt op; struct symstruct *source; struct symstruct *target; { store_t regmark; bool_t sflag; regmark = reguse; saveopreg(); (void) f_indirect(source); if (!(reguse & OPREG) && (source->storage == OPREG)) { reguse |= source->storage; saveopreg(); } fpush(target); sflag = TRUE; if (source->flags != TEMP || source->offset.offi != sp + dtypesize) { sflag = FALSE; if (source->storage == OPREG) restoreopreg(); pointat(source); } switch ((op_t) op) { case ADDOP: call("Fadd"); break; case DIVOP: call("Fdiv"); break; case EQOP: call("Fcomp"); sp += dtypesize; /* target is popped */ break; /* target symbol now invalid but is not used */ case MULOP: call("Fmul"); break; case SUBOP: call("Fsub"); break; } if (sflag) { outnl(); sp += dtypesize; /* source is popped */ } else outntypechar(source->type); onstack(target); reguse = regmark; /* early so opreg is not reloaded if source */ restoreopreg(); } /*----------------------------------------------------------------------------- fpush(source leaf of scalar type) converts source to double and pushes it to stack OPREG must be free -----------------------------------------------------------------------------*/ PUBLIC void fpush(source) struct symstruct *source; { scalar_t scalar; if ((scalar = source->type->scalar) & RSCALAR) { if (f_indirect(source)) return; pointat(source); } else if (scalar & DLONG) load(source, OPREG); else load(source, DREG); call("Fpush"); if (scalar & UNSIGNED) outbyte('u'); outntypechar(source->type); justpushed(source); } /*----------------------------------------------------------------------------- justpushed(target leaf) records that target has just been pushed to a double on the stack -----------------------------------------------------------------------------*/ PUBLIC void justpushed(target) struct symstruct *target; { sp -= dtypesize; onstack(target); target->type = dtype; } dev86-0.16.21/bcc/function.c000066400000000000000000000230501231050321700153270ustar00rootroot00000000000000/* function.c - function call protocol for bcc */ /* Copyright (C) 1992 Bruce Evans */ #include "bcc.h" #include "align.h" #include "byteord.h" #include "gencode.h" #include "parse.h" #include "reg.h" #include "sc.h" #include "table.h" #include "type.h" #include "scan.h" #ifdef I8088 # define ADJUSTLONGRETURN # define CANHANDLENOFRAME # undef CANHANDLENOFRAME # define STUPIDFRAME #endif FORWARD void out_callstring P((void)); /* call a named (assembly interface) procedure, don't print newline after */ PUBLIC void call(name) char *name; { out_callstring(); outstr(name); } PUBLIC void function(source) struct symstruct *source; { if (source->indcount == 0 && source->storage == GLOBAL && !(source->flags & LABELLED) && *source->name.namep != 0) { out_callstring(); outnccname(source->name.namep); } else { #ifdef XENIX_AS if (source->indcount == 0) /* fix call fixed address */ out_callstring(); else #endif outcalladr(); #ifdef MC6809 if (source->indcount == 1) ++source->indcount; /* fake for outadr */ #endif outadr(source); } source->type = source->type->nexttype; #ifdef LONGRETSPECIAL /* LONGRETURNREGS!=RETURNREG && RETURNREG==LONGREG2 */ if (source->type->scalar & DLONG) { # ifdef ADJUSTLONGRETURN # if DYNAMIC_LONG_ORDER if (long_big_endian) # endif # if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN { regexchange(LONGREG2, LONGRETURNREGS & ~LONGREG2); regexchange(LONGREG2, DXREG); } # endif # if DYNAMIC_LONG_ORDER else # endif # if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN == 0 regtransfer(DXREG, LONGRETURNREGS & ~LONGREG2); # endif # endif source->storage = LONGRETURNREGS & ~LONGREG2; } else #endif if (source->type->scalar & CHAR) { #if RETURNREG != DREG transfer(source, DREG); #endif source->storage = BREG; } #ifdef I80386 else if (i386_32) { if (source->type->scalar & DOUBLE) source->storage = doublreturnregs & ~DREG; else source->storage = RETURNREG; } else #endif { if (source->type->scalar & DOUBLE) source->storage = doublreturnregs; #ifdef I8088 else if (source->type->scalar & FLOAT) source->storage = RETURNREG|DATREG2; #endif else source->storage = RETURNREG; } source->offset.offi = source->indcount = 0; if (source->level == OFFKLUDGELEVEL) source->level = EXPRLEVEL; if (source->type->constructor & STRUCTU) { transfer(source, getindexreg()); /* so it can be indirected * and/or preserved in blockmove() */ source->indcount = 1; source->flags = TEMP; /* kludge so blockpush can be avoided */ } } PUBLIC void ldregargs() { register struct symstruct *symptr; store_pt targreg; struct symstruct temptarg; for (symptr = &locsyms[0]; symptr < locptr && symptr->level == ARGLEVEL; symptr = (struct symstruct *) align(&symptr->name.namea[strlen(symptr->name.namea) + 1])) { if ((store_t) (targreg = symptr->storage) & allregs) { /* load() is designed to work on expression symbols, so don't * trust it on reg variables although it almost works. */ temptarg = *symptr; if (arg1inreg && symptr == &locsyms[0]) { temptarg.storage = ARGREG; temptarg.offset.offi = 0; } else { temptarg.storage = LOCAL; temptarg.indcount = 1; } load(&temptarg, targreg); symptr->offset.offi = 0; } } regarg = FALSE; } PUBLIC void loadretexpression() { if (returntype->constructor & STRUCTU) { struct nodestruct *etmark; struct nodestruct *exp; struct symstruct *exprmark; struct symstruct *structarg; etmark = etptr; exprmark = exprptr; exp = expression(); makeleaf(exp); structarg = constsym((value_t) 0); structarg->type = pointype(returntype); onstack(structarg); indirec(structarg); structarg->flags = 0; /* assign() doesn't like TEMP even for indir */ structarg->offset.offi = returnadrsize; assign(exp->left.symptr, structarg); etptr = etmark; exprptr = exprmark; } #ifdef LONGRETSPECIAL /* LONGRETURNREGS!=RETURNREG && RETURNREG==LONGREG2 */ else if (returntype->scalar & DLONG) { loadexpression(LONGRETURNREGS & ~LONGREG2, returntype); # ifdef ADJUSTLONGRETURN # if DYNAMIC_LONG_ORDER if (long_big_endian) # endif # if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN { regexchange(LONGREG2, DXREG); regexchange(LONGREG2, LONGRETURNREGS & ~LONGREG2); } # endif # if DYNAMIC_LONG_ORDER else # endif # if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN == 0 regtransfer(LONGRETURNREGS & ~LONGREG2, DXREG); # endif # endif } else #endif { #ifdef I80386 if (i386_32) { if (returntype->scalar & DOUBLE) loadexpression(doublreturnregs & ~DREG, returntype); else loadexpression(RETURNREG, returntype); } else #endif { if (returntype->scalar & DOUBLE) loadexpression(doublreturnregs, returntype); #ifdef I8088 else if (returntype->scalar & FLOAT) loadexpression(/* REURNREG|*/ DATREG2, returntype); #endif else loadexpression(RETURNREG, returntype); } } } PUBLIC void listo(target, lastargsp) struct symstruct *target; offset_T lastargsp; { extend(target); push(target); if (lastargsp != 0 && sp != lastargsp - target->type->typesize) { loadany(target); modstk(lastargsp); push(target); if (sp != lastargsp - target->type->typesize) { bugerror("botched push of arg"); #ifdef DBNODE outstr("arg type is "); dbtype(target->type); outnl(); #endif } } } PUBLIC void listroot(target) struct symstruct *target; { extend(target); /* necessary regs are free since they were saved for function */ if (target->type->scalar & DLONG) load(target, LONGARGREGS & ~LONGREG2); else load(target, ARGREG); } PRIVATE void out_callstring() { outop3str(callstring); #ifdef I80386 if (i386_32) bumplc2(); #endif } #ifdef FRAMEPOINTER PUBLIC void popframe() { #ifdef STUPIDFRAME #ifndef NO_DEL_PUSH if (optimise && !callersaves) { outstr("if "); outstr(funcname); outnstr(".off=0"); } poplist(callee1mask); if (optimise && !callersaves) outnstr("endif"); #else poplist(callee1mask); #endif poplist(FRAMEREG); #else poplist(frame1list); #endif } #endif /* reserve storage for locals if necessary */ /* also push 1st function arg and load register args if necessary */ PUBLIC void reslocals() { #ifdef FRAMEPOINTER # ifndef STUPIDFRAME bool_t loadframe = FALSE; # endif #endif if (switchnow != NULL) { #ifdef FRAMEPOINTER if (framep == 0 && softsp != sp) bugerror("local variables in switch statement messed up, sorry"); #else if (sp != softsp) bugerror("local variables in switch statement don't work, sorry"); #endif if (lowsp > softsp) lowsp = softsp; sp = softsp; return; } #ifdef FRAMEPOINTER if (framep == 0) { # ifdef STUPIDFRAME pushreg(FRAMEREG); regtransfer(STACKREG, FRAMEREG); framep = sp; #ifndef NO_DEL_PUSH if (optimise && !callersaves) { outstr("if "); outstr(funcname); outnstr(".off=0"); } pushlist(callee1mask); if (optimise && !callersaves) outnstr("endif"); #else pushlist(callee1mask); #endif # else /* not STUPIDFRAME */ # ifdef CANHANDLENOFRAME if (stackarg || softsp != -frameregsize) /* args or locals */ # endif { pushlist(frame1list); loadframe = TRUE; } # endif /* not STUPIDFRAME */ } #else if (sp == 0) pushlist(callee1mask); #endif /* FRAMEPOINTER */ if (arg1size) { switch ((fastin_t) arg1size) { case 8: pushlist(doubleargregs); break; case 4: # ifdef I80386 if (!i386_32) # endif { pushlist(LONGARGREGS); break; } case 2: # ifdef I8088 pushlist(ARGREG); # endif # ifdef MC6809 switch (sp - softsp) { case 3: pushlist(LOC1REGS | ARGREG); break; case 4: pushlist(LOC2REGS | ARGREG); break; case 5: pushlist(LOC3REGS | ARGREG); break; case 6: pushlist(LOC4REGS | ARGREG); break; default: pushlist(ARGREG); break; } # endif /* MC6809 */ } arg1size = 0; /* show 1st arg allocated */ } #ifdef FRAMEPOINTER # ifndef STUPIDFRAME /* else this moved above for compat with Xenix cc frame */ if (loadframe || softsp != -frameregsize) modstk(softsp); /* else avoid modstk() because softsp holds space for frame pointer only) */ /* but pointer has not been pushed (must keep softsp for later levels) */ if (loadframe) { regtransfer(STACKREG, FRAMEREG); framep = sp; } # else /* STUPIDFRAME */ modstk(softsp); # endif /* STUPIDFRAME */ #else /* no FRAMEPOINTER */ modstk(softsp); #endif /* FRAMEPOINTER */ if (regarg) ldregargs(); } /* clean up stack and return from a function */ PUBLIC void ret() { #ifdef FRAMEPOINTER offset_T newsp; if (framep != 0) { newsp = -(offset_T) func1saveregsize; if (switchnow != NULL || newsp - sp >= 0x80) changesp(newsp, TRUE); else modstk(newsp); popframe(); } outreturn(); #else /* no FRAMEPOINTER */ # ifdef MC6809 store_pt reglist; switch (sp) { case -1: reglist = JUNK1REGS | PCREG; break; case -2: reglist = JUNK2REGS | PCREG; break; case -3: reglist = JUNK3REGS | PCREG; break; case -4: reglist = JUNK4REGS | PCREG; break; default: modstk(0); outreturn(); return; } poplist(reglist); #else if (sp != 0) { modstk(-(offset_T) func1saveregsize); poplist(callee1mask); } outreturn(); # endif /* no MC6809 */ #endif /* no FRAMEPOINTER */ } dev86-0.16.21/bcc/gencode.c000066400000000000000000000413741231050321700151170ustar00rootroot00000000000000/* gencode.c - generate code for an expression tree for bcc */ /* Copyright (C) 1992 Bruce Evans */ #define islvalop(op) \ (((op) >= ASSIGNOP && (op) <= SUBABOP) || (op) == PTRADDABOP) #include "bcc.h" #include "align.h" #include "condcode.h" #include "reg.h" #include "sc.h" #include "scan.h" #include "type.h" #undef EXTERN #define EXTERN #include "gencode.h" #include "sizes.h" #define FIRSTOPDATA GTOP #if MAXINDIRECT <= 1 # define istooindirect(t) ((t)->indcount > MAXINDIRECT) #else # define istooindirect(t) ((t)->indcount >= MAXINDIRECT && \ ((t)->indcount > MAXINDIRECT || \ (t)->type->typesize > maxregsize || \ (t)->type->constructor & FUNCTION)) #endif #ifdef I8088 #if NOTFINISHED PUBLIC store_pt allregs = BREG | DREG | DATREG1 | DATREG2 | INDREG0 | INDREG1 | INDREG2; #else PUBLIC store_pt allregs = BREG | DREG | INDREG0 | INDREG1 | INDREG2; #endif PUBLIC store_pt allindregs = INDREG0 | INDREG1 | INDREG2; PUBLIC uoffset_T alignmask = ~(uoffset_T) 0x0001; PUBLIC bool_t arg1inreg = FALSE; PUBLIC store_pt calleemask = INDREG1 | INDREG2; PUBLIC bool_t callersaves = FALSE; PUBLIC char *callstring = "call\t"; PUBLIC store_pt doubleargregs = DREG | INDREG0 | DATREG1 | DATREG2; PUBLIC store_pt doubleregs = DREG | INDREG0 | DATREG1 | DATREG2; PUBLIC store_pt doublreturnregs = DREG | INDREG0 | DATREG1 | DATREG2; PUBLIC offset_T jcclonger = 3; PUBLIC offset_T jmplonger = 1; PUBLIC char *jumpstring = "br \t"; PUBLIC char *regpulllist = "f2ax2ax2bx2si2di2bp2qx2qx2cx2dx2"; PUBLIC char *regpushlist = "dx2cx2qx2qx2bp2di2si2bx2ax2ax2f2"; #if NOTFINISHED PUBLIC store_pt regregs = INDREG1 | INDREG2 | DATREG1 | DATREG2; #else PUBLIC store_pt regregs = INDREG1 | INDREG2; #endif PUBLIC char *acclostr = "al"; PUBLIC char *accumstr = "ax"; PUBLIC char *badregstr = "qx"; PUBLIC char *dreg1str = "cx"; PUBLIC char *dreg1bstr = "cl"; PUBLIC char *dreg2str = "dx"; PUBLIC char *ireg0str = "bx"; PUBLIC char *ireg1str = "si"; PUBLIC char *ireg2str = "di"; #ifdef FRAMEPOINTER PUBLIC char *localregstr = "bp"; #else PUBLIC char *localregstr = "sp"; #endif PUBLIC char *stackregstr = "sp"; #endif #ifdef MC6809 PUBLIC store_pt allregs = BREG | DREG | INDREG0 | INDREG1 | INDREG2; PUBLIC store_pt allindregs = INDREG0 | INDREG1 | INDREG2; PUBLIC uoffset_T alignmask = ~(uoffset_T) 0x0000; PUBLIC bool_t arg1inreg = TRUE; PUBLIC store_pt calleemask = INDREG1 | INDREG2; PUBLIC bool_t callersaves = TRUE; PUBLIC char *callstring = "JSR\t>"; #ifndef VERY_SMALL_MEMORY PUBLIC bool_t ancient = FALSE; #endif PUBLIC store_pt doubleargregs = DREG | INDREG0 | INDREG1 | INDREG2; PUBLIC store_pt doubleregs = DREG | INDREG0 | INDREG1 | INDREG2; PUBLIC store_pt doublreturnregs = DREG | INDREG0 | INDREG1 | INDREG2; PUBLIC offset_T jcclonger = 2; PUBLIC offset_T jmplonger = 1; PUBLIC char *jumpstring = "JMP\t>"; PUBLIC char *regpulllist = "CC1B1D2X2U2Y2DP1PC2"; PUBLIC char *regpushlist = "PC2DP1Y2U2X2D2B1CC1"; PUBLIC store_pt regregs = INDREG1 | INDREG2; PUBLIC char *acclostr = "B"; PUBLIC char *accumstr = "D"; PUBLIC char *badregstr = "Q"; PUBLIC char *ireg0str = "X"; PUBLIC char *ireg1str = "U"; PUBLIC char *ireg2str = "Y"; PUBLIC char *localregstr = "S"; #endif PUBLIC uoffset_T accregsize = 2; #ifdef FRAMEPOINTER PUBLIC uoffset_T frameregsize = 2; #endif PUBLIC uoffset_T maxregsize = 2; PUBLIC uoffset_T opregsize = 2; PUBLIC uoffset_T pshregsize = 2; PUBLIC uoffset_T returnadrsize = 2; #ifndef MC6809 PUBLIC uvalue_t intmaskto = 0xFFFFL; PUBLIC uvalue_t maxintto = 0x7FFFL; PUBLIC uvalue_t maxlongto = 0x7FFFFFFFL; PUBLIC uvalue_t maxoffsetto = 0x7FFFL; PUBLIC uvalue_t maxshortto = 0x7FFFL; PUBLIC uvalue_t maxuintto = 0xFFFFL; PUBLIC uvalue_t maxushortto = 0xFFFFL; PUBLIC uvalue_t shortmaskto = 0xFFFFL; #endif PRIVATE store_pt callermask; PRIVATE offset_T lastargsp; PRIVATE smalin_t opdata[] = { /* GTOP, LTOP, ADDOP, DIVOP, */ GT, LT, 0, 0, /* MODOP, LOGNOTOP, NOTOP, STRUCELTOP, */ 0, 0, 0, 0, /* STRUCPTROP, ASSIGNOP, ADDABOP, ANDABOP, */ 0, 0, 0, ANDOP, /* DIVABOP, EORABOP, MODABOP, MULABOP, */ DIVOP, EOROP, MODOP, MULOP, /* ORABOP, SLABOP, SRABOP, SUBABOP, */ OROP, SLOP, SROP, 0, /* COMMAOP, COLONOP, LOGOROP, LOGANDOP, */ 0, 0, 0, 0, /* EQOP, NEOP, GEOP, LEOP, */ EQ, NE, GE, LE, }; FORWARD void abop P((op_pt op, struct symstruct *source, struct symstruct *target)); FORWARD void smakeleaf P((struct nodestruct *exp)); FORWARD void tcheck P((struct nodestruct *exp)); PRIVATE void abop(op, source, target) op_pt op; struct symstruct *source; struct symstruct *target; { store_pt regmark; store_pt regpushed; store_pt regtemp; struct symstruct temptarg; regpushed = preslval(source, target); temptarg = *target; if ((source->type->scalar ^ target->type->scalar) & (DLONG | RSCALAR) && op != SLABOP && op != SRABOP) /* XXX - perhaps not float */ { pres2(target, source); cast(source->type, &temptarg); } switch (op) { case ADDABOP: add(source, &temptarg); break; case ANDABOP: case EORABOP: case ORABOP: op1((opdata - FIRSTOPDATA)[op], source, &temptarg); break; case DIVABOP: case MODABOP: case MULABOP: case SLABOP: case SRABOP: softop((opdata - FIRSTOPDATA)[op], source, &temptarg); break; case PTRADDABOP: regtemp = 0; if ((reguse & allindregs) == allindregs) { /* free a temporary index not used for source or target */ regmark = reguse; reguse = source->storage | temptarg.storage; pushreg(regtemp = getindexreg()); reguse = regmark & ~regtemp; } indexadr(source, &temptarg); if (regtemp) { load(&temptarg, DREG); recovlist(regtemp); } break; case SUBABOP: sub(source, &temptarg); break; } assign(&temptarg, target); recovlist(regpushed); } PUBLIC void bileaf(exp) struct nodestruct *exp; { bool_t commutop; bool_t tookaddress; store_t regmark; struct nodestruct *indchase; struct nodestruct *left; struct nodestruct *right; struct symstruct *source; struct symstruct *target; left = exp->left.nodeptr; if ((right = exp->right) == NULL) { makeleaf(left); #ifdef DBNODE dbnode(exp); #endif return; } switch (exp->tag) { case ADDOP: case ANDOP: case EOROP: case OROP: case EQOP: case NEOP: case MULOP: commutop = TRUE; break; case FUNCOP: makeleaf(left); if ((target = left->left.symptr)->storage & allregs && right->tag != LEAF && target->flags != REGVAR) { if (target->indcount == 0) push(target); else { --target->indcount; push(target); ++target->indcount; } } default: commutop = FALSE; break; } regmark = reguse; if (right->tag != LEAF) { if (left->tag != LEAF && commutop && left->weight > right->weight) { exp->left.nodeptr = right; right = exp->right = left; left = exp->left.nodeptr; #ifdef DBNODE dbnodeswap(); #endif } makeleaf(right); } else if (left->tag != LEAF) makeleaf(left); source = right->left.symptr; if (left->tag != LEAF) { for (indchase = left; indchase->tag == INDIRECTOP || indchase->tag == STRUCELTOP; indchase = indchase->left.nodeptr) ; tookaddress = FALSE; if (source->storage & allindregs || indchase->tag != LEAF) { if (exp->nodetype->constructor & STRUCTU && exp->tag == ASSIGNOP) { address(source); tookaddress = TRUE; } if (source->storage & allindregs && source->indcount == 0 && (source->type->scalar & (DLONG | RSCALAR) || (left->tag == FUNCOP && source->flags != REGVAR))) push(source); /* XXX - perhaps not float */ else preserve(source); } makeleaf(left); if (tookaddress) indirec(source); } target = left->left.symptr; if (istooindirect(source)) { /* want to makelessindirect(source) */ /* this uses source->storage if that is a free index */ /* otherwise, must preserve target if that is an index */ tookaddress = FALSE; if (!(source->storage & ~reguse & allindregs) && target->storage & allindregs) { /* want to pres2(source, target) */ /* this requires target to be < MAXINDIRECT indirect */ /* it is safe to makelessindirect(target) */ /* since source is not a free index */ if (islvalop(exp->tag) && target->indcount != 0) { address(target); tookaddress = TRUE; } if (istooindirect(target)) makelessindirect(target); pres2(source, target); } makelessindirect(source); if (tookaddress) indirec(target); } if (istooindirect(target)) { tookaddress = FALSE; if (!(target->storage & ~reguse & allindregs) && source->storage & allindregs) { if (exp->nodetype->constructor & STRUCTU && exp->tag == ASSIGNOP) { address(source); tookaddress = TRUE; } pres2(target, source); } makelessindirect(target); if (tookaddress) indirec(source); } reguse = regmark; #ifdef DBNODE dbnode(exp); #endif if (commutop && ((target->storage == CONSTANT && !(target->type->scalar & (DLONG | RSCALAR))) || source->storage & ALLDATREGS || (source->type->scalar & (DLONG | RSCALAR) && source->indcount == 0 && target->indcount != 0))) { exp->left.nodeptr = right; exp->right = left; #ifdef DBNODE dbnodeswap(); #endif } } PUBLIC fastin_pt bitcount(number) register uvalue_t number; { register fastin_pt count; for (count = 0; number != 0; number >>= 1) if (number & 1) ++count; return count; } PUBLIC void codeinit() { #ifdef I80386 if (i386_32) { /* Need DATREG2 for doubles although handling of extra data regs is * not finished. * XXX - might need more regs for 16-bit mode doubles or floats. */ allregs = BREG | DREG | INDREG0 | INDREG1 | INDREG2 | DATREG1 | DATREG1B | DATREG2; #if NOTFINISHED allindregs = INDREG0 | INDREG1 | INDREG2 | DATREG1 | DATREG2; #else allindregs = INDREG0 | INDREG1 | INDREG2; #endif alignmask = ~(uoffset_T) 0x00000003; calleemask = INDREG0 | INDREG1 | INDREG2; doubleargregs = DREG | DATREG2; doubleregs = DREG | DATREG2; doublreturnregs = DREG | DATREG2; jcclonger = 4; jmplonger = 3; regpulllist = "fd4eax4eax4ebx4esi4edi4ebp4qx4qx4ecx4edx4"; regpushlist = "edx4ecx4qx4qx4ebp4edi4esi4ebx4eax4eax4fd4"; accumstr = "eax"; dreg1str = "ecx"; dreg2str = "edx"; ireg0str = "ebx"; ireg1str = "esi"; ireg2str = "edi"; #ifdef FRAMEPOINTER localregstr = "ebp"; #else localregstr = "esp"; #endif stackregstr = "esp"; opregsize = returnadrsize = pshregsize = maxregsize = #ifdef FRAMEPOINTER frameregsize = #endif accregsize = 4; intmaskto = (unsigned long) 0xFFFFFFFFL; maxintto = 0x7FFFFFFFL; maxoffsetto = 0x7FFFFFFFL; maxuintto = (unsigned long) 0xFFFFFFFFL; } #endif #ifdef POSINDEPENDENT if (posindependent) { # ifdef MC6809 callstring = "LBSR\t"; jumpstring = "LBRA\t"; # endif } #endif if (callersaves) calleemask = 0; callermask = ~calleemask; #ifdef FRAMEPOINTER funcsaveregsize = bitcount((uvalue_t) calleemask) * maxregsize + frameregsize; funcdsaveregsize = bitcount((uvalue_t) calleemask & ~doubleregs) * maxregsize + frameregsize; framelist = FRAMEREG | calleemask; #else funcsaveregsize = bitcount((uvalue_t) calleemask) * maxregsize; funcdsaveregsize = bitcount((uvalue_t) calleemask & ~doubleregs) * maxregsize; #endif } PUBLIC fastin_pt highbit(number) register uvalue_t number; { register fastin_pt bit; for (bit = -1; number != 0; number >>= 1) ++bit; return bit; } PUBLIC void makeleaf(exp) struct nodestruct *exp; { ccode_t condtrue; op_pt op; store_t regmark; offset_T saveargsp = 0; /* for -Wall */ store_t savelist = 0; /* for -Wall */ offset_T saveoffset = 0; /* for -Wall */ struct symstruct *source; offset_T spmark; struct symstruct *structarg = 0; /* for -Wall */ struct symstruct *target; if ((op_t) (op = exp->tag) == LEAF) { target = exp->left.symptr; if (istooindirect(target)) makelessindirect(target); #ifdef SELFTYPECHECK tcheck(exp); #endif return; } if ((op_t) op == INDIRECTOP || (op_t) op == STRUCELTOP) { smakeleaf(exp); target = exp->left.symptr; if (istooindirect(target)) makelessindirect(target); #ifdef SELFTYPECHECK tcheck(exp); #endif return; } if ((op_t) op == COMMAOP) { spmark = sp; makeleaf(exp->left.nodeptr); modstk(spmark); makeleaf(exp->right); exp->tag = LEAF; exp->left.symptr = exp->right->left.symptr; #ifdef SELFTYPECHECK tcheck(exp); #endif return; } if ((op_t) op == CONDOP) { condop(exp); #ifdef SELFTYPECHECK tcheck(exp); #endif return; } if ((op_t) op == LOGANDOP || (op_t) op == LOGNOTOP || (op_t) op == LOGOROP) { logop(exp); #ifdef SELFTYPECHECK tcheck(exp); #endif return; } regmark = reguse; if ((op_t) op == FUNCOP) { saveargsp = lastargsp; lastargsp = savelist = 0; if (exp->nodetype->constructor & STRUCTU) { modstk(sp - (offset_T) exp->nodetype->typesize); onstack(structarg = constsym((value_t) 0)); } else { if (exp->nodetype->scalar & DOUBLE) { if (regmark & doublreturnregs) savelist = doublreturnregs; } else if (regmark & RETURNREG) /* XXX size long == float ? */ savelist = exp->nodetype->scalar & DLONG ? LONGRETURNREGS : RETURNREG; if (savelist != 0) modstk(saveoffset = sp - exp->nodetype->typesize); } pushlist(regmark & callermask); } spmark = sp; bileaf(exp); if (exp->right != NULL) source = exp->right->left.symptr; else source = NULL; target = exp->left.nodeptr->left.symptr; switch ((op_t) op) { case ADDABOP: case ANDABOP: case DIVABOP: case EORABOP: case SUBABOP: case MODABOP: case MULABOP: case ORABOP: case PTRADDABOP: case SLABOP: case SRABOP: abop(op, source, target); break; case ADDOP: add(source, target); break; case ADDRESSOP: address(target); break; case ANDOP: case EOROP: case OROP: op1(op, source, target); break; case ASSIGNOP: assign(source, target); break; case CASTOP: cast(source->type, target); break; case DIVOP: case MODOP: case MULOP: case SLOP: case SROP: softop(op, source, target); break; case EQOP: case GEOP: case GTOP: case LEOP: case LTOP: case NEOP: condtrue = (opdata - FIRSTOPDATA)[op]; cmp(source, target, &condtrue); break; case FUNCOP: /* kludge update pushed regs */ /* may only work for si, di */ /* -2 skips for ax and bx */ /* need dirtymask to mostly avoid this */ savereturn(regmark & callermask & regregs, spmark - 2 * (offset_T) pshregsize); if (exp->nodetype->constructor & STRUCTU) { address(structarg); push(structarg); } function(target); break; case INDIRECTOP: indirec(target); break; case LISTOP: listo(target, lastargsp); lastargsp = sp; break; case NEGOP: neg(target); break; case NOTOP: not(target); break; case POSTDECOP: case POSTINCOP: case PREDECOP: case PREINCOP: incdec(op, target); break; case PTRADDOP: indexadr(source, target); break; case PTRSUBOP: ptrsub(source, target); break; case ROOTLISTOP: listroot(target); lastargsp = sp; break; case STRUCELTOP: struc(source, target); break; case SUBOP: sub(source, target); break; } if (target->storage == LOCAL && target->offset.offi < spmark && target->flags == TEMP) spmark = target->offset.offi; #if 1 /* XXX - why does sp get changed without this? */ if ((op_t) op != ROOTLISTOP) #endif modstk(spmark); if ((op_t) op == FUNCOP) { lastargsp = saveargsp; if (savelist != 0) { savereturn(savelist, saveoffset); onstack(target); target->offset.offi = saveoffset; } recovlist(regmark & callermask); } reguse = regmark; exp->tag = LEAF; exp->left.symptr = target; if (istooindirect(target)) makelessindirect(target); #ifdef SELFTYPECHECK tcheck(exp); #endif } PRIVATE void smakeleaf(exp) struct nodestruct *exp; { struct nodestruct *left; left = exp->left.nodeptr; if (left->tag == INDIRECTOP || left->tag == STRUCELTOP) smakeleaf(left); else if (left->tag != LEAF) makeleaf(left); if (exp->tag == INDIRECTOP) indirec(left->left.symptr); else { if (left->left.symptr->indcount > MAXINDIRECT + 1) makelessindirect(left->left.symptr); struc(exp->right->left.symptr, left->left.symptr); } exp->tag = LEAF; exp->left.symptr = left->left.symptr; } #ifdef SELFTYPECHECK PRIVATE void tcheck(exp) register struct nodestruct *exp; { register struct symstruct *target; if (exp->nodetype != (target = exp->left.symptr)->type) { { bugerror("botched nodetype calculation"); #ifdef DBNODE comment(); outstr("runtime type is "); dbtype(target->type); outstr(", calculated type is "); dbtype(exp->nodetype); outnl(); #endif } } } #endif /* SELFTYPECHECK */ dev86-0.16.21/bcc/gencode.h000066400000000000000000000100061231050321700151100ustar00rootroot00000000000000/* gencode.h - code generation for bcc */ /* Copyright (C) 1992 Bruce Evans */ #ifdef MC6809 # define CANABXCUTOFF 7 /* favour ABX over MUL before this */ #endif #define EXPRLEVEL 126 /* level for symbols in exptree, > real levs */ #define OFFKLUDGELEVEL 127 /* level for expr sym with offset from name */ #define OPERANDSEPARATOR ',' /* char separating operands */ #define OPSEPARATOR '\t' /* char separating op string and operand */ EXTERN uoffset_T arg1size; /* size of 1st arg to function */ /* zero after allocation of 1st arg */ EXTERN store_pt callee1mask; /* calleemask with doubleregs masked if nec */ EXTERN uoffset_T dataoffset; /* amount of initialized data so far */ #ifdef DBNODE EXTERN bool_t dbnodeon; /* nonzero to print debugging messages */ /* depends on zero init */ #endif #ifdef FRAMEPOINTER EXTERN store_pt framelist; /* bit pattern for frame and saved regs */ EXTERN store_pt frame1list; /* framelist with doubleregs masked if nec */ EXTERN offset_T framep; /* hardware relative frame ptr */ #endif EXTERN uoffset_T func1saveregsize; /* choice of next two values */ EXTERN uoffset_T funcdsaveregsize; /* funcsaveregsize adjusted for doubles */ EXTERN uoffset_T funcsaveregsize; /* tot size of framelist/calleemask regs */ #ifdef I80386 EXTERN bool_t i386_32; /* nonzero to generate 386 32 bit code */ /* depends on zero init */ #endif #ifdef DYNAMIC_LONG_ORDER EXTERN bool_t long_big_endian; /* nonzero if high long word is first */ /* depends on zero init */ #endif EXTERN offset_T lowsp; /* low water sp (collects locals in switch) */ #ifdef POSINDEPENDENT EXTERN bool_t posindependent; /* nonzero to generate pos-independent code */ /* depends on zero init */ #endif EXTERN bool_t printf_fp; /* nonzero if *printf called with FP arg */ EXTERN bool_t regarg; /* nonzero to show unloaded register arg */ /* depends on zero init */ EXTERN store_t reguse; /* registers in use */ EXTERN bool_t scanf_fp; /* nonzero if *scanf called with ptr-to-FP */ EXTERN offset_T softsp; /* software sp (leads sp during declares) */ EXTERN offset_T sp; /* hardware relative stack ptr */ /* depends on zero init */ EXTERN store_t regfuse; /* registers in use in function. */ #ifdef FRAMEPOINTER EXTERN bool_t stackarg; /* nonzero to show function has arg on stack */ #endif EXTERN struct switchstruct *switchnow; /* currently active switch */ /* depends on NULL init */ EXTERN bool_t optimise; /* nonzero to add optimisation code */ /* variables to be initialised to nonzero */ extern store_pt allindregs; /* mask (in) for index registers */ extern store_pt allregs; /* mask (in) for registers */ extern bool_t arg1inreg; /* nonzero to pass 1st arg in reg */ extern store_pt calleemask; /* mask (in) for regs to be saved by callee */ extern bool_t callersaves; /* nonzero to make caller save regs */ extern char *callstring; /* opcode string for call */ extern store_pt doubleargregs; /* mask (in) for regs for 1st arg if double */ extern store_pt doubleregs; /* mask (in) for regs to temp contain double */ extern store_pt doublreturnregs; /* mask (in) for regs for returning double */ extern offset_T jcclonger; /* amount jcc long jumps are longer */ extern offset_T jmplonger; /* amount long jumps is longer */ extern char *jumpstring; /* opcode string for jump */ extern char *regpulllist; /* reg names and sizes (0 store_t bit first) */ extern char *regpushlist; /* reg names and sizes (0 store_t bit last) */ extern store_pt regregs; /* mask (in) for regs which can be reg vars */ /* register names */ extern char *acclostr; extern char *accumstr; extern char *badregstr; #ifdef I8088 extern char *dreg1str; extern char *dreg1bstr; extern char *dreg2str; #endif extern char *ireg0str; extern char *ireg1str; extern char *ireg2str; extern char *localregstr; #ifdef I8088 extern char *stackregstr; #endif /* register sizes */ extern uoffset_T accregsize; #ifdef FRAMEPOINTER extern uoffset_T frameregsize; #endif extern uoffset_T maxregsize; extern uoffset_T opregsize; extern uoffset_T pshregsize; extern uoffset_T returnadrsize; dev86-0.16.21/bcc/genloads.c000066400000000000000000000762131231050321700153070ustar00rootroot00000000000000/* genloads.c - generate loads of registers and memory for bcc */ /* Copyright (C) 1992 Bruce Evans */ #include "bcc.h" #include "byteord.h" #include "condcode.h" #include "gencode.h" #include "reg.h" #include "sc.h" #include "scan.h" #include "sizes.h" #include "type.h" FORWARD void badaddress P((void)); FORWARD void blockpush P((struct symstruct *source)); FORWARD void loadadr P((struct symstruct *source, store_pt targreg)); FORWARD void loadlongindirect P((struct symstruct *source, store_pt targreg)); FORWARD void outnamoffset P((struct symstruct *adr)); FORWARD void outnnadr P((struct symstruct *adr)); FORWARD fastin_pt pushpull P((store_pt reglist, bool_pt pushflag)); PUBLIC void addoffset(source) struct symstruct *source; { #ifdef I8088 if (source->level == OFFKLUDGELEVEL) { outadd(); outregname(source->storage); outcomma(); outimmed(); outnamoffset(source); outnl(); if (source->storage & (AXREG | ALREG)) unbumplc(); if (source->level == OFFKLUDGELEVEL) source->level = EXPRLEVEL; source->offset.offi = 0; } else #endif if (source->offset.offi != 0) { addconst(source->offset.offi, source->storage); source->offset.offi = 0; } } PUBLIC void address(source) struct symstruct *source; { if (source->indcount == 0) bugerror("taking address of non-lvalue"); else { if (source->type->constructor & (ARRAY | FUNCTION)) bugerror("botched indirect array or function"); else if (--source->indcount == 0 && source->storage == GLOBAL && !(source->flags & LABELLED) && *source->name.namep == 0) source->storage = CONSTANT; source->type = pointype(source->type); } } PRIVATE void badaddress() { bugerror("bad address"); } PRIVATE void blockpush(source) struct symstruct *source; { struct symstruct *length; offset_T spmark; uoffset_T typesize; typesize = source->type->typesize; length = constsym((value_t) typesize); length->type = uitype; address(source); modstk(spmark = sp - (offset_T) typesize); #ifdef STACKREG regtransfer(STACKREG, DREG); #else #ifdef MC6809 /* XXX ? */ regtransfer(LOCAL, DREG); #else #include "need STACKREG and stackregstr" #endif #endif push(length); push(source); pushreg(DREG); call("_memcpy"); outnl(); modstk(spmark); indirec(source); } PUBLIC void exchange(source, target) struct symstruct *source; struct symstruct *target; { store_t tempreg; regexchange(source->storage, target->storage); tempreg = target->storage; target->storage = source->storage; source->storage = tempreg; } /*----------------------------------------------------------------------------- getindexreg() returns the "best" available index register -----------------------------------------------------------------------------*/ PUBLIC store_pt getindexreg() { if (!(reguse & INDREG0)) return INDREG0; if (!(reguse & INDREG1)) return INDREG1; if (!(reguse & INDREG2)) return INDREG2; #if NOTFINISHED #ifdef I80386 if (i386_32) { if (!(reguse & DATREG1)) return DATREG1; if (!(reguse & DATREG2)) return DATREG2; } #endif #endif bugerror("out of index regs"); return 0; } /*----------------------------------------------------------------------------- indexadr(index leaf, pointer leaf) is used by the index and add and subtract (pointer) routines it handles expressions like pointer + index &array[index] the target becomes register direct with offset (except for index = 0, when nothing is changed) constant indexes are optimised by leaving them as offsets register direct pointers are optimised by leaving the offset alone (except for PC register direct, since there is no LEAX D,PC) -----------------------------------------------------------------------------*/ PUBLIC void indexadr(source, target) struct symstruct *source; struct symstruct *target; { #ifdef MC6809 bool_t canABX; #endif uoffset_T size; store_pt sourcereg; struct typestruct *targtype; store_pt targreg; if (!(target->type->constructor & (ARRAY | POINTER))) { bugerror("cannot index"); return; } size = target->type->nexttype->typesize; if (source->storage == CONSTANT) { if (source->offset.offv != 0) { if (target->indcount != 0) loadany(target); target->offset.offi += source->offset.offv * size; } return; } if (target->storage & ALLDATREGS) push(target); if ((store_t) (sourcereg = target->storage) & ~reguse & allindregs) targreg = sourcereg; else targreg = getindexreg(); #ifdef I8088 if ((store_t) sourcereg == GLOBAL && target->indcount == 0 && !(source->type->scalar & CHAR) && source->storage != DREG) load(source, targreg); else #endif load(source, DREG); #ifdef I8088 softop(MULOP, constsym((value_t) size), source); #endif #ifdef MC6809 /*----------------------------------------------------------------------------- do some calculations in advance to decide if index can be done with ABX -----------------------------------------------------------------------------*/ if ((store_t) targreg == XREG && source->type->scalar & CHAR && size < CANABXCUTOFF) canABX = TRUE; else { canABX = FALSE; softop(MULOP, constsym((value_t) size), source); } #endif /*----------------------------------------------------------------------------- deal with constant target - constant becomes offset, result in DREG -----------------------------------------------------------------------------*/ if (target->storage == CONSTANT) { target->storage = DREG; return; } /*----------------------------------------------------------------------------- load target if it is indirect or GLOBAL or canABX so D or B can be added otherwise, it is register direct (maybe S register, maybe with offset) and the offset can be left after adding DREG -----------------------------------------------------------------------------*/ #ifdef I8088 if (target->indcount != 0) { targtype = target->type; target->type = itype; add(source, target); target->type = targtype; return; } if ((store_t) sourcereg == GLOBAL) { target->storage = source->storage; target->level = OFFKLUDGELEVEL; return; } #endif #ifdef MC6809 if (canABX || (store_t) sourcereg == GLOBAL) { load(target, targreg); sourcereg = targreg; } else if (target->indcount != 0) { targtype = target->type; target->type = itype; add(source, target); target->type = targtype; return; } if (canABX) while (size--) outABX(); else #endif { #ifdef I8088 if ((store_t) targreg != (store_t) sourcereg) regtransfer(sourcereg, targreg); outadd(); outregname(targreg); outncregname(DREG); #endif #ifdef MC6809 outlea(); outregname(targreg); outtab(); outregname(DREG); outncregname(sourcereg); #endif } if ((store_t) sourcereg == LOCAL) #ifdef FRAMEPOINTER target->offset.offi -= framep; #else target->offset.offi -= sp; #endif target->storage = targreg; } PUBLIC void indirec(source) struct symstruct *source; { if (!(source->type->constructor & (ARRAY | POINTER))) bugerror("illegal indirection"); else if (source->indcount == (indn_t) - 1) limiterror("too many indirections (256)"); else { if (source->storage & ALLDATREGS) transfer(source, getindexreg()); if (!((source->type = source->type->nexttype)->constructor & (ARRAY | FUNCTION))) ++source->indcount; if (source->storage == CONSTANT) source->storage = GLOBAL; } } /*----------------------------------------------------------------------------- load(source leaf, target register) loads the specified register without changing any others (except CC) if the type is long or float, DREG is paired with the target register the result has no offset -----------------------------------------------------------------------------*/ PUBLIC void load(source, targreg) struct symstruct *source; store_pt targreg; { if (source->type->scalar & DLONG) { if (source->storage == CONSTANT) loadreg(source, targreg); else if (source->indcount == 0) { #if DYNAMIC_LONG_ORDER if (!long_big_endian) #endif #if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN == 0 { if ((store_t) targreg == DREG) source->storage = DREG; } #endif if (source->storage != (store_t) targreg) transfer(source, targreg); if (source->offset.offi != 0) bugerror("loading direct long with offset not implemented"); } else loadlongindirect(source, targreg); } else if (source->type->scalar & DOUBLE) { if (source->storage == targreg && source->indcount == 0) return; if (source->storage == CONSTANT) { #ifdef I80386 if (i386_32) { loadconst(((offset_T *) source->offset.offd)[0], DREG); loadconst(((offset_T *) source->offset.offd)[1], targreg&~DREG); } else /* XXX - more for non-386 */ #endif { int regs, i, off=1; loadconst(((unsigned short *) source->offset.offd)[0], DREG); regs = (targreg&~DREG); for(i=1; i; i<<=1) { if( regs&i ) loadconst( ((unsigned short *) source->offset.offd)[off++], i); } } } else { push(source); poplist(targreg | DREG); /* actually it's the full reg list */ } source->storage = targreg; /* XXX - multi for non-386 */ source->indcount = 0; source->flags = 0; if (source->level == OFFKLUDGELEVEL) source->level = EXPRLEVEL; source->offset.offi = 0; } else if (source->type->scalar & FLOAT && source->storage == CONSTANT) { float val; val = *source->offset.offd; #ifdef I80386 if (i386_32) loadconst(((offset_T *) &val)[0], targreg); /* XXX 386 */ else #endif { loadconst(((unsigned short *) &val)[0], DREG); loadconst(((unsigned short *) &val)[1], targreg&~DREG); } } #ifdef I80386 else if (!i386_32 && source->type->scalar & FLOAT) #else else if (source->type->scalar & FLOAT) #endif { /* Treat a float just like a long ... */ if (source->indcount == 0) { if (source->storage != (store_t) targreg) transfer(source, targreg); if (source->offset.offi != 0) bugerror("loading direct float with offset not implemented"); } else loadlongindirect(source, targreg); } else if (source->indcount == 0 && source->storage != CONSTANT) loadadr(source, targreg); else if (source->type->scalar || source->type->constructor & (ARRAY | POINTER)) loadreg(source, targreg); else bugerror("attempting to load non-scalar non-pointer"); } PRIVATE void loadadr(source, targreg) struct symstruct *source; store_pt targreg; { if ((store_t) targreg & ALLDATREGS) { if (source->storage == GLOBAL) { #ifdef MC6809 if (posindependent) { pushreg(INDREG0); loadreg(source, INDREG0); transfer(source, DREG); recovlist(INDREG0); } else #endif loadreg(source, targreg); } if (source->storage == LOCAL) #ifdef FRAMEPOINTER source->offset.offi -= framep; #else source->offset.offi -= sp; #endif if (source->type->scalar & CHAR) targreg = BREG; #ifdef I8088 if (source->storage == DREG) addoffset(source); #endif if (source->storage != (store_t) targreg) transfer(source, targreg); addoffset(source); } else if (source->storage & ALLDATREGS) { addoffset(source); transfer(source, targreg); } else if (source->storage != (store_t) targreg || source->offset.offi != 0 || source->level == OFFKLUDGELEVEL) loadreg(source, targreg); } PUBLIC void loadany(source) struct symstruct *source; { if (source->indcount != 0 || source->offset.offi != 0 || /* kludge u cmp */ source->level == OFFKLUDGELEVEL || !(source->storage & allregs)) { if (source->type->scalar & RSCALAR) load(source, doubleregs & ~DREG); else if ((source->storage == CONSTANT && !(source->type->scalar & DLONG)) || source->type->scalar & CHAR) load(source, DREG); else if (source->storage & ~reguse & allregs) load(source, source->storage); else if (((reguse & allindregs) == allindregs || ((!(source->type->constructor & (ARRAY | POINTER)) && source->indcount != 0) && !(source->type->scalar & DLONG)))) load(source, DREG); else load(source, getindexreg()); } } PRIVATE void loadlongindirect(source, targreg) struct symstruct *source; store_pt targreg; { sc_t flags; offset_T offset; store_t reg; struct typestruct *type; if (source->level == OFFKLUDGELEVEL) addoffset(source); /* else kludge is lost and offsets big */ flags = source->flags; offset = source->offset.offi; reg = source->storage; type = source->type; source->type = itype; loadreg(source, DREG); source->flags = flags; source->storage = reg; source->indcount = 1; source->offset.offi = offset + accregsize; loadreg(source, targreg); source->type = type; } PUBLIC void loadreg(source, targreg) struct symstruct *source; store_pt targreg; { offset_T longhigh; offset_T longlow; if (source->storage == CONSTANT) { if (source->type->scalar & CHAR && (store_t) targreg & ALLDATREGS) targreg = BREG; longlow = (offset_T) source->offset.offv; if (source->type->scalar & DLONG) { longlow &= (offset_T) intmaskto; longhigh = (offset_T) (source->offset.offv >> INT16BITSTO) & (offset_T) intmaskto; if ((store_t) targreg != LONGREG2) /* loading the whole long */ { #if DYNAMIC_LONG_ORDER if (long_big_endian) #endif #if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN loadconst(longhigh, DREG); #endif #if DYNAMIC_LONG_ORDER else #endif #if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN == 0 { loadconst(longlow, DREG); longlow = longhigh; } #endif } } loadconst(longlow, targreg); source->storage = targreg; source->offset.offi = 0; } else { #ifdef I8088 if (source->indcount == 0 && source->storage != GLOBAL && (source->offset.offi != 0 || source->level == OFFKLUDGELEVEL)) { if ((store_t) targreg == source->storage) { addoffset(source); return; } source->indcount = 1; /* fake for outadr() to produce "()" */ outlea(); } else { #ifdef I8088 /* Added acess to CPU registers. Just declare _AX etc. as * extern int, and you can use them to get/set * the register values. (vak) */ if (source->storage == GLOBAL && !(source->flags & LABELLED) && *source->name.namep != 0 && strncmp(source->name.namep, "__", 2) == 0) { if (strcmp (source->name.namep, "__AX") == 0) { /* Load AX register - do nothing. */ done: if (targreg != AXREG) bugerror("specified access of register clone variable not implemented"); source->storage = AXREG; /* in register for further use */ source->flags = 0; if (source->level == OFFKLUDGELEVEL) source->level = EXPRLEVEL; source->offset.offi = 0; /* indcount was adjusted by outadr */ return; } if (strcmp (source->name.namep, "__BX") == 0) { outstr ("mov\tax,bx\n"); goto done; } if (strcmp (source->name.namep, "__CX") == 0) { outstr ("mov\tax,cx\n"); goto done; } if (strcmp (source->name.namep, "__DX") == 0) { outstr ("mov\tax,dx\n"); goto done; } if (strcmp (source->name.namep, "__SP") == 0) { outstr ("mov\tax,sp\n"); goto done; } if (strcmp (source->name.namep, "__BP") == 0) { outstr ("mov\tax,bp\n"); goto done; } if (strcmp (source->name.namep, "__SI") == 0) { outstr ("mov\tax,si\n"); goto done; } if (strcmp (source->name.namep, "__DI") == 0) { outstr ("mov\tax,di\n"); goto done; } if (strcmp (source->name.namep, "__CS") == 0) { outstr ("mov\tax,cs\n"); goto done; } if (strcmp (source->name.namep, "__DS") == 0) { outstr ("mov\tax,ds\n"); goto done; } if (strcmp (source->name.namep, "__ES") == 0) { outstr ("mov\tax,es\n"); goto done; } if (strcmp (source->name.namep, "__SS") == 0) { outstr ("mov\tax,ss\n"); goto done; } if (strcmp (source->name.namep, "__FLAGS") == 0) { outstr ("pushf\npop\tax\n"); goto done; } } #endif outload(); if (source->storage == GLOBAL && source->indcount != 0 && (store_t) targreg & (AXREG | ALREG)) unbumplc(); } #endif #ifdef MC6809 if (source->indcount == 0 && (source->storage != GLOBAL || posindependent)) outlea(); else { outload(); if ((store_t) targreg == YREG) bumplc(); } #endif movereg(source, targreg); } } PUBLIC void makelessindirect(source) struct symstruct *source; { store_pt lreg; if (!((store_t) (lreg = source->storage) & ~reguse & allindregs)) lreg = getindexreg(); while (source->indcount > MAXINDIRECT) loadreg(source, lreg); #if MAXINDIRECT > 1 if (source->indcount == MAXINDIRECT && (source->type->typesize > maxregsize || source->type->constructor & FUNCTION)) { source->indcount = 1; loadreg(source, lreg); source->indcount = 1; } #endif } PUBLIC void movereg(source, targreg) struct symstruct *source; store_pt targreg; { if ((store_t) targreg & ALLDATREGS && source->type->scalar & CHAR) targreg = BREG; #ifdef I8086 if (source->type->scalar & CHAR && targreg != BREG && targreg != DATREG1B ) { bugerror("moving char sym into int register"); } #endif #ifdef I80386 if (i386_32 && source->type->scalar & SHORT && source->indcount <= 1) { outshortregname(targreg); bumplc(); } else #endif outregname(targreg); if (source->storage == CONSTANT) adjlc((offset_T) source->offset.offv, targreg); #ifdef I8088 outcomma(); #endif outadr(source); source->storage = targreg; /* in register for further use */ source->flags = 0; if (source->level == OFFKLUDGELEVEL) source->level = EXPRLEVEL; source->offset.offi = 0; /* indcount was adjusted by outadr */ } PUBLIC void onstack(target) register struct symstruct *target; { target->storage = LOCAL; target->flags = TEMP; if (target->level == OFFKLUDGELEVEL) target->level = EXPRLEVEL; target->indcount = 1; target->offset.offi = sp; } PUBLIC void outadr(adr) struct symstruct *adr; { outnnadr(adr); outnl(); } PUBLIC void outcregname(reg) store_pt reg; { outcomma(); outregname(reg); } PRIVATE void outnamoffset(adr) struct symstruct *adr; { if (adr->flags & LABELLED) outlabel(adr->name.label); else outccname(adr->name.namep); if (adr->offset.offi != 0) { if (adr->offset.offi > 0) outplus(); outshex(adr->offset.offi); } bumplc2(); #ifdef I80386 if (i386_32) bumplc2(); #endif } /* print comma, then register name, then newline */ PUBLIC void outncregname(reg) store_pt reg; { outcomma(); outnregname(reg); } PRIVATE void outnnadr(adr) struct symstruct *adr; { bool_t indflag; indflag = FALSE; #ifdef I8088 if (adr->indcount >= MAXINDIRECT) indflag = TRUE; #endif #ifdef MC6809 outtab(); if (adr->indcount >= MAXINDIRECT && (adr->indcount & 1) == 0) { indflag = TRUE; /* indirection means double indirect */ outindleft(); } #endif switch (adr->storage) { case CONSTANT: outimmadr((offset_T) adr->offset.offv); break; #ifdef I8088 case DREG: if (indflag || adr->offset.offi != 0 || adr->level == OFFKLUDGELEVEL) badaddress(); else outregname(DREG); break; #endif #ifdef I8088 case DATREG1: case DATREG2: #ifdef I80386 if (indflag && !i386_32) #else if (indflag) #endif { outnl(); badaddress(); break; } #endif case INDREG0: case INDREG1: case INDREG2: if (adr->level == OFFKLUDGELEVEL) { #ifdef I8088 if (!indflag) #endif outimmed(); outnamoffset(adr); } #ifndef MC6809 else if (adr->offset.offi != 0) #endif outoffset(adr->offset.offi); #ifdef I8088 if (indflag) outindleft(); outregname(adr->storage); # ifdef XENIX_AS if (indflag) outindright(); # endif #endif #ifdef MC6809 if (indflag && adr->offset.offi != 0 && is5bitoffset(adr->offset.offi)) bumplc(); outcregname(adr->storage); #endif break; case LOCAL: #ifdef I8088 # ifdef FRAMEPOINTER if (framep == 0) bugerror("no frame pointer"); if (indflag) { if (adr->offset.offi == framep) bumplc(); else { int off; if (switchnow != NULL && adr->flags == TEMP) outswoffset(off = adr->offset.offi); else outoffset(off = adr->offset.offi - framep); #ifndef NO_DEL_PUSH if (optimise && !callersaves && off < 0) { outstr("+"); outstr(funcname); outstr(".off"); } #endif } outindleft(); } else if (adr->offset.offi != framep) badaddress(); outregname(LOCAL); # else if (indflag) { bumplc(); if (adr->offset.offi != sp) outoffset(adr->offset.offi - sp); outindleft(); } else if (adr->offset.offi != sp) badaddress(); outregname(LOCAL); # endif /* FRAMEPOINTER */ # ifdef XENIX_AS if (indflag) outindright(); # endif #endif /* I8088 */ #ifdef MC6809 if (adr->flags == TEMP && adr->offset.offi == sp && adr->indcount == 1) { outcregname(LOCAL); outplus(); ++sp; if (adr->type->typesize != 1) { outplus(); ++sp; } break; } outoffset(adr->offset.offi - sp); if (indflag && adr->offset.offi != sp && is5bitoffset(adr->offset.offi - sp)) bumplc(); outcregname(LOCAL); #endif /* MC6809 */ break; case GLOBAL: #ifdef I8088 bumplc(); #ifdef I80386 if (i386_32) bumplc2(); #endif if (!indflag) outimmed(); else { # ifndef XENIX_AS outindleft(); # endif bumplc(); } #endif #ifdef MC6809 if (!posindependent) { if (adr->indcount == 0) { outimmed(); bumplc(); } else if (indflag) { outextended(); bumplc2(); } else if (adr->flags & DIRECTPAGE) outdirectpage(); else { outextended(); bumplc(); } } #endif if (adr->flags & LABELLED) outlabel(adr->name.label); else if (*adr->name.namep == 0) /* constant address */ { outhex((uoffset_T) adr->offset.offi); break; } else outccname(adr->name.namep); if (adr->offset.offi != 0) { if (adr->offset.offi > 0) outplus(); outshex(adr->offset.offi); } #ifdef MC6809 if (posindependent) { outcregname(GLOBAL); bumplc2(); } #endif break; default: outnl(); badaddress(); break; } #ifdef I8088 if (indflag) { --adr->indcount; # ifndef XENIX_AS outindright(); # endif } #endif #ifdef MC6809 if (indflag) { outindright(); adr->indcount -= MAXINDIRECT; } else if (adr->indcount != 0) --adr->indcount; #endif } /* print register name, then newline */ PUBLIC void outnregname(reg) store_pt reg; { outregname(reg); outnl(); } /* print register name */ PUBLIC void outregname(reg) store_pt reg; { switch ((store_t) reg) { case BREG: outstr(acclostr); break; case DREG: outstr(accumstr); break; #ifdef MC6809 case GLOBAL: outstr("PC"); break; #endif case INDREG0: outstr(ireg0str); regfuse |= INDREG0; break; case INDREG1: outstr(ireg1str); regfuse |= INDREG1; break; case INDREG2: outstr(ireg2str); regfuse |= INDREG2; break; case LOCAL: outstr(localregstr); regfuse |= LOCAL; break; #ifdef STACKREG case STACKREG: outstr(stackregstr); break; #endif #ifdef DATREG1 case DATREG1: outstr(dreg1str); break; #endif #ifdef DATREG1B case DATREG1B: outstr(dreg1bstr); break; #endif #ifdef DATREG2 case DATREG2: outstr(dreg2str); break; #endif default: { int i; if (reg) for(i=1; i; i<<=1) { if( reg&i ) { outregname(i); outstr(" "); } } else outstr(badregstr); } break; } } #if defined(I8088) && defined(I80386) /* print register name for short type */ PUBLIC void outshortregname(reg) store_pt reg; { switch ((store_t) reg) { case DREG: outstr(accumstr + 1); break; case INDREG0: outstr(ireg0str + 1); break; case INDREG1: outstr(ireg1str + 1); break; case INDREG2: outstr(ireg2str + 1); break; case DATREG1: outstr(dreg1str + 1); break; case DATREG2: outstr(dreg2str + 1); break; default: outstr(badregstr); break; } } #endif /*----------------------------------------------------------------------------- pointat(target leaf) point OPREG at target target must be singly indirect or float or double -----------------------------------------------------------------------------*/ PUBLIC void pointat(target) struct symstruct *target; { if (target->type->scalar & RSCALAR) (void) f_indirect(target); address(target); load(target, OPREG); target->type = target->type->nexttype; } PUBLIC void poplist(reglist) store_pt reglist; { if (reglist) sp += pushpull(reglist, FALSE); } PUBLIC void push(source) struct symstruct *source; { store_t reg; #ifdef I8088 uoffset_T size; #endif scalar_t sscalar; if (source->type->constructor & STRUCTU) { if (source->flags != TEMP) /* TEMP must be from last function */ blockpush(source); } else if ((sscalar = source->type->scalar) & RSCALAR) { if (!f_indirect(source)) { saveopreg(); fpush(source); restoreopreg(); } } #ifdef I8088 else if ((source->indcount == 1 && (sscalar & (SHORT | INT | LONG | FLOAT) || source->type->constructor & POINTER)) #ifdef I80386 || (source->storage == CONSTANT && i386_32) #endif ) { size = source->type->typesize; if (size == 1) size = 2; if (sscalar & DLONG) { source->offset.offi += itypesize; outpshs(); bumplc(); outtab(); outadr(source); source->indcount = 1; source->offset.offi -= itypesize; } outpshs(); bumplc(); outtab(); #ifdef I80386 if (i386_32) { if (source->storage == CONSTANT) { unbumplc(); adjlc((offset_T) source->offset.offv, INDREG0); } if (size == 2) { outword(); bumplc(); } else outdword(); } #endif outadr(source); sp -= size; } #endif else { reg = source->storage; loadany(source); if (sscalar & DLONG) pushlist(DREG | source->storage); else if (sscalar & CHAR) pushchar(); else pushreg(source->storage); if (source->flags != REGVAR) reguse &= ~(reg | source->storage); } onstack(source); } PUBLIC void pushlist(reglist) store_pt reglist; { if ((store_t) reglist) sp -= pushpull(reglist, TRUE); } PRIVATE fastin_pt pushpull(reglist, pushflag) store_pt reglist; bool_pt pushflag; { store_pt lastregbit; void (*ppfunc) P((void)); char *regptr; #ifdef MC6809 int separator; /* promoted char for output */ #endif fastin_t bytespushed; store_pt regbit; if ((bool_t) pushflag) { ppfunc = outpshs; #ifdef I8088 regbit = 1 << 10; #else regbit = 1 << 7; #endif regptr = regpushlist; lastregbit = 1; } else { ppfunc = outpuls; regbit = 1; regptr = regpulllist; #ifdef I8088 lastregbit = 1 << 10; #else lastregbit = 1 << 7; #endif } #ifdef MC6809 /* temp use pull strings to keep old order */ regbit = 1; regptr = regpulllist; lastregbit = 1 << 7; #endif #ifdef MC6809 separator = OPSEPARATOR; (*ppfunc) (); #endif bytespushed = 0; while (TRUE) { if (regbit & reglist) { #ifdef I8088 (*ppfunc)(); if (*regptr != FLAGSREGCHAR) outtab(); #endif #ifdef MC6809 outbyte(separator); #endif do outbyte(*regptr++); while (*regptr >= MINREGCHAR); bytespushed += *regptr++ - '0'; #ifdef I8088 outnl(); #endif #ifdef MC6809 separator = OPERANDSEPARATOR; #endif } else do ; while (*regptr++ >= MINREGCHAR); if (regbit == lastregbit) break; #ifdef MC6809 /* temp use pull strings to keep old order */ regbit <<= 1; #else /* this should normally be unconditional */ if ((bool_t) pushflag) regbit >>= 1; else regbit <<= 1; #endif } #ifdef MC6809 outnl(); #endif return bytespushed; } PUBLIC void pushreg(reg) store_pt reg; { outpshs(); outtab(); outnregname(reg); sp -= pshregsize; } PUBLIC void storereg(sourcereg, target) store_pt sourcereg; struct symstruct *target; { store_pt targreg; if (target->indcount == 0) { if (target->offset.offi != 0 || target->level == OFFKLUDGELEVEL || !(target->storage & allregs) || target->storage & CHARREGS) bugerror("bad register store"); else if ((store_t) (targreg = target->storage) != (store_t) sourcereg) { target->storage = sourcereg; loadadr(target, targreg); /* do LEA or TFR */ } } else { #ifdef I8088 /* Added acess to CPU registers. Just declare _AX etc. as * extern int, and you can use them to get/set * the register values. (vak) */ if (target->storage == GLOBAL && !(target->flags & LABELLED) && *target->name.namep != 0 && strncmp(target->name.namep, "__", 2) == 0) { if (strcmp (target->name.namep, "__AX") == 0) { return; } if (strcmp (target->name.namep, "__BX") == 0) { outstr ("mov\tbx,"); outregname(sourcereg); outnl(); return; } if (strcmp (target->name.namep, "__CX") == 0) { outstr ("mov\tcx,"); outregname(sourcereg); outnl(); return; } if (strcmp (target->name.namep, "__DX") == 0) { outstr ("mov\tdx,"); outregname(sourcereg); outnl(); return; } if (strcmp (target->name.namep, "__SP") == 0) { outstr ("mov\tsp,"); outregname(sourcereg); outnl(); return; } if (strcmp (target->name.namep, "__BP") == 0) { outstr ("mov\tbp,"); outregname(sourcereg); outnl(); return; } if (strcmp (target->name.namep, "__SI") == 0) { outstr ("mov\tsi,"); outregname(sourcereg); outnl(); return; } if (strcmp (target->name.namep, "__DI") == 0) { outstr ("mov\tdi,"); outregname(sourcereg); outnl(); return; } if (strcmp (target->name.namep, "__CS") == 0) { outstr ("mov\tcs,"); outregname(sourcereg); outnl(); return; } if (strcmp (target->name.namep, "__DS") == 0) { outstr ("mov\tds,"); outregname(sourcereg); outnl(); return; } if (strcmp (target->name.namep, "__ES") == 0) { outstr ("mov\tes,"); outregname(sourcereg); outnl(); return; } if (strcmp (target->name.namep, "__SS") == 0) { outstr ("mov\tss,"); outregname(sourcereg); outnl(); return; } if (strcmp (target->name.namep, "__FLAGS") == 0) { outstr ("push\tax"); outregname(sourcereg); outstr ("\npopf\n"); return; } } #endif outstore(); #ifdef I8088 if (target->storage == GLOBAL && (store_t) sourcereg & (AXREG | ALREG)) unbumplc(); outnnadr(target); outcomma(); #ifdef I80386 if (i386_32 && target->type->scalar & SHORT) { outshortregname(sourcereg); bumplc(); outnl(); } else #endif outnregname(sourcereg); #endif #ifdef MC6809 if ((store_t) sourcereg == YREG) bumplc(); outregname(sourcereg); outadr(target); #endif } } /*----------------------------------------------------------------------------- struc(element leaf, structure leaf) evaluates the expression structure.element -----------------------------------------------------------------------------*/ PUBLIC void struc(source, target) struct symstruct *source; struct symstruct *target; { address(target); if (source->offset.offi != 0 || source->level == OFFKLUDGELEVEL) { if (target->indcount != 0 || target->level == OFFKLUDGELEVEL) load(target, getindexreg()); target->offset.offi += source->offset.offi; } if (source->indcount == 0) target->type = source->type; else { target->type = pointype(source->type); /* lost by = */ indirec(target); } } PUBLIC void transfer(source, targreg) struct symstruct *source; store_pt targreg; { regtransfer(source->storage, targreg); source->storage = targreg; } dev86-0.16.21/bcc/glogcode.c000066400000000000000000000317521231050321700152750ustar00rootroot00000000000000/* glogcode.c - generate code for logical expressions for bcc */ /* Copyright (C) 1992 Bruce Evans */ #include "bcc.h" #include "condcode.h" #include "gencode.h" #include "reg.h" #include "scan.h" #include "sizes.h" #include "type.h" #define cc_signed(cc) ((cc) >= 4 && (cc) < 8) PRIVATE char oppcc[] = /* opposite condition codes LT --> GE etc */ /* EQ, NE, RA, RN, LT, GE, LE, GT, LO, HS, LS, HI, indices */ { NE, EQ, RN, RA, GE, LT, GT, LE, HS, LO, HI, LS, }; PRIVATE char reverscc[] = /* reverse condition codes LT --> GT etc */ { EQ, NE, RN, RA, GT, LE, GE, LT, HI, LS, HS, LO, }; PRIVATE char testcc[] = /* test condition codes LS --> EQ etc */ { EQ, NE, RA, RN, LT, GE, LE, GT, RN, RA, EQ, NE, }; PRIVATE char unsigncc[] = /* unsigned condition codes LT --> LO etc */ { EQ, NE, RA, RN, LO, HS, LS, HI, LO, HS, LS, HI, }; FORWARD void cmplocal P((struct symstruct *source, struct symstruct *target, ccode_t *pcondtrue)); #ifdef MC6809 FORWARD void cmporsub P((struct symstruct *target)); FORWARD bool_pt cmpsmallconst P((value_t intconst, struct symstruct *target, ccode_t *pcondtrue)); #endif FORWARD void comparecond P((struct nodestruct *exp, label_no truelab, label_no falselab, bool_pt nojump)); FORWARD void jumpcond P((struct nodestruct *exp, label_no truelab, label_no falselab, bool_pt nojump)); FORWARD void loadlogical P((struct symstruct *source, label_no falselab)); FORWARD void logandcond P((struct nodestruct *exp, label_no truelab, label_no falselab, bool_pt nojump)); FORWARD void logorcond P((struct nodestruct *exp, label_no truelab, label_no falselab, bool_pt nojump)); FORWARD void reduceconst P((struct symstruct *source)); FORWARD void test P((struct symstruct *target, ccode_t *pcondtrue)); FORWARD void testcond P((struct nodestruct *exp, label_no truelab, label_no falselab, bool_pt nojump)); PUBLIC void cmp(source, target, pcondtrue) struct symstruct *source; struct symstruct *target; ccode_t *pcondtrue; { label_no falselab; cmplocal(source, target, pcondtrue); #if 0 #ifdef I80386 if (i386_32) { if (*pcondtrue == LO) { getlabel(); getlabel(); outnop2str("sbb\teax,eax"); outnop1str("inc eax"); target->storage = BREG; target->type = ctype; return; } if (*pcondtrue == HS) { getlabel(); getlabel(); outnop2str("sbb\teax,eax"); outnop2str("neg eax"); target->storage = BREG; target->type = ctype; return; } } #endif #endif sbranch(oppcc[(int)*pcondtrue], falselab = getlabel()); loadlogical(target, falselab); } PRIVATE void cmplocal(source, target, pcondtrue) struct symstruct *source; struct symstruct *target; ccode_t *pcondtrue; { scalar_t sscalar; scalar_t tempscalar; scalar_t tscalar; reduceconst(source); reduceconst(target); sscalar = source->type->scalar; tscalar = target->type->scalar; if ((source->storage != CONSTANT && (target->storage == CONSTANT || (sscalar & CHAR && !(tscalar & CHAR)) || ((sscalar & CHAR || !(tscalar & CHAR)) && source->indcount == 0 && target->indcount != 0))) || (tscalar & DLONG && target->indcount != 0)) { swapsym(target, source); *pcondtrue = reverscc[(int)*pcondtrue]; tempscalar = sscalar; sscalar = tscalar; tscalar = tempscalar; } if ((sscalar & CHAR && tscalar & CHAR && (source->type != sctype || target->type != sctype)) || (sscalar | tscalar) & UNSIGNED || (source->type->constructor | target->type->constructor) & (ARRAY | POINTER)) *pcondtrue = unsigncc[(int)*pcondtrue]; if (source->type->scalar & DLONG) { longop(EQOP, source, target); return; } if (source->type->scalar & RSCALAR) { floatop(EQOP, source, target); return; } if (source->storage == CONSTANT) { if (sscalar & CHAR) { if (tscalar & CHAR) *pcondtrue = unsigncc[(int)*pcondtrue]; else { source->type = iscalartotype(sscalar); sscalar = source->type->scalar; } } if (source->offset.offv == 0) { test(target, pcondtrue); return; } #ifdef MC6809 if (cmpsmallconst(source->offset.offv, target, pcondtrue)) return; #endif } if (!(sscalar & CHAR) && tscalar & CHAR) { loadpres(target, source); extend(target); } #ifndef MC6809 # define posindependent 0 #endif if (source->indcount == 0 && source->storage != CONSTANT && (posindependent || source->storage != GLOBAL)) { loadpres(source, target); #ifdef MC6809 push(source); #endif } loadpres(target, source); #ifdef MC6809 cmporsub(target); #else outcmp(); #endif #ifdef I8088 if (source->storage == GLOBAL && source->indcount == 0 && !(target->storage & (AXREG | ALREG))) bumplc(); #endif movereg(source, target->storage); } #ifdef MC6809 PRIVATE void cmporsub(target) struct symstruct *target; { if (target->storage & ALLDATREGS) outsub(); else { outcmp(); if (target->storage != XREG) bumplc(); } } PRIVATE bool_pt cmpsmallconst(intconst, target, pcondtrue) value_t intconst; struct symstruct *target; ccode_t *pcondtrue; { store_pt targreg; if ((*pcondtrue == EQ || *pcondtrue == NE) && !(target->storage & ALLDATREGS) && !(target->type->scalar & CHAR) && isnegbyteoffset(intconst) && (reguse & (XREG | YREG)) != (XREG | YREG)) { targreg = XREG; if (reguse & XREG) targreg = YREG; if (target->indcount != 0) load(target, targreg); target->offset.offi -= (offset_T) intconst; loadreg(target, targreg); return TRUE; } return FALSE; } #endif PRIVATE void comparecond(exp, truelab, falselab, nojump) struct nodestruct *exp; label_no truelab; label_no falselab; bool_pt nojump; /* NB if nonzero, is ~0 so complement is 0 */ { ccode_t condtrue; store_t regmark; struct symstruct *source; offset_T spmark; struct symstruct *target; regmark = reguse; spmark = sp; bileaf(exp); target = exp->left.nodeptr->left.symptr; source = exp->right->left.symptr; /* exp->right != NULL since cond */ switch (exp->tag) { case GEOP: condtrue = GE; break; case GTOP: condtrue = GT; break; case LEOP: condtrue = LE; break; case EQOP: condtrue = EQ; break; case LTOP: condtrue = LT; break; case NEOP: condtrue = NE; break; } cmplocal(source, target, &condtrue); changesp(spmark, FALSE); reguse = regmark; if ((bool_t) nojump) lbranch(oppcc[(int)condtrue], falselab); else lbranch(condtrue, truelab); } PUBLIC void condop(exp) struct nodestruct *exp; { label_no exitlab; label_no falselab; struct nodestruct *falsenode; struct symstruct *falsesym; label_no truelab; struct nodestruct *truenode; struct symstruct *truesym; jumpcond(exp->left.nodeptr, truelab = getlabel(), falselab = getlabel(), ~0); deflabel(truelab); makeleaf(truenode = exp->right->left.nodeptr); loadany(truesym = truenode->left.symptr); if (truesym->storage & reguse) { /* This can happen if truesym was a reg variable. */ if (truesym->type->scalar & RSCALAR) /* XXX - always happens for non-386 with 2 regs vars assigned. */ bugerror("loaded float or double into used reg"); load(truesym, DREG); } falsenode = exp->right->right; if (/* falsenode->tag != LEAF || XXX */ truesym->type != falsenode->left.symptr->type) cast(truenode->nodetype == falsenode->nodetype ? truenode->nodetype : exp->nodetype, truesym); jump(exitlab = getlabel()); deflabel(falselab); makeleaf(falsenode); falsesym = falsenode->left.symptr; if (falsesym->type != truesym->type) cast(truesym->type, falsesym); load(falsesym, truesym->storage); deflabel(exitlab); exp->tag = LEAF; exp->left.symptr = truesym; } PRIVATE void jumpcond(exp, truelab, falselab, nojump) struct nodestruct *exp; label_no truelab; label_no falselab; bool_pt nojump; /* NB if nonzero, is ~0 so complement is 0 */ { switch (exp->tag) { case GEOP: case GTOP: case LEOP: case EQOP: case LTOP: case NEOP: comparecond(exp, truelab, falselab, nojump); break; case LOGANDOP: logandcond(exp, truelab, falselab, nojump); break; case LOGNOTOP: jumpcond(exp->left.nodeptr, falselab, truelab, ~nojump); break; case LOGOROP: logorcond(exp, truelab, falselab, nojump); break; default: testcond(exp, truelab, falselab, nojump); break; } } PUBLIC void jumpfalse(exp, label) struct nodestruct *exp; label_no label; { label_no truelab; jumpcond(exp, truelab = getlabel(), label, ~0); deflabel(truelab); } PUBLIC void jumptrue(exp, label) struct nodestruct *exp; label_no label; { label_no falselab; jumpcond(exp, label, falselab = getlabel(), 0); deflabel(falselab); } PRIVATE void loadlogical(source, falselab) struct symstruct *source; label_no falselab; { label_no exitlab; struct symstruct *target; target = constsym((value_t) TRUE); target->type = ctype; loadreg(target, DREG); sbranch(RA, exitlab = getlabel()); deflabel(falselab); target = constsym((value_t) FALSE); target->type = ctype; *source = *target; loadreg(source, DREG); outnlabel(exitlab); } PRIVATE void logandcond(exp, truelab, falselab, nojump) struct nodestruct *exp; label_no truelab; label_no falselab; bool_pt nojump; /* NB if nonzero, is ~0 so complement is 0 */ { label_no andlab; andlab = getlabel(); jumpcond(exp->left.nodeptr, andlab, falselab, ~0); deflabel(andlab); jumpcond(exp->right, truelab, falselab, nojump); } PUBLIC void logop(exp) struct nodestruct *exp; { label_no falselab; struct symstruct *target; label_no truelab; jumpcond(exp, truelab = getlabel(), falselab = getlabel(), ~0); deflabel(truelab); target = constsym((value_t) 0); /* anything, loadlogical makes B reg */ target->type = ctype; loadlogical(target, falselab); exp->tag = LEAF; exp->left.symptr = target; } PRIVATE void logorcond(exp, truelab, falselab, nojump) struct nodestruct *exp; label_no truelab; label_no falselab; bool_pt nojump; /* NB if nonzero, is ~0 so complement is 0 */ { label_no orlab; orlab = getlabel(); jumpcond(exp->left.nodeptr, truelab, orlab, 0); deflabel(orlab); jumpcond(exp->right, truelab, falselab, nojump); } PRIVATE void reduceconst(source) struct symstruct *source; { if (source->storage == CONSTANT && ischarconst(source->offset.offv) && (source->type->scalar & (CHAR | SHORT | INT | DLONG)) != DLONG) { if (source->type->scalar & UNSIGNED) source->type = uctype; else source->type = ctype; } } PRIVATE void test(target, pcondtrue) struct symstruct *target; ccode_t *pcondtrue; { #ifdef I8088 store_t targreg; #endif *pcondtrue = testcc[(int)*pcondtrue]; if (target->type->scalar & DLONG) { long1op(EQOP, target); return; } if (target->type->scalar & RSCALAR) { float1op(EQOP, target); return; } #ifdef I8088 if (target->indcount != 0 || (target->storage == LOCAL && target->offset.offi != sp)) load(target, DREG); if (target->storage == GLOBAL) load(target, getindexreg()); if (target->type->scalar & CHAR) load(target, DREG); targreg = target->storage; if (target->offset.offi != 0 && cc_signed(*pcondtrue)) load(target, targreg); #ifdef I80386 /* Extension was not done in exptree for the == 0 case, to allow * optimization here - which we don't do for shorts. (foo--) is * newfoo == -1 here and used to be missed. */ if (i386_32 && target->type->scalar & SHORT) extend(target); #endif if (target->offset.offi == 0) { outtest(); outregname(targreg); outcomma(); outnregname(targreg); return; } outcmp(); outimadj(-target->offset.offi, targreg); #endif #ifdef MC6809 if (target->indcount != 0 || target->storage == LOCAL && target->offset.offi != sp) { load(target, DREG); return; } if (cmpsmallconst(0, target, pcondtrue)) return; if (target->storage == GLOBAL) load(target, getindexreg()); if (target->type->scalar & CHAR) load(target, DREG); if (target->offset.offi != 0 && cc_signed(*pcondtrue)) load(target, target->storage); if (target->type->scalar & CHAR) { if (target->offset.offi == 0) { outtest(); outnregname(BREG); return; } outcmp(); outimadj(-target->offset.offi, BREG); } else { cmporsub(target); outimadj(-target->offset.offi, target->storage); } #endif } /* test expression and jump depending on NE/EQ */ PRIVATE void testcond(exp, truelab, falselab, nojump) struct nodestruct *exp; label_no truelab; label_no falselab; bool_pt nojump; /* NB if nonzero, is ~0 so complement is 0 */ { ccode_t condtrue; struct symstruct *source; makeleaf(exp); source = exp->left.symptr; reduceconst(source); if (source->storage != CONSTANT) { condtrue = NE; test(source, &condtrue); if ((bool_t) nojump) lbranch(oppcc[(int)condtrue], falselab); else lbranch(condtrue, truelab); } else if (source->offset.offi == 0) { if ((bool_t) nojump) jump(falselab); } else if (!(bool_t) nojump) jump(truelab); } dev86-0.16.21/bcc/hardop.c000066400000000000000000000251231231050321700147620ustar00rootroot00000000000000/* hardop.c - hardware operations for bcc */ /* Copyright (C) 1992 Bruce Evans */ #include "bcc.h" #include "byteord.h" #include "condcode.h" #include "gencode.h" #include "reg.h" #include "sc.h" #include "scan.h" #include "sizes.h" #include "type.h" FORWARD void sub1 P((struct symstruct *source, struct symstruct *target)); PUBLIC void add(source, target) struct symstruct *source; struct symstruct *target; { scalar_t sscalar; if (source->indcount == 0 && source->storage != CONSTANT && (target->indcount != 0 || target->storage & ALLDATREGS)) swapsym(target, source); if ((sscalar = source->type->scalar) & DLONG) { longop(ADDOP, source, target); return; } if (sscalar & RSCALAR) { floatop(ADDOP, source, target); return; } if (source->storage == CONSTANT) { extend(target); if (target->indcount != 0 || target->storage & reguse) loadany(target); target->offset.offi += (offset_T) source->offset.offv; } else if (source->indcount == 0) { /* target is also direct */ sscalar |= target->type->scalar; /* remember if unsigned/long */ target->type = pctype; /* fake to use indexadr() */ indexadr(source, target); } else { /* source is indirect and not DREG */ extend(target); load(target, DREG); outadd(); movereg(source, DREG); if (source->type->scalar & CHAR) adc0(); } target->type = iscalartotype(target->type->scalar | sscalar); } PUBLIC void incdec(op, source) op_pt op; struct symstruct *source; { offset_T bump; bool_t postflag; store_t regmark; struct symstruct *target; struct symstruct targ; #ifdef MC6809 store_pt targreg; #endif *(target = &targ) = *source; bump = 1; if (targ.type->constructor & POINTER) bump = targ.type->nexttype->typesize; if (op == PREDECOP || op == POSTDECOP) bump = -bump; postflag = FALSE; if (op == POSTDECOP || op == POSTINCOP) postflag = TRUE; reguse |= targ.storage; if (targ.type->scalar & DLONG) /* cannot be direct */ { if (postflag) { regmark = reguse; if (((reguse |= OPREG) & allindregs) == allindregs) { saveopreg(); load(source, OPREG); pushreg(source->storage); restoreopreg(); } else { loadany(source); reguse = regmark | source->storage; saveopreg(); } } else saveopreg(); pointat(target); switch (op) { case PREDECOP: case POSTDECOP: call("ldec"); break; case PREINCOP: case POSTINCOP: call("linc"); break; } outlongendian(); restoreopreg(); if (postflag && source->storage == OPREG) poplist(OPREG); return; } if (targ.type->scalar & RSCALAR) { saveopreg(); pointat(target); switch (op) { case PREDECOP: call("Fpredec"); break; case PREINCOP: call("Fpreinc"); break; case POSTDECOP: call("Fpostdec"); break; case POSTINCOP: call("Fpostinc"); break; } outntypechar(targ.type); restoreopreg(); if (postflag) { justpushed(source); source->type = targ.type; } return; } loadany(source); #ifdef MC6809 if (postflag && targ.flags != REGVAR && !(source->storage & ALLDATREGS) && ((reguse |= source->storage) & allindregs) != allindregs) { targreg = getindexreg(); outlea(); outregname(targreg); outtab(); outshex(bump); outncregname(source->storage); } else { addconst(bump, targreg = source->storage); if (postflag) source->offset.offi = -bump; } storereg(targreg, target); target->storage = targreg; target->offset.offi = 0; #else addconst(bump, source->storage); if (postflag) source->offset.offi = -bump; storereg(source->storage, target); target->storage = source->storage; target->offset.offi = 0; #endif } PUBLIC void neg(target) struct symstruct *target; { scalar_t scalar; struct symstruct *source; if ((scalar = target->type->scalar) & DLONG) long1op(NEGOP, target); else if (scalar & RSCALAR) float1op(NEGOP, target); else { if (scalar & SHORT) extend(target); if (!(target->storage & ALLDATREGS)) { /* load 0, subtract is shorter than load, negate */ /* if no hardware integer negate; about the same if there is */ sub1(target, source = constsym((value_t) 0)); *target = *source; } else { load(target, DREG); negreg(target->storage); target->storage = DREG; } target->type = iscalartotype(scalar); } } PUBLIC void not(target) struct symstruct *target; { if (target->type->scalar & DLONG) long1op(NOTOP, target); else { extend(target); load(target, DREG); comDreg(); } } /* 1-byte ops like AND acting on integers (not both constant) */ PUBLIC void op1(op, source, target) op_pt op; struct symstruct *source; struct symstruct *target; { char *opstr; #ifdef OP1 # if MAXINDIRECT > 1 indn_t indcount; # endif #endif bool_t resultchar; scalar_t resultscalar; scalar_t sscalar; scalar_t tscalar; if ((sscalar = source->type->scalar) & DLONG) { longop(op, source, target); return; } /* Emergency fix. The types of constants should be reduced here and in * other low-level routines anyway, and not in exptree.c and table.c, * and for the 80386 and maybe the 8086 they would be better not * reduced. */ if (source->storage == CONSTANT && ischarconst(source->offset.offv)) { if (sscalar & UNSIGNED) source->type = uctype; else source->type = ctype; sscalar = source->type->scalar; } tscalar = target->type->scalar; if (target->storage == CONSTANT && ischarconst(target->offset.offv)) { if (sscalar & UNSIGNED) target->type = uctype; else target->type = ctype; tscalar = target->type->scalar; } resultscalar = sscalar | tscalar; if (op != ANDOP) resultchar = sscalar & tscalar & CHAR; else if ((resultchar = (sscalar | tscalar) & CHAR) != 0 && source->storage == CONSTANT) { source->offset.offv &= CHMASKTO; if (sscalar & UNSIGNED) source->type = uctype; else source->type = ctype; sscalar = source->type->scalar; } if (target->indcount != 0 && ((tscalar & CHAR && !(sscalar & CHAR) && op != ANDOP) || (source->indcount == 0 && source->storage != CONSTANT))) { swapsym(target, source); sscalar = tscalar; tscalar = target->type->scalar; } if (source->indcount == 0 && source->storage != CONSTANT) { loadpres(source, target); push(source); } #if MAXINDIRECT > 1 else if (source->indcount >= MAXINDIRECT && !(sscalar & CHAR)) { address(source); if (!(target->storage & ALLDATREGS)) preserve(target); load(source, getindexreg()); indirec(source); } #endif if (!(tscalar & CHAR) && op == ANDOP && sscalar & CHAR && target->indcount == 1) cast(ctype, target); if (!(target->storage & ALLDATREGS) || target->indcount != 0) pres2(target, source); load(target, DREG); opstr = opstring(op); if (source->storage == CONSTANT && op == ANDOP) andconst((offset_T) source->offset.offv); #ifdef OP1 else if (tscalar & CHAR && !(sscalar & CHAR) && op != ANDOP) outload(); else outop2str(opstr); #else /* OP1 */ else { if (tscalar & CHAR && !(sscalar & CHAR) && op != ANDOP) extend(target); outop2str(opstr); } #endif /* OP1 */ if (source->storage == CONSTANT) { if (op != ANDOP) { #ifdef OP1 if (!(sscalar & CHAR)) { outhiaccum(); outncimmadr((offset_T) ((uoffset_T) source->offset.offv >> (INT16BITSTO - CHBITSTO))); outop2str(opstr); } outregname(BREG); outncimmadr((offset_T) source->offset.offv & CHMASKTO); #else /* OP1 */ if (!(sscalar & CHAR)) { outregname(DREG); bumplc(); } else outregname(BREG); # ifdef I80386 if (i386_32 && !(sscalar & CHAR)) bumplc2(); # endif outncimmadr((offset_T) source->offset.offv); #endif /* OP1 */ } } else if (sscalar & CHAR) { outregname(BREG); outopsep(); outadr(source); } else { #ifdef MC6809 source->type = ctype; /* fool outadr to avoid ,S++ */ #endif #ifdef OP1 if (!(tscalar & CHAR) || op != ANDOP) { outhiaccum(); # if MAXINDIRECT > 1 indcount = source->indcount; # endif outopsep(); # if INT_BIG_ENDIAN == 0 ++source->offset.offi; # endif outadr(source); # if INT_BIG_ENDIAN == 0 --source->offset.offi; # endif # if MAXINDIRECT > 1 source->indcount = indcount; # else source->indcount = 1; # endif outop2str(opstr); } outregname(BREG); outopsep(); # if INT_BIG_ENDIAN ++source->offset.offi; # endif outadr(source); } #else /* OP1 */ if (!(tscalar & CHAR) || op != ANDOP) outregname(DREG); else outregname(BREG); outopsep(); outadr(source); } #endif /* OP1 */ if (resultchar) { target->storage = BREG; if (resultscalar & UNSIGNED) target->type = uctype; else target->type = ctype; } else { target->storage = DREG; target->type = iscalartotype(resultscalar); } } PUBLIC void ptrsub(source, target) struct symstruct *source; struct symstruct *target; { label_no exitlab; uoffset_T factor; label_no usignlab; if (source->indcount == 0 && source->storage != CONSTANT) { loadpres(source, target); push(source); } if (target->indcount == 0) { pres2(target, source); load(target, DREG); } factor = target->type->nexttype->typesize; source->type = target->type = itype; sub1(source, target); if (factor != 1) { pushlist(CCREG); sbranch(HS, usignlab = getlabel()); /* HS == no carry */ negDreg(); outnlabel(usignlab); target->type = uitype; softop(DIVOP, constsym((value_t) factor), target); target->type = itype; poplist(CCREG); sbranch(HS, exitlab = getlabel()); negDreg(); outnlabel(exitlab); } } PUBLIC void sub(source, target) struct symstruct *source; struct symstruct *target; { scalar_t sscalar; if ((sscalar = source->type->scalar) & DLONG) { longop(SUBOP, source, target); return; } if (sscalar & RSCALAR) { floatop(SUBOP, source, target); return; } if (source->storage == CONSTANT) { extend(target); if (target->indcount != 0 || target->storage & reguse) loadany(target); target->offset.offi -= (offset_T) source->offset.offv; } else sub1(source, target); target->type = iscalartotype(target->type->scalar | sscalar); } PRIVATE void sub1(source, target) struct symstruct *source; struct symstruct *target; { if (source->storage == CONSTANT) source->type = itype; else if (source->indcount == 0) { loadpres(source, target); push(source); } extend(target); load(target, DREG); outsub(); movereg(source, DREG); if (source->type->scalar & CHAR) sbc0(); } dev86-0.16.21/bcc/hashcmd.c000066400000000000000000000070121231050321700151110ustar00rootroot00000000000000 /* decode remaining preprocessor lines, minimal version. */ /* Copyright (C) GPL V2, derived from preproc.c by RDB. */ #include "bcc.h" #include "input.h" #include "os.h" #include "output.h" #include "parse.h" #include "sc.h" #include "scan.h" #include "table.h" #include "type.h" #ifndef BUILTIN_CPP FORWARD void control P((void)); FORWARD void asmcontrol P((void)); FORWARD void warningcntl P((void)); FORWARD void errorcntl P((void)); /* docontrol() - process control statement, #line and #asm only. */ PUBLIC void docontrol() { control(); skipline(); return; } /* control() - select and switch to control statement */ PRIVATE void control() { char sname[NAMESIZE + 1]; sym_t ctlcase; struct symstruct *symptr; if (ctext && asmmode) { comment(); outudec(input.linenumber); outbyte(' '); outline(lineptr); } sname[0] = '#'; /* prepare for bad control */ sname[1] = 0; if (blanksident()) strcat(sname, gsname); if (sname[1] == 0 && ch == EOL) return; if (SYMOFCHAR(ch) == INTCONST) { linecontol(); return; } if ((symptr = findlorg(sname)) == NULL) { error(" bad control"); return; } ctlcase = symptr->offset.offsym; switch (ctlcase) { case ASMCNTL: if (asmmode) error(" bad control"); else asmcontrol(); break; case ENDASMCNTL: if (!asmmode) error(" bad control"); asmmode = FALSE; break; case LINECNTL: { linecontol(); break; } case WARNINGCNTL: warningcntl(); break; case ERRORCNTL: errorcntl(); break; default: error(" bad control"); break; } } /* asmcontrol() - process #asm */ PRIVATE void asmcontrol() { #ifdef ASM_BARE char treasure; /* to save at least one leading blank */ #endif asmmode = TRUE; if (expect_statement) return; outnstr("!BCC_ASM"); dumplocs(); #ifndef ASM_BARE cppscan(1); #else while (TRUE) { skipline(); skipeol(); if (eofile) { eofin("#asm"); break; } if (SYMOFCHAR(ch) == SPECIALCHAR) specialchar(); treasure = 0; if (SYMOFCHAR(ch) == WHITESPACE) treasure = ch; blanks(); if (ch == '#') { if (ctext) { register char *lptr; comment(); if (treasure != 0) outbyte(treasure); lptr = lineptr; while (*lptr++ != EOL) /* XXX - handle COEOL too */ outbyte(ch); outnl(); } gch1(); docontrol(); if (!asmmode) break; } else { if (treasure != 0) outbyte(treasure); while (ch != EOL) /* XXX - handle COEOL too */ { outbyte(ch); gch1(); } outnl(); } } #endif outnstr("!BCC_ENDASM"); } /* warningcntl() - process #warning */ PRIVATE void warningcntl() { char estr[256], *ep = estr; *ep++ = '%'; *ep++ = 'w'; while( ch != EOL ) { if (ep < estr+sizeof(estr)-2 ) *ep++ = ch; gch1(); } *ep = 0; error(estr); } /* errorcntl() - process #error */ PRIVATE void errorcntl() { char estr[256], *ep = estr; while( ch != EOL ) { if (ep < estr+sizeof(estr)-2 ) *ep++ = ch; gch1(); } *ep = 0; error(estr); } /* skipline() - skip rest of line */ PUBLIC void skipline() { while (TRUE) { blanks(); if (ch == EOL) return; if (ch == '\\') { gch1(); if (ch == EOL) /* XXX - I think blanks() eats \EOL */ return; gch1(); /* XXX - escape() better? */ } else if (ch == '"' || ch == '\'') { stringorcharconst(); charptr = constant.value.s; } else gch1(); } } #endif dev86-0.16.21/bcc/input.c000066400000000000000000000451201231050321700146430ustar00rootroot00000000000000/* input.c - input for bcc */ /* Copyright (C) 1992 Bruce Evans */ #define ARBITRARY_BACKSLASH_NEWLINES_NOT #define INSERT_BACKSLASH_NEWLINES_NOT #include "bcc.h" #include "gencode.h" #include "output.h" #include "os.h" #include "sc.h" #include "scan.h" #include "table.h" #ifndef VERY_SMALL_MEMORY #include "parse.h" #endif #undef EXTERN #define EXTERN #include "input.h" #define INBUFSIZE 2048 #define NO_EOFHACK struct fbufstruct /* file buffer structure */ { struct fcbstruct fcb; /* status after opening an include sub-file */ char *fname; /* file name */ bool_t fname_malloced; /* nonzero if fname was malloced */ char pushback[3]; /* allows pushback to 2 before start of fbuf * XXX 3 chars before? * XXX should do everything in fbuf */ char fbuf[INBUFSIZE + 1]; /* buffer to read into */ }; #ifdef BUILTIN_CPP struct inclist /* list of include file directories */ { char *incdirname; struct inclist *incnext; }; PRIVATE char filemacro[] = "__FILE__"; PRIVATE struct inclist incabsolute; /* dummy list for absolute names */ /* depends on zero (NULL) init */ PRIVATE struct inclist incfirst; /* begin include searches here for "" */ /* at next in list for <> */ /* -I directories are put in list */ /* between first and last */ PRIVATE struct inclist inclast = { #ifdef DEFAULT_INCLUDE_DIR DEFAULT_INCLUDE_DIR, #endif NULL, }; PRIVATE fastin_t inclevel; /* nest level of include files */ /* depends on zero init */ #endif PRIVATE struct fbufstruct *inputbuf; /* current input file buffer */ /* its fcb only to date in includes */ /* depends on zero (NULL) init */ PRIVATE bool_t suppress_line_numbers; #ifdef ARBITRARY_BACKSLASH_NEWLINES FORWARD void backslash P((void)); #endif #ifdef BUILTIN_CPP FORWARD void definefile P((char *fname)); FORWARD void leaveinclude P((void)); #endif FORWARD void inputinit P((char *fname, fd_t fd)); FORWARD void usage P((void)); #ifdef ARBITRARY_BACKSLASH_NEWLINES PRIVATE void backslash() { static unsigned nbackslash; if (nbackslash != 0) --nbackslash; more: ++nbackslash; while (*(lineptr + 1) == '\\') { ++nbackslash; ++lineptr; } if (*(lineptr + 1) != EOL) { if (--nbackslash != 0) *--lineptr = '\\'; /* force look at current backslash again */ return; } ch = *++lineptr; more1: if (!eofile && lineptr >= input.limit) skipeol(); if (ch == EOL) { --nbackslash; if (eofile) eofin("backslash-newline"); else { skipeol(); if (ch == EOL && !eofile && lineptr >= input.limit) skipeol(); #ifdef COEOL /* XXX - this should go through specialchar() */ if (ch == COEOL) { ch = *++lineptr; if (ch == EOL && !eofile && lineptr >= input.limit) skipeol(); } #endif } if (ch == '\\') goto more; if (nbackslash != 0 && ch == EOL && !eofile) goto more1; if (nbackslash != 0) { ch = *--lineptr = '\\'; if (--nbackslash != 0) ch = *--lineptr = '\\'; } return; } if (ch == '\\') goto more; if (ch == EOL && !eofile) goto more1; ch = *--lineptr = '\\'; /* pushback */ if (--nbackslash != 0) ch = *--lineptr = '\\'; } #endif PUBLIC void closein() { #ifdef FAKE_INBUFSIZE_1 fclose(input.fp); #else close(input.fd); #endif #ifdef BUILTIN_CPP while (inclevel != 0) leaveinclude(); #endif } #ifdef BUILTIN_CPP PRIVATE void definefile(fname) char *fname; { char *def; def = ourmalloc(sizeof filemacro - 1 + 2 + strlen(fname) + 1 + 1); strcpy(def, filemacro); strcat(def, "=\""); strcat(def, fname); strcat(def, "\""); definestring(def); ourfree(def); } #endif PUBLIC void errorloc() { register struct fbufstruct *infbuf; if ((infbuf = inputbuf) == NULL) return; outstr(infbuf->fname); outbyte(':'); if (eofile) outstr("eof"); else { outudec(input.linenumber); outbyte('.'); #ifdef BUILTIN_CPP if (maclevel == 0) outudec((unsigned) (lineptr - inputbuf->fbuf) - input.lineoffset); else { outudec((unsigned) (savedlineptr() - inputbuf->fbuf) - input.lineoffset); outstr(" (macro level "); outudec((unsigned) maclevel); outbyte(')'); } #else outudec((unsigned) (lineptr - inputbuf->fbuf) - input.lineoffset); #endif } infbuf->fcb.includer = input.includer; while ((infbuf = infbuf->fcb.includer) != NULL) { outstr(" (from "); outstr(infbuf->fname); outbyte(':'); outudec(infbuf->fcb.linenumber); outbyte(')'); } outstr(": "); } /* gch1() - get next char, advance ptr (only works on current line) */ PUBLIC void gch1() { if (SYMOFCHAR(ch = *++lineptr) != SPECIALCHAR) return; specialchar(); } #ifdef BUILTIN_CPP /* process #include */ PUBLIC void include() { char *dirnameptr; char *dirnamend; unsigned dirnamelen; fd_t fd; char *fnameptr; char *fullnameptr; struct inclist *incptr; char terminator; while (blanksident()) { if ((gsymptr = findlorg(gsname)) == NULL || gsymptr->flags != DEFINITION) break; entermac(); } if ((terminator = ch) == '<') terminator = '>'; else if (terminator != '"') { error("bad file name"); return; } gch1(); fnameptr = charptr; while (TRUE) { if (ch == EOL) /* no escapes in file names */ break; if (ch == terminator) { gch1(); blanks(); break; } if (charptr >= chartop) fnameptr = growobject(fnameptr, 1); #ifdef TS ++ts_n_filename; ++ts_s_filename; ++ts_s_filename_tot; #endif *charptr++ = ch; gch1(); } if (charptr >= chartop) fnameptr = growobject(fnameptr, 1); #ifdef TS ++ts_n_filename_term; ++ts_s_filename_term; ++ts_s_filename_tot; #endif *charptr++ = 0; dirnamend = NULL; if (isabspath(fnameptr, &ch)) incptr = &incabsolute; else { incptr = &incfirst; if (terminator == '>') incptr = incptr->incnext; else { dirnameptr = inputbuf->fname; if ((dirnamend = strrchr(dirnameptr, DIRCHAR)) == NULL) incptr->incdirname = NULL; else { *dirnamend = 0; incptr->incdirname = dirnameptr; } } } do { if (incptr->incdirname == NULL) { fullnameptr = ourmalloc(strlen(fnameptr) + 1); #ifdef TS ++ts_n_pathname; ts_s_pathname += strlen(fnameptr) + 1; ts_s_pathname_tot += strlen(fnameptr) + 1; #endif strcpy(fullnameptr, fnameptr); } else { dirnamelen = strlen(incptr->incdirname); fullnameptr = ourmalloc(dirnamelen + (int) (charptr - fnameptr) + 2); /* 2 extra for null and maybe DIRCHAR */ #ifdef TS ++ts_n_pathname; ts_s_pathname += dirnamelen + (charptr - fnameptr) + 2; ts_s_pathname_tot += dirnamelen + (charptr - fnameptr) + 2; #endif dirnameptr = fullnameptr + dirnamelen; strcpy(fullnameptr, incptr->incdirname); if (*fullnameptr != 0 && *(dirnameptr - 1) != DIRCHAR) strcat(fullnameptr, DIRSTRING); strcat(fullnameptr, fnameptr); if (dirnamend != NULL) { *dirnamend = DIRCHAR; dirnamend = NULL; } } fd = open(fullnameptr, 0); if (fd >= 0) { #ifdef TS ts_s_filename_tot -= charptr - fnameptr; #endif charptr = fnameptr; input.lineptr = lineptr; inputbuf->fcb = input; ++inclevel; /* XXX - will run out of memory before overflow */ inputinit(fullnameptr, fd); inputbuf->fname_malloced = TRUE; return; } #ifdef TS ts_s_pathname_tot -= strlen(fullnameptr) + 1; #endif ourfree(fullnameptr); } while ((incptr = incptr->incnext) != NULL); fullnameptr = ourmalloc(strlen(fnameptr) + 40); strcpy(fullnameptr, "cannot find include file "); strcat(fullnameptr, fnameptr); error(fullnameptr); ourfree(fullnameptr); #ifdef TS ts_s_filename_tot -= charptr - fnameptr; #endif charptr = fnameptr; } #endif /* initialise current input file */ PRIVATE void inputinit(fname, fd) char *fname; fd_t fd; { register struct fbufstruct *newinputbuf; /* don't allocate after saying input.includer = inputbuf (to save a reg) * or an error in the alloc would cycle trying to print the include list */ newinputbuf = (struct fbufstruct *) ourmalloc(sizeof *inputbuf); #ifdef TS ++ts_n_inputbuf; ts_s_inputbuf += sizeof *inputbuf; ts_s_inputbuf_tot += sizeof *inputbuf; #endif input.fd = fd; #ifdef FAKE_INBUFSIZE_1 input.fp = fdopen(fd, "r"); #endif input.linenumber = 0; input.lineoffset = 0; input.includer = inputbuf; inputbuf = newinputbuf; newinputbuf->fname = fname; newinputbuf->fname_malloced = FALSE; #ifdef BUILTIN_CPP undefinestring(filemacro); definefile(fname); if (orig_cppmode && !suppress_line_numbers) outcpplinenumber(1, fname, input.includer == NULL ? "" : " 1"); #endif *(input.limit = newinputbuf->fbuf) = EOL; /* dummy line so processing can start with skipline() */ ch = *(lineptr = newinputbuf->fbuf - 1) = EOL; } PUBLIC void linecontol() { char linename[256]; char * ptr; int i=0; blanks(); input.linenumber = atoi(lineptr)-1; while( SYMOFCHAR(ch) == INTCONST ) gch1(); blanks(); if( ch != '"' ) return; for(ptr=lineptr+1; *ptr && *ptr != EOL && *ptr != '"' && ifname_malloced) { #ifdef TS ts_s_pathname_tot -= strlen(inputbuf->fname) + 1; #endif ourfree(inputbuf->fname); } inputbuf->fname_malloced = TRUE; ptr = ourmalloc(strlen(linename)+1); strcpy(ptr, linename); inputbuf->fname = ptr; ptr=lineptr; #ifdef BUILTIN_CPP undefinestring(filemacro); definefile(inputbuf->fname); #endif ch = *(lineptr = ptr); } #ifdef BUILTIN_CPP /* switch from include file to file which included it */ PRIVATE void leaveinclude() { --inclevel; if (inputbuf->fname_malloced) { #ifdef TS ts_s_pathname_tot -= strlen(inputbuf->fname) + 1; #endif ourfree(inputbuf->fname); } #ifdef TS ts_s_inputbuf_tot -= sizeof *inputbuf; #endif ourfree((char *) inputbuf); #ifndef NO_EOFHACK if(input.fd>=0) #endif close(input.fd); #ifdef FAKE_INBUFSIZE_1 fclose(input.fp); #endif inputbuf = input.includer; input = inputbuf->fcb; undefinestring(filemacro); definefile(inputbuf->fname); ch = *(lineptr = input.lineptr); skipline(); if (orig_cppmode && !suppress_line_numbers) outcpplinenumber(input.linenumber, inputbuf->fname, " 2"); } #endif /* open input and output files and get options */ PUBLIC void openio(argc, argv) int argc; char *argv[]; { register char *arg; int argn; fd_t fd; char *fname; #ifdef BUILTIN_CPP struct inclist *incnew; struct inclist *incptr; #endif bool_t flag[128]; #if 0 lineptr = "\n"; /* empty line in case error message */ #endif fd = 0; /* standard input */ memset(flag, 0, sizeof flag); #ifdef I80386 flag['3'] = sizeof (int) >= 4; #endif fname = "stdin"; #ifdef BUILTIN_CPP (incptr = &incfirst)->incnext = &inclast; #endif initout(); for (argn = 1; argn < argc; ++argn) { arg = argv[argn]; if (*arg != '-') { if (fd != 0) fatalerror("more than one input file"); fname = arg; if ((fd = open(arg, 0)) < 0) fatalerror("cannot open input"); } else switch (arg[1]) { #ifdef I8088 case '0': /* generate 16-bit code */ #endif #ifdef I80386 case '3': /* generate 32-bit code */ #endif case 'c': /* caller saves */ #ifdef DBNODE case 'd': /* print debugging information in asm output */ #endif #ifdef BUILTIN_CPP case 'E': /* acting as cpp */ #endif case 'f': /* pass first argument in register */ #ifdef DYNAMIC_LONG_ORDER case 'l': /* long big-endian */ #endif case 'P': /* if acting as cpp, suppress line numbers */ #ifdef POSINDEPENDENT case 'p': /* generate almost-position-independent code */ #endif case 't': /* print source code in asm output */ case 'w': /* watch location counter */ #ifndef VERY_SMALL_MEMORY case '7': /* accept ancient K&R code */ #endif case 'O': /* Optimisation. */ if (arg[2] == 0) flag[(int)arg[1]] = TRUE; else if (arg[2] == '-' && arg[3] == 0) flag[(int)arg[1]] = FALSE; else usage(); if (arg[1] == '0') /* flag 0 is negative logic flag 3 */ flag['3'] = TRUE + FALSE - flag['0']; break; #ifdef BUILTIN_CPP case 'D': definestring(arg + 2); break; case 'I': (incnew = (struct inclist *) ourmalloc(sizeof *incnew)) ->incdirname = arg + 2; #ifdef TS ++ts_n_includelist; ts_s_includelist += sizeof *incnew; #endif incnew->incnext = incptr->incnext; incptr = incptr->incnext = incnew; break; case 'U': undefinestring(arg + 2); break; #endif case 'o': if (arg[2] != 0 || ++argn >= argc) usage(); openout(argv[argn]); break; default: usage(); break; } } #ifdef BUILTIN_CPP #ifdef I8088 #ifdef I80386 if (flag['3']) { i386_32 = TRUE; definestring("__AS386_32__"); definestring("__i386__"); } else #endif { definestring("__AS386_16__"); definestring("__8086__"); } #endif #ifdef MC6809 definestring("__AS09__"); #endif if (flag['c']) { callersaves = TRUE; definestring("__CALLER_SAVES__"); } #ifdef DBNODE dbnodeon = flag['d']; #endif orig_cppmode = cppmode = flag['E']; if (flag['f']) { arg1inreg = TRUE; #ifdef I8088 definestring("__FIRST_ARG_IN_AX__"); #endif #ifdef MC6808 definestring("__FIRST_ARG_IN_X__"); #endif } arg1op = arg1inreg ? ROOTLISTOP : LISTOP; #ifdef DYNAMIC_LONG_ORDER if (flag['l']) { long_big_endian = TRUE; definestring("__LONG_BIG_ENDIAN__"); } #endif suppress_line_numbers = flag['P']; #ifdef POSINDEPENDENT if (flag['p']) { posindependent = TRUE; definestring("__POS_INDEPENDENT__"); } #endif #ifndef VERY_SMALL_MEMORY if (flag['7']) { ancient = TRUE; definestring("__ANCIENT__"); } #endif if (flag['O']) { optimise = TRUE; definestring("__OPTIMISED__"); } #ifdef NOFLOAT definestring("__HAS_NO_FLOATS__"); #endif #else /* !BUILTIN_CPP */ #ifdef I80386 if (flag['3']) i386_32 = TRUE; #endif if (flag['c']) callersaves = TRUE; #ifdef DBNODE dbnodeon = flag['d']; #endif if (flag['f']) arg1inreg = TRUE; arg1op = arg1inreg ? ROOTLISTOP : LISTOP; #ifdef DYNAMIC_LONG_ORDER if (flag['l']) long_big_endian = TRUE; #endif suppress_line_numbers = flag['P']; #ifdef POSINDEPENDENT if (flag['p']) posindependent = TRUE; #endif if (flag['O']) optimise = TRUE; #endif ctext = flag['t']; #ifdef DBNODE if (ctext) dbnodeon = 1; #endif watchlc = flag['w']; setoutbufs(); inputinit(fname, fd); } /* advance over EOL sentinel to new line */ PUBLIC void skipeol() { #ifdef FAKE_INBUFSIZE_1 static int ich; #endif #ifdef INSERT_BACKSLASH_NEWLINES static int bs_state; static bool_t skip_printing_nl; #endif int nread; debug(7, "skipeol %s:%d", inputbuf->fname, input.linenumber); if (eofile) return; if (lineptr < input.limit) { ++input.linenumber; ch = *++lineptr; if (ctext && !asmmode) { comment(); outudec(input.linenumber); outbyte(' '); outline(lineptr); } #ifdef BUILTIN_CPP #ifndef ASM_BARE if (!virtual_nl && (orig_cppmode || asmmode)) #else if (orig_cppmode && !asmmode) #endif #ifdef INSERT_BACKSLASH_NEWLINES if (!skip_printing_nl) #endif outbyte('\n'); #else /* !BUILTIN_CPP */ if (asmmode) #ifdef INSERT_BACKSLASH_NEWLINES if (!skip_printing_nl) #endif outbyte('\n'); #endif #ifdef INSERT_BACKSLASH_NEWLINES if (bs_state == 1 && *(lineptr - 1) == EOL) #endif input.lineoffset = (int) (lineptr - inputbuf->fbuf); return; } input.lineoffset -= (int) (lineptr - inputbuf->fbuf); #ifdef FAKE_INBUFSIZE_1 lineptr = inputbuf->fbuf; #ifdef INSERT_BACKSLASH_NEWLINES switch (bs_state) { case0: case 0: bs_state = nread = (ich = getc(input.fp)) == EOF ? 0 : 1; skip_printing_nl = FALSE; break; case 1: if (ich == '\\') goto case0; /* avoid chance of splitting \EOL */ ich = '\\'; nread = 1; bs_state = 2; ++input.lineoffset; break; case 2: ich = EOL; nread = 1; bs_state = 0; skip_printing_nl = TRUE; ++input.lineoffset; --input.linenumber; break; } #else nread = (ich = getc(input.fp)) == EOF ? 0 : 1; #endif *lineptr = ich; #else #ifndef NO_EOFHACK if(input.fd<0) nread=0; else { #endif nread = read(input.fd, lineptr = inputbuf->fbuf, INBUFSIZE); #ifndef NO_EOFHACK #ifdef BUILTIN_CPP if( nread == 0 && inclevel > 0 ) { close(input.fd); input.fd = -1; memcpy(inputbuf->fbuf, "\n", 1); nread = 1; } #endif } #endif #endif if (nread < 0) fatalerror("input error"); *(input.limit = lineptr + nread) = EOL; ch = *lineptr; if (nread == 0) { #ifdef BUILTIN_CPP if (inclevel == 0) { eofile = TRUE; checknotinif(); } else { leaveinclude(); skipeol(); } #else eofile = TRUE; #endif return; } if (ctext && !asmmode) { comment(); outudec(input.linenumber); outbyte(' '); outline(lineptr); } } PUBLIC void specialchar() { #ifdef BUILTIN_CPP if (maclevel != 0) { if (ch == EOL) /* it might also be backslash or COEOL */ leavemac(); if (ch != EOL) return; } #endif more: #ifdef ARBITRARY_BACKSLASH_NEWLINES if (ch == '\\') backslash(); #endif if (!eofile && lineptr >= input.limit) { skipeol(); #ifdef ARBITRARY_BACKSLASH_NEWLINES if (ch == '\\') backslash(); #endif } #ifndef ARBITRARY_BACKSLASH_NEWLINES if (ch == '\\') { if (*(lineptr + 1) == EOL) { if (lineptr + 1 >= input.limit) { ++lineptr; skipeol(); ch = *--lineptr = '\\'; /* pushback */ } if (*(lineptr + 1) == EOL) { if (eofile) eofin("backslash-newline"); else { ++lineptr; skipeol(); if (SYMOFCHAR(ch) == SPECIALCHAR) { #ifdef COEOL if (ch != COEOL || SYMOFCHAR(ch = *++lineptr) == SPECIALCHAR) #endif goto more; } } } } #endif } #ifdef COEOL if (ch == EOL && !eofile) { if (*(lineptr + 1) == EOL && lineptr + 1 >= input.limit) { ++lineptr; skipeol(); /* refill buffer */ ch = *--lineptr = EOL; /* pushback */ } if (*(lineptr + 1) == COEOL) *++lineptr = EOL; /* discard COEOL */ } #endif } PRIVATE void usage() { fatalerror( #ifdef BUILTIN_CPP # ifdef MC6809 "usage: cc1 [-cdfptw[-]] [-Ddefine] [-Iincdir] [-Uundef] [-o outfile] [infile]" # else # ifdef I80386 "usage: cc1 [-03cdfltw[-]] [-Ddefine] [-Iincdir] [-Uundef] [-o outfile] [infile]" # else "usage: cc1 [-cdfltw[-]] [-Ddefine] [-Iincdir] [-Uundef] [-o outfile] [infile]" # endif # endif #else # ifdef I80386 "usage: cc1 [-03cdfltw[-]] [-o outfile] [infile]" # else "usage: cc1 [-cdfltw[-]] [-o outfile] [infile]" # endif #endif ); } dev86-0.16.21/bcc/input.h000066400000000000000000000025211231050321700146460ustar00rootroot00000000000000/* input.h - input for bcc */ /* Copyright (C) 1992 Bruce Evans */ #define FAKE_INBUFSIZE_1_NOT #ifdef FAKE_INBUFSIZE_1 #include FILE *fdopen(); #endif struct fcbstruct /* file control block structure */ { fd_t fd; /* file descriptor */ #ifdef FAKE_INBUFSIZE_1 FILE *fp; #endif unsigned linenumber; /* current line in file */ int lineoffset; /* offset to start of current line in buf */ char *lineptr; /* current spot in line */ char *limit; /* end of used part of input buffer */ struct fbufstruct *includer; /* buffer of file which included current one */ }; EXTERN bool_t asmmode; /* nonzero when processing assembler code */ /* depends on zero init */ EXTERN char ch; /* current char */ EXTERN bool_t eofile; /* nonzero after end of main file reached */ /* depends on zero init */ EXTERN struct fcbstruct input; /* current input file control block */ /* input.lineptr is not kept up to date */ EXTERN char *lineptr; /* ptr to current char */ #ifdef BUILTIN_CPP EXTERN bool_t cppmode; /* nonzero if acting as cpp not as compiler */ EXTERN maclev_t maclevel; /* nest level of #defined identifiers */ /* depends on zero init */ EXTERN bool_t orig_cppmode; /* same as cppmode ex. not varied while in # */ EXTERN bool_t virtual_nl; /* For -C and asm, don't print first nl */ #endif dev86-0.16.21/bcc/label.c000066400000000000000000000213611231050321700145640ustar00rootroot00000000000000/* label.c - label handling routines for bcc */ /* Copyright (C) 1992 Bruce Evans */ #include "bcc.h" #include "condcode.h" #include "gencode.h" #include "label.h" #include "output.h" #include "sc.h" #include "scan.h" #include "sizes.h" #include "type.h" #ifdef I8088 # define outlbranch() outop3str( "b") # define outsbranch() outop2str( "j") #endif #ifdef MC6809 # define outlbranch() outop3str( "LB") # define outsbranch() outop2str( "B") #endif #define MAXVISLAB 32 struct labdatstruct { label_no labnum; /* 0 if not active */ offset_T lablc; /* location counter for branch or label */ char *labpatch; /* buffer ptr for branch, NULL for label */ ccode_t labcond; /* condition code for branch */ }; #ifdef I8088 PRIVATE char lcondnames[][2] = /* names of long condition codes */ { { 'e', 'q', }, { 'n', 'e', }, { 'r', ' ', }, { 'r', 'n', }, { 'l', 't', }, { 'g', 'e', }, { 'l', 'e', }, { 'g', 't', }, { 'l', 'o', }, { 'h', 'i', }, { 'l', 'o', }, { 'h', 'i' }, }; PRIVATE char scondnames[][2] = /* names of short condition codes */ { { 'e', ' ', }, { 'n', 'e', }, { 'm', 'p', }, { 'n', 0, }, { 'l', ' ', }, { 'g', 'e', }, { 'l', 'e', }, { 'g', ' ', }, { 'b', ' ', }, { 'a', 'e', }, { 'b', 'e', }, { 'a', ' ', }, }; #endif #ifdef MC6809 PRIVATE char condnames[][2] = /* names of condition codes */ { { 'E', 'Q', }, { 'N', 'E', }, { 'R', 'A', }, { 'R', 'N', }, { 'L', 'T', }, { 'G', 'E', }, { 'L', 'E', }, { 'G', 'T', }, { 'L', 'O', }, { 'H', 'S', }, { 'L', 'S', }, { 'H', 'I', }, }; #endif PRIVATE label_no lasthighlab = 0xFFFF+1; /* temp & temp init so labels fixed */ /* lint */ PRIVATE label_no lastlab; /* bss init to 0 */ PRIVATE offset_T lc; /* bss init to 0 */ PRIVATE struct labdatstruct vislab[MAXVISLAB]; /* bss, all labnum's init 0 */ PRIVATE smalin_t nextvislab; /* bss init to NULL */ PRIVATE struct symstruct *namedfirst; /* bss init to NULL */ PRIVATE struct symstruct *namedlast; /* bss init to NULL */ FORWARD void addlabel P((ccode_pt cond, label_no label, char *patch)); FORWARD struct labdatstruct *findlabel P((label_no label)); /* add label to circular list */ PRIVATE void addlabel(cond, label, patch) ccode_pt cond; label_no label; char *patch; { register struct labdatstruct *labptr; labptr = &vislab[(int)nextvislab]; labptr->labcond = cond; labptr->labnum = label; labptr->lablc = lc; labptr->labpatch = patch; if (++nextvislab == MAXVISLAB) nextvislab = 0; } /* bump location counter */ PUBLIC void bumplc() { ++lc; } /* bump location counter by 2 */ PUBLIC void bumplc2() { lc += 2; } /* bump location counter by 3 */ PUBLIC void bumplc3() { lc += 3; } /* clear out labels in function */ PUBLIC void clearfunclabels() { register struct symstruct *symptr; register struct symstruct *tmp; for (symptr = namedfirst; symptr != NULL;) { if (symptr->indcount == 2) error("undefined label"); symptr->indcount = 0; tmp = symptr; symptr = (struct symstruct *) symptr->type; tmp->type = NULL; } namedlast = namedfirst = NULL; } /* clear out labels no longer in buffer */ PUBLIC void clearlabels(patchbuf, patchtop) char *patchbuf; char *patchtop; { register struct labdatstruct *labptr; struct labdatstruct *labtop; register char *labpatch; for (labptr = &vislab[0], labtop = &vislab[MAXVISLAB]; labptr < labtop; ++labptr) if ((labpatch = labptr->labpatch) >= patchbuf && labpatch < patchtop) labptr->labnum = 0; } /* clear out labels in switch statement */ PUBLIC void clearswitchlabels() { register struct symstruct *symptr; for (symptr = namedfirst; symptr != NULL; symptr = (struct symstruct *) symptr->type) if (symptr->indcount == 3) { equlab(symptr->offset.offlabel, lowsp); symptr->indcount = 4; } } /* return location counter */ PUBLIC uoffset_T getlc() { return (uoffset_T) lc; } /* define location of label and backpatch references to it */ PUBLIC void deflabel(label) label_no label; { char *cnameptr; struct labdatstruct *labmin; struct labdatstruct *labmax; struct labdatstruct *labmid; struct labdatstruct *labptrsave; offset_T nlonger; outnlabel(label); { register struct labdatstruct *labptr; register char *labpatch; labmin = &vislab[0]; labmax = &vislab[MAXVISLAB]; labptr = labmid = &vislab[(int)nextvislab]; if (!watchlc) do { if (labptr == labmin) labptr = &vislab[MAXVISLAB]; --labptr; if (labptr->labnum == label) { if ((labpatch = labptr->labpatch) != NULL && isshortbranch(lc - labptr->lablc)) { #ifdef I8088 /* patch "bcc(c) to j(c)(c)( ) */ *labpatch = 'j'; *(labpatch + 1) = *(cnameptr = scondnames[(int)labptr->labcond]); #endif #ifdef MC6809 # ifdef NEW_MC6809 /* patch JMP\t> or LBCC\t to BCC \t */ *labpatch = 'B'; *(labpatch + 4) = '\t'; /* redundant unless JMP */ *(labpatch + 1) = *(cnameptr = condnames[labptr->labcond]); # else if (labptr->labcond == RA) strncpy(labpatch, "BRA\t\t", 5); else *labpatch = '\t'; goto over; # endif #endif *(labpatch + 2) = *(cnameptr + 1); *(labpatch + 3) = ' '; #ifdef MC6809 # ifndef NEW_MC6809 /* patch JMP\t> or LBCC\t to BCC \t */ over: ; /* temp regression test kludge */ # endif #endif nlonger = jcclonger; if (labptr->labcond == RA) nlonger = jmplonger; lc -= nlonger; labptrsave = labptr; while (++labptr != labmid) if (labptr == labmax) labptr = &vislab[-1]; else labptr->lablc -= nlonger; labptr = labptrsave; } } } while (labptr != labmid); } addlabel((ccode_pt) 0, label, (char *) NULL); } PRIVATE struct labdatstruct *findlabel(label) label_no label; { register struct labdatstruct *labptr; struct labdatstruct *labtop; for (labptr = &vislab[0], labtop = &vislab[MAXVISLAB]; labptr < labtop; ++labptr) if (labptr->labnum == label) { if (labptr->labpatch != 0) break; return labptr; } return (struct labdatstruct *) NULL; } /* reserve a new label, from top down to temp avoid renumbering low labels */ PUBLIC label_no gethighlabel() { return --lasthighlab; } /* reserve a new label */ PUBLIC label_no getlabel() { return ++lastlab; } /* jump to label */ PUBLIC void jump(label) label_no label; { lbranch(RA, label); } /* long branch on condition to label */ PUBLIC void lbranch(cond, label) ccode_pt cond; label_no label; { #ifdef I8088 char *cnameptr; #endif struct labdatstruct *labptr; char *oldoutptr; if ((ccode_t) cond == RN) return; if ((labptr = findlabel(label)) != NULL && isshortbranch(lc - labptr->lablc + 2)) { sbranch(cond, label); return; } oldoutptr = outbufptr; if (cond == RA) outjumpstring(); else { outlbranch(); #ifdef I8088 outbyte(*(cnameptr = lcondnames[(int) cond])); outbyte(*(cnameptr + 1)); if ((ccode_t) cond == LS || (ccode_t) cond == HS) outbyte('s'); /* "blos" or "bhis" */ else outbyte(' '); outtab(); bumplc2(); #ifdef I80386 if (i386_32) bumplc(); #endif #endif #ifdef MC6809 outcond(cond); bumplc(); #endif } outlabel(label); outnl(); if (labptr == NULL && oldoutptr < outbufptr) /* no wrap-around */ addlabel(cond, label, oldoutptr); } /* look up the name gsname in label space, install it if new */ PUBLIC struct symstruct *namedlabel() { struct symstruct *symptr; gs2name[1] = 0xFF; if ((symptr = findlorg(gs2name + 1)) == NULL) { symptr = addglb(gs2name + 1, vtype); symptr->flags = LABELLED; } if (symptr->indcount < 2) { symptr->indcount = 2; symptr->offset.offlabel = gethighlabel(); if (namedfirst == NULL) namedfirst = symptr; else namedlast->type = (struct typestruct *) symptr; namedlast = symptr; symptr->type = NULL; } return symptr; } #ifdef MC6809 /* print condition code name */ PUBLIC void outcond(cond) ccode_pt cond; { char *cnameptr; outbyte(*(cnameptr = condnames[(ccode_t) cond])); outbyte(*(cnameptr + 1)); outtab(); } #endif /* print label */ PUBLIC void outlabel(label) label_no label; { outbyte(LABELSTARTCHAR); outhexdigs((uoffset_T) label); } /* print label and newline */ PUBLIC void outnlabel(label) label_no label; { outlabel(label); #ifdef LABELENDCHAR outnbyte(LABELENDCHAR); #else outnl(); #endif } /* short branch on condition to label */ PUBLIC void sbranch(cond, label) ccode_pt cond; label_no label; { #ifdef I8088 char *cnameptr; if ((ccode_t) cond != RN) { outsbranch(); outbyte(*(cnameptr = scondnames[(int) cond])); outbyte(*(cnameptr + 1)); outtab(); outlabel(label); outnl(); } #endif #ifdef MC6809 outsbranch(); outcond(cond); outlabel(label); outnl(); #endif } /* reverse bump location counter */ PUBLIC void unbumplc() { --lc; } dev86-0.16.21/bcc/label.h000066400000000000000000000010611231050321700145640ustar00rootroot00000000000000/* label.h - assembler-specific label characters for bcc */ /* Copyright (C) 1992 Bruce Evans */ /* defaults */ #define CCNAMEPREFIX '_' # define LABELENDCHAR ':' /* last char of ALL labels */ #define LABELSTARTCHAR '.' /* first char of names of generated labels */ #define LOCALSTARTCHAR '.' /* first char of local names */ #define PUBLICENDCHAR ':' /* adjustments for other assemblers */ #ifdef AS09 # undef LABELENDCHAR #endif #ifdef XENIX_AS # undef LABELSTARTCHAR # define LABELSTARTCHAR 'L' # undef LOCALSTARTCHAR # define LOCALSTARTCHAR 'L' #endif dev86-0.16.21/bcc/loadexp.c000066400000000000000000000102551231050321700151410ustar00rootroot00000000000000/* loadexp.c - load expressions for bcc */ /* Copyright (C) 1992 Bruce Evans */ #include "bcc.h" #include "byteord.h" #include "gencode.h" #include "parse.h" #include "reg.h" #include "sc.h" #include "scan.h" #include "sizes.h" #include "table.h" #include "type.h" PUBLIC value_t constexpression() { struct nodestruct *etmark; struct nodestruct *exp; struct symstruct *exprmark; struct symstruct *symptr; etmark = etptr; exprmark = exprptr; exp = assignment_exp(); etptr = etmark; exprptr = exprmark; if (exp->tag == LEAF && (symptr = exp->left.symptr)->storage == CONSTANT && symptr->type->scalar & ISCALAR) return symptr->offset.offv; error("constant expression required"); return 1; } PUBLIC void initexpression(type) struct typestruct *type; { struct nodestruct *etmark; struct nodestruct *exp; struct symstruct *exprmark; struct nodestruct *lhs; struct symstruct *symptr; uoffset_T value; if (gvarsymptr->storage != GLOBAL) reslocals(); exprmark = exprptr; etmark = etptr; exp = assignment_exp(); if (gvarsymptr->storage != GLOBAL) { lhs = leafnode(exprsym(gvarsymptr)); if (!(lhs->nodetype->constructor & (ARRAY | FUNCTION | VOID))) lhs->flags = LVALUE; makeleaf(node(ASSIGNOP, lhs, exp)); } else if (exp->tag != LEAF || ((symptr = exp->left.symptr)->storage != CONSTANT && (symptr->storage != GLOBAL || symptr->indcount != 0 || type->scalar & DLONG)) || (type->constructor | (symptr->type->constructor & ~FUNCTION)) & ~(ARRAY | POINTER)) error("initializer too complicated"); else { if ((symptr->type->scalar | type->scalar) & RSCALAR) { /* Can only afford castnode if result known constant. */ exp = castnode(type, exp); symptr = exp->left.symptr; } if (type->scalar & RSCALAR) { if (type->scalar & FLOAT) { float val; val = *symptr->offset.offd; deflong(((uoffset_T *) &val)[0]); } else { deflong(((uoffset_T *) symptr->offset.offd)[0]); deflong(((uoffset_T *) symptr->offset.offd)[1]); } etptr = etmark; /* XXX - stuff from end of function */ exprptr = exprmark; return; } if (type->typesize == 1) defbyte(); else if (type->typesize == 2) defword(); #ifdef I8088 else if (!(type->scalar & DLONG)) defdword(); #endif switch (symptr->storage) { case CONSTANT: value = (uoffset_T) symptr->offset.offv; if (type->scalar & DLONG) { deflong(value); break; } /* XXX - put sizes in type struct to avoid tests */ if (type->scalar & CHAR) value &= CHMASKTO; else if (type->scalar & SHORT) value &= shortmaskto; else if (type->scalar & INT) value &= intmaskto; /* XXX - no longmaskto */ outnhex(value); break; case GLOBAL: if (symptr->flags & LABELLED) { outlabel(symptr->name.label); outplus(); outnhex((uoffset_T) symptr->offset.offi); break; } if (*symptr->name.namep == 0) /* constant address */ { outnhex((uoffset_T) symptr->offset.offi); break; } outccname(symptr->name.namep); if (symptr->offset.offi != 0) { if (symptr->offset.offi > 0) outplus(); outshex(symptr->offset.offi); } outnl(); break; } } etptr = etmark; exprptr = exprmark; } PUBLIC struct typestruct *loadexpression(targreg, targtype) store_pt targreg; struct typestruct *targtype; { struct nodestruct *etmark; struct nodestruct *exp; struct symstruct *exprmark; etmark = etptr; exprmark = exprptr; exp = expression(); if (targtype != NULL) exp = castnode(targtype, exp); makeleaf(exp); if (targtype == NULL) /* this is for a switch */ { targtype = exp->left.symptr->type; if (!(targtype->scalar & (CHAR | INT)) && (targtype->scalar & (LONG | DLONG)) != LONG) { if (targtype->scalar & SHORT) targtype = promote(targtype); else { error("non-integral selector in switch"); targtype = itype; } makeleaf(exp = castnode(targtype, exp)); } } load(exp->left.symptr, targreg); /* resets stack if value was there */ etptr = etmark; exprptr = exprmark; return exp->left.symptr->type; } dev86-0.16.21/bcc/longop.c000066400000000000000000000077131231050321700150100ustar00rootroot00000000000000/* longop.c - software operations on longs for bcc */ /* Copyright (C) 1992 Bruce Evans */ #include "bcc.h" #include "byteord.h" #include "gencode.h" #include "reg.h" #include "scan.h" #include "type.h" /*----------------------------------------------------------------------------- longop(operation code, source leaf, target leaf) handles all binary operations on longs source and target must already have been converted to long, (except source is int for shifts) and not more than singly indirect hence they must be direct (in an index reg paired with DREG), or singly indirect (local, global, or from an index reg) -----------------------------------------------------------------------------*/ PUBLIC void longop(op, source, target) op_pt op; struct symstruct *source; struct symstruct *target; { store_pt reglist; store_t regmark; bool_t shiftflag; scalar_t scalar; offset_T spmark; pushlist(reglist = (regmark = reguse) & (OPREG | OPWORKREG)); reguse &= ~reglist; spmark = sp; shiftflag = FALSE; scalar = target->type->scalar; if ((op_t) op == SLOP || (op_t) op == SROP) shiftflag = TRUE; else scalar |= source->type->scalar; if ((source->indcount == 0 && !shiftflag) || source->type->scalar & CHAR || source->storage & (BREG | DREG | OPREG | OPWORKREG)) { pres2(source, target); push(source); } if (!shiftflag) address(source); load(target, OPREG); if (source->storage == CONSTANT && shiftflag) { if (scalar & UNSIGNED) target->type = ultype; if ((op_t) op == SLOP) source->offset.offv = lslconst(source->offset.offv, target->storage); else source->offset.offv = lsrconst(source->offset.offv, target->storage, scalar & UNSIGNED); if (source->offset.offv == 0) goto shiftdone; } #ifdef I8088 /* This is ugly! But it works. I should be able to stop it being used * by removing the char demotion. */ if (source->type->scalar & CHAR && !(source->storage & (BREG|DREG|DATREG1B))) { load(source, DATREG1B); outop2str("xor\tch,ch"); outnl(); source->storage = DATREG1; } #endif load(source, OPWORKREG); switch ((op_t) op) { case ADDOP: call("ladd"); break; case ANDOP: call("land"); break; case DIVOP: call("ldiv"); break; case EOROP: call("leor"); break; case EQOP: call("lcmp"); break; case MODOP: call("lmod"); break; case MULOP: call("lmul"); break; case OROP: call("lor"); break; case SLOP: call("lsl"); break; case SROP: call("lsr"); break; case SUBOP: call("lsub"); break; } if (scalar & UNSIGNED) { outbyte('u'); target->type = ultype; } outlongendian(); shiftdone: if ((reguse = regmark) & OPREG && op != EQOP) load(target, getindexreg()); if (reglist) { #ifdef I8088 if (op == EQOP) changesp(spmark, FALSE); else #endif modstk(spmark); poplist(reglist); } } /*----------------------------------------------------------------------------- long1op(operation code, target leaf) handles all unary operations on longs except inc/dec target must be not more than singly indirect hence it must be direct (in an index reg paired with DREG), or singly indirect (local, global, or from an index reg) -----------------------------------------------------------------------------*/ PUBLIC void long1op(op, target) op_pt op; struct symstruct *target; { pushlist(reguse & OPREG); load(target, OPREG); if (op == NOTOP) call("lcom"); else if (op == NEGOP) call("lneg"); else call("ltst"); outlongendian(); if (reguse & OPREG) { if (op != EQOP) load(target, getindexreg()); poplist(reguse & OPREG); } } PUBLIC void outlongendian() { #ifdef MC6809 outbyte('_'); #endif #if DYNAMIC_LONG_ORDER if (long_big_endian) #endif #if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN outnbyte('b'); #endif #if DYNAMIC_LONG_ORDER else #endif #if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN == 0 outnbyte('l'); #endif } dev86-0.16.21/bcc/os.h000066400000000000000000000023151231050321700141310ustar00rootroot00000000000000/* os.h - source/target operating system dependencies for bcc */ /* Copyright (C) 1992 Bruce Evans */ /* must have unix-near-compatible creat, open, read, write and close source O/S's supported: default: *IX special: EDOS (#define SOS_EDOS if required) MSDOS (#define SOS_MSDOS) target O/S's supported: default: *IX MSDOS special: EDOS (#define TOS_EDOS) */ /* defaults */ #define CREATPERMS 0666 /* permissions for creat */ #define EOL 10 /* source newline */ #define EOLTO 10 /* target newline */ #define DIRCHAR '/' #define DIRSTRING "/" #define isabspath(fnameptr, tempcptr) \ ((*(tempcptr) = *(fnameptr)) == DIRCHAR) /* special */ #ifdef SOS_EDOS # undef DEFAULT_INCLUDE_DIR # define DEFAULT_INCLUDE_DIR "3" # undef DIRCHAR # define DIRCHAR ':' # undef DIRSTRING # define DIRSTRING ":" # define AS09 # undef EOL # define EOL 13 # undef isabspath # define isabspath(fnameptr, tempcptr) \ ((*(tempcptr) = *(fnameptr)) >= '0' && *(tempcptr) <= '9' && \ (fnameptr)[1] == DIRCHAR) #endif #ifdef TOS_EDOS # undef EOLTO # define EOLTO 13 #endif /* don't let names dealt with here affect anything outside this file */ #undef SOS_EDOS #undef SOS_MSDOS dev86-0.16.21/bcc/output.c000066400000000000000000000301651231050321700150470ustar00rootroot00000000000000/* output.c - output and error handling for bcc */ /* Copyright (C) 1992 Bruce Evans */ #include "bcc.h" #include "input.h" #include "os.h" #include "sizes.h" #include "table.h" #undef EXTERN #define EXTERN #include "output.h" #ifdef XENIX_AS # define HEXSTARTCHAR '/' #else # define HEXSTARTCHAR '$' #endif #define OUTBUFSIZE 2048 #define opcodeleadin() /* outtab() for fussy assemblers */ PRIVATE unsigned errcount; /* # errors in compilation */ /* depends on zero init */ PRIVATE char hexdigits[] = "0123456789ABCDEF"; PRIVATE char *outbuf; EXTERN char *outbufend; /* end of pair of output buffers */ PRIVATE char *outbufmid; PRIVATE fd_t output; PRIVATE fastin_t outstage; /* depends on zero init */ FORWARD void errorsummary P((void)); FORWARD void errsum1 P((void)); #ifdef MC6809 #ifdef DBNODE FORWARD void outvaldigs P((uvalue_t num)); #endif #endif PUBLIC void bugerror(message) char *message; { error2error("compiler bug? - ", message); } PUBLIC void closeout() { char *saveoutptr; if (outstage == 3) { saveoutptr = outbufptr; flushout(); /* buffer from last stage */ outbufptr = saveoutptr; } outstage = 0; /* flush from top to current ptr */ flushout(); close(output); } /* error handler */ PUBLIC void error(message) char *message; { error2error(message, ""); } /* error handler - concatenate 2 messages */ PUBLIC void error2error(message1, message2) char *message1; char *message2; { char *warning; if (message1[0] == '%' && message1[1] == 'w') { message1 += 2; warning = "warning: "; } else { ++errcount; warning = "error: "; } if (output != 1) { char *old_outbuf; char *old_outbufptr; char *old_outbuftop; fd_t old_output; fastin_t old_outstage; char smallbuf[81]; /* don't use heap - might be full or busy */ old_outbuf = outbuf; old_outbufptr = outbufptr; old_outbuftop = outbuftop; old_output = output; old_outstage = outstage; outbufptr = outbuf = &smallbuf[0]; outbuftop = &smallbuf[sizeof smallbuf]; output = 1; outstage = 0; errorloc(); outstr(warning); outstr(message1); outstr(message2); outnl(); flushout(); outbuf = old_outbuf; outbufptr = old_outbufptr; outbuftop = old_outbuftop; output = old_output; outstage = old_outstage; } outstr("fail"); comment(); errorloc(); outstr(warning); outstr(message1); outstr(message2); outnl(); } /* summarise errors */ PRIVATE void errorsummary() { if (errcount != 0) { outfail(); errsum1(); } outnl(); comment(); errsum1(); } PRIVATE void errsum1() { outudec(errcount); outnstr(" errors detected"); } /* fatal error, exit early */ PUBLIC void fatalerror(message) char *message; { error(message); finishup(); } /* finish up compile */ PUBLIC void finishup() { #ifdef BUILTIN_CPP if (!orig_cppmode) #endif { if (watchlc) { cseg(); outop0str("if *-.program.start-"); outnhex(getlc()); outfail(); outnstr("phase error"); outop0str("endif\n"); } #ifdef HOLDSTRINGS dumpstrings(); #endif dumpglbs(); errorsummary(); } closein(); closeout(); exit(errcount == 0 ? 0 : 1); } /* flush output file */ PUBLIC void flushout() { unsigned nbytes; switch (outstage) { case 0: nbytes = (unsigned) (outbufptr - outbuf); outbufptr = outbuf; break; case 2: nbytes = OUTBUFSIZE; outbufptr = outbuf; outbuftop = outbufmid; outstage = 3; break; default: nbytes = OUTBUFSIZE; if (outstage == 1) nbytes = 0; outbufptr = outbufmid; outbuftop = outbufend; outstage = 2; break; } if (nbytes != 0) { #ifdef BUILTIN_CPP if (!orig_cppmode) #endif clearlabels(outbufptr, outbufptr + nbytes); if (write(output, outbufptr, nbytes) != nbytes) { write(2, "output file error\n", 18); closein(); close(output); exit(1); } } } PUBLIC void initout() { static char smallbuf[1]; outbufend = outbuftop = (outbuf = outbufptr = smallbuf) + sizeof smallbuf; output = 1; /* standard output */ } PUBLIC void limiterror(message) char *message; { error2error("compiler limit exceeded - ", message); finishup(); } PUBLIC void openout(oname) char *oname; { if (output != 1) fatalerror("more than one output file"); if ((output = creat(oname, CREATPERMS)) < 0) { output = 1; fatalerror("cannot open output"); } } /* print character */ PUBLIC void outbyte(c) int c; { #if C_CODE || __AS09__ + __AS386_16__ + __AS386_32__ != 1 register char *outp; outp = outbufptr; *outp++ = c; outbufptr = outp; if (outp >= outbuftop) flushout(); #else /* !C_CODE etc */ #if __AS09__ # asm TFR X,D LDX _outbufptr,PC STB ,X+ STX _outbufptr,PC CMPX _outbuftop,PC LBHS CALL.FLUSHOUT # endasm #endif /* __AS09__ */ #if __AS386_16__ # asm # if !__FIRST_ARG_IN_AX__ pop dx pop ax dec sp dec sp # else # if ARGREG != DREG xchg ax,bx # endif # endif mov bx,[_outbufptr] mov [bx],al inc bx mov [_outbufptr],bx cmp bx,[_outbuftop] jae Outbyte.Flush # if !__FIRST_ARG_IN_AX__ jmp dx # else ret # endif Outbyte.Flush: # if !__FIRST_ARG_IN_AX__ push dx # endif br _flushout # endasm #endif /* __AS386_16__ */ #if __AS386_32__ # asm # if !__FIRST_ARG_IN_AX__ mov eax,_outbyte.c[esp] # else # if ARGREG != DREG xchg eax,ebx # endif # endif mov ecx,[_outbufptr] mov [ecx],al inc ecx mov [_outbufptr],ecx cmp ecx,[_outbuftop] jae Outbyte.Flush ret Outbyte.Flush: br _flushout # endasm #endif /* __AS386_32__ */ #endif /* C_CODE etc */ } /* print comma */ PUBLIC void outcomma() { outbyte(','); } /* print line number in format ("# %u \"%s\"%s", nr, fname, str) */ PUBLIC void outcpplinenumber(nr, fname, str) unsigned nr; char *fname; char *str; { outstr("# "); outudec(nr); outstr(" \""); outstr(fname); outstr("\""); outnstr(str); } /* print unsigned offset, hex format */ PUBLIC void outhex(num) uoffset_T num; { #ifdef HEXSTARTCHAR if (num >= 10) outbyte(HEXSTARTCHAR); #endif outhexdigs(num); #ifdef HEXENDCHAR if (num >= 10) outbyte(HEXENDCHAR); #endif } /* print unsigned offset, hex format with digits only (no hex designator) */ PUBLIC void outhexdigs(num) register uoffset_T num; { if (num >= 0x10) { outhexdigs(num / 0x10); num %= 0x10; } outbyte(hexdigits[(int) num]); } /* print string terminated by EOL */ PUBLIC void outline(s) char *s; { register char *outp; register char *rs; outp = outbufptr; rs = s; #ifdef COEOL if (*rs == COEOL) ++rs; #endif do { *outp++ = *rs; if (outp >= outbuftop) { outbufptr = outp; flushout(); outp = outbufptr; } } while (*rs++ != EOL); outbufptr = outp; #ifdef COEOL if (*rs == COEOL) outbyte(COEOL); #endif } /* print minus sign */ PUBLIC void outminus() { outbyte('-'); } /* print character, then newline */ PUBLIC void outnbyte(byte) int byte; { outbyte(byte); outnl(); } /* print unsigned offset, hex format, then newline */ PUBLIC void outnhex(num) uoffset_T num; { outhex(num); outnl(); } /* print newline */ PUBLIC void outnl() { if (watchlc) { outtab(); comment(); outhex(getlc()); } outbyte('\n'); } /* print opcode and newline, bump lc by 1 */ PUBLIC void outnop1str(s) char *s; { opcodeleadin(); outstr(s); bumplc(); outnl(); } /* print opcode and newline, bump lc by 2 */ PUBLIC void outnop2str(s) char *s; { opcodeleadin(); outstr(s); bumplc2(); outnl(); } /* print string, then newline */ PUBLIC void outnstr(s) char *s; { outstr(s); outnl(); } /* print opcode */ PUBLIC void outop0str(s) char *s; { opcodeleadin(); outstr(s); } /* print opcode, bump lc by 1 */ PUBLIC void outop1str(s) char *s; { opcodeleadin(); outstr(s); bumplc(); } /* print opcode, bump lc by 2 */ PUBLIC void outop2str(s) char *s; { opcodeleadin(); outstr(s); bumplc2(); } /* print opcode, bump lc by 3 */ PUBLIC void outop3str(s) char *s; { opcodeleadin(); outstr(s); bumplc3(); } /* print plus sign */ PUBLIC void outplus() { outbyte('+'); } /* print signed offset, hex format */ PUBLIC void outshex(num) offset_T num; { if (num >= -(maxoffsetto + 1)) { outminus(); num = -num; } outhex((uoffset_T) num); } /* print string */ PUBLIC void outstr(s) char *s; { #if C_CODE || __AS09__ + __AS386_16__ + __AS386_32__ != 1 register char *outp; register char *rs; outp = outbufptr; rs = s; while (*rs) { *outp++ = *rs++; if (outp >= outbuftop) { outbufptr = outp; flushout(); outp = outbufptr; } } outbufptr = outp; #else /* !C_CODE etc */ #if __AS09__ # asm LEAU ,X LDX _outbuftop,PC PSHS X LDX _outbufptr,PC BRA OUTSTR.NEXT CALL.FLUSHOUT PSHS U,B STX _outbufptr,PC LBSR _flushout LDX _outbufptr,PC LDY _outbuftop,PC PULS B,U,PC OUTSTR.LOOP STB ,X+ CMPX ,S BLO OUTSTR.NEXT BSR CALL.FLUSHOUT STY ,S OUTSTR.NEXT LDB ,U+ BNE OUTSTR.LOOP STX _outbufptr,PC LEAS 2,S # endasm #endif /* __AS09__ */ #if __AS386_16__ # asm # if !__CALLER_SAVES__ mov dx,di mov cx,si # endif # if !__FIRST_ARG_IN_AX__ pop ax pop si dec sp dec sp push ax # else # if ARGREG == DREG xchg si,ax # else mov si,bx # endif # endif mov di,[_outbufptr] mov bx,[_outbuftop] br OUTSTR.NEXT CALL.FLUSHOUT: push si # if !__CALLER_SAVES__ push dx push cx # endif push ax mov [_outbufptr],di call _flushout mov di,[_outbufptr] mov bx,[_outbuftop] pop ax # if !__CALLER_SAVES__ pop cx pop dx #endif pop si ret OUTSTR.LOOP: stosb cmp di,bx jb OUTSTR.NEXT call CALL.FLUSHOUT OUTSTR.NEXT: lodsb test al,al jne OUTSTR.LOOP mov [_outbufptr],di # if !__CALLER_SAVES__ mov si,cx mov di,dx # endif # endasm #endif /* __AS386_16__ */ #if __AS386_32__ # asm # if !__CALLER_SAVES__ mov edx,edi push esi # define TEMPS 4 # else # define TEMPS 0 # endif # if !__FIRST_ARG_IN_AX__ mov esi,TEMPS+_outstr.s[esp] # else # if ARGREG == DREG xchg esi,eax # else mov esi,ebx # endif # endif mov edi,[_outbufptr] mov ecx,[_outbuftop] br OUTSTR.NEXT CALL.FLUSHOUT: push esi # if !__CALLER_SAVES__ push edx # endif push eax mov [_outbufptr],edi call _flushout mov edi,[_outbufptr] mov ecx,[_outbuftop] pop eax # if !__CALLER_SAVES__ pop edx # endif pop esi ret OUTSTR.LOOP: stosb cmp edi,ecx jb OUTSTR.NEXT call CALL.FLUSHOUT OUTSTR.NEXT: lodsb test al,al jne OUTSTR.LOOP mov [_outbufptr],edi # if !__CALLER_SAVES__ pop esi mov edi,edx # endif # endasm #endif /* __AS386_32__ */ #endif /* C_CODE etc */ } /* print tab */ PUBLIC void outtab() { outbyte('\t'); } /* print unsigned, decimal format */ PUBLIC void outudec(num) unsigned num; { char str[10 + 1]; str[sizeof str - 1] = 0; outstr(pushudec(str + sizeof str - 1, num)); } #ifdef MC6809 #ifdef DBNODE /* print unsigned value, hex format (like outhex except value_t is larger) */ PUBLIC void outuvalue(num) uvalue_t num; { #ifdef HEXSTARTCHAR if (num >= 10) outbyte(HEXSTARTCHAR); #endif outvaldigs(num); #ifdef HEXENDCHAR if (num >= 10) outbyte(HEXENDCHAR); #endif } /* print unsigned value, hex format with digits only (no hex designator) */ PRIVATE void outvaldigs(num) register uvalue_t num; { if (num >= 0x10) { outvaldigs(num / 0x10); num %= 0x10; } outbyte(hexdigits[(fastin_t) num]); } /* print signed value, hex format (like outshex except value_t is larger) */ PUBLIC void outvalue(num) register value_t num; { if (num < 0) { outminus(); num = -num; } outuvalue((uoffset_T) num); } #endif /* DBNODE */ #endif /* MC6809 */ /* push decimal digits of an unsigned onto a stack of chars */ PUBLIC char *pushudec(s, num) register char *s; register unsigned num; { register unsigned reduction; while (num >= 10) { reduction = num / 10; *--s = num - 10 * reduction + '0'; num = reduction; } *--s = num + '0'; return s; } PUBLIC void setoutbufs() { if (!isatty(output)) { outbufptr = outbuf = ourmalloc(2 * OUTBUFSIZE); #ifdef TS ts_s_outputbuf += 2 * OUTBUFSIZE; #endif outbufmid = outbuftop = outbufptr + OUTBUFSIZE; outbufend = outbufmid + OUTBUFSIZE; outstage = 1; } if (watchlc) outnstr(".program.start:\n"); /* kludge temp label */ } dev86-0.16.21/bcc/output.h000066400000000000000000000010161231050321700150450ustar00rootroot00000000000000/* output.h - output for bcc */ /* Copyright (C) 1992 Bruce Evans */ #define OUTBYTE(ch) \ do {register char *outp = outbufptr; *outp++ = (ch); \ outbufptr = outp; if (outp >= outbuftop) flushout(); } while (0) EXTERN bool_t ctext; /* nonzero to intermix C source */ /* depends on zero init */ EXTERN char *outbufptr; /* current spot in output buffer */ EXTERN char *outbuftop; /* top of current output buffer */ EXTERN bool_t watchlc; /* nonzero to print lc after every line */ /* depends on zero init */ dev86-0.16.21/bcc/parse.h000066400000000000000000000010511231050321700146160ustar00rootroot00000000000000/* parse.h - parser for bcc */ /* Copyright (C) 1992 Bruce Evans */ /* possible scope levels */ #define ARGLEVEL 1 #define GLBLEVEL 0 #define MAXLEVEL 125 #define MINLOCLEVEL 1 /* possible node flags */ #define LVALUE (1 << 0) EXTERN struct nodestruct *etptr; /* ptr to next entry in expression tree */ EXTERN struct symstruct *gvarsymptr; /* gsymptr for last identifier declared */ EXTERN scopelev_t level; /* scope level */ /* depends on zero init */ #ifndef VERY_SMALL_MEMORY EXTERN bool_t ancient; /* undersand ancient K&R */ #endif dev86-0.16.21/bcc/preproc.c000066400000000000000000000514761231050321700151710ustar00rootroot00000000000000/* preprocessor routines for bcc */ /* Copyright (C) 1992 Bruce Evans */ #include "bcc.h" #include "input.h" #include "os.h" #include "output.h" #include "parse.h" #include "sc.h" #include "scan.h" #include "table.h" #include "type.h" /* blanksident() - return nonzero if at blanks followed by an identifier */ PUBLIC bool_pt blanksident() { blanks(); return isident(); } #ifdef BUILTIN_CPP #define MAX_IF 32 #define MAX__LINE__ 10 /* enough for 32-bit source unsigneds */ #define MAX_MACRO 32 #define MAX_PARAM 127 /* max char with no sign on all machines */ /* Definition types. These are kept in the 'storage' member of struct * symstruct and must be distinct from 'LOCAL' because dumplocs() doesn't * check. */ enum { DEF_LINE, /* __LINE__ keyword */ DEF_NONE /* nothing special */ }; struct ifstruct { bool_t elseflag; bool_t ifflag; }; struct macroposition { char *maclineptr; char **paramlist; char *paramspot; bool_t inparam; indn_t nparam; struct symstruct *symptr; }; PRIVATE char dummyparam[] = { EOL, 0 }; PRIVATE fastin_t iflevel; /* depends on zero init */ PRIVATE struct ifstruct ifstate; /* elseflag depends on zero init */ PRIVATE struct ifstruct ifstack[MAX_IF]; PRIVATE struct macroposition macrostack[MAX_MACRO]; FORWARD void asmcontrol P((void)); FORWARD void warningcntl P((void)); FORWARD void errorcntl P((void)); FORWARD void control P((void)); FORWARD void defineorundefinestring P((char *str, bool_pt defineflag)); FORWARD void elifcontrol P((void)); FORWARD void elsecontrol P((void)); FORWARD void endif P((void)); FORWARD fastin_pt getparnames P((void)); FORWARD void ifcontrol P((sym_pt ifcase)); FORWARD void undef P((void)); /* asmcontrol() - process #asm */ PRIVATE void asmcontrol() { #ifdef ASM_BARE char treasure; /* to save at least one leading blank */ #endif asmmode = TRUE; if (expect_statement) return; if (orig_cppmode) outnstr("#asm"); else { outnstr("!BCC_ASM"); dumplocs(); } #ifndef ASM_BARE cppscan(1); #else while (TRUE) { skipline(); skipeol(); if (eofile) { eofin("#asm"); break; } if (SYMOFCHAR(ch) == SPECIALCHAR) specialchar(); treasure = 0; if (SYMOFCHAR(ch) == WHITESPACE) treasure = ch; blanks(); if (ch == '#') { if (ctext) { register char *lptr; comment(); if (treasure != 0) outbyte(treasure); lptr = lineptr; while (*lptr++ != EOL) /* XXX - handle COEOL too */ outbyte(ch); outnl(); } gch1(); docontrol(); if (!asmmode) break; } else { if (treasure != 0) outbyte(treasure); while (ch != EOL) /* XXX - handle COEOL too */ { outbyte(ch); gch1(); } outnl(); } } #endif if (orig_cppmode) outnstr("#endasm"); else outnstr("!BCC_ENDASM"); } PUBLIC void checknotinif() { while (iflevel != 0) { if (ifstate.ifflag) eofin("true #conditional"); else eofin("false #conditional"); endif(); } } /* warningcntl() - process #warning */ PRIVATE void warningcntl() { char estr[256], *ep = estr; if (!orig_cppmode) { *ep++ = '%'; *ep++ = 'w'; } while( ch != EOL ) { if (ep < estr+sizeof(estr)-2 ) *ep++ = ch; gch1(); } *ep = 0; if (!orig_cppmode) error(estr); else { outstr("#warning"); outnstr(estr); } } /* errorcntl() - process #error */ PRIVATE void errorcntl() { char estr[256], *ep = estr; while( ch != EOL ) { if (ep < estr+sizeof(estr)-2 ) *ep++ = ch; gch1(); } *ep = 0; if (!orig_cppmode) error(estr); else { outstr("#error"); outnstr(estr); } } /* control() - select and switch to control statement */ PRIVATE void control() { char sname[NAMESIZE + 1]; sym_t ctlcase; struct symstruct *symptr; if (ctext && asmmode) { comment(); outudec(input.linenumber); outbyte(' '); outline(lineptr); } sname[0] = '#'; /* prepare for bad control */ sname[1] = 0; while (blanksident()) { if ((gsymptr = findlorg(gsname)) == NULL || gsymptr->flags != DEFINITION) { strcat(sname, gsname); break; } entermac(); } if (sname[1] == 0 && ch == EOL) return; if (SYMOFCHAR(ch) == INTCONST) { linecontol(); return; } if ((symptr = findlorg(sname)) == NULL) { if (ifstate.ifflag) error(" bad control"); return; } ctlcase = symptr->offset.offsym; if (ifstate.ifflag == FALSE && (ctlcase < ELIFCNTL || ctlcase > IFNDEFCNTL)) return; switch (ctlcase) { case ASMCNTL: if (asmmode) { if (ifstate.ifflag) error(" bad control"); } else asmcontrol(); break; case DEFINECNTL: define(); break; case ELIFCNTL: elifcontrol(); break; case ELSECNTL: elsecontrol(); break; case ENDASMCNTL: if (!asmmode) { if (ifstate.ifflag) error(" bad control"); } asmmode = FALSE; break; case ENDIFCNTL: endif(); break; case IFCNTL: case IFDEFCNTL: case IFNDEFCNTL: ifcontrol(symptr->offset.offsym); break; case INCLUDECNTL: include(); break; case LINECNTL: { linecontol(); break; } case UNDEFCNTL: undef(); break; case WARNINGCNTL: warningcntl(); break; case ERRORCNTL: errorcntl(); break; } } /* define() - process #define */ /* MACRO storage. A symbol recording the macro name is added to the symbol table. This overrides all current scopes of the name (put at head of hash chain). The flags are set to DEFINITION. The indcount is 0 if no parameters, else 1 + number of parameters. The offset field points to the macro string. The macro string is null-terminated but EOL-sentineled. It consists of EOL-terminated substrings followed by parameter numbers, e.g., junk(x,y)=-x+y is stored as '-', EOL, 1, '+', EOL, 2, EOL, 0. Here 1 is for the 1st parameter (start at 1 so 0 can terminate). EOL acts as a sentinel for the scanner. This choice works well because EOL cannot occur in a macro string. */ PUBLIC void define() { char sname[NAMESIZE]; char quote; struct symstruct **hashptr; struct symstruct *locmark = NULL; /* for -Wall */ char *macstring; fastin_t nparnames; char *oldstring; struct symstruct *symptr; if (!blanksident()) { error("illegal macro name"); return; } strcpy(sname, gsname); /* will overwrite gsname if parameters */ if (ch == '(') { locmark = locptr; newlevel(); /* temp storage for parameter names */ nparnames = getparnames() + 1; } else nparnames = 0; blanks(); macstring = charptr; quote = 0; while (ch != EOL) { if (charptr >= char1top) /* check room for char and end of string */ macstring = growobject(macstring, 2); if (nparnames && isident()) { if ((symptr = findlorg(gsname)) != NULL && symptr->level == level) { #ifdef TS ++ts_n_macstring_param; ts_s_macstring += 2; #endif *charptr++ = EOL; /* end current string */ *charptr++ = symptr->indcount; /* param to insert */ } else { if (charptr + strlen(gsname) >= chartop) /* null too */ macstring = growobject(macstring, strlen(gsname) + 1); #ifdef TS ++ts_n_macstring_ident; ts_s_macstring += strlen(gsname);; #endif strcpy(charptr, gsname); charptr += strlen(gsname); /* discard null */ } continue; } if (ch == '\\') { gch1(); *charptr = '\\'; *(charptr + 1) = ch; #ifdef TS ++ts_n_macstring_quoted; ts_s_macstring += 2; #endif charptr += 2; gch1(); continue; } if (quote) { if (ch == quote) quote = 0; } else if (ch == '"' || ch == '\'') quote = ch; else if (ch == '/') { if (SYMOFCHAR(*(lineptr + 1)) == SPECIALCHAR) { gch1(); ch = *--lineptr = '/'; /* pushback */ } if (*(lineptr + 1) == '*') { gch1(); skipcomment(); #if 0 /* comment is space in modern cpp's but they have '##' too */ ch = *--lineptr = ' '; #else continue; #endif } } #ifdef TS ++ts_n_macstring_ordinary; ++ts_s_macstring; #endif *charptr++ = ch; gch1(); } { register char *rcp; /* strip trailing blanks, but watch out for parameters */ for (rcp = charptr; rcp > macstring && SYMOFCHAR(*(rcp - 1)) == WHITESPACE && (--rcp == macstring || *(rcp - 1) != EOL); ) charptr = rcp; } if (charptr+1 >= char1top) macstring = growobject(macstring, 3); #ifdef TS ++ts_n_macstring_term; ts_s_macstring += 3; #endif *charptr++ = ' '; /* Added to prevent tail recursion on expansion */ *charptr++ = EOL; *charptr++ = 0; if (nparnames) { oldlevel(); locptr = locmark; } /* if (asmmode) equ(sname, macstring); */ if ((symptr = findlorg(sname)) != NULL && symptr->flags == DEFINITION) { if (strcmp(macstring, oldstring = symptr->offset.offp) != 0) error("%wredefined macro"); if (strlen(macstring) > strlen(oldstring = symptr->offset.offp)) symptr->offset.offp = macstring; else { strcpy(oldstring, macstring); /* copy if == to avoid test */ charptr = macstring; } return; } symptr = qmalloc(sizeof (struct symstruct) + strlen(sname)); #ifdef TS ++ts_n_defines; ts_s_defines += sizeof (struct symstruct) + strlen(sname); #endif addsym(sname, vtype, symptr); symptr->storage = DEF_NONE; symptr->indcount = nparnames; symptr->flags = DEFINITION; symptr->level = GLBLEVEL; symptr->offset.offp = macstring; if (*(hashptr = gethashptr(sname)) != NULL) { symptr->next = *hashptr; symptr->next->prev = &symptr->next; } *hashptr = symptr; symptr->prev = hashptr; } PRIVATE void defineorundefinestring(str, defineflag) char *str; /* "name[=def]" or "name def" */ bool_pt defineflag; { char *fakeline; unsigned len; bool_t old_eof; len = strlen(str); strcpy(fakeline = (char *) ourmalloc(3 + len + 2 + 2) + 3, str); /* 3 pushback, 2 + 2 guards */ #ifdef TS ts_s_fakeline += 3 + len + 2 + 2; ts_s_fakeline_tot += 3 + len + 2 + 2; #endif { register char *endfakeline; endfakeline = fakeline + len; endfakeline[0] = EOL; /* guards any trailing backslash */ endfakeline[1] = EOL; /* line ends here or before */ } old_eof = eofile; eofile = TRUE; /* valid after first EOL */ ch = *(lineptr = fakeline); if (defineflag) { if (blanksident()) /* if not, let define() produce error */ { blanks(); if (ch == '=') *lineptr = ' '; else if (ch == EOL) { register char *lptr; lptr = lineptr; lptr[0] = ' '; lptr[1] = '1'; /* 2 extra were allocated for this & EOL */ lptr[2] = EOL; } } ch = *(lineptr = fakeline); define(); } else undef(); eofile = old_eof; #ifdef TS ts_s_fakeline_tot -= len + 2 + 2; #endif ourfree(fakeline - 3); } PUBLIC void definestring(str) char *str; /* "name[=def]" or "name def" */ { defineorundefinestring(str, TRUE); } /* docontrol() - process control statement, loop till "#if" is true */ PUBLIC void docontrol() { while (TRUE) { control(); skipline(); if (ifstate.ifflag) return; while (TRUE) { skipeol(); if (eofile) return; blanks(); if (ch == '#') { gch1(); break; } skipline(); } } } /* elifcontrol() - process #elif */ PRIVATE void elifcontrol() { if (iflevel == 0) { error("elif without if"); return; } if (ifstate.elseflag) { register struct ifstruct *ifptr; ifptr = &ifstack[(int)--iflevel]; ifstate.elseflag = ifptr->elseflag; ifstate.ifflag = ifptr->ifflag; ifcontrol(IFCNTL); } else { ifstate.ifflag = ifstate.elseflag; ifstate.elseflag = FALSE; } } /* elsecontrol() - process #else */ PRIVATE void elsecontrol() { if (iflevel == 0) { error("else without if"); return; } ifstate.ifflag = ifstate.elseflag; ifstate.elseflag = FALSE; } /* endif() - process #endif */ PRIVATE void endif() { if (iflevel == 0) { error("endif without if"); return; } { register struct ifstruct *ifptr; ifptr = &ifstack[(int)--iflevel]; ifstate.elseflag = ifptr->elseflag; ifstate.ifflag = ifptr->ifflag; } } /* entermac() - switch line ptr to macro string */ PUBLIC void entermac() { char quote; struct symstruct *symptr; char **paramhead; char **paramlist; int ngoodparams; int nparleft; int lpcount; if (maclevel >= MAX_MACRO) { limiterror("macros nested too deeply (33 levels)"); return; } symptr = gsymptr; symptr->name.namea[0] |= 0x80; /* SMUDGE macro definition */ ngoodparams = 0; paramhead = NULL; if (symptr->indcount != 0) { nparleft = symptr->indcount - 1; if (nparleft == 0) paramhead = NULL; else paramhead = ourmalloc(sizeof *paramlist * nparleft); paramlist = paramhead; #ifdef TS ++ts_n_macparam; ts_s_macparam += sizeof *paramlist * nparleft; ts_s_macparam_tot += sizeof *paramlist * nparleft; #endif blanks(); while (ch == EOL && !eofile) { skipeol(); blanks(); } if (ch != '(') { if (nparleft > 0) /* macro has params, doesn't match bare word */ { symptr->name.namea[0] &= 0x7f; /* UnSMUDGE macro definition */ outstr(symptr->name.namea); return; } error("missing '('"); } else { gch1(); while (nparleft) { --nparleft; ++ngoodparams; *(paramlist++) = charptr; quote = 0; lpcount = 1; while (TRUE) { if (ch == '\\') { gch1(); if (charptr >= char1top) *(paramlist - 1) = growobject(*(paramlist - 1), 2); #ifdef TS ++ts_n_macparam_string_quoted; ++ts_s_macparam_string; ++ts_s_macparam_string_tot; #endif *charptr++ = '\\'; } else if (quote) { if (ch == quote) quote = 0; } else if (ch == '"' || ch == '\'') quote = ch; else if (ch == '/') { if (SYMOFCHAR(*(lineptr + 1)) == SPECIALCHAR) { gch1(); ch = *--lineptr = '/'; /* pushback */ } if (*(lineptr + 1) == '*') { gch1(); skipcomment(); ch = *--lineptr = ' '; /* pushback */ } } else if (ch == '(') ++lpcount; else if ((ch == ')' && --lpcount == 0) || (ch == ',' && lpcount == 1)) break; if (ch == EOL) ch = ' '; if (charptr >= char1top) *(paramlist - 1) = growobject(*(paramlist - 1), 2); #ifdef TS ++ts_n_macparam_string_ordinary; ++ts_s_macparam_string; ++ts_s_macparam_string_tot; #endif *charptr++ = ch; if (*lineptr == EOL) { skipeol(); /* macro case disposed of already */ if (SYMOFCHAR(ch) == SPECIALCHAR) specialchar(); if (eofile) break; } else gch1(); } #ifdef TS ++ts_n_macparam_string_term; ++ts_s_macparam_string; ++ts_s_macparam_string_tot; #endif *charptr++ = EOL; { register char *newparam; register char *oldparam; unsigned size; oldparam = *(paramlist - 1); size = (/* size_t */ unsigned) (charptr - oldparam); newparam = ourmalloc(size); #ifdef TS ts_s_macparam_string_alloced += size; ts_s_macparam_string_alloced_tot += size; #endif memcpy(newparam, oldparam, size); *(paramlist - 1) = newparam; #ifdef TS ts_s_macparam_string_tot -= charptr - oldparam; #endif charptr = oldparam; } if (ch == ',') gch1(); else break; } } blanks(); while (ch == EOL && !eofile) { skipeol(); blanks(); } if (eofile) eofin("macro parameter expansion"); if (nparleft) { error("too few macro parameters"); do *(paramlist++) = dummyparam; while (--nparleft); } if (ch == ')') gch1(); else if (ch == ',') { error("too many macro parameters"); /* XXX - should read and discard extra parameters. Also check * for eof at end. */ while (ch != ')') { if (ch == EOL) { skipeol(); if (eofile) break; continue; } gch1(); } } else error("missing ')'"); } if (symptr->storage == DEF_LINE) { char *str; str = pushudec(symptr->offset.offp + MAX__LINE__, input.linenumber); memcpy(symptr->offset.offp, str, /* size_t */ (unsigned) (symptr->offset.offp + MAX__LINE__ + 1 + 1 - str)); } { register struct macroposition *mpptr; mpptr = ¯ostack[maclevel]; mpptr->paramlist = paramhead; mpptr->maclineptr = lineptr; ch = *(lineptr = symptr->offset.offp); mpptr->inparam = FALSE; mpptr->nparam = ngoodparams; mpptr->symptr = symptr; mpptr->symptr->name.namea[0] |= 0x80; /* SMUDGE macro definition */ ++maclevel; } /* comment(); outstr("MACRO (level "); outudec((unsigned) maclevel); outstr(") "); outline(lineptr); */ } /* getparnames() - get parameter names during macro definition, return count */ PRIVATE fastin_pt getparnames() { fastin_t nparnames; struct symstruct *symptr; nparnames = 0; gch1(); while (blanksident()) { if ((symptr = findlorg(gsname)) != NULL && symptr->level == level) error("repeated parameter"); symptr = addloc(gsname, itype); if (nparnames >= MAX_PARAM) limiterror("too many macro parameters (128)"); else ++nparnames; /* number params from 1 */ symptr->indcount = nparnames; /* param number */ blanks(); if (ch == ',') gch1(); } if (ch != ')') error("missing ')'"); else gch1(); return nparnames; } /* ifcontrol - process #if, #ifdef, #ifndef */ PRIVATE void ifcontrol(ifcase) sym_pt ifcase; { bool_t iftrue; struct symstruct *symptr; if (iflevel >= MAX_IF) { limiterror("#if's nested too deeply (33 levels)"); return; } { register struct ifstruct *ifptr; ifptr = &ifstack[(int)iflevel++]; ifptr->elseflag = ifstate.elseflag; ifptr->ifflag = ifstate.ifflag; ifstate.elseflag = FALSE; /* prepare for !(if now)||(if future)*/ } if (ifstate.ifflag) { if ((sym_t) ifcase != IFCNTL) { iftrue = FALSE; if (blanksident() && (symptr = findlorg(gsname)) != NULL && symptr->flags == DEFINITION) iftrue = TRUE; } else { incppexpr = TRUE; nextsym(); iftrue = constexpression() != 0; incppexpr = FALSE; } if ((!iftrue && (sym_t) ifcase != IFNDEFCNTL) || (iftrue && (sym_t) ifcase == IFNDEFCNTL)) { ifstate.elseflag = TRUE; ifstate.ifflag = FALSE; } } } /* ifinit() - initialise if state */ PUBLIC void ifinit() { ifstate.ifflag = TRUE; } PUBLIC int ifcheck() { return (ifstate.ifflag == TRUE); } /* leavemac() - leave current and further macro substrings till not at end */ PUBLIC void leavemac() { register struct macroposition *mpptr; do { mpptr = ¯ostack[maclevel - 1]; if (mpptr->inparam) { lineptr = ++mpptr->paramspot; mpptr->inparam = FALSE; } else { mpptr->symptr->name.namea[0] &= 0x7F;/* UnSMUDGE macro definition */ ch = *++lineptr; /* gch1() would mess up next param == EOL-1 */ if (ch != 0 && mpptr->paramlist) { mpptr->paramspot = lineptr; lineptr = mpptr->paramlist[ch - 1]; mpptr->inparam = TRUE; } else { lineptr = mpptr->maclineptr; if (mpptr->nparam != 0) { register char **paramlist; #ifdef TS ts_s_macparam_tot -= sizeof *paramlist * mpptr->nparam; #endif paramlist = mpptr->paramlist; do { #ifdef TS ts_s_macparam_string_alloced_tot -= strchr(*paramlist, EOL) - *paramlist + 1; #endif ourfree(*paramlist++); } while (--mpptr->nparam != 0); ourfree(mpptr->paramlist); } --maclevel; } } } while ((ch = *lineptr) == EOL && maclevel != 0); } PUBLIC void predefine() { definestring("__BCC__ 1"); definestring("__LINE__ 0123456789"); /* MAX__LINE__ digits */ findlorg("__LINE__")->storage = DEF_LINE; } PUBLIC char *savedlineptr() { return macrostack[0].maclineptr; } PUBLIC void skipcomment() { /* Skip current char, then everything up to '*' '/' or eof. */ gch1(); do { while (TRUE) { { register char *reglineptr; reglineptr = lineptr; symofchar['*'] = SPECIALCHAR; while (SYMOFCHAR(*reglineptr) != SPECIALCHAR) ++reglineptr; symofchar['*'] = STAR; lineptr = reglineptr; if (*reglineptr == '*') break; ch = *reglineptr; } specialchar(); if (ch == EOL) { skipeol(); if (eofile) break; } else if (ch != '*') gch1(); } gch1(); if (eofile) { eofin("comment"); return; } } while (ch != '/'); gch1(); } /* skipline() - skip rest of line */ PUBLIC void skipline() { while (TRUE) { blanks(); if (ch == EOL) return; if (ch == '\\') { gch1(); if (ch == EOL) /* XXX - I think blanks() eats \EOL */ return; gch1(); /* XXX - escape() better? */ } else if (ch == '"' || ch == '\'') { stringorcharconst(); charptr = constant.value.s; } else gch1(); } } /* undef() - process #undef */ PRIVATE void undef() { struct symstruct *symptr; if (blanksident() && (symptr = findlorg(gsname)) != NULL && symptr->flags == DEFINITION) delsym(symptr); } PUBLIC void undefinestring(str) char *str; { defineorundefinestring(str, FALSE); } #endif dev86-0.16.21/bcc/preserve.c000066400000000000000000000114011231050321700153320ustar00rootroot00000000000000/* preserve.c - preserve opererands or registers in use for bcc */ /* Copyright (C) 1992 Bruce Evans */ #include "bcc.h" #include "gencode.h" #include "reg.h" #include "type.h" #include "scan.h" /* change stack ptr without changing condition codes */ PUBLIC void changesp(newsp, absflag) offset_T newsp; bool_pt absflag; { if (newsp != sp || ((bool_t) absflag && switchnow != NULL)) { #ifdef FRAMEPOINTER if (newsp != framep || (!(bool_t) absflag && switchnow != NULL)) { int off; outleasp(); if (!(bool_t) absflag && switchnow != NULL) outswoffset(off = newsp); else outoffset(off = newsp - framep); #ifndef NO_DEL_PUSH if (optimise && !callersaves && off < 0) { outstr("+"); outstr(funcname); outstr(".off"); } #endif outindframereg(); outnl(); } else regtransfer(FRAMEREG, STACKREG); sp = newsp; if (framep == 0) bugerror("no frame pointer"); #else # ifdef I8088 outleasp(); outoffset(newsp - sp); outindstackreg(); outnl(); # else modstk(newsp); /* this should preserve CC */ # endif #endif /* FRAMEPOINTER */ } } /* load source to any while preserving target */ PUBLIC void loadpres(source, target) struct symstruct *source; struct symstruct *target; { store_t regmark; if (target->storage & ALLDATREGS) { if (source->type->scalar & CHAR) { push(target); load(source, DREG); } else load(source, getindexreg()); } else { regmark = reguse; reguse |= target->storage; loadany(source); reguse = regmark; } } /* change stack ptr */ PUBLIC void modstk(newsp) offset_T newsp; { if (newsp != sp) { #ifdef FRAMEPOINTER if (newsp != framep || framep == 0 || switchnow != NULL) addconst(newsp - sp, STACKREG); else regtransfer(FRAMEREG, STACKREG); #else # ifdef I8088 addconst(newsp - sp, STACKREG); # else outleasp(); outoffset(newsp - sp); outncspregname(); # endif #endif sp = newsp; } } /* preserve target without changing source */ PUBLIC void pres2(source, target) struct symstruct *source; struct symstruct *target; { if (target->storage & allregs) { if (target->storage & (allregs - allindregs) /* XXX */ || (target->indcount == 0 && target->type->scalar & (DLONG | RSCALAR))) push(target); /* XXX - perhaps not float */ else if (((target->storage | reguse) & allindregs) == allindregs) { loadpres(target, source); push(target); } else reguse |= target->storage; } } /* preserve source */ PUBLIC void preserve(source) struct symstruct *source; { if (source->storage & allregs) { if (source->storage & (allregs - allindregs) /* XXX */ || ((source->storage | reguse) & allindregs) == allindregs) push(source); else reguse |= source->storage; } } /* preserve lvalue target without changing source or target */ PUBLIC store_pt preslval(source, target) struct symstruct *source; struct symstruct *target; { store_pt regpushed; if (target->indcount == 0) reguse &= ~target->storage; else reguse = (target->storage | reguse) & allindregs; if (!((source->type->scalar | target->type->scalar) & (DLONG | RSCALAR)) || reguse != allindregs) return 0; /* XXX - perhaps not float */ reguse = source->storage | target->storage; /* free one other than s/t */ pushreg(regpushed = getindexreg()); reguse = ~(store_t) regpushed & allindregs; return regpushed; } PUBLIC void recovlist(reglist) store_pt reglist; { poplist(reglist); reguse |= (store_t) reglist; } #ifdef I8088 PRIVATE smalin_t regoffset[] = {0, 0, 0, 1, 2, 3, 0, 0, 0, 4, 5}; /* CONSTANT, BREG, ax = DREG, bx = INDREG0, si = INDREG1, di = INDREG2 */ /* LOCAL, GLOBAL, STACKREG, cx = DATREG1, dx = DATREG2 */ #endif #ifdef MC6809 PRIVATE smalin_t regoffset[] = {0, 0, 0, 1, 3, 2}; /* CONSTANT, BREG, DREG, XREG = INDREG0, UREG = INDREG1, YREG = INDREG2 */ #endif PUBLIC void savereturn(savelist, saveoffset) store_pt savelist; offset_T saveoffset; { store_t reg; smalin_t *regoffptr; offset_T spoffset; if (savelist == 0) return; #ifdef MC6809 /* must check this */ if (savelist == XREG || savelist == INDREG1) saveoffset -= accregsize; /* patch for DREG/YREG not saved */ #endif for (reg = 1, regoffptr = regoffset; reg != 0; ++regoffptr, reg <<= 1) if (reg & savelist) { outstore(); spoffset = saveoffset + *regoffptr * maxregsize; #ifdef I8088 # ifdef FRAMEPOINTER if (switchnow != NULL) outswoffset(spoffset); else outoffset(spoffset - framep); outindframereg(); # else outoffset(spoffset - sp); outindstackreg(); # endif outncregname(reg); #endif #ifdef MC6809 if (reg == YREG) bumplc(); outregname(reg); outtab(); outoffset(spoffset - sp); outncspregname(); #endif } } dev86-0.16.21/bcc/proto.h000066400000000000000000000304311231050321700146530ustar00rootroot00000000000000/* proto.h - extern functions for bcc */ /* Copyright (C) 1992 Bruce Evans */ /* assign.c */ void assign P((struct symstruct *source, struct symstruct *target)); void cast P((struct typestruct *type, struct symstruct *target)); void extend P((struct symstruct *target)); /* codefrag.c */ void adjsp P((label_no label)); void clrBreg P((void)); void comment P((void)); void ctoi P((void)); void defbyte P((void)); void deflong P((uoffset_T value)); void defword P((void)); void defdword P((void)); void even P((void)); void negDreg P((void)); void comDreg P((void)); void outadd P((void)); void outaddsp P((void)); void outcalladr P((void)); void outcmp P((void)); void outdec P((void)); void outdword P((void)); void outfail P((void)); void outinc P((void)); void outindleft P((void)); void outindright P((void)); void outindstackreg P((void)); void outldaccum P((void)); void outldmulreg P((void)); void outlea P((void)); void outleasp P((void)); void outload P((void)); void outmulmulreg P((void)); void outopsep P((void)); void outpshs P((void)); void outpuls P((void)); void outreturn P((void)); void outstore P((void)); void outsub P((void)); void outtest P((void)); void outword P((void)); void sctoi P((void)); void stoi P((void)); void ustoi P((void)); void outABX P((void)); void outdirectpage P((void)); void outextended P((void)); void outncspregname P((void)); void outindframereg P((void)); void adc0 P((void)); void addconst P((offset_T offset, store_pt reg)); void adjlc P((offset_T offset, store_pt reg)); void andconst P((offset_T offset)); void bssseg P((void)); label_no casejump P((void)); void common P((char *name)); void cseg P((void)); void defnulls P((uoffset_T nullcount)); label_no defstr P((char *sptr, char *stop, bool_pt dataflag)); bool_pt diveasy P((value_t divisor, bool_pt uflag)); void dpseg P((void)); void dseg P((void)); void equ P((char *name, char *string)); void equlab P((label_no label, offset_T offset)); void globl P((char *name)); void import P((char *name)); void itol P((store_pt reg)); void lcommlab P((label_no label)); void lcommon P((char *name)); void lea P((offset_T offset, store_pt sourcereg, store_pt targreg)); void loadconst P((offset_T offset, store_pt reg)); int lslconst P((value_t shift, store_pt reg)); int lsrconst P((value_t shift, store_pt reg, bool_pt uflag)); bool_pt modeasy P((value_t divisor, bool_pt uflag)); bool_pt muleasy P((uvalue_t factor, store_pt reg)); void negreg P((store_pt reg)); char *opstring P((op_pt op)); void outccname P((char *name)); void outhiaccum P((void)); void outimmadr P((offset_T offset)); void outimadj P((offset_T offset, store_pt targreg)); void outimmed P((void)); void outjumpstring P((void)); void outnccname P((char *name)); void outncimmadr P((offset_T offset)); void outoffset P((offset_T offset)); void public P((char *name)); void private P((char *name)); void regexchange P((store_pt sourcereg, store_pt targreg)); void regtransfer P((store_pt sourcereg, store_pt targreg)); void sbc0 P((void)); void set P((char *name, offset_T value)); void sl1 P((store_pt reg)); void slconst P((value_t shift, store_pt reg)); void srconst P((value_t shift, bool_pt uflag)); void uitol P((store_pt reg)); void restoreopreg P((void)); void saveopreg P((void)); /* dbnode.c */ void dbitem P((struct symstruct *item)); void dbtype P((struct typestruct *type)); void dbnode P((struct nodestruct *exp)); void dbnodeswap P((void)); /* declare.c */ void colon P((void)); void decllist P((void)); void lparen P((void)); void needvarname P((void)); void program P((void)); void rbrace P((void)); void rbracket P((void)); void rparen P((void)); void semicolon P((void)); struct typestruct *typename P((void)); #ifndef VERY_SMALL_MEMORY int lastanon P((void)); void anonname P((char *name, int i)); void anonstruct P((void)); #endif /* express.c */ struct nodestruct *assignment_exp P((void)); struct nodestruct *expression P((void)); /* exptree.c */ struct nodestruct *castnode P((struct typestruct *type, struct nodestruct *nodeptr)); void etreeinit P((void)); struct nodestruct *leafnode P((struct symstruct *source)); struct nodestruct *node P((op_pt t, struct nodestruct *p1, struct nodestruct *p2)); /* floatop.c */ bool_pt f_indirect P((struct symstruct *target)); void float1op P((op_pt op, struct symstruct *source)); void floatop P((op_pt op, struct symstruct *source, struct symstruct *target)); void fpush P((struct symstruct *source)); void justpushed P((struct symstruct *target)); /* function.c */ void call P((char *name)); void function P((struct symstruct *source)); void ldregargs P((void)); void loadretexpression P((void)); void listo P((struct symstruct *target, offset_T lastargsp)); void listroot P((struct symstruct *target)); void popframe P((void)); void reslocals P((void)); void ret P((void)); /* gencode.c */ void bileaf P((struct nodestruct *exp)); fastin_pt bitcount P((uvalue_t number)); void codeinit P((void)); fastin_pt highbit P((uvalue_t number)); void makeleaf P((struct nodestruct *exp)); /* genloads.c */ void addoffset P((struct symstruct *source)); void address P((struct symstruct *source)); void exchange P((struct symstruct *source, struct symstruct *target)); store_pt getindexreg P((void)); void indexadr P((struct symstruct *source, struct symstruct *target)); void indirec P((struct symstruct *source)); void load P((struct symstruct *source, store_pt targreg)); void loadany P((struct symstruct *source)); void loadreg P((struct symstruct *source, store_pt targreg)); void makelessindirect P((struct symstruct *source)); void movereg P((struct symstruct *source, store_pt targreg)); void onstack P((struct symstruct *target)); void outadr P((struct symstruct *adr)); void outcregname P((store_pt reg)); void outncregname P((store_pt reg)); void outnregname P((store_pt reg)); void outregname P((store_pt reg)); void outshortregname P((store_pt reg)); void pointat P((struct symstruct *target)); void poplist P((store_pt reglist)); void push P((struct symstruct *source)); void pushlist P((store_pt reglist)); void pushreg P((store_pt reg)); void storereg P((store_pt sourcereg, struct symstruct *target)); void struc P((struct symstruct *source, struct symstruct *target)); void transfer P((struct symstruct *source, store_pt targreg)); /* glogcode.c */ void cmp P((struct symstruct *source, struct symstruct *target, ccode_t *pcondtrue)); void condop P((struct nodestruct *exp)); void jumpfalse P((struct nodestruct *exp, label_no label)); void jumptrue P((struct nodestruct *exp, label_no label)); void logop P((struct nodestruct *exp)); /* hardop.c */ void add P((struct symstruct *source, struct symstruct *target)); void incdec P((op_pt op, struct symstruct *source)); void neg P((struct symstruct *target)); void not P((struct symstruct *target)); void op1 P((op_pt op, struct symstruct *source, struct symstruct *target)); void ptrsub P((struct symstruct *source, struct symstruct *target)); void sub P((struct symstruct *source, struct symstruct *target)); /* input.c */ void closein P((void)); void errorloc P((void)); void gch1 P((void)); void include P((void)); void openio P((int argc, char **argv)); void skipeol P((void)); void specialchar P((void)); void linecontol P((void)); /* label.c */ void bumplc P((void)); void bumplc2 P((void)); void bumplc3 P((void)); void clearfunclabels P((void)); void clearlabels P((char *patchbuf, char *patchtop)); void clearswitchlabels P((void)); uoffset_T getlc P((void)); void deflabel P((label_no label)); label_no gethighlabel P((void)); label_no getlabel P((void)); void jump P((label_no label)); void lbranch P((ccode_pt cond, label_no label)); struct symstruct *namedlabel P((void)); void outcond P((ccode_pt cond)); void outlabel P((label_no label)); void outnlabel P((label_no label)); void sbranch P((ccode_pt cond, label_no label)); void unbumplc P((void)); /* loadexp.c */ value_t constexpression P((void)); void initexpression P((struct typestruct *type)); struct typestruct *loadexpression P((store_pt targreg, struct typestruct *targtype)); /* longop.c */ void longop P((op_pt op, struct symstruct *source, struct symstruct *target)); void long1op P((op_pt op, struct symstruct *target)); void outlongendian P((void)); /* output.c */ void bugerror P((char *message)); void closeout P((void)); void error P((char *message)); void error2error P((char *message1, char *message2)); void fatalerror P((char *message)); void finishup P((void)); void flushout P((void)); void limiterror P((char *message)); void initout P((void)); void openout P((char *oname)); void outbyte P((int ch)); void outcomma P((void)); void outcpplinenumber P((unsigned nr, char *fname, char *str)); void outhex P((uoffset_T num)); void outhexdigs P((uoffset_T num)); void outline P((char *s)); void outminus P((void)); void outnl P((void)); void outnbyte P((int byte)); void outnhex P((uoffset_T num)); void outnop1str P((char *s)); void outnop2str P((char *s)); void outnstr P((char *s)); void outop0str P((char *s)); void outop1str P((char *s)); void outop2str P((char *s)); void outop3str P((char *s)); void outplus P((void)); void outshex P((offset_T num)); void outstr P((char *s)); void outtab P((void)); void outudec P((unsigned num)); #ifndef I8088 void outuvalue P((uvalue_t num)); void outvalue P((value_t num)); #endif char *pushudec P((char *s, unsigned num)); void setoutbufs P((void)); /* preproc.c */ void blanks P((void)); bool_pt blanksident P((void)); void checknotinif P((void)); void define P((void)); void definestring P((char *str)); void docontrol P((void)); void entermac P((void)); void ifinit P((void)); int ifcheck P((void)); void leavemac P((void)); void predefine P((void)); char *savedlineptr P((void)); void skipcomment P((void)); void skipline P((void)); void undefinestring P((char *str)); /* preserve.c */ void changesp P((offset_T newsp, bool_pt absflag)); void loadpres P((struct symstruct *source, struct symstruct *target)); void modstk P((offset_T newsp)); void pres2 P((struct symstruct *source, struct symstruct *target)); void preserve P((struct symstruct *source)); store_pt preslval P((struct symstruct *source, struct symstruct *target)); void recovlist P((store_pt reglist)); void savereturn P((store_pt savelist, offset_T saveoffset)); /* sc.c */ int main P((int argc, char **argv)); /* scan.c */ void cppscan P((int asmonly)); void eofin P((char *message)); bool_pt isident P((void)); void nextsym P((void)); void stringorcharconst P((void)); /* softop.c */ void softop P((op_pt op, struct symstruct *source, struct symstruct *target)); /* state.c */ void compound P((void)); void outswoffset P((offset_T offset)); void outswstacklab P((void)); void doasm P((void)); /* table.c */ struct symstruct *addglb P((char *name, struct typestruct *type)); struct symstruct *addloc P((char *name, struct typestruct *type)); struct symstruct *addlorg P((char *name, struct typestruct *type)); void addsym P((char *name, struct typestruct *type, struct symstruct *symptr)); struct symstruct *constsym P((value_t intconst)); void delsym P((struct symstruct *symptr)); void dumpglbs P((void)); void dumplocs P((void)); void dumpstrings P((void)); struct symstruct *exprsym P((struct symstruct *symptr)); struct symstruct *findlorg P((char *name)); struct symstruct *findstruct P((char *name)); struct symstruct **gethashptr P((char *sname)); void growheap P((unsigned size)); void *growobject P((void *object, unsigned extra)); label_no holdstr P((char *sptr, char *stop)); void newlevel P((void)); void oldlevel P((void)); void ourfree P((void *ptr)); void *ourmalloc P((unsigned nbytes)); void outofmemoryerror P((char *message)); void *qmalloc P((unsigned size)); void swapsym P((struct symstruct *sym1, struct symstruct *sym2)); void syminit P((void)); #ifndef VERY_SMALL_MEMORY struct symstruct *findstrm P((struct typestruct *type, char *name)); #endif /* type.c */ struct typestruct *addstruct P((char *structname)); #ifndef VERY_SMALL_MEMORY void laststruct P((char *sname)); #endif struct typestruct *iscalartotype P((scalar_pt scalar)); struct typestruct *newtype P((void)); void outntypechar P((struct typestruct *type)); struct typestruct *pointype P((struct typestruct *type)); struct typestruct *prefix P((constr_pt constructor, uoffset_T size, struct typestruct *type)); struct typestruct *promote P((struct typestruct *type)); struct typestruct *tosigned P((struct typestruct *type)); struct typestruct *tounsigned P((struct typestruct *type)); void typeinit P((void)); dev86-0.16.21/bcc/reg.h000066400000000000000000000101731231050321700142660ustar00rootroot00000000000000/* reg.h - registers for bcc */ /* Copyright (C) 1992 Bruce Evans */ /* The compiler generates "addresses" of the form indirect(indcount) (rx + offset) where rx is a machine register (possibly null) n is the indirection count (possibly 0) offset is a constant. It does not support more complicated formats like indirect(indcount) (rx + index * scale + offset). The register is coded as bit flag in the storage component of the symbol structure. This allows groups of registers to be tested using bitwise "&". Throughout the compiler, the group of these bit flags has the type reg_t. If there are only a few registers, reg_t can be an unsigned char. It must be unsigned if the high bit is used, to avoid sign extension problems. For bootstrapping the compiler from a compiler with no unsigned char, the unsigned type should be used instead (with a signifigant waste of storage). The bit flags should really be defined as ((reg_t) whatever) but then they would not (necessarily) be constant expressions and couldn't be used in switch selectors or (worse) preprocessor expressions. The CONSTANT and GLOBAL (non-) register bits are almost equivalent. A constant with nonzero indirection is marked as a GLOBAL and not a CONSTANT. This makes it easier to test for a constant CONSTANT. Globals which are formed in this way are converted to constants if their indirection count is reset to 0 (by & operator). */ /* register bit flags */ #define NOSTORAGE 0x000 /* structure/union member offsets */ #define CONSTANT 0x001 /* offsets are values */ #define BREG 0x002 #define DREG 0x004 #define INDREG0 0x008 #define INDREG1 0x010 #define INDREG2 0x020 #define LOCAL 0x040 #define GLOBAL 0x080 /* offsets from storage name or 0 */ #define CCREG CONSTANT /* arg to PSHS/PULS functions only */ #ifdef I8088 # ifdef FRAMEPOINTER # define FRAMEREG LOCAL # endif # define STACKREG 0x100 # define DATREG1 0x200 # define DATREG2 0x400 # define DATREG1B 0x800 #endif #ifdef MC6809 # define DPREG LOCAL /* arg to PSHS/PULS functions only */ # define PCREG GLOBAL /* arg to PSHS/PULS functions only */ #endif /* data for pushing and pulling registers */ #define MINREGCHAR 'A' #ifdef I8088 # define FLAGSREGCHAR 'f' # define pushchar() pushlist(AXREG) #endif #ifdef MC6809 # define pushchar() pushlist(BREG) #endif /* special registers */ #ifdef I8088 # define ALREG BREG # define AXREG DREG # define DXREG DATREG2 # define MULREG DATREG1B # define SHIFTREG DATREG1B #endif #ifdef MC6809 # define XREG INDREG0 /* XREG is special for ABX in index & switch */ # define YREG INDREG2 /* XREG and YREG allow LEA (Z test) in cmp() */ #endif /* groups of registers */ #define ALLDATREGS (BREG|DREG) #define CHARREGS BREG #define MAXREGS 1 /* number of data registers */ #define WORKDATREGS (BREG|DREG) /* function call and return registers */ #define ARGREG RETURNREG /* for (1st) argument */ #define LONGARGREGS LONGRETURNREGS /* for long or float arg */ #define LONGRETURNREGS (INDREG0|LONGREG2) #define LONGREG2 DREG #ifdef I8088 # define LONGRETSPECIAL /* LONGRETURNREGS!=RETURNREG && RETURNREG==LONGREG2 */ # define RETURNREG DREG #endif #ifdef MC6809 # define RETURNREG INDREG0 #endif /* registers which can be pulled as a group with the program counter */ /* to perform an efficient function return */ #ifdef MC6809 #define JUNK1REGS BREG /* 1 bytes locals to discard */ #define JUNK2REGS INDREG2 #define JUNK3REGS (BREG|INDREG2) #define JUNK4REGS (INDREG1|INDREG2) #endif /* registers which can be pushed as a group with the first argument */ /* to perform an efficient function startup */ #ifdef MC6809 # define LOC1REGS CCREG /* 1 bytes local to allocate */ # define LOC2REGS DREG # define LOC3REGS (CCREG|DREG) # define LOC4REGS (CCREG|DREG|DPREG) # endif /* registers to be used by software operations */ #define OPREG INDREG0 /* 2nd reg for software ops (1st is DREG) */ #define OPWORKREG INDREG2 /* 3rd register for software ops */ /* maximum indirection count for 1 instruction */ #ifdef I8088 # define MAXINDIRECT 1 #endif #ifdef MC6809 # define MAXINDIRECT 2 #endif dev86-0.16.21/bcc/sc.h000066400000000000000000000017631231050321700141230ustar00rootroot00000000000000/* sc.h - storage classes for bcc */ /* Copyright (C) 1992 Bruce Evans */ #ifdef MC6809 #define DIRECTPAGE 0x01 /* modifier on global to show in dpseg */ #endif #define EXTERNAL 0x02 /* external */ #define STATIC 0x04 /* symbols with flags above the 1st initialised value are not to be dumped */ #define MAXDUMPFLAG 0x07 #define INITIALIZED 0x08 /* modifier on global to show initialized */ #define LABELLED 0x10 /* modifier on static to show labelled */ /* and on STRING to show labelled */ /* remaining "flags" are numbers, not flags */ /* they are disjoint from all combinations of flags above */ /* except STRING => LABELLED (and no other flags) */ #define DEFINITION 0x20 /* #defined name */ #define KEYWORD 0x40 /* reserved word for C */ #define STRUCTNAME 0x60 /* struct/union name or member name */ #define REGVAR 0x80 /* register variable */ #define TEMP 0xa0 /* temporary on stack expression eval */ #define STRING 0xc0 /* string constant (=> LABELLED) */ dev86-0.16.21/bcc/scan.c000066400000000000000000000436601231050321700144370ustar00rootroot00000000000000/* scan.c - lexical analyser for bcc */ /* Copyright (C) 1992 Bruce Evans */ #define GCH1() do { if (SYMOFCHAR(ch = *++lineptr) == SPECIALCHAR) specialchar(); } while (0) #include "bcc.h" #include "input.h" #include "os.h" #include "output.h" #include "sc.h" #include "sizes.h" #include "table.h" #include "type.h" #ifndef VERY_SMALL_MEMORY #include "parse.h" #endif #undef EXTERN #define EXTERN #include "scan.h" PUBLIC sym_t symofchar[256] = { BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, WHITESPACE, SPECIALCHAR, BADCHAR, WHITESPACE, SPECIALCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, WHITESPACE, LOGNOTOP, STRINGCONST, CONTROL, /* !"# */ BADCHAR, MODOP, AMPERSAND, CHARCONST, /* $%&' */ LPAREN, RPAREN, STAR, ADDOP, /* ()*+ */ COMMA, HYPHEN, FLOATCONST, SLASH, /* ,-./ */ INTCONST, INTCONST, INTCONST, INTCONST, /* 0123 */ INTCONST, INTCONST, INTCONST, INTCONST, /* 4567 */ INTCONST, INTCONST, COLON, SEMICOLON, /* 89:; */ LTOP, ASSIGNOP, GTOP, CONDOP, /* <=>? */ BADCHAR, IDENT, IDENT, IDENT, /* @ABC */ IDENT, IDENT, IDENT, IDENT, /* DEFG */ IDENT, IDENT, IDENT, IDENT, /* HIJK */ IDENT, IDENT, IDENT, IDENT, /* LMNO */ IDENT, IDENT, IDENT, IDENT, /* PQRS */ IDENT, IDENT, IDENT, IDENT, /* TUVW */ IDENT, IDENT, IDENT, LBRACKET, /* XYZ[ */ SPECIALCHAR, RBRACKET, EOROP, IDENT, /* \]^_ */ BADCHAR, IDENT, IDENT, IDENT, /* `abc */ IDENT, IDENT, IDENT, IDENT, /* defg */ IDENT, IDENT, IDENT, IDENT, /* hijk */ IDENT, IDENT, IDENT, IDENT, /* lmno */ IDENT, IDENT, IDENT, IDENT, /* pqrs */ IDENT, IDENT, IDENT, IDENT, /* tuvw */ IDENT, IDENT, IDENT, LBRACE, /* xyz{ */ OROP, RBRACE, NOTOP, BADCHAR, /* |}~ */ BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR }; FORWARD void getident P((void)); FORWARD void intconst P((void)); FORWARD void ppnumber P((void)); PRIVATE void newstringorcharconst P((void)); /* skip white space up to end of line (skip EOL's if in comments) */ PUBLIC void blanks() { register char *reglineptr; while (TRUE) { reglineptr = lineptr; while (SYMOFCHAR(*reglineptr) == WHITESPACE) ++reglineptr; lineptr = reglineptr; if (SYMOFCHAR(ch = *reglineptr) == SPECIALCHAR) { specialchar(); if (ch == EOL) return; if (SYMOFCHAR(ch) == WHITESPACE) continue; reglineptr = lineptr; } #ifdef BUILTIN_CPP if (*reglineptr != '/') return; if (SYMOFCHAR(*(reglineptr + 1)) == SPECIALCHAR) { ch = *(lineptr = reglineptr + 1); specialchar(); ch = *(reglineptr = --lineptr) = '/'; /* pushback */ } if (*(reglineptr + 1) != '*') return; gch1(); skipcomment(); #else return; #endif } } PUBLIC void cppscan(asm_only) int asm_only; { int start_of_line = 1; #ifndef ASM_BARE #ifdef BUILTIN_CPP virtual_nl = 1; #endif #endif while (!asm_only || asmmode) { int cppsym = SYMOFCHAR(ch); switch (cppsym) { case CONTROL: if( !start_of_line ) cppsym=BADCHAR; break; case WHITESPACE: break; case SPECIALCHAR: if( ch == '\\' ) cppsym=BADCHAR; start_of_line = 1; break; case CHARCONST: case STRINGCONST: if( asmmode ) cppsym=BADCHAR; default: start_of_line = 0; } switch (cppsym) { case CHARCONST: case STRINGCONST: stringorcharconst(); *charptr = 0; /* room reserved */ outstr(constant.value.s); /* XXX - embedded null would kill it */ charptr = constant.value.s; break; #ifdef BUILTIN_CPP case CONTROL: gch1(); if (maclevel != 0) { error("# in a macro: not preprocessed"); /* XXX? */ break; } else { docontrol(); #ifndef ASM_BARE virtual_nl = 1; #endif continue; } case SLASH: gch1(); if (ch == '*') { skipcomment(); break; } outbyte('/'); break; #else /* !BUILTIN_CPP */ case CONTROL: gch1(); docontrol(); continue; #endif case FLOATCONST: gch1(); if (SYMOFCHAR(ch) == INTCONST) { --lineptr; ch = '.'; /* pushback */ ppnumber(); outstr(constant.value.s); charptr = constant.value.s; } else outbyte('.'); break; case IDENT: getident(); #ifdef BUILTIN_CPP if ((gsymptr = findlorg(gsname)) != NULL) { if (gsymptr->flags == DEFINITION) { entermac(); break; } } #endif outstr(gsname); break; case INTCONST: ppnumber(); outstr(constant.value.s); charptr = constant.value.s; break; case SPECIALCHAR: specialchar(); /* XXX - this is necessary because entermac * and skipeol can leave lineptr at a special * char although GCH1 cannot. entermac would * be easy to fix, but too many places already * have to handle the extra work after skipeol * for other reasons. */ if (ch == EOL) { skipeol(); if (eofile) return; break; } #ifdef COEOL if (ch == COEOL) { gch1(); break; } #endif if (SYMOFCHAR(ch) != SPECIALCHAR) break; /* specialchar advanced the input */ /* must be '\\' */ default: /* Allow for multi-instruction lines in asm */ #ifdef BUILTIN_CPP if( ch == '^' && !orig_cppmode && asmmode ) ch='\n'; #else if( ch == '^' && asmmode ) ch='\n'; #endif OUTBYTE(ch); ch = *++lineptr; if (SYMOFCHAR(ch) == SPECIALCHAR && ch != '\\') specialchar(); break; } #ifndef ASM_BARE #ifdef BUILTIN_CPP virtual_nl = 0; #endif #endif } } PUBLIC void eofin(message) char *message; { error2error("end of file in ", message); } /* get identifier in gsname == gs2name + 2 */ PRIVATE void getident() { register int c; register char *idptr; register int length; register char *reglineptr; idptr = gsname; length = NAMESIZE; reglineptr = lineptr; c = ch; more: do { *idptr++ = c; c = (unsigned char) *++reglineptr; } while (symofchar[c] <= MAXIDSYM && --length != 0); ch = c; *idptr = 0; debug(7, "Got ident %s", gsname); lineptr = reglineptr; if (symofchar[c] == SPECIALCHAR) { specialchar(); if (SYMOFCHAR(ch) <= MAXIDSYM && length != 0) { reglineptr = lineptr; c = ch; goto more; } } } /* return nonzero if at an identifier */ PUBLIC bool_pt isident() { if (SYMOFCHAR(ch) != IDENT) return FALSE; getident(); return TRUE; } PRIVATE void intconst() { fastin_t base; fastin_t digit; register char *digptr; fastin_t lcount; fastin_t ucount; bool_t dflag; ppnumber(); digptr = charptr = constant.value.s; if (*digptr == '0') { if (digptr[1] != 'x' && digptr[1] != 'X') base = 8; else { base = 16; digptr += 2; } } else base = 10; dflag = FALSE; if (*digptr == 0) error("constant has no digits"); if (base != 16) { while (SYMOFCHAR(*digptr) == INTCONST) ++digptr; if (*digptr == '.') { dflag = TRUE; ++digptr; while (SYMOFCHAR(*digptr) == INTCONST) ++digptr; } if (*digptr == 'E' || *digptr == 'e') { dflag = TRUE; ++digptr; if (*digptr == '+' || *digptr == '-') ++digptr; if (SYMOFCHAR(*digptr) != INTCONST) error("exponent has no digits"); while (SYMOFCHAR(*digptr) == INTCONST) ++digptr; } } if (dflag) { constant.type = dtype; digit = *digptr; *digptr = 0; constant.value.d = atof(constant.value.s); *digptr = digit; if (digit == 'F' || digit == 'f') { ++digptr; constant.type = fltype; constant.value.d = (float) constant.value.d; } sym = FLOATCONST; if (*digptr != 0) error("junk at end of floating point constant"); return; } if (base != 16) digptr = constant.value.s; constant.value.v = 0; while (*digptr >= '0') { digit = *digptr; if (digit > '9') { if (base != 16) break; if (digit >= 'a' && digit <= 'f') digit = digit + (-'a' + '0' + 10); else if (digit >= 'A' && digit <= 'F') digit = digit + (-'A' + '0' + 10); else break; } constant.value.v = base * constant.value.v + (digit - '0'); ++digptr; } ucount = lcount = 0; while (TRUE) { if (*digptr == 'L' || *digptr == 'l') ++lcount; else if (*digptr == 'U' || *digptr == 'u') ++ucount; else break; ++digptr; } if (constant.value.v <= maxintto && lcount == 0 && ucount == 0) constant.type = itype; else if (constant.value.v <= maxuintto && lcount == 0 && (base != 10 || ucount != 0)) constant.type = uitype; else if (constant.value.v <= maxlongto && ucount == 0) constant.type = ltype; else constant.type = ultype; if (lcount > 1 || ucount > 1 || *digptr != 0) error("junk at end of integer constant"); } PUBLIC void nextsym() { static char lastch; register char *reglineptr; if (expect_statement && asmmode) { outnstr("!BCC_ASM"); dumplocs(); cppscan(1); outnstr("!BCC_ENDASM"); } else while (TRUE) /* exit with short, fast returns */ { reglineptr = lineptr; while ((sym = SYMOFCHAR(*reglineptr)) == WHITESPACE) ++reglineptr; lastch = *reglineptr; if (SYMOFCHAR(ch = *(lineptr = reglineptr + 1)) == SPECIALCHAR && sym != SPECIALCHAR) specialchar(); debug(7, "In nextsym, got %d \"%C\"", sym, lastch); switch (sym) { case CHARCONST: --lineptr; ch = lastch; /* pushback */ stringorcharconst(); newstringorcharconst(); if (charptr == constant.value.s) { charptr = constant.value.s; error("empty character constant"); constant.value.v = 0; } else { if (charptr != constant.value.s + 1) error("character constant too long"); charptr = constant.value.s; constant.value.v = *constant.value.s & CHMASKTO; } constant.type = itype; return; case CONTROL: #ifdef BUILTIN_CPP if (maclevel != 0) { error("# in a macro: not preprocessed"); /* XXX? */ return; } else #endif { int old_asmmode = asmmode; docontrol(); if (asmmode && !old_asmmode) { sym = SEMICOLON; return; } break; } case FLOATCONST: if (SYMOFCHAR(ch) == INTCONST) { --lineptr; ch = lastch; intconst(); } else sym = STRUCELTOP; return; case IDENT: --lineptr; ch = lastch; getident(); if ((gsymptr = findlorg(gsname)) != NULL) { #ifdef BUILTIN_CPP if (gsymptr->flags == DEFINITION) { entermac(); break; } #endif if (gsymptr->flags == KEYWORD) sym = gsymptr->offset.offsym; } return; case INTCONST: --lineptr; ch = lastch; intconst(); return; case SPECIALCHAR: ch = *(lineptr = reglineptr); specialchar(); if (ch == EOL) { if (incppexpr) { sym = SEMICOLON; return; } skipeol(); if (eofile) { sym = EOFSYM; return; } break; } if (SYMOFCHAR(ch) != SPECIALCHAR) break; gch1(); /* fall through to BADCHAR case */ case BADCHAR: error("illegal character"); break; case STRINGCONST: --lineptr; ch = lastch; /* pushback */ stringorcharconst(); newstringorcharconst(); #ifdef TS ts_n_string += charptr - constant.value.s; #endif return; case COLON: /* could be COLONOP or in label */ case COMMA: /* could be COMMAOP or in list */ case CONDOP: case LBRACE: case LBRACKET: case LPAREN: case NOTOP: case RBRACE: case RBRACKET: case RPAREN: case SEMICOLON: return; case ASSIGNOP: if (ch == '=') { sym = EQOP; gch1(); } /* There's no ancient switch on low memory systems */ #ifndef VERY_SMALL_MEMORY /* This is how things were in old K&R code. * Note that =- and =* behave differently from ANSI C, * where =- would be assignment and unary minus and * =* would be assignment and pointer dereference. */ else if (ancient) { if (ch == '+') { sym = ADDABOP; gch1(); } else if (ch == '-') { sym = SUBABOP; gch1(); } else if (ch == '*') { sym = MULABOP; gch1(); } else if (ch == '/') { sym = DIVABOP; gch1(); } else if (ch == '|') { sym = ORABOP; gch1(); } else if (ch == '&') { sym = ANDABOP; gch1(); } } #endif return; case ADDOP: if (ch == '+') { sym = INCSYM; /* PREINCOP or POSINCOP */ gch1(); } else if (ch == '=') { sym = ADDABOP; gch1(); } return; case HYPHEN: /* NEGOP or SUBOP or decoded below */ if (ch == '-') { sym = DECSYM; /* PREDECOP or POSTDECOP */ gch1(); } else if (ch == '=') { sym = SUBABOP; gch1(); } else if (ch == '>') { sym = STRUCPTROP; gch1(); } return; case STAR: /* INDIRECTOP or MULOP or as below */ if (ch == '=') { sym = MULABOP; gch1(); } return; case SLASH: #ifdef BUILTIN_CPP if (ch == '*') { skipcomment(); break; } #endif if (ch == '=') { sym = DIVABOP; gch1(); } else sym = DIVOP; return; case MODOP: if (ch == '=') { sym = MODABOP; gch1(); } return; case LTOP: if (ch == '=') { sym = LEOP; gch1(); } else if (ch == '<') { gch1(); if (ch == '=') { sym = SLABOP; gch1(); } else { sym = SLOP; } } return; case GTOP: if (ch == '=') { sym = GEOP; gch1(); } else if (ch == '>') { gch1(); if (ch == '=') { sym = SRABOP; gch1(); } else { sym = SROP; } } return; case AMPERSAND: /* ADDRESSOP or ANDOP or as below */ if (ch == '&') { sym = LOGANDOP; gch1(); } else if (ch == '=') { sym = ANDABOP; gch1(); } return; case EOROP: if (ch == '=') { sym = EORABOP; gch1(); } return; case OROP: if (ch == '|') { sym = LOGOROP; gch1(); } else if (ch == '=') { sym = ORABOP; gch1(); } return; case LOGNOTOP: if (ch == '=') { sym = NEOP; gch1(); } return; } } } PRIVATE void ppnumber() { constant.value.s = charptr; while (TRUE) { if (charptr >= char1top) constant.value.s = growobject(constant.value.s, 2); *charptr++ = ch; if (ch == 'E' || ch == 'e') { gch1(); if (ch == '+' || ch == '-') continue; } else GCH1(); if (SYMOFCHAR(ch) > MAXPPNUMSYM) break; } *charptr = 0; } PUBLIC void stringorcharconst() { char terminator; constant.value.s = charptr; terminator = ch; while (TRUE) { if (charptr >= char3top) constant.value.s = growobject(constant.value.s, 4); *charptr++ = ch; if (ch == '\\') { gch1(); if (ch == EOL) { #ifdef BUILTIN_CPP if (!orig_cppmode) #endif eofin("escape sequence"); break; } *charptr++ = ch; } GCH1(); if (ch == EOL) { #ifdef BUILTIN_CPP if (!orig_cppmode && ifcheck() ) #endif error(terminator == '"' ? "end of line in string constant" : "end of line in character constant"); break; } if (ch == terminator) { *charptr++ = terminator; /* This adds ansi string concatenation BUT only on one line */ do { ch = *++lineptr; } while(SYMOFCHAR(ch) == WHITESPACE); if( ch == terminator ) /* Hang on .. that's another string ... */ { charptr--; /* Stick it together */ gch1(); } else break; } } } PRIVATE void newstringorcharconst() { char *endinptr; int escvalue; fastin_t maxdigits; register char *inptr; register char *outptr; outptr = constant.value.s; inptr = charptr - 1; if (inptr == outptr || *inptr != *outptr) endinptr = charptr; /* not properly terminated */ else endinptr = inptr; inptr = outptr + 1; while (inptr != endinptr) { if (*inptr == '\\') { if (++inptr == endinptr) break; /* error reported already */ if (*inptr >= '0' && *inptr < '8') { escvalue = 0; maxdigits = 3; do { escvalue = 8 * escvalue + *inptr - '0'; ++inptr; } while (--maxdigits != 0 && *inptr >= '0' && *inptr < '8'); --inptr; *outptr++ = escvalue; } else switch (*inptr) { case '"': case '\'': case '\\': *outptr++ = *inptr; break; case 'a': *outptr++ = 7; break; case 'b': *outptr++ = 8; break; case 'f': *outptr++ = 12; break; case 'n': *outptr++ = EOLTO; break; case 'r': *outptr++ = 13; break; case 't': *outptr++ = 9; break; case 'v': *outptr++ = 11; break; default: error("%wnonstandard escape sequence"); *outptr++ = *inptr; break; } } else *outptr++ = *inptr; ++inptr; } charptr = outptr; } dev86-0.16.21/bcc/scan.h000066400000000000000000000102231231050321700144310ustar00rootroot00000000000000/* scan.h - scanner for bcc */ /* Copyright (C) 1992 Bruce Evans */ #define NAMESIZE 64 /* limit on identifier lengths */ #define SYMOFCHAR(ch) (symofchar[(unsigned char) (ch)]) /* scanner codes */ enum scan_states { /* The first group of entries consists of all the values that occur in the switch for cppscan(). */ IDENT, INTCONST, #define MAXIDSYM INTCONST /* IDENT and INTCONST must be the only * symofchar[] entries below this */ FLOATCONST, #define MAXPPNUMSYM FLOATCONST /* IDENT, INTCONST and FLOATCONST must be the * only symofchar[] entries below this */ CHARCONST, CONTROL, SLASH, SPECIALCHAR, STRINGCONST, /* The next group of entries are all the rest of the values that occur in symofchar[] and so in the switch for nextsym(). */ AMPERSAND, /* ADDRESSOP or ANDOP */ BADCHAR, COLON, /* also COLONOP */ COMMA, /* also COMMAOP */ DECSYM, /* PREDECOP or POSTDECOP */ EOFSYM, HYPHEN, /* NEGOP or SUBOP */ INCSYM, /* PREINCOP or POSTINCOP */ LBRACE, LBRACKET, LPAREN, RBRACE, RBRACKET, RPAREN, SEMICOLON, STAR, /* INDIRECTOP or MULOP */ WHITESPACE, /* The next group of entries consists of all operator codes. These codes must be contiguous so they can be used as (offsetted) array indexes. The group is ordered by operator-precedence (this is not necessary). The first part of it overlaps the previous group. */ /* Assign-abops (level 1) belong here but are at end to improve switch. */ #define FIRSTOP CONDOP CONDOP, /* level 2 */ OROP, /* level 5 */ EOROP, /* level 6 */ ANDOP, /* level 7 */ GTOP, /* level 9 */ LTOP, ADDOP, /* level 11 */ DIVOP, /* level 12 */ MODOP, LOGNOTOP, /* level 13 */ NOTOP, STRUCELTOP, /* level 14 */ STRUCPTROP, /* End of symbols that appear in symofchar[]. */ ASSIGNOP, /* level 1 - assign ops must be contiguous */ ADDABOP, ANDABOP, DIVABOP, EORABOP, MODABOP, MULABOP, ORABOP, SLABOP, SRABOP, SUBABOP, COMMAOP, /* level 0 */ COLONOP, /* level 2 */ LOGOROP, /* level 3 */ LOGANDOP, /* level 4 */ EQOP, /* level 8 */ NEOP, GEOP, /* level 9 */ LEOP, SLOP, /* level 10 */ SROP, SUBOP, /* level 11 */ MULOP, /* level 12 */ ADDRESSOP, /* level 13 */ CASTOP, INDIRECTOP, NEGOP, PREDECOP, PREINCOP, POSTDECOP, POSTINCOP, FUNCOP, /* level 14 */ LISTOP, ROOTLISTOP, LEAF, /* special */ PTRADDABOP, PTRADDOP, PTRSUBOP, /* end of operator codes (they must stay contiguous) */ #define LASTOP PTRSUBOP ENUMDECL, NULLDECL, SIGNDECL, STRUCTDECL, TYPEDECL, TYPEDEFNAME, UNIONDECL, UNSIGNDECL, AUTODECL, EXTERNDECL, REGDECL, STATICDECL, TYPEDEFDECL, ASMSYM, BREAKSYM, CASESYM, CONTSYM, DEFAULTSYM, DEFINEDSYM, DOSYM, ELSESYM, FORSYM, GOTOSYM, IFSYM, RETURNSYM, SIZEOFSYM, SWITCHSYM, WHILESYM, ASMCNTL, DEFINECNTL, ENDASMCNTL, INCLUDECNTL, LINECNTL, UNDEFCNTL, WARNINGCNTL, ERRORCNTL, ELIFCNTL, /* "IF" controls must be contiguous */ ELSECNTL, ENDIFCNTL, IFCNTL, IFDEFCNTL, IFNDEFCNTL }; EXTERN op_pt arg1op; /* LISTOP, or ROOTLISTOP if arg1inreg */ EXTERN struct { union { char *s; value_t v; double d; } value; struct typestruct *type; } constant; /* value of last constant scanned */ /* sym tells type */ EXTERN char funcname[NAMESIZE]; /* name of current function for unique labels */ EXTERN char gs2name[2 + NAMESIZE]; /* 2 reserved for namespace keys */ #define gsname (gs2name + 2) /* before last identifier */ EXTERN struct symstruct *gsymptr; /* symbol ptr for last identifier */ EXTERN bool_t incppexpr; /* nonzero while scanning cpp expression */ EXTERN sym_t sym; /* current symbol */ extern sym_t symofchar[]; /* table to convert chars to their symbols */ EXTERN bool_t expect_statement; /* If set #asm needs to clear the recursive * pending operations. ie: if stmts. */ dev86-0.16.21/bcc/sizes.h000066400000000000000000000036331231050321700146510ustar00rootroot00000000000000/* sizes.h - target scalar type sizes for bcc */ /* Copyright (C) 1992 Bruce Evans */ /* the compiler is not very portable in this area it only directly supports I8088-I80386 and MC6809 it assumes sizeof(source long) >= sizeof(target long) usual register size = int long = 2 int sizes */ #define CHBITSTO 8 /* bits in a character */ #define CHMASKTO 0xFF /* mask to reduce SOURCE int to TARGET uchar */ #define INT16BITSTO 16 /* not accessed in non-16 bit case */ #define INT32BITSTO 32 /* not accessed in non-32 bit case */ #define MAXINTBITSTO 32 /* max bits in an integer (var processors) */ #define MAXSCHTO 127 /* maximum signed character */ #define MAXUCHTO 255 /* maximum unsigned character */ #define MINSCHTO (-128) /* minimum signed character */ #ifdef MC6809 # define is5bitoffset(n) ((uoffset_T) (n) + 0x10 < 0x20) #endif #define isbyteoffset(n) ((uoffset_T) (n) - MINSCHTO <= MAXSCHTO - MINSCHTO) #define ischarconst(n) ((uvalue_t) (n) <= MAXUCHTO) #define isnegbyteoffset(n) ((uvalue_t) (n) + MAXSCHTO <= MAXSCHTO - MINSCHTO) #define isshortbranch(n) ((uoffset_T) (n) - MINSCHTO <= MAXSCHTO - MINSCHTO) #ifdef MC6809 /* Hack to reduce number of direct page variables. */ #define intmaskto ((uvalue_t) 0xFFFFL) #define maxintto ((uvalue_t) 0x7FFFL) #define maxlongto ((uvalue_t) 0x7FFFFFFFL) #define maxoffsetto ((uvalue_t) 0x7FFFL) #define maxshortto ((uvalue_t) 0x7FFFL) #define maxuintto ((uvalue_t) 0xFFFFL) #define maxushortto ((uvalue_t) 0xFFFFL) #define shortmaskto ((uvalue_t) 0xFFFFL) #else extern uvalue_t intmaskto; /* mask for ints */ extern uvalue_t maxintto; /* maximum int */ extern uvalue_t maxlongto; /* maximum long */ extern uvalue_t maxoffsetto; /* maximum offset */ extern uvalue_t maxshortto; /* maximum short */ extern uvalue_t maxuintto; /* maximum unsigned */ extern uvalue_t maxushortto; /* maximum unsigned short */ extern uvalue_t shortmaskto; /* mask for shorts */ #endif dev86-0.16.21/bcc/softop.c000066400000000000000000000135241231050321700150210ustar00rootroot00000000000000/* softop.c - software operations for bcc */ /* Copyright (C) 1992 Bruce Evans */ #include "bcc.h" #include "gencode.h" #include "reg.h" #include "scan.h" #include "sizes.h" #include "type.h" /*----------------------------------------------------------------------------- softop(operation code, source leaf, target leaf) handles binary operations which are not done in hardware if the result type is (unsigned) long, float or double, all the work is immediately passed on to routines in other files. Otherwise: source and target may be either char, int or unsigned int they are not cast to ints or unsigneds before they get here considerable effort goes into avoiding unnecessary pushes -----------------------------------------------------------------------------*/ PUBLIC void softop(op, source, target) op_pt op; struct symstruct *source; struct symstruct *target; { store_t regpushed; store_t regmark; scalar_t resultscalar; scalar_t sscalar; scalar_t tscalar; value_t sourceval; bool_t uflag; store_t workreg; if ((tscalar = target->type->scalar) & DLONG) { longop(op, source, target); return; } if (tscalar & RSCALAR) { floatop(op, source, target); return; } sscalar = source->type->scalar; resultscalar = tscalar; uflag = tscalar & UNSIGNED; if (op != SLOP && op != SROP) { resultscalar |= sscalar; uflag |= sscalar & UNSIGNED; } #ifdef MC6809 if ((op_t) op == MULOP && sscalar & CHAR && tscalar & CHAR && (source->storage != CONSTANT || (uvalue_t) source->offset.offv > 2)) { if (source->storage & WORKDATREGS) push(source); load(target, DREG); outldmulreg(); outadr(source); outmulmulreg(); target->storage = DREG; target->type = iscalartotype(resultscalar); return; } #endif if (source->storage == CONSTANT) { extend(target); #ifdef I8088 if (op == MULOP || op == SLOP) loadany(target); else #endif load(target, DREG); target->type = iscalartotype(resultscalar); sourceval = source->offset.offv; switch ((op_t) op) { case DIVOP: if (diveasy(sourceval, uflag)) return; break; case MODOP: if (modeasy(sourceval, uflag)) { if ((uvalue_t) sourceval <= MAXUCHTO + 1) { target->storage = BREG; target->type = ctype; if (uflag) target->type = uctype; } return; } break; case MULOP: if (muleasy((uvalue_t) sourceval, target->storage)) return; load(target, DREG); break; case SLOP: slconst(sourceval, target->storage); return; case SROP: srconst(sourceval, uflag); return; } sscalar = (source->type = iscalartotype(resultscalar))->scalar; } /* to load source first if it is CHAR: */ /* need work register if target is in WORKDATREGS */ /* use OPREG unless it will become overloaded later */ /* to preserve source while target is loaded: */ /* if source is in WORKDATREGS, put it in OPREG, */ /* unless target is OPREG-indirect */ /* otherwise, if source is in WORKDATREGS, put it in work reg not OPREG */ /* also assign a work reg if source is already in OPREG and target needs one */ regpushed = (regmark = reguse) & OPREG; workreg = OPREG; if ((sscalar & CHAR && target->storage & WORKDATREGS && source->storage == OPREG && source->indcount != 0) || ((sscalar & CHAR || source->storage & WORKDATREGS) && target->storage == OPREG && target->indcount != 0) || #ifdef MC6809 /* for -Wall */ ( #endif (source->storage == OPREG && target->storage == GLOBAL && target->indcount == 0) #ifdef MC6809 && posindependent) #endif ) { if ((regmark | OPREG) == allindregs) regpushed |= (workreg = OPWORKREG); else { reguse |= OPREG; workreg = getindexreg(); } } pushlist(regpushed); /* no more pushes */ reguse = allindregs; /* error if another reg unexpectedly needed */ if (sscalar & CHAR) { if (target->storage & WORKDATREGS) { extend(target); if (source->storage == workreg) exchange(source, target); else transfer(target, workreg); } extend(source); if (target->storage != OPREG && (target->storage != GLOBAL || target->indcount != 0 #ifdef MC6809 || !posindependent #endif )) workreg = OPREG; } if (source->storage & WORKDATREGS) { if (target->storage == OPREG && target->indcount == 0) exchange(source, target); else { transfer(source, workreg); workreg = OPREG; } } if (target->storage == GLOBAL && target->indcount == 0 #ifdef MC6809 && posindependent #endif ) load(target, workreg); /* source and target now in position to be loaded without any more registers */ extend(target); load(target, DREG); #if defined(I8088) if ((op_t) op != DIVOP && (op_t) op != MODOP ) { load(source, DATREG1); /* CX */ switch ((op_t) op) { case MULOP: outop2str("imul\t"); outnregname(DATREG1); break; case SLOP: outop2str("shl\t"); outregname(DREG); outnstr(",cl"); break; case SROP: if (uflag) outop2str("shr\t"); else outop2str("sar\t"); outregname(DREG); outnstr(",cl"); break; } } else #endif { load(source, OPREG); switch ((op_t) op) { case DIVOP: #ifdef I8088 if (uflag) call("idiv_"); else { #ifdef I80386 if (i386_32) outnop1str("cdq"); else #endif outnop1str("cwd"); outop2str("idiv\t"); outregname(INDREG0); } #else call("idiv"); #endif break; case MODOP: call("imod"); break; case MULOP: #ifdef I8088 call("imul_"); #else call("imul"); #endif break; case SLOP: call("isl"); break; case SROP: call("isr"); break; } if (uflag) outbyte('u'); outnl(); } target->type = iscalartotype(resultscalar); poplist(regpushed); reguse = regmark; } dev86-0.16.21/bcc/state.c000066400000000000000000000432461231050321700146330ustar00rootroot00000000000000/* state.c - statement routines for bcc */ /* Copyright (C) 1992 Bruce Evans */ #include "bcc.h" #include "align.h" #include "condcode.h" #include "gencode.h" #include "input.h" /* just for ch and eof for label check */ #include "label.h" #include "os.h" /* just for EOL */ #include "parse.h" #include "reg.h" #include "scan.h" #include "sizes.h" #include "table.h" #include "type.h" #define COLONCHAR ':' /* for label */ #define GROWCASES 64 /* extra cases for growth of switch struct */ #define INITIALCASES 16 /* initial cases in switch structure */ struct loopstruct { label_no breaklab; /* destination for break */ label_no contlab; /* destination for continue */ struct nodestruct *etmark; /* expression tree built during loop */ struct symstruct *exprmark; /* expression symbols built during loop */ struct symstruct *locmark; /* local variables built during loop */ struct loopstruct *prevloop; /* previous active for, switch or while */ offset_T spmark; /* stack value for continue and break */ }; struct switchstruct { struct casestruct *caseptr; /* current spot in caselist */ struct casestruct *casetop; /* last in caselist + 1 */ bool_t charselector; /* tells if case selector is char */ label_no dfaultlab; /* destination for default case (0 if none) */ struct switchstruct *prevswitch; /* previous active switch */ struct casestruct { value_t casevalue; /* value giving this case */ label_no caselabel; /* corresponding label */ } caselist[INITIALCASES]; /* perhaps larger */ }; PRIVATE struct loopstruct *loopnow; /* currently active for/switch/while */ /* depends on NULL init */ PRIVATE bool_t returnflag; /* set if last effective statement */ /* was a return */ PRIVATE label_no swstacklab; /* label giving stack for switch statement */ FORWARD void addloop P((struct loopstruct *newloop)); FORWARD void badloop P((void)); FORWARD void deleteloop P((void)); FORWARD void evalexpression P((struct nodestruct *exp)); FORWARD void exprstatement P((void)); FORWARD bool_pt isforever P((struct nodestruct *exp)); FORWARD void sort P((struct casestruct *caselist, int count)); FORWARD void dobreak P((void)); FORWARD void docase P((void)); FORWARD void docont P((void)); FORWARD void dodefault P((void)); FORWARD void dodowhile P((void)); FORWARD void dofor P((void)); FORWARD void dogoto P((void)); FORWARD void doif P((void)); FORWARD void doreturn P((void)); FORWARD void doswitch P((void)); FORWARD void dowhile P((void)); FORWARD void jumptocases P((void)); FORWARD void statement P((void)); /* --- utility routines --- */ PRIVATE void addloop(newloop) struct loopstruct *newloop; { newloop->breaklab = getlabel(); newloop->contlab = getlabel(); newloop->etmark = etptr; newloop->exprmark = exprptr; newloop->locmark = locptr; newloop->prevloop = loopnow; newloop->spmark = sp; loopnow = newloop; } PRIVATE void badloop() { error(" no active fors, switches or whiles"); } PRIVATE void deleteloop() { etptr = loopnow->etmark; exprptr = loopnow->exprmark; locptr = loopnow->locmark; loopnow = loopnow->prevloop; } PRIVATE void evalexpression(exp) struct nodestruct *exp; { offset_T spmark; spmark = sp; makeleaf(exp); modstk(spmark); } PRIVATE void exprstatement() { struct nodestruct *etmark; struct symstruct *exprmark; etmark = etptr; exprmark = exprptr; evalexpression(expression()); etptr = etmark; exprptr = exprmark; } PRIVATE bool_pt isforever(exp) register struct nodestruct *exp; { return exp == NULL || (exp->tag == LEAF && exp->left.symptr->storage == CONSTANT && exp->left.symptr->offset.offv != 0); } PRIVATE void sort(caselist, count) /* shell sort */ struct casestruct *caselist; int count; { register int gap; register int i; int j; struct casestruct swaptemp; gap = 1; do gap = 3 * gap + 1; while (gap <= count); while (gap != 1) { gap /= 3; for (j = gap; j < count; ++j) for (i = j - gap; i >= 0 && caselist[i].casevalue > caselist[i + gap].casevalue; i -= gap) { swaptemp = caselist[i]; caselist[i] = caselist[i + gap]; caselist[i + gap] = swaptemp; } } } /* --- syntax routines --- */ /* ---------------------------------------------------------------------------- compound-statement: "{" "}" ---------------------------------------------------------------------------- */ PUBLIC void compound() /* have just seen "{" */ { struct symstruct *locmark; store_t regmark; #ifdef FRAMEPOINTER offset_T framepmark; offset_T softspmark; #else /* softsp == sp here unless level == ARGLEVEL so mark is unnec */ /* this is also true if funcsaveregsize != 0 but the tests are too messy */ #endif offset_T spmark; locmark = locptr; regmark = reguse; #ifdef FRAMEPOINTER softspmark = softsp; framepmark = framep; #endif spmark = sp; newlevel(); expect_statement++; decllist(); softsp &= alignmask; if (sym != RBRACE) /* no need for locals if empty compound */ reslocals(); returnflag = FALSE; while (sym != RBRACE && sym != EOFSYM) statement(); expect_statement--; oldlevel(); if (!returnflag) { if (level != ARGLEVEL) { if (switchnow == NULL) { #ifdef FRAMEPOINTER if (framep != 0) { /* some args or locals, maybe at lower levels */ modstk(softspmark); if (framep != framepmark) /* frame was just set up */ popframe(); } #else modstk(spmark); #endif } } else ret(); } #ifdef FRAMEPOINTER framep = framepmark; sp = spmark; softsp = softspmark; #else softsp = sp = spmark; #endif reguse = regmark; locptr = locmark; rbrace(); } PUBLIC void doasm() { if (sym == LPAREN) nextsym(); if (sym!=STRINGCONST) error("string const expected"); else { outnstr("!BCC_ASM"); for(;;) { constant.value.s[charptr-constant.value.s]='\0'; outbyte('\t'); outnstr(constant.value.s); /* XXX: Need to investigate: wasting memory? * * charptr = constant.value.s; */ nextsym(); if (sym == COMMA) nextsym(); if (sym!=STRINGCONST) break; } outnstr("!BCC_ENDASM"); if (sym == RPAREN) nextsym(); semicolon(); } } PRIVATE void dobreak() { offset_T spmark; if (loopnow == NULL) badloop(); else { if (switchnow == NULL) { spmark = sp; modstk(loopnow->spmark); sp = spmark; } jump(loopnow->breaklab); } } PRIVATE void docase() { value_t caseval; caseval = constexpression() & intmaskto; /* FIXME: warn overflow */ if (caseval > maxintto) caseval -= (maxuintto + 1); colon(); if (switchnow == NULL) error("case not in switch"); else { if (switchnow->charselector && (caseval < 0 || caseval > 255)) error("%wcase cannot be reached with char switch"); else { if (switchnow->caseptr >= switchnow->casetop) { int ncases; ncases = (/* ptrdiff_t */ int) (switchnow->caseptr - &switchnow->caselist[0]); switchnow = realloc(switchnow, (/* size_t */ unsigned) ((char *) switchnow->caseptr - (char *) switchnow) + GROWCASES * sizeof (struct casestruct)); #ifdef TS ++ts_n_case_realloc; ts_s_case += GROWCASES * sizeof (struct casestruct); ts_s_case_tot += GROWCASES * sizeof (struct casestruct); #endif if (switchnow == NULL) outofmemoryerror(""); switchnow->caseptr = &switchnow->caselist[ncases]; switchnow->casetop = switchnow->caseptr + GROWCASES; } switchnow->caseptr->casevalue = caseval; deflabel(switchnow->caseptr->caselabel = getlabel()); ++switchnow->caseptr; } } } PRIVATE void docont() { struct loopstruct *contloop; offset_T spmark; struct switchstruct *switchthen; for (contloop = loopnow, switchthen = switchnow; ; contloop = contloop->prevloop, switchthen = switchthen->prevswitch) { if (contloop == NULL) { badloop(); return; } if (contloop->contlab != 0) break; } if (switchnow == NULL) { spmark = sp; modstk(contloop->spmark); sp = spmark; } else if (switchthen == NULL) { outaddsp(); outshex(contloop->spmark); outminus(); outswstacklab(); #ifdef MC6809 outcregname(LOCAL); #endif #ifdef I80386 if (i386_32) bumplc2(); #endif outnl(); } jump(contloop->contlab); } PRIVATE void dodefault() { colon(); if (switchnow == NULL) error("default not in switch"); else if (switchnow->dfaultlab != 0) error("multiple defaults"); else deflabel(switchnow->dfaultlab = getlabel()); } PRIVATE void dodowhile() { struct loopstruct dwhileloop; label_no dolab; addloop(&dwhileloop); deflabel(dolab = getlabel()); statement(); if (sym == WHILESYM) nextsym(); else error("missing while at end of do-while"); deflabel(dwhileloop.contlab); lparen(); jumptrue(expression(), dolab); rparen(); semicolon(); deflabel(dwhileloop.breaklab); deleteloop(); } PRIVATE void dofor() { struct loopstruct forloop; label_no forstatlab; label_no fortestlab = 0; /* for -Wall */ struct nodestruct *testexp; struct nodestruct *loopexp; lparen(); if (sym != SEMICOLON) exprstatement(); semicolon(); addloop(&forloop); if (sym == SEMICOLON) testexp = NULL; else testexp = expression(); /* remember test expression */ semicolon(); if (sym == RPAREN) loopexp = NULL; else loopexp = expression(); /* remember loop expression */ rparen(); if (!isforever(testexp)) jump(fortestlab = getlabel()); /* test at bottom */ deflabel(forstatlab = getlabel()); /* back here if test succeeds */ statement(); deflabel(forloop.contlab); if (loopexp != NULL) evalexpression(loopexp); if (isforever(testexp)) jump(forstatlab); else { deflabel(fortestlab); /* test label */ jumptrue(testexp, forstatlab); } deflabel(forloop.breaklab); deleteloop(); } PRIVATE void dogoto() { struct symstruct *symptr; if (sym == IDENT || sym == TYPEDEFNAME) { symptr = namedlabel(); /* if (symptr->indcount == 4) modstk( else */ adjsp(symptr->offset.offlabel); jump(symptr->offset.offlabel); nextsym(); } else error("need identifier"); } PRIVATE void doif() { struct nodestruct *etmark; label_no elselab; label_no exitlab; struct symstruct *exprmark; lparen(); etmark = etptr; exprmark = exprptr; jumpfalse(expression(), elselab = getlabel()); etptr = etmark; exprptr = exprmark; rparen(); statement(); /* true, do a statement */ if (sym == ELSESYM) /* "if .. else" statement */ { nextsym(); jump(exitlab = getlabel()); /* over "else" label and code */ deflabel(elselab); statement(); deflabel(exitlab); } else deflabel(elselab); } PRIVATE void doreturn() { offset_T spmark; spmark = sp; if (sym != SEMICOLON) /* returning expression */ loadretexpression(); ret(); /* clean up stack and return */ sp = spmark; /* restore stack for rest of function */ } PRIVATE void doswitch() { struct switchstruct *sw; struct loopstruct switchloop; offset_T spmark = 0; /* for -Wall */ label_no sdecidelab; sw = (struct switchstruct *) ourmalloc(sizeof *sw); #ifdef TS ++ts_n_case; ts_s_case += sizeof *sw; ts_s_case_tot += sizeof *sw; #endif lparen(); sw->charselector = loadexpression(DREG, NULLTYPE)->scalar & CHAR; rparen(); if (switchnow == NULL) spmark = lowsp = sp; addloop(&switchloop); sw->dfaultlab = switchloop.contlab = 0; /* kill to show this is a switch */ sw->casetop = (sw->caseptr = sw->caselist) + INITIALCASES; sw->prevswitch = switchnow; jump(sdecidelab = getlabel()); /* to case decision label */ if (switchnow == NULL) swstacklab = gethighlabel(); switchnow = sw; statement(); /* cases */ sw = switchnow; jump(switchloop.breaklab); /* over case decision to break label */ deflabel(sdecidelab); if (sw->prevswitch == NULL) modstk(lowsp); jumptocases(); deflabel(switchloop.breaklab); if ((switchnow = sw->prevswitch) == NULL) { equlab(swstacklab, lowsp); clearswitchlabels(); modstk(spmark); } deleteloop(); #ifdef TS ts_s_case_tot -= (char *) sw->casetop - (char *) sw; #endif ourfree(sw); } PRIVATE void dowhile() { struct loopstruct whileloop; struct nodestruct *testexp; label_no wstatlab; lparen(); addloop(&whileloop); testexp = expression(); rparen(); if (!isforever(testexp)) jump(whileloop.contlab); /* test at bottom */ deflabel(wstatlab = getlabel()); /* back here if test succeeds */ statement(); deflabel(whileloop.contlab); jumptrue(testexp, wstatlab); deflabel(whileloop.breaklab); deleteloop(); } PRIVATE void jumptocases() { value_t basevalue; struct casestruct *case1ptr; struct casestruct *caseptr; struct casestruct *casetop; value_t caseval; bool_t charselector; bool_t dfaultflag; label_no dfaultlab; label_no jtablelab; ccode_t lowcondition; store_pt targreg; label_no zjtablelab; caseptr = switchnow->caselist; casetop = switchnow->caseptr; sort(caseptr, (/* ptrdiff_t */ int) (casetop - caseptr)); basevalue = 0; if ((charselector = switchnow->charselector) != 0) { targreg = BREG; lowcondition = LO; } else { targreg = DREG; lowcondition = LT; } dfaultflag = TRUE; if ((dfaultlab = switchnow->dfaultlab) == 0) { dfaultflag = FALSE; dfaultlab = loopnow->breaklab; } --casetop; for (case1ptr = caseptr; case1ptr < casetop; ++case1ptr) if (case1ptr->casevalue == (case1ptr + 1)->casevalue) error("duplicate case in switch"); while (caseptr <= casetop) { outsub(); outimadj((offset_T) (caseptr->casevalue - basevalue), targreg); basevalue = caseptr->casevalue; for (case1ptr = caseptr; case1ptr < casetop; ++case1ptr) if (case1ptr->casevalue < (case1ptr + 1)->casevalue - 10) break; if (case1ptr < caseptr + 5) { lbranch(EQ, caseptr->caselabel); ++caseptr; } else { lbranch(lowcondition, dfaultlab); outcmp(); outimadj((offset_T) (case1ptr->casevalue - basevalue), targreg); lbranch(HI, zjtablelab = getlabel()); if (charselector) ctoi(); #ifdef MC6809 else bumplc(); /* extra for CMPD */ #endif slconst((value_t) (ptypesize / 2), DREG); /* really log ptypesize */ deflabel(jtablelab = casejump()); #ifdef I8088 jtablelab = jtablelab; /* not used, allocated for regress */ #endif for (caseval = caseptr->casevalue; caseval <= case1ptr->casevalue; ++caseval) { #ifdef I8088 if (ptypesize > 2) defdword(); else #endif defword(); if (caseval != caseptr->casevalue) outlabel(dfaultlab); else { outlabel(caseptr->caselabel); ++caseptr; } #ifdef MC6809 if (posindependent) { outminus(); outlabel(jtablelab); } #endif bumplc2(); #ifdef I8088 if (ptypesize > 2) bumplc2(); #endif outnl(); } deflabel(zjtablelab); } lowcondition = LO; /* 1st subtraction makes rest unsigned */ } if (dfaultflag) jump(dfaultlab); } PUBLIC void outswoffset (offset) offset_T offset; { #ifdef FRAMEPOINTER outoffset(offset - softsp - framep); #else outoffset(offset - softsp - sp); #endif outplus(); outswstacklab(); #ifdef I8088 bumplc(); #ifdef I80386 if (i386_32) bumplc2(); #endif #endif } PUBLIC void outswstacklab() { outbyte(LOCALSTARTCHAR); outlabel(swstacklab); } /* ---------------------------------------------------------------------------- statement: ; ---------------------------------------------------------------------------- */ PRIVATE void statement() { #if 1 struct symstruct *symptr; #endif more: switch (sym) { case LBRACE: nextsym(); compound(); return; case IFSYM: nextsym(); doif(); break; case ELSESYM: error("unexpected else"); nextsym(); break; case WHILESYM: nextsym(); dowhile(); break; case FORSYM: nextsym(); dofor(); break; case RETURNSYM: nextsym(); doreturn(); semicolon(); returnflag = TRUE; return; case SWITCHSYM: nextsym(); doswitch(); break; case BREAKSYM: nextsym(); dobreak(); semicolon(); break; case CASESYM: nextsym(); docase(); goto more; case DEFAULTSYM: nextsym(); dodefault(); goto more; case DOSYM: nextsym(); dodowhile(); break; case CONTSYM: nextsym(); docont(); semicolon(); break; case GOTOSYM: nextsym(); dogoto(); semicolon(); break; case SEMICOLON: outnstr("!BCC_EOS"); nextsym(); return; case ASMSYM: nextsym(); doasm(); break; case IDENT: case TYPEDEFNAME: blanks(); /* cannot afford nextsym() */ while (ch == EOL && !eofile) { /* this now fails only on #controls and macros giving ':' */ skipeol(); blanks(); } if (ch == COLONCHAR) { #if 0 struct symstruct *symptr; #endif symptr = namedlabel(); if (symptr->indcount != 2) error("redefined label"); else { deflabel(symptr->offset.offlabel); if (switchnow != NULL) symptr->indcount = 3; else { symptr->indcount = 4; outbyte(LOCALSTARTCHAR); outlabel(symptr->offset.offlabel); outop0str("\t=\t"); outshex(sp); outnl(); } } nextsym(); nextsym(); goto more; } /* else fall into default */ default: exprstatement(); semicolon(); break; } returnflag = FALSE; } dev86-0.16.21/bcc/sysproto.h000066400000000000000000000016601231050321700154140ustar00rootroot00000000000000 /* library - fcntl.h */ int creat P((const char *_path, int _mode)); int open P((const char *_path, int _oflag, ...)); /* library - stdlib.h */ double atof P((const char *_str)); void exit P((int _status)); /* library - string.h */ void *memcpy P((void *_t, const void *_s, unsigned _length)); void *memset P((void *_s, int _c, unsigned _nbytes)); char *strcat P((char *_target, const char *_source)); char *strchr P((const char *_s, int _ch)); int strcmp P((const char *_s1, const char *_s2)); char *strcpy P((char *_target, const char *_source)); unsigned strlen P((const char *_s)); char *strncpy P((char *_target, const char *_source, unsigned _maxlength)); char *strrchr P((const char *_s, int _ch)); /* library - unistd.h */ int close P((int _fd)); int isatty P((int _fd)); long lseek P((int _fd, long _offset, int _whence)); int read P((int _fd, char *_buf, unsigned _nbytes)); int write P((int _fd, char *_buf, unsigned _nbytes)); dev86-0.16.21/bcc/table.c000066400000000000000000000452551231050321700146040ustar00rootroot00000000000000/* table.c - table handler for bcc */ /* Copyright (C) 1992 Bruce Evans */ /* Can I now get rid of EXPRLEVEL? Yes, except expression symbols must * usually be set to some level different from OFFKLUDGELEVEL. */ #include "bcc.h" #include "align.h" #include "gencode.h" #include "os.h" #include "parse.h" #include "reg.h" #include "sc.h" #include "scan.h" #include "sizes.h" #include "type.h" #undef EXTERN #define EXTERN #include "table.h" #define GOLDEN 157 /* GOLDEN/HASHTABSIZE approx golden ratio */ #define HASHTABSIZE 256 #define MARKER ((unsigned) 0x18C396A5L) /* lint everywhere it is used */ #ifdef VERY_SMALL_MEMORY #define MAXEXPR 125 #else #define MAXEXPR 500 #endif #define MAXLOCAL 100 #define NKEYWORDS 39 #ifdef NOFLOAT #define NSCALTYPES 10 #else #define NSCALTYPES 12 #endif #define STACKSPACE 256 /* punt for normal recursions - switch extra */ struct keywordstruct { char *kwname; sym_t kwcode; }; #ifdef HOLDSTRINGS struct string { struct string *snext; char *sptr; char *stop; label_no slabel; }; #endif struct typedatastruct { char *tdname; bool_t tdkeyscalar; scalar_t tdscalar; smalin_t tdsize; struct typestruct **tdtypeptr; }; PRIVATE struct symstruct exprsyms[MAXEXPR]; PRIVATE struct symstruct *hashtab[HASHTABSIZE]; /* depends on zero init */ #ifdef HOLDSTRINGS PRIVATE struct string *laststring; /* last in list of strings */ /* depends on NULL init */ #endif PUBLIC struct symstruct locsyms[MAXLOCAL]; PRIVATE struct symstruct constemplate = { CONSTANT, /* storage */ 0, /* indcount */ 0, /* flags */ EXPRLEVEL, /* level */ NULL, /* next */ NULL, /* prev */ NULL, /* type, init later to itype */ /* offset is a union, set every time constemplate is used */ /* name is a union, namea member is constant "\0" */ }; PRIVATE struct keywordstruct keywords[NKEYWORDS] = { { "enum", ENUMDECL, }, { "struct", STRUCTDECL, }, { "union", UNIONDECL, }, { "unsigned", UNSIGNDECL, }, { "signed", SIGNDECL, }, { "auto", AUTODECL, }, { "extern", EXTERNDECL, }, { "register", REGDECL, }, { "static", STATICDECL, }, { "typedef", TYPEDEFDECL, }, { "asm", ASMSYM, }, { "break", BREAKSYM, }, { "case", CASESYM, }, { "continue", CONTSYM, }, { "default", DEFAULTSYM, }, { "do", DOSYM, }, { "else", ELSESYM, }, { "for", FORSYM, }, { "goto", GOTOSYM, }, { "if", IFSYM, }, { "return", RETURNSYM, }, { "sizeof", SIZEOFSYM, }, { "switch", SWITCHSYM, }, { "while", WHILESYM, }, { "#asm", ASMCNTL, }, { "#define", DEFINECNTL, }, { "#elif", ELIFCNTL, }, { "#else", ELSECNTL, }, { "#endasm", ENDASMCNTL, }, { "#endif", ENDIFCNTL, }, { "#if", IFCNTL, }, { "#ifdef", IFDEFCNTL, }, { "#include", INCLUDECNTL, }, { "#ifndef", IFNDEFCNTL, }, { "#line", LINECNTL, }, { "#undef", UNDEFCNTL, }, { "#warning", WARNINGCNTL, }, { "#error", ERRORCNTL, }, { "defined", DEFINEDSYM, }, /* should be deactivated except in #if's */ }; PRIVATE struct typedatastruct scaltypes[NSCALTYPES] = { { "void", TRUE, 0, 0, &vtype, }, /* first - addkeyword uses vtype */ { "char", TRUE, CHAR, 1, &ctype, }, { "char", FALSE, UNSIGNED | CHAR, 1, &uctype, }, { "char", FALSE, CHAR, 1, &sctype, }, { "short", TRUE, SHORT, 2, &stype, }, { "short", FALSE, UNSIGNED | SHORT, 2, &ustype, }, { "int", TRUE, INT, 2, &itype, }, { "int", FALSE, UNSIGNED | INT, 2, &uitype, }, { "long", TRUE, LONG | DLONG, 4, <ype, }, { "long", FALSE, UNSIGNED | LONG | DLONG, 4, &ultype, }, #ifndef NOFLOAT { "float", TRUE, FLOAT, 4, &fltype, }, { "double", TRUE, DOUBLE, 8, &dtype, }, #endif }; FORWARD struct symstruct *addkeyword P((char *name, sym_pt code)); FORWARD void heapcorrupterror P((void)); PUBLIC struct symstruct *addglb(name, type) char *name; struct typestruct *type; { struct symstruct **hashptr; struct symstruct *oldsymptr = NULL; /* for -Wall */ register struct symstruct *symptr; hashptr = gethashptr(name); symptr = *hashptr; while (symptr != NULL) { oldsymptr = symptr; symptr = symptr->next; } symptr = qmalloc(sizeof (struct symstruct) + strlen(name)); #ifdef TS ++ts_n_global; ts_size_global += sizeof (struct symstruct) + strlen(name); #endif addsym(name, type, symptr); symptr->storage = GLOBAL; symptr->level = GLBLEVEL; if (*hashptr == NULL) { *hashptr = symptr; symptr->prev = hashptr; } else { oldsymptr->next = symptr; symptr->prev = &oldsymptr->next; } return symptr; } PRIVATE struct symstruct *addkeyword(name, code) char *name; sym_pt code; { struct symstruct *symptr; (symptr = addglb(name, vtype))->flags = KEYWORD; symptr->offset.offsym = code; return symptr; } PUBLIC struct symstruct *addloc(name, type) char *name; struct typestruct *type; { struct symstruct **hashptr; register struct symstruct *symptr; hashptr = gethashptr(name); symptr = *hashptr; while (symptr != NULL) symptr = symptr->next; symptr = locptr; locptr = (struct symstruct *) align(&symptr->name.namea[strlen(name) + 1]); if (locptr >= &locsyms[MAXLOCAL]) limiterror("too many local symbols (101)"); addsym(name, type, symptr); if (type->constructor == FUNCTION) symptr->storage = GLOBAL; else symptr->storage = LOCAL; symptr->level = level; if (*hashptr != NULL) { symptr->next = *hashptr; symptr->next->prev = &symptr->next; } *hashptr = symptr; symptr->prev = hashptr; return symptr; } PUBLIC struct symstruct *addlorg(name, type) char *name; struct typestruct *type; { if (level != GLBLEVEL) return addloc(name, type); return addglb(name, type); } PUBLIC void addsym(name, type, symptr) char *name; struct typestruct *type; register struct symstruct *symptr; { if (type->constructor & (ARRAY | FUNCTION)) symptr->indcount = 0; else symptr->indcount = 1; symptr->flags = 0; symptr->next = NULL; symptr->type = type; symptr->offset.offi = 0; strcpy(symptr->name.namea, name); } PUBLIC struct symstruct *constsym(longconst) value_t longconst; { register struct symstruct *symptr; symptr = exprsym(&constemplate); symptr->offset.offv = longconst; return symptr; } PUBLIC void delsym(symptr) register struct symstruct *symptr; { if ((*(symptr->prev) = symptr->next) != NULL) symptr->next->prev = symptr->prev; } /* dumpglbs() - define locations of globals and reserve space for them */ PUBLIC void dumpglbs() { int i; register struct symstruct *symptr; register struct typestruct *type; #ifdef TS extern char *brksize; struct ts { char *what; uvalue_t *where; }; static struct ts ts[] = { "ts_n_newtypelist ", &ts_n_newtypelist, "ts_s_newtypelist ", &ts_s_newtypelist, "ts_n_filename_term ", &ts_n_filename_term, "ts_s_filename_term ", &ts_s_filename_term, "ts_n_filename ", &ts_n_filename, "ts_s_filename ", &ts_s_filename, "ts_s_filename_tot ", &ts_s_filename_tot, "ts_n_pathname ", &ts_n_pathname, "ts_s_pathname ", &ts_s_pathname, "ts_s_pathname_tot ", &ts_s_pathname_tot, "ts_n_inputbuf ", &ts_n_inputbuf, "ts_s_inputbuf ", &ts_s_inputbuf, "ts_s_inputbuf_tot ", &ts_s_inputbuf_tot, "ts_n_includelist ", &ts_n_includelist, "ts_s_includelist ", &ts_s_includelist, "ts_s_outputbuf ", &ts_s_outputbuf, "ts_n_macstring_ident ", &ts_n_macstring_ident, "ts_n_macstring_ordinary ", &ts_n_macstring_ordinary, "ts_n_macstring_param ", &ts_n_macstring_param, "ts_n_macstring_quoted ", &ts_n_macstring_quoted, "ts_n_macstring_term ", &ts_n_macstring_term, "ts_s_macstring ", &ts_s_macstring, "ts_n_defines ", &ts_n_defines, "ts_s_defines ", &ts_s_defines, "ts_n_macparam ", &ts_n_macparam, "ts_s_macparam ", &ts_s_macparam, "ts_s_macparam_tot ", &ts_s_macparam_tot, "ts_n_macparam_string_ordinary ", &ts_n_macparam_string_ordinary, "ts_n_macparam_string_quoted ", &ts_n_macparam_string_quoted, "ts_n_macparam_string_term ", &ts_n_macparam_string_term, "ts_s_macparam_string ", &ts_s_macparam_string, "ts_s_macparam_string_tot ", &ts_s_macparam_string_tot, "ts_s_macparam_string_alloced ", &ts_s_macparam_string_alloced, "ts_s_macparam_string_alloced_tot ", &ts_s_macparam_string_alloced_tot, "ts_s_fakeline ", &ts_s_fakeline, "ts_s_fakeline_tot ", &ts_s_fakeline_tot, "ts_n_string ", &ts_n_string, "ts_n_case ", &ts_n_case, "ts_n_case_realloc ", &ts_n_case_realloc, "ts_s_case ", &ts_s_case, "ts_s_case_tot ", &ts_s_case_tot, "ts_n_structname ", &ts_n_structname, "ts_s_structname ", &ts_s_structname, "ts_n_type ", &ts_n_type, "ts_s_type ", &ts_s_type, "ts_n_global ", &ts_n_global, "ts_size_global ", &ts_size_global, "ts_n_holdstr ", &ts_n_holdstr, "ts_size_holdstr ", &ts_size_holdstr, "ts_n_growobj ", &ts_n_growobj, "ts_size_growobj_wasted ", &ts_size_growobj_wasted, "ts_n_growheap ", &ts_n_growheap, "ts_s_growheap ", &ts_s_growheap, }; struct ts *tp; for (tp = &ts[0]; tp < &ts[sizeof ts / sizeof ts[0]]; ++tp) { comment(); outstr(tp->what); outstr(""); outuvalue(*tp->where); outnl(); } comment(); outstr("brksize "); outhex((uvalue_t) brksize); outnl(); #endif #ifndef DIRECTPAGE bssseg(); #endif for (i = 0; i < HASHTABSIZE; ++i) for (symptr = hashtab[i]; symptr != NULL; symptr = symptr->next) if (symptr->storage == GLOBAL && !(symptr->flags & EXTERNAL) && *symptr->name.namea >= 'A' && symptr->flags <= MAXDUMPFLAG /* Don't access type unless flags <= MAXDUMPFLAG, because * type is punned to a symbol pointer for the label chain * and might be null. */ && symptr->type->constructor != FUNCTION) { #ifdef DIRECTPAGE if (symptr->flags & DIRECTPAGE) dpseg(); else dseg(); #endif type = symptr->type; if (symptr->flags & STATIC) lcommon(symptr->name.namea); else common(symptr->name.namea); outnhex(type->typesize); } if (printf_fp) globl("__xfpcvt"); if (scanf_fp) globl("__xfptvc"); } /* dumplocs() - define offsets of current locals */ PUBLIC void dumplocs() { register struct symstruct *symptr; int i; #ifdef ASM_USES_CALLEE_REGS if (framep && optimise && !callersaves) { regfuse |= callee1mask; outnstr("! Assuming #asm uses all callee saves registers"); } #endif for (i = 0; i < HASHTABSIZE; ++i) for (symptr = hashtab[i]; symptr != NULL; symptr = symptr->next) if (symptr->storage == LOCAL) set(symptr->name.namea, symptr->offset.offi - sp); } #ifdef HOLDSTRINGS /* dumpstrings() - dump held-up strings */ PUBLIC void dumpstrings() { struct string *stringp; dseg(); for (stringp = laststring; stringp != NULL; stringp = stringp->snext) { outnlabel(stringp->slabel); defstr(stringp->sptr, stringp->stop, TRUE); dataoffset += stringp->stop - stringp->sptr + 1; } } #endif PUBLIC struct symstruct *exprsym(symptr) struct symstruct *symptr; { register struct symstruct *newsymptr; newsymptr = exprptr++; if (exprptr >= &exprsyms[MAXEXPR]) #if MAXEXPR == 500 limiterror("expression too complex (501 symbols)"); #else limiterror("expression too complex (MAXEXPR)"); #endif *newsymptr = *symptr; newsymptr->level = EXPRLEVEL; newsymptr->name.namep = symptr->name.namea; return newsymptr; } PUBLIC struct symstruct *findlorg(name) char *name; { struct symstruct *symptr; symptr = *gethashptr(name); while (symptr != NULL && (strcmp(symptr->name.namea, name) != 0 || symptr->flags == STRUCTNAME)) symptr = symptr->next; return symptr; } PUBLIC struct symstruct *findstruct(name) char *name; { struct symstruct *symptr; symptr = *gethashptr(name); while (symptr != NULL && (symptr->flags != STRUCTNAME || strcmp(symptr->name.namea, name) != 0)) symptr = symptr->next; return symptr; } /* convert name to a hash table ptr */ PUBLIC struct symstruct **gethashptr(sname) char *sname; { register int hashval; register char *rsname; hashval = 0; rsname = sname; #if 1 while (*rsname) hashval = hashval * 2 + *rsname++; #else hashval = rsname[0]; if (rsname[1] != 0) hashval = (rsname[2] << 2) ^ rsname[1] ^ (rsname[0] << 1); else hashval = rsname[0]; #endif return hashtab + ((hashval * GOLDEN) & (HASHTABSIZE - 1)); } PRIVATE void heapcorrupterror() { outofmemoryerror(" (heap corrupt - stack overflow?)"); } #ifdef HOLDSTRINGS /* hold string for dumping at end, to avoid mixing it with other data */ PUBLIC label_no holdstr(sptr, stop) char *sptr; char *stop; { register struct string *stringp; stringp = qmalloc(sizeof *stringp); #ifdef TS ++ts_n_holdstr; ts_size_holdstr += sizeof *stringp; #endif stringp->snext = laststring; stringp->sptr = sptr; stringp->stop = stop; laststring = stringp; return stringp->slabel = getlabel(); } #endif /* HOLDSTRINGS */ PUBLIC void newlevel() { if (*(unsigned *) chartop != MARKER) heapcorrupterror(); if (level >= MAXLEVEL) limiterror("compound statements nested too deeply (126 levels)"); else ++level; } PUBLIC void oldlevel() { register struct symstruct *symptr; if (*(unsigned *) chartop != MARKER) heapcorrupterror(); if (level == 0) bugerror("not in a compound statement"); else --level; for (symptr = &locsyms[0]; symptr < locptr; symptr = (struct symstruct *) align(&symptr->name.namea[strlen(symptr->name.namea) + 1])) if (symptr->level > level) delsym(symptr); } PUBLIC void ourfree(ptr) void *ptr; { free(ptr); } PUBLIC void *ourmalloc(nbytes) unsigned nbytes; { void *ptr; if ((ptr = malloc(nbytes)) == NULL) outofmemoryerror(""); return ptr; } PUBLIC void outofmemoryerror(message) char *message; { error2error("compiler out of memory", message); #ifdef __AS386_16__ { unsigned size; char *ptr; for (size = 0x1000; size != 0; --size) if ((ptr = malloc(size)) != NULL) { outstr("found free memory at "); outuvalue((uvalue_t) ptr); outstr(" size "); outuvalue((uvalue_t) size); outnl(); } } #endif finishup(); } PUBLIC void *growobject(object, extra) void *object; unsigned extra; { /* size_t */ unsigned oblength; /* It would be nice to realloc the previous memory if it can be left in * the same place. Since a realloc that moves the memory can almost be * relied on to mess up pointers before *obptr, and since malloc(extra) * would be unlikely to produce memory adjoining chartop, it is not * clear how to do this. */ #ifdef TS ts_size_growobj_wasted += chartop - (char *) object; #endif oblength = (/* size_t */ unsigned) (charptr - (char *) object); growheap(oblength + extra); #ifdef TS ++ts_n_growobj; #endif memcpy(charptr, object, oblength); object = charptr; charptr += oblength; return object; } #define ALLOC_UNIT ((unsigned) 0x400) #ifdef S_ALIGNMENT #define ALLOC_OVERHEAD (S_ALIGNMENT - 1 + sizeof (unsigned)) #else #define ALLOC_OVERHEAD (sizeof (unsigned)) #endif PUBLIC void growheap(size) unsigned size; { register char *newptr; if ((newptr = malloc(size += ALLOC_UNIT + ALLOC_OVERHEAD)) == NULL && (newptr = malloc(size -= ALLOC_UNIT)) == NULL) outofmemoryerror(""); #ifdef TS ++ts_n_growheap; ts_s_growheap += size; #endif charptr = newptr; newptr = (char *) align(newptr + size - ALLOC_OVERHEAD); chartop = newptr; char1top = newptr - 1; char3top = newptr - 3; *(unsigned *) newptr = MARKER; } PUBLIC void *qmalloc(size) unsigned size; { register char *ptr; if ((charptr = (char *) align(charptr)) + size > chartop) growheap(size); ptr = charptr; charptr += size; return ptr; } PUBLIC void swapsym(sym1, sym2) struct symstruct *sym1; struct symstruct *sym2; { struct symstruct swaptemp; swaptemp = *sym1; *sym1 = *sym2; *sym2 = swaptemp; } PUBLIC void syminit() { struct keywordstruct *kwptr; struct typedatastruct *tdptr; struct typestruct *type; exprptr = exprsyms; locptr = locsyms; for (tdptr = scaltypes; tdptr < scaltypes + NSCALTYPES; ++tdptr) { (*tdptr->tdtypeptr = type = newtype())->scalar = tdptr->tdscalar; type->alignmask = ~((type->typesize = tdptr->tdsize) - 1) | alignmask; type->tname = tdptr->tdname; if (tdptr->tdkeyscalar) addkeyword(tdptr->tdname, TYPEDECL)->type = type; } for (kwptr = keywords; kwptr < keywords + NKEYWORDS; ++kwptr) addkeyword(kwptr->kwname, kwptr->kwcode); constemplate.type = itype; } #ifndef VERY_SMALL_MEMORY PUBLIC struct symstruct *findstrm(type, name) struct typestruct *type; char *name; { struct symstruct *symptr; int i; char anon[2 + NAMESIZE]; struct typelist *tl; /* Look for a struct member named as given */ name[0] = type->structkey[0]; name[1] = type->structkey[1]; if ((symptr = findlorg(name)) != NULL) return symptr; /* No match? Fine, let's see if there are any anynymous structures * or unions that we could recurse into */ for (i = 0; i < lastanon(); i++) { anon[0] = type->structkey[0]; anon[1] = type->structkey[1]; anonname(&anon[2], i); if ((symptr = findlorg(anon)) != NULL) { /* Found an anonymous struture */ if (!(symptr->type->constructor & STRUCTU)) error("Anonymous structure not a structure?!"); /* Look for the member */ strcpy(&anon[2], &name[2]); if ((symptr = findstrm(symptr->type, anon)) != NULL) return symptr; } } #ifndef VERY_SMALL_MEMORY /* In ancient UNIX, C structure members were global */ if (!ancient) return NULL; /* Find any structure member of given name */ laststruct(name); while (name[0]) { if ((symptr = findlorg(name)) != NULL) return symptr; if (--name[1] == 0) { name[1] = 255; name[0]--; } } #endif return NULL; } #endif dev86-0.16.21/bcc/table.h000066400000000000000000000037351231050321700146060ustar00rootroot00000000000000/* table.h - table handler for bcc */ /* Copyright (C) 1992 Bruce Evans */ EXTERN char *charptr; /* next free spot in catchall table */ EXTERN char *chartop; /* spot after last in table */ EXTERN char *char1top; /* last character spot in table */ EXTERN char *char3top; /* third last character spot in table */ EXTERN struct symstruct *exprptr; /* next entry in expression symbol table */ EXTERN struct symstruct *locptr; /* next entry in local symbol table */ extern struct symstruct locsyms[]; /* local symbol table */ #define TS1 #ifdef TS uvalue_t ts_n_newtypelist; uvalue_t ts_s_newtypelist; uvalue_t ts_n_filename_term; uvalue_t ts_s_filename_term; uvalue_t ts_n_filename; uvalue_t ts_s_filename; uvalue_t ts_s_filename_tot; uvalue_t ts_n_pathname; uvalue_t ts_s_pathname; uvalue_t ts_s_pathname_tot; uvalue_t ts_n_inputbuf; uvalue_t ts_s_inputbuf; uvalue_t ts_s_inputbuf_tot; uvalue_t ts_n_includelist; uvalue_t ts_s_includelist; uvalue_t ts_s_outputbuf; uvalue_t ts_n_macstring_ident; uvalue_t ts_n_macstring_ordinary; uvalue_t ts_n_macstring_param; uvalue_t ts_n_macstring_quoted; uvalue_t ts_n_macstring_term; uvalue_t ts_s_macstring; uvalue_t ts_n_defines; uvalue_t ts_s_defines; uvalue_t ts_n_macparam; uvalue_t ts_s_macparam; uvalue_t ts_s_macparam_tot; uvalue_t ts_n_macparam_string_ordinary; uvalue_t ts_n_macparam_string_quoted; uvalue_t ts_n_macparam_string_term; uvalue_t ts_s_macparam_string; uvalue_t ts_s_macparam_string_tot; uvalue_t ts_s_macparam_string_alloced; uvalue_t ts_s_macparam_string_alloced_tot; uvalue_t ts_s_fakeline; uvalue_t ts_s_fakeline_tot; uvalue_t ts_n_string; uvalue_t ts_n_case; uvalue_t ts_n_case_realloc; uvalue_t ts_s_case; uvalue_t ts_s_case_tot; uvalue_t ts_n_structname; uvalue_t ts_s_structname; uvalue_t ts_n_type; uvalue_t ts_s_type; uvalue_t ts_n_global; uvalue_t ts_size_global; uvalue_t ts_n_holdstr; uvalue_t ts_size_holdstr; uvalue_t ts_n_growobj; uvalue_t ts_size_growobj_wasted; uvalue_t ts_n_growheap; uvalue_t ts_s_growheap; #endif dev86-0.16.21/bcc/type.c000066400000000000000000000114051231050321700144640ustar00rootroot00000000000000/* type.c - type and storage-class routines for bcc */ /* Copyright (C) 1992 Bruce Evans */ #include "bcc.h" #include "align.h" #include "gencode.h" /* s.b. switches.h */ #include "sc.h" #include "scan.h" #include "table.h" #undef EXTERN #define EXTERN #include "type.h" PUBLIC uoffset_T ctypesize = 1; PUBLIC uoffset_T dtypesize = 8; PUBLIC uoffset_T ftypesize = 0; PUBLIC uoffset_T itypesize = 2; PUBLIC uoffset_T ptypesize = 2; PUBLIC uoffset_T stypesize = 2; PRIVATE char skey0; PRIVATE char skey1; PUBLIC struct typestruct *addstruct(structname) char *structname; { unsigned namelength; struct symstruct *symptr; struct typestruct *structype; (structype = newtype())->constructor = STRUCTU; structype->alignmask = ctype->alignmask; if (++skey1 == 0) { ++skey1; /* must be nonzero or key string would end */ ++skey0; /* will never reach 'A' to be an identifier */ } structype->structkey[0] = skey0; structype->structkey[1] = skey1; if (*structname != 0) { symptr = addlorg(structname, structype); symptr->storage = 0; symptr->flags = STRUCTNAME; if (charptr + (namelength = strlen(structname)) >= chartop) growheap(namelength + 1); #ifdef TS ++ts_n_structname; ts_s_structname += namelength + 1; #endif structype->tname = strcpy(charptr, structname); charptr += namelength + 1; } return structype; } #ifndef VERY_SMALL_MEMORY PUBLIC void laststruct(char *sname) { sname[0] = skey0; sname[1] = skey1; } #endif PUBLIC struct typestruct *iscalartotype(scalar) scalar_pt scalar; { if (scalar & LONG) { if (scalar & UNSIGNED) return ultype; return ltype; } if (scalar & UNSIGNED) return uitype; return itype; } PUBLIC struct typestruct *newtype() { register struct typestruct *type; type = qmalloc(sizeof *type); #ifdef TS ++ts_n_type; ts_s_type += sizeof *type; #endif type->typesize = /* (uoffset_T) */ type->scalar = /* (scalar_t) */ type->constructor = /* (constr_t) */ type->structkey[0] = 0; type->nexttype = type->prevtype = type->sidetype = NULL; type->listtype = NULL; type->tname = ""; return type; } PUBLIC void outntypechar(type) struct typestruct *type; { outnbyte(*type->tname); } PUBLIC struct typestruct *pointype(type) struct typestruct *type; { return prefix(POINTER, ptypesize, type); } PUBLIC struct typestruct *prefix(constructor, size, type) constr_pt constructor; uoffset_T size; struct typestruct *type; { register struct typestruct *searchtype; for (searchtype = type->prevtype; searchtype != NULL; searchtype = searchtype->sidetype) if (searchtype->constructor == (constr_t) constructor && searchtype->typesize == size) return searchtype; switch ((searchtype = newtype())->constructor = constructor) { case ARRAY: searchtype->alignmask = type->alignmask; break; case FUNCTION: searchtype->alignmask = ~(uoffset_T) 0; break; case POINTER: searchtype->alignmask = ~(ptypesize - 1) | alignmask; break; case STRUCTU: bugerror("prefixing structure/union"); searchtype->alignmask = alignmask; break; } searchtype->typesize = size; searchtype->nexttype = type; searchtype->sidetype = type->prevtype; return type->prevtype = searchtype; } PUBLIC struct typestruct *promote(type) struct typestruct *type; { scalar_t scalar; if ((scalar = type->scalar) & (CHAR | SHORT)) { if (scalar & UNSIGNED) return uitype; return itype; } if (scalar & FLOAT) return dtype; if (type->constructor & ARRAY) return pointype(type->nexttype); if (type->constructor & FUNCTION) return pointype(type); return type; } PUBLIC struct typestruct *tosigned(type) struct typestruct *type; { switch (type->scalar & ~(UNSIGNED | DLONG)) { case CHAR: return sctype; case SHORT: return stype; case INT: return itype; case LONG: return ltype; default: error("signed only applies to integral types"); return type; } } PUBLIC struct typestruct *tounsigned(type) struct typestruct *type; { switch (type->scalar & ~(UNSIGNED | DLONG)) { case CHAR: return uctype; case SHORT: return ustype; case INT: return uitype; case LONG: return ultype; default: error("unsigned only applies to integral types"); return type; } } PUBLIC void typeinit() { #ifdef I80386 if (i386_32) { uitype->typesize = itype->typesize = ptypesize = itypesize = 4; dtype->alignmask = fltype->alignmask = uitype->alignmask = ltype->alignmask = ultype->alignmask = itype->alignmask = ~(uoffset_T) (4 - 1); ltype->scalar = LONG; /* not DLONG */ ultype->scalar = UNSIGNED | LONG; } #endif fitype = prefix(FUNCTION, ftypesize, itype); pctype = pointype(ctype); skey0 = 1; vtype->constructor = VOID; } dev86-0.16.21/bcc/type.h000066400000000000000000000050261231050321700144730ustar00rootroot00000000000000/* type.h - types for bcc */ /* Copyright (C) 1992 Bruce Evans */ /* A type is essentially a "constructor", a size, and a list of pointers leading to a scalar type. The type constructors are codes for the scalar types and (), [], *, struct and union. The scalar types are char, short, int, long, float and double. The type lists are triply linked. Part of the type structure might look like int (int) = func <-------> int (int ()) | = --> ptr <--> int (int *) (the exact structure depends on the order of declarations). This layout results from the pre-declared (int) and (int ()) followed by a declaration using (int *). The sideways link (from func to ptr here) allows all types leading to a given type to be found. This allows different declarations of (int *) to be recognised as the same. Type equivalence is equality of type pointers. */ /* flags for scalar types up to 3 of the flags may be set (none for constructed types) the 2nd and third flags can only be UNSIGNED or DLONG UNSIGNED only applies to integral types DLONG only applies to long and unsigned long types and says that these are actually longer than an int */ #define CHAR 0x01 #define SHORT 0x02 #define INT 0x04 #define LONG 0x08 #define FLOAT 0x10 #define DOUBLE 0x20 #define UNSIGNED 0x40 #define DLONG 0x80 #define ISCALAR (CHAR | SHORT | INT | LONG) #define RSCALAR (FLOAT | DOUBLE) /* flags for type constructor at most 1 of the flags may be set (none for scalar types) flags are used for fast testing for array/pointer */ #define ARRAY 1 #define FUNCTION 2 #define POINTER 4 #define STRUCTU 8 #define VOID 0x10 /* type sizes */ /* default sizes and long and float sizes are hard-coded into type data */ extern uoffset_T ctypesize; extern uoffset_T dtypesize; extern uoffset_T ftypesize; extern uoffset_T itypesize; extern uoffset_T ptypesize; extern uoffset_T stypesize; /* basic scalar types */ EXTERN struct typestruct *dtype; EXTERN struct typestruct *fltype; EXTERN struct typestruct *itype; EXTERN struct typestruct *ltype; EXTERN struct typestruct *sctype; EXTERN struct typestruct *stype; EXTERN struct typestruct *uctype; EXTERN struct typestruct *uitype; EXTERN struct typestruct *ultype; EXTERN struct typestruct *ustype; EXTERN struct typestruct *vtype; /* working type */ EXTERN struct typestruct *ctype; /* constructed types */ EXTERN struct typestruct *fitype; EXTERN struct typestruct *pctype; /* return type of current function */ EXTERN struct typestruct *returntype; dev86-0.16.21/bcc/types.h000066400000000000000000000125461231050321700146630ustar00rootroot00000000000000/* types.h - type definitions for bcc */ /* Copyright (C) 1992 Bruce Evans */ /* source types big enough to handle target quantities these have to be match the source compiler and target machine this is impossible if the source long type is too small */ typedef unsigned char char_t; /* target char */ typedef long value_t; /* target ints, longs and offsets */ typedef unsigned long uvalue_t; /* target unsigned ints, longs and offsets */ #ifdef I8088 typedef long offset_T; /* target machine offset */ typedef unsigned long uoffset_T; /* target unsigned machine offset */ #define outuvalue outhex #define outvalue outshex #endif #ifdef MC6809 typedef int offset_T; typedef unsigned uoffset_T; #endif /* storage class type must hold all the flags defined elsewhere it must have a few more bits than the target has registers */ #ifdef I8088 typedef unsigned store_pt; /* promoted store_t */ typedef unsigned store_t; /* storage class flags */ #endif #ifdef MC6809 #ifdef __STDC__ typedef int store_pt; # else typedef unsigned store_pt; # endif typedef unsigned char store_t; #endif /* types for library routines */ typedef int fd_t; /* file descriptor */ /* basic scalar types - may be tuned to suit machine */ typedef int fastin_pt; /* promoted fastin_t */ /* always an int - use to show that the */ /* value may be accessed as a fastin_t */ typedef char fastin_t; /* fast int - a small integer value */ /* on some machines, chars can be accessed */ /* more efficiently than ints for arithmetic */ /* such as comparing and masking which */ /* does not requiring promotion */ /* change to int if chars are inefficient */ /* or if char has < 8 bits */ typedef int smalin_pt; /* promoted smalin_t */ typedef char smalin_t; /* small int - a small integer value */ /* on most machines, chars are stored in */ /* less space than any other type */ /* change to fastin_t if this is not true */ /* or if char has < 8 bits */ /* or if space is not a limiting factor */ #ifdef __STDC__ typedef int smalu_pt; #else typedef unsigned smalu_pt; #endif typedef unsigned char smalu_t; /* derived scalar types the types containing bit flags fit in an 8 bit smalin_t */ typedef fastin_pt bool_pt; /* promoted bool_t */ typedef fastin_t bool_t; /* boolean: TRUE if nonzero */ typedef fastin_pt ccode_pt; /* promoted ccode_t */ typedef fastin_t ccode_t; /* condition code code */ typedef smalu_pt constr_pt; /* promoted constr_t */ typedef smalu_t constr_t; /* type constructor flags */ typedef smalu_pt indn_pt; /* promoted indn_t */ typedef smalu_t indn_t; /* storage indirection count */ typedef unsigned label_no; /* label number */ typedef smalu_t maclev_t; /* macro expansion level */ typedef smalin_pt op_pt; /* promoted op_t */ typedef smalin_t op_t; /* operator code */ typedef smalu_t sc_t; /* storage class flags */ typedef smalu_pt scalar_pt; /* promoted scalar_t */ typedef smalu_t scalar_t; /* type scalar flags */ typedef smalu_t scopelev_t; /* scope level */ typedef fastin_pt sym_pt; /* promoted sym_t */ typedef fastin_t sym_t; /* symbol code from scanner */ typedef smalu_t weight_t; /* expression tree node weight */ /* derived structure types the fields are ordered in a way that is most space-efficient when smalin_t is char and smalu_t is unsigned char the first element of the structures is the one most frequently accessed */ /* expression table entry format */ struct nodestruct { op_t tag; weight_t weight; smalu_t flags; struct typestruct *nodetype; union nodeunion { struct nodestruct *nodeptr; struct symstruct *symptr; } left; struct nodestruct *right; }; /* symbol table entry format */ struct symstruct { store_t storage; indn_t indcount; sc_t flags; scopelev_t level; struct symstruct *next; struct symstruct **prev; struct typestruct *type; union { double *offd; /* value for double constants */ offset_T offi; /* offset for register or global storage */ label_no offlabel; /* label number for strings */ char *offp; /* to string for macro definitions */ sym_pt offsym; /* symbol code for keywords */ value_t offv; /* value for integral constants */ } offset; union { label_no label; /* label number for strings */ char namea[1]; /* variable length array for declarations */ char *namep; /* to constant storage for exprs */ } name; }; /* type table entry format */ struct typestruct { scalar_t scalar; /* scalar type flags u d f l i s c */ constr_t constructor; /* constructed type flags a f p s/u */ char structkey[2]; /* unique prefix for member names */ /* ranges from "\001\001" to "@\377" */ /* avoiding nulls */ uoffset_T alignmask; /* alignment mask, typesize - 1 for scalars */ uoffset_T typesize; /* size of this type */ char *tname; /* name of scalar type or constructor */ struct typelist *listtype; /* list of member types */ struct typestruct *nexttype; /* next in list */ struct typestruct *prevtype; /* previous in list */ struct typestruct *sidetype; /* next in sideways list */ }; /* list of type structures */ struct typelist { struct typelist *tlnext; struct typestruct *tltype; }; /* definitions to avoid passing raw NULLs to functions */ #define NULLNODE ((struct nodestruct *) NULL) #define NULLTYPE ((struct typestruct *) NULL) dev86-0.16.21/bin86/000077500000000000000000000000001231050321700135355ustar00rootroot00000000000000dev86-0.16.21/bin86/ChangeLog000066400000000000000000000066001231050321700153110ustar00rootroot00000000000000 This file is NOT the current changelog. Please see the Changes file in the directory above (the main directory of the Dev86 package). Robert de Bath. Fri Jun 11 13:08:27 BST 1999 Robert de Bath (rdebath@poboxes.com) * objdump86 program included. * Updated for libc6 * As86 fixes for multi-segment (The linker can't really cope tho) Sat Mar 13 16:45:42 GMT 1999 Robert de Bath (rdebath@poboxes.com) * Vsn 0.15.0, more documentation! * Linker can now generate QMAGIC 386 executables. Fri Jul 31 09:33:18 BST 1998 Robert de Bath (rdebath@poboxes.com) * version 0.14.4, This package is based on the ELKS dev86 package of the same version number. * Improved documentation (There's actually a man page!) * The linker will produce either Linux-8086, DOS-COM or Native Linux-386 OMAGIC executable files. * The assembler has many instruction fixes: jmp near, jmpi dword x,y, org, use32/use16 ... etc and can also read source from stdin. * Assembler macros work. * The assembler command 'include' works. * Conditionals and string conditionals work. * Various additions for multi-segment work. * The assembler can create bare binary files with simple ASCII symbol files, these are ideal for generating encapsulated binaries and a simple script for doing this is included. * The assembler will generate warning messages when 386 instructions are used with the assembler in an 8086 mode. * Many minor bug fixes and portability fixes. Sat Nov 16 18:38:14 1995 H.J. Lu (hjl@gnu.ai.mit.edu) * version 0.4 is released. * Makefile (CFLAGS): add _POSIX_SOURCE. * as/as.c, as/flag.h, as/genlist.c, as/pops.c,v, as/readsrc.c: change warn to warning. Fri Jun 16 02:02:03 1995 Michael Shields (shields@tembel.org) * as/Makefile (endian.h): Don't rely on . being in $PATH. Tue May 16 22:01:05 1995 H.J. Lu (hjl@nynexst.com) * version 0.3 is released. * Makefile: fix a few typos. * as/const.h: include "endian.h". (LOW_BYTE): check the byte order. * as/Makefile (endian.h): new target. (const.h): depend on endian.h. * as/det_endian.c: new from glibc. Sat Mar 18 16:39:19 1995 Francois-Rene Rideau (rideau@clipper.ens.fr) * as/pops.c (doif): support nested conditionals. Mon Nov 21 22:48:26 1994 H.J. Lu (hlu@nighthawk) * version 0.2 is released. * Makefile (MFLAGS): new. add BINDIR and CC. Fri Nov 18 22:25:24 1994 Package Maintainer (opt@calum.csclub.uwaterloo.ca) * ./as/Makefile: * ./as/const.h: * ./as/proto.h: * ./as/readsrc.c: * ./as/type.h: * ./ld/Makefile: * ./ld/align.h: * ./ld/config.h: * ./ld/type.h: * ./ld/typeconv.c: remove endian dependency. Thu Mar 3 15:12:23 1994 H.J. Lu (hlu@nighthawk) * version 0.1 is released. * Makefile: new. * a.out.h/bsd-a.out.h (struct exec): use short form if __linux__ is defined. * as/Makefile: minor changes. (CLFAGS): add -I../a.out.h. * ld/Makefile: minor changes. (CLFAGS): add -I../a.out.h. * ld/io.c (MY_STAT_H): don't define it if __linux__ is defined. * ld/ld.c (flag['z']): initialized to 0 if __linux__ is defined. * ld/obj.h (roundup): * ld/writebin.c (roundup): ld/readobj.c (roundup): change that to ld_roundup to avoid the conflict with the system's roundup. * ld/writebin.c: cleanup for the latest Linux C library. (FILEHEADERLENGTH): change to sizeof (struct exec). don't write a_trsize and its friends. dev86-0.16.21/bin86/Makefile000066400000000000000000000022101231050321700151700ustar00rootroot00000000000000 CFLAGS=-O2 -D_POSIX_SOURCE LDFLAGS= DIRS=ld as PREFIX=/usr/local BINDIR=$(PREFIX)/bin LIBDIR=$(PREFIX)/lib ifeq ($(PREFIX),/usr) MANDIR=$(PREFIX)/share/man/man1 else MANDIR=$(PREFIX)/man/man1 endif SUF=86 INSTALL_OPT=-m 755 INSTALL_OPTS=-m 755 -s MAN_OPTS =-m 644 MFLAGS= "LIBS=$(LIBS)" \ "CFLAGS=$(CFLAGS)" \ "LDFLAGS=$(LDFLAGS)" \ "BINDIR=$(BINDIR)" \ "LIBDIR=$(LIBDIR)" \ "CC=$(CC)" all: set -e ; for d in $(DIRS); do \ (cd $$d && $(MAKE) $(MFLAGS) $@;); \ done install: all install $(INSTALL_OPTS) as/as86 $(BINDIR)/as$(SUF) install $(INSTALL_OPTS) ld/ld86 $(BINDIR)/ld$(SUF) install $(INSTALL_OPTS) ld/objdump86 $(BINDIR)/objdump$(SUF) install $(MAN_OPTS) man/*.1 $(MANDIR) ln -sf objdump$(SUF) $(BINDIR)/nm$(SUF) ln -sf objdump$(SUF) $(BINDIR)/size$(SUF) depend clean clobber: set -e ; for d in $(DIRS); do \ (cd $$d && $(MAKE) $(MFLAGS) $@;); \ done ungrab: ../as/as.c rm -rf as ld man grab: cp -a ../as ../ld . rm -f ld/ar.h && cp -p ../libc/include/ar.h ld/ar.h mkdir man cp -p ../man/ld86.1 man cp -p ../man/as86.1 man touch -r ../Changes . as ld man dev86-0.16.21/bin86/README000066400000000000000000000014671231050321700144250ustar00rootroot00000000000000 This is a simple assember and linker for 8086 - 80386 machine code. There have been a large number of changes since bin86-0.4 so I strongly suggest you read the manpages. To install: make PREFIX=/usr install or make PREFIX=/usr/local install This version has been tested under Linux, older versions were also tested and working under SunOS and AIX. ------------- This is based on the as86 and ld86 distribution written by Bruce Evans. Bruce has released this under the GPL and the changes I've made are also under the same license The BCC components that were distributed in this package are now in the dev86 package along with a working C compiler and libc for 8086 ELKS, DOS and standalone code. The most recent address I have for Bruce is Robert de Bath 1998/7/31 dev86-0.16.21/bin86/README-0.4000066400000000000000000000053541231050321700147230ustar00rootroot00000000000000To build this real mode as/ld for x86, just edit Makefile and then do make install It is only tested under SunOS 4.1.3 and Linux. H.J. Lu hjl@nynexst.com 11/21/94 ------ We seem to have cross bin86 for Solaris working. The most important changes involve alignment (it needs to be on) and byte ordering. Some of the patches just eliminate compiler warnings (conversion of pointer to integer without a cast, etc.) and some (in the Makefiles) reflect the local setup, and can probably be ignored (the change to $BINDIR, for example). - Ian (iagoldbe@csclub.uwaterloo.ca) ---- I modified it for the latest Linux C library 4.5.21 and released it as bin86 0.1. It is only tested for building the Linux kernel and is not intended for any other purposes. To build it under Linux, just type make all make install It is not tested for cross-compiling. If you have any patches for cross-compiling, please send them to me. Thanks. H.J. Lu hjl@nynexst.com 03/03/94 ------------- This is the as86 and ld86 distribution written by Bruce Evans. It's copyright Bruce Evans, all rights reserved although you may use and copy it for your personal use. It's a complete 8086 assembler and loader which can make 32-bit code for the 386+ processors (under linux it's used only to create the 16-bit bootsector and setup binaries). The syntax is not compatible with the GNU assembler, but closer to intel syntax ("wrong" order of operands etc). Hints for compiling: - you'll need the a.out.h-files from the a.out.h directory for the linker. These aren't really part of the distribution, but I included them for ease of setup (in case you need to crosscompile etc). Do a cp a.out.h/* ld/ or similar before compiling the linker. - the assembler needs the typeconv.o file produced by the linker compilation. So compile the linker first, and then do a cp ld/typeconv.o as/ before making the assembler. This distribution also contains some test-files etc that aren't actually needed, but as they also give some idea of the assembler syntax, I left them in. The directories are as follows: as - the assembler sources (minus typeconv.c) ld - linker sources bcc - bruce evans' cc frontend sources (the actual compiler isn't included). bccfp - assembly floating point routines written by bruce evans. Note that these use integer register returns, and won't work with the linux libraries. They can be used as examples of as86 code. a.out.h - header files for crosscompilation. Note that I am NOT the author of this package, but I'll forward any comments to bruce evans and I'll try to answer any questions about the assembler/linker I can. I just made it available as bde doesn't have ftp capability right now. Bruce Evans does have mail as . Linus Torvalds dev86-0.16.21/bootblocks/000077500000000000000000000000001231050321700147505ustar00rootroot00000000000000dev86-0.16.21/bootblocks/Makefile000066400000000000000000000120711231050321700164110ustar00rootroot00000000000000 HOSTCC=cc HOSTCCFLAGS=-O BCC=bcc AS86=as86 DEFS= CC=$(BCC) CFLAGS=-ansi -Ms -Oi -O $(DEFS) LDFLAGS=-s -i -H0x10000 ASFLAGS=-0 -w MINIXDEFS=-DDOTS # CFLAGS=-ansi -Ms $(DEFS) LST=-l $*.lst default: makeboot makeboot.com monitor.sys minix_elks.bin lsys.com all: bootbin bootsys default tgz bootsys: bootfile.sys boottar.sys bootminix.sys monitor.sys boot_win.sys CSRC=minix.c SSRC=tarboot.s skip.s mbr.s mbr_dm.s msdos.s noboot.s nombr.s \ boot_fpy.s killhd.s bb_linux.s bb_init1.s bb_init2.s SINC=sysboot16.s sysboot.s sysmbr.s sysmbrtail.s encap: $(SSRC:s=v) $(CSRC:c=v) minixhd.v mbr_chs.v mbr_lin.v mbr_lba.v pbr.v msdos16.v bootbin: $(SSRC:s=bin) $(CSRC:c=bin) minixhd.bin mbr_chs.bin mbr_lin.bin mbr_lba.bin pbr.bin msdos16.bin minix_elks.bin MOBJ=monitor.o commands.o i86_funcs.o relocate.o help.o bzimage.o \ buffer.o unix.o fs.o fs_tar.o fs_min.o fs_dos.o MSRC=monitor.c commands.c i86_funcs.c relocate.c help.c bzimage.c \ buffer.c unix.c fs.c fs_tar.c fs_min.c fs_dos.c MINC=i86_funcs.h readfs.h monitor.h BOOTBLOCKS=sysboot.v noboot.v skip.v msdos.v msdos16.v \ tarboot.v minix.v minixhd.v mbr.v killhd.v \ sysboot16.v nombr.v mbr_dm.v mbr_chs.v mbr_lin.v mbr_lba.v \ pbr.v EXTRAS=minix.h zimage.s minix_elks.c lsys.c boot_win.c \ freedosboot.zip freedos.h install: makeboot install -m 755 -s makeboot $(DIST)$(PREFIX)/bin/makeboot monitor.com: $(MOBJ) $(CC) $(CFLAGS) $(LDFLAGS) $(MONDEFS) -d $(MOBJ) -o monitor.com -M > monitor.sym monitor.out: $(MOBJ) $(CC) $(CFLAGS) $(LDFLAGS) $(MONDEFS) $(MOBJ) -o monitor.out -M > monitor.sym $(MOBJ): $(MINC) fs_min.o: minix.h bootfile.sys: $(MSRC) $(MINC) @rm -f $(MOBJ) make 'CFLAGS=$(CFLAGS) -DDOSFLOPPY' monitor.out mv monitor.out bootfile.sys @rm -f $(MOBJ) boottar.sys: $(MSRC) $(MINC) tarboot.bin @rm -f $(MOBJ) make 'CFLAGS=$(CFLAGS) -DTARFLOPPY' monitor.out mv monitor.out boottar.sys @rm -f $(MOBJ) bootminix.sys: $(MSRC) $(MINC) minix.bin @rm -f $(MOBJ) make 'CFLAGS=$(CFLAGS) -DMINFLOPPY' monitor.out mv monitor.out bootminix.sys @rm -f $(MOBJ) monitor.sys: $(MSRC) $(MINC) @rm -f $(MOBJ) make monitor.out mv monitor.out monitor.sys @rm -f $(MOBJ) monitor: $(MSRC) $(MINC) @rm -f $(MOBJ) make 'CFLAGS=-ansi $(DEFS)' monitor.out mv monitor.out monitor @rm -f $(MOBJ) bzimage.o: bzimage.c zimage.v minix.s: minix.c Makefile $(CC) -Mf -O -DTRY_FLOPPY $(MINIXDEFS) -S minix.c minix_elks.s: minix_elks.c Makefile minix.v $(CC) -Mf -O $(MINIXDEFS) -S minix_elks.c minixhd.s: minix.c Makefile $(CC) -Mf -O -DHARDDISK $(MINIXDEFS) -S minix.c -o minixhd.s msdos16.s: msdos.s Makefile sed 's/^fatbits=12/fatbits=16/' < msdos.s > msdos16.s mbr_chs.s: mbr.s Makefile sed -e 's/^linear=1/linear=0/' \ -e 's/^useCHS=0/useCHS=1/' \ -e 's/^linCHS=1/linCHS=0/' \ -e 's/^mbrkey=1/mbrkey=0/' \ -e 's/^preboot=1/preboot=0/' \ -e 's/^pbr=1/pbr=0/' \ -e 's/^direct=1/direct=0/' \ -e 's/^message=1/message=0/' \ < mbr.s > mbr_chs.s mbr_lin.s: mbr.s Makefile sed -e 's/^linear=1/linear=0/' \ -e 's/^useCHS=0/useCHS=1/' \ -e 's/^linCHS=0/linCHS=1/' \ -e 's/^mbrkey=1/mbrkey=0/' \ -e 's/^preboot=1/preboot=0/' \ -e 's/^pbr=1/pbr=0/' \ -e 's/^direct=1/direct=0/' \ -e 's/^message=1/message=0/' \ < mbr.s > mbr_lin.s pbr.s: mbr.s Makefile sed -e 's/^linear=0/linear=1/' \ -e 's/^useCHS=1/useCHS=0/' \ -e 's/^linCHS=1/linCHS=0/' \ -e 's/^mbrkey=1/mbrkey=0/' \ -e 's/^preboot=1/preboot=0/' \ -e 's/^pbr=0/pbr=1/' \ -e 's/^direct=1/direct=0/' \ -e 's/^message=1/message=0/' \ < mbr.s > pbr.s mbr_lba.s: mbr.s Makefile sed -e 's/^linear=0/linear=1/' \ -e 's/^useCHS=1/useCHS=0/' \ -e 's/^linCHS=1/linCHS=0/' \ -e 's/^mbrkey=1/mbrkey=0/' \ -e 's/^preboot=1/preboot=0/' \ -e 's/^pbr=1/pbr=0/' \ -e 's/^direct=1/direct=0/' \ -e 's/^message=1/message=0/' \ < mbr.s > mbr_lba.s boot_win.sys: boot_win.c $(CC) -Ms -H0x6000 -s boot_win.c -o boot_win.sys makeboot: makeboot.c $(BOOTBLOCKS) freedos.h $(HOSTCC) $(HOSTCCFLAGS) -o makeboot makeboot.c ldboot: ldboot.c $(HOSTCC) $(HOSTCCFLAGS) -o ldboot ldboot.c makeboot.com: makeboot.c $(BOOTBLOCKS) freedos.h $(CC) -Md -O -o makeboot.com makeboot.c lsys.com: lsys.c msdos.v msdos16.v $(CC) -Md -O -o lsys.com lsys.c clean realclean: rm -f bootfile.sys boottar.sys bootminix.sys monitor.sys boot_win.sys rm -f monitor makeboot bootblocks.tar.gz rm -f minix.s minixhd.s minix_elks.s msdos16.s mbr_chs.s mbr_lin.s mbr_lba.s pbr.s rm -f *.com *.o *.bin *.out *.lst *.sym *.v *.tmp tgz: minix.bin monitor.sys makeboot.com makeboot tar cfV bootblocks.tar ENIAC monitor.sys \ README Makefile \ $(MSRC) \ $(MINC) \ makeboot.c $(CSRC) freedos.h \ $(SSRC) $(SINC) \ makeboot.com minix.bin \ $(EXTRAS) makeboot tar bootblocks.tar gzip -f9 bootblocks.tar distribution: tar czf /tmp/bootblocks.tar.gz \ README Makefile $(MSRC) $(MINC) makeboot.c $(CSRC) $(SSRC) $(SINC) $(EXTRAS) .SUFFIXES: .bin .v .s.bin: $(AS86) -w- -0 -b $*.bin -s $*.sym $*.s $(LST) .s.v: as86_encap $*.s $*.v $*_ $(ASFLAGS) $(LST) dev86-0.16.21/bootblocks/README000066400000000000000000000142671231050321700156420ustar00rootroot00000000000000 Contents 1.0 ) Boot sectors 1.1 ) Master boot sector 1.2 ) Dosfs boot sector 1.3 ) Minixfs boot block 1.4 ) Tar boot sector 1.5 ) Skip boot sector 1.6 ) Panic boot sector 2.1 ) Booting i86 standalone executable 2.2 ) Booting Elks kernel 2.3 ) Booting Linux-i386 [b]zImage -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- 1.0 ) Boot sectors These boot sectors are mostly designed for floppy use, the exceptions being the MinixFS and Master boot sectors. The makeboot program makes them very easy to install just format the disk add the correct filesystem then run a command like ... $ makeboot minix /dev/fd0 As far as I know all boot sectors and programs are 8086 clean, with the exception that, obviously, the Linux-i386 loader needs access to extended memory. 1.1 ) Master boot sector This MBR is a very simple one with no frills by default. The actual code is less that 254 bytes long so it can be used as an MBR for a disk with old style 'Disk manager' partitions. The code now only boots one of the last four partitions. Option 2 is a boot message that displayed as soon as the MBR loads. Option 3 is code to accept a keypress from the user to select which partition to boot (or the floppy). 1.2 ) Dosfs boot sector Install with makeboot, there is also a version for 16 bit FAT filesystems for big floppies (eg LS-120 disks) or hard disk partitions. This boot sector loads and executes a binary BOOTFILE.SYS from the root directory of the floppy. The file can be any length and is loaded at $07C00. Because of the load address this boot sector can be configured to load another boot sector, for example LILO can be succesfully used in this way. Note this boot sector loads the executable 1 sector at a time, as far as my testing has gone this is only significant on 8086 machines, all others (286 8Mhz +) are fast enough to keep up at a 1-1 interleve. But some versions of superformat can defeat this because they do not correctly calculate intersector gaps. I suggest using fdformat as this uses a 'safe' layout for standard 1440k disks. 1.3 ) Minixfs boot block This boot block has varients for floppy and harddisk and works similarly for both. For the hard disk it must be installed in the partition boot block with a normal MBR in sector zero of the disk. This boot sector can be installed with makeboot or simply by copying the 1k file to the start of the partition (or floppy) to be booted. The sector looks for a file or directory called 'boot' if it's a directory it loads that and does the search again. When it finds a file it loads it at location $10000 and executes it, note this is limited to a file size of 519k. There is also support for a helper boot which mean this is the only boot sector able to load an ELKS image (almost) directly. 1.4 ) Tar boot sector This boot sector converts a tar file with a GNU Volume label into a bootable floppy image. The boot sector loads and executes the first item in the tar file after the label: $ tar cvfV the_file.tar ENIAC monitor.sys item2 item3 $ makeboot tar the_file.tar $ cp the_file.tar /dev/fd0 This sequence makes a bootable floppy that tar sees as a normal labeled tar file but when booted from will load and execute 'monitor.sys' at location $00800 (Yes thats 2k!) Warning: the tar boot sector moves the BPB to the location $666. 1.5 ) Skip boot sector This bootsector displays a message then loads and executes the hard disk MBR at location $07C00 1.6 ) Panic boot sector Displays the message 'PANIC! NO OS Found!' (or the message specified on install) and freezes. -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- 2.1 ) Booting i86 standalone executable All the boot sectors (dos, minix, tar) check for a ELKS-i86 magic number at the start of the file they load and will correctly set the segment registers before calling. The executable should be a 'standalone' executable compiled with 'bcc -Ms ...' or similar. 2.2 ) Booting Elks kernel Only the minix boot sector can directly boot an elks kernel and even that needs a helper function because of the complexity. The helper is called 'minix_elks.bin' and needs to be copied onto the disk as '/boot/boot' with the ELKS image copied on as '/boot/linux'. This works, with the correct boot block, on either floppy or harddisk. 2.3 ) Booting Linux-i386 [b]zImage None of the boot blocks can _directly_ boot a Linux-i386 kernel the program 'monitor.sys' must loaded by the boot sector and this can load a zimage or bzimage from an MSDOS, Minix or Tar floppy. It can also load the image from a minix hard disk filesystem. This example is for and MSDOS floppy, Tar is very similar except that 'monitor.sys' must be the first file in the tar and can have any name. Note also for a tar file the 'ramdisk.gz' file must start on the first disk but can extend across as many floppies as is needed. $ mformat a: $ makeboot dos /dev/fd0 $ mount -t msdos /dev/fd0 /mnt $ cp monitor.sys /mnt/bootfile.sys $ cp /usr/src/linux/arch/i386/boot/zImage /mnt/vmlinuz $ echo 'root=/dev/ram ramdisk_file=ramdisk.gz mem=80M' > /mnt/vmlinuz.cfg $ cp /archive/ramdisk.gz /mnt/ramdisk.gz $ umount /dev/fd0 The stuff about ramdisk is only if you want an init ramdisk. If the ramdisk isn't on this floppy monitor.sys will ask for the right floppy. If you specify multiple ramdisk files then will be concatenated and passed to the kernel as one ramdisk, each file can be on a different floppy. If the file isn't called 'vmlinuz' you can still boot it by typing "=linux" at the prompt '>' where 'linux' is the name of the bzImage file. Escape or ^C will interrupt the boot and drop you to the '>' prompt. ^C at the '>' prompt will reboot A file called 'help.txt' will be displayed upto the first line that starts with a '%', chunks after that (seperated by '%'s) will be displayed when the user presses a function key, home, page up or page down. -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- Robert de Bath dev86-0.16.21/bootblocks/bb_init1.s000066400000000000000000000004341231050321700166240ustar00rootroot00000000000000ORGADDR=0x0600 ! $0500..0600 stack or move ORGADDR down. .org ORGADDR entry start public start start: cld xor ax,ax mov si,#$7C00 mov di,#ORGADDR mov ss,ax mov sp,si ! ax, di or si push ax pop ds push ax pop es mov cx,#256 rep movsw jmpi go,#0 go: dev86-0.16.21/bootblocks/bb_init2.s000066400000000000000000000005241231050321700166250ustar00rootroot00000000000000ORGADDR=$0500 org ORGADDR cld mov bx,#$7C00 ! Pointer to start of BB. xor ax,ax ! Segs all to zero mov ds,ax mov es,ax mov ss,ax mov sp,bx ! SP Just below BB mov cx,#$100 ! Move 256 words mov si,bx ! From default BB mov di,#ORGADDR ! To the correct address. rep movsw jmpi cont,#0 ! Set CS:IP correct. cont: dev86-0.16.21/bootblocks/bb_linux.s000066400000000000000000000004261231050321700167400ustar00rootroot00000000000000 INITSEG = $9000 org 0 mov ax,#$07c0 mov ds,ax mov ax,#INITSEG mov es,ax mov cx,#256 sub si,si sub di,di cld rep movsw jmpi go,INITSEG go: mov di,#0x4000-12 mov ds,ax mov ss,ax ! put stack at INITSEG:0x4000-12. mov sp,di dev86-0.16.21/bootblocks/boot_fpy.s000066400000000000000000000123311231050321700167550ustar00rootroot00000000000000! This binary is for loading a dev86 a.out file from a floppy without ! a filesystem; to make a bootable disk just do: ! ! cat boot_fpy.bin monitor.out > /dev/fd0 ! ORGADDR=0x0600 EXEADDR=0x0800 ! This must be up to 0x7E0 or 0x0800 LOADSEG=0x0080 ! Must be 512b aligned for DMA ! Padding so you can join with 'cat'. .org EXEADDR-1 .byte 0 ! This marker is needed by many boot managers (and bochs) but the BIOS does ! NOT require it on a floppy. if EXEADDR=0x0800 .org ORGADDR+0x1FE .word 0xAA55 endif .org ORGADDR entry start public start start: xor ax,ax mov si,#$7C00 mov di,#ORGADDR mov ss,ax mov sp,di ! Or si or ax push ax pop ds push ax pop es mov cx,#256 cld rep movsw jmpi go,#0 go: ! Grrr, have to load sector 1 in by hand. if EXEADDR=0x0800 Loopi: mov ax,#$0201 ! Read 1 sector mov bx,#EXEADDR ! Into EXEADDR mov cx,#$0002 ! From sector 2 xor dx,dx ! Of the floppy drive head zero int $13 jc Loopi endif mov si,#Boot_message call puts mov ax,[a_text] ! How many sectors to load mov cl,#4 shr ax,cl mov bx,ax mov ax,[a_data] mov cl,#4 shr ax,cl add ax,bx add ax,#$1F mov cl,#5 shr ax,cl ! ax = sectors to read ! This routine starts by loading one sector at a time, with most ! modern PCs the processor is fast enough to keep up with single ! sector reads, in reality an 8Mhz 286 can keep up! ! But occasionally some older machines have really poor BIOSes ! (Some modern ones too) so once we know how many sectors to read ! we switch to reading a track at a time. But we only try it once ! for each track. Normally, as long as the load address is sector ! aligned, this will work every time but with some BIOSes we can't ! read a track without messing with the BPB so if the track read ! fails it's one try we fall back to sector reads. ! ! Overall this usually gives good performance, and with a BIOS that ! isn't completely broken and correctly formatted floppies will run ! at about 2.5 rotations per cylinder (1.25 per track). If you find ! your BIOS is one of the bad ones you'll have to format your disks ! to a 2:1 interleave. ! ! BTW: It's very easy to make superformat incorrectly calculate the ! inter-sector gaps so it ends up squeezing the sectors to the start ! of the track. This means that only a full track read is fast enough. ! I suggest you use fdformat as it always uses 'safe' parameters for ! a 1440k floppy. ! AX = count of sectors mov cx,#2 ! CX = First sector mov bx,#LOADSEG ! ES:BX = Where to load mov es,bx xor bx,bx ! Initial offset xor dx,dx ! DX = Drive 0 ! ax=cnt, dl=drv, ch=*, dh=*, cl=sec, es:bx=buffer. read_data: mov si,ax ! Save big count. xor ch,ch xor dh,dh mov maxsect,cl ! Save first sector. load_loop: mov di,#5 ! Error retry. sect_retry: mov ax,#$0201 ! ah=2, al=1, dl=drv, ch=cyl, dh=head, cl=sec, es:bx=buffer. int $13 jnc next_sect dec di ! Retry counter jz sect_error cmp cl,maxsect ! If this is first sector or previously ok sector jle sect_retry ! number then retry. mov maxsect,cl j inc_trk next_sect: mov ax,es ! Inc load address. add ax,#32 mov es,ax dec si ! Had enough ? jz all_loaded inc_sect: inc cl cmp cl,maxsect jnz load_loop inc_trk: ! Reached end of track, seek to next. mov cl,#1 xor dh,cl jnz load_track inc ch load_track: cmp si,maxsect ! Is the whole track needed ? jb load_loop ! no, goto load_loop for 1 by 1 ! Try to load the track _once_ only, if it fails go 1 by 1 again. mov ax,maxsect dec ax mov ah,#$02 ! ah=2, al=*, dl=drv, ch=cyl, dh=head, cl=sec, es:bx=buffer. int $13 jc load_loop mov ax,maxsect ! Ok that worked, update the pointers dec ax mov cl,#5 shl ax,cl mov di,es add ax,di mov es,ax inc si sub si,maxsect jnz inc_trk all_loaded: ! Now it's loaded turn off the floppy motor. mov dx,#0x3f2 xor al, al outb ! And start up the program. xor dx,dx ! DX=0 => floppy drive push dx ! CX=0 => partition offset = 0 mov si,dx ! Sect/track = 0 mov bx,#EXEADDR>>4 mov ds,bx ! DS = loadaddress xor di,di ! Zero mov ax,[di+2] and ax,#$20 ! Is it split I/D ? jz impure ! No ... mov cl,#4 mov ax,[di+8] shr ax,cl impure: pop cx ! Partition offset. inc bx inc bx ! bx = initial CS add ax,bx mov ss,ax mov sp,[di+24] ! Chmem value mov ds,ax ! AX=ds, BX=cs, CX=X, DX=X, SI=X, DI=0, BP=X, ES=X, DS=*, SS=*, CS=* bad_magic: push bx ! jmpi 0,#LOADSEG+2 push di retf sect_error: ! Disk error, wait then reboot. mov si,#reboot_msg call puts xor ax,ax ! Wait for the user. int $16 jmpi $0,$FFFF puts: lodsb cmp al,#0 jz EOS push bx mov bx,#7 mov ah,#$E ! Can't use $13 cause that's AT+ only! int $10 pop bx jmp puts EOS: ret maxsect: .word 0 reboot_msg: .asciz "Disk error, press a key to reboot:" Boot_message: .asciz "Boot sector loaded.\r\n" ! Check for overlap end_of_code: if end_of_code>hitme fail! Overlap at end_of_code endif .org EXEADDR hitme: magic: .space 2 ! A.out header btype: .space 2 headerlen: .space 4 a_text: .space 4 a_data: .space 4 a_bss: .space 4 a_entry: .space 4 a_total: .space 4 a_syms: .space 4 dev86-0.16.21/bootblocks/boot_win.c000066400000000000000000000203551231050321700167410ustar00rootroot00000000000000/* * This program is designed to be put onto an MSDOS filesystem floppy or * a floppy image on a CD-ROM. * * The hexdump at the end is from Windows 95 boot sector and can be used * to start a Windows 9X io.sys. * * This program runs first and if the hard disk appears bootable will load * and start that unless you press return. * * If you press a key you have the option of Zapping the MBR! * */ #include #define sysboot_dosfs_stat 0x000B #define sysboot_codestart 0x003E #define sysboot_bootblock_magic 0x01FE extern char win95_bb[512]; char bs_buf[512]; char buf2[512]; unsigned memseg, memlen; fatal(str) char * str; { cprintf(str); getch(); exit(0); } main() { int i, rv; int floppy_only = 0; int c,h,s,os; reset_screen(); cprintf("...\n"); relocate(); if (__get_cs() != 0x80) fatal("ERROR - program incorrectly compiled.\n"); for(i=0; i<6; i++) if (!(rv = _bios_disk_read(0x80, 0, 0, 1, 1, bs_buf))) break; if (rv != 0 || bs_buf[510] != 0x55 || bs_buf[511] != (char)0xAA) { cprintf("Hard disk not bootable.\n"); floppy_only = 1; /* Check for zapped MBR */ for(i=0; i<512; i++) { if (bs_buf[i]) break; if (i==511) boot_floppy(); } } if (!floppy_only) { for(rv=-1, i=0x1BE; i<0x1FE; i+= 16) { if (bs_buf[i] == (char)0x80) { rv = 0; s = (bs_buf[i+2] & 63) ; h = (bs_buf[i+1] & 255) ; c = (bs_buf[i+3] & 255) + ((bs_buf[i+2] & 0xC0) << 2); os = (bs_buf[i+4] & 255) ; break; } } if (rv) { cprintf("Hard disk has no active partition.\n"); floppy_only = 1; } } if (!floppy_only && (os==4 || os==6 || os==11 || os==12 || os==13)) { for(i=0; i<6; i++) if (!(rv = _bios_disk_read(0x80, c, h, s, 1, bs_buf))) break; if (rv != 0 || bs_buf[510] != 0x55 || bs_buf[511] != (char)0xAA) { cprintf("DOS Partition not bootable.\n"); floppy_only = 1; } } if (floppy_only) cprintf("Press return to wipe MBR: "); else cprintf("Press return to skip hard disk boot: "); __set_es(0x40); for(i=0; ; i++) { unsigned int tv = __deek_es(0x6c); while (tv == __deek_es(0x6c)) if (kbhit()) { getch(); cprintf("\n"); goto break_break; } if (i%10 == 0) cprintf("."); if (i>= 18*5) { cprintf(" Booting.\n"); if(floppy_only) boot_floppy(); else boot_hd(); } } break_break:; cprintf("Do you want to leave the hard disk intact?\n"); cprintf("(Y/n) "); i = (getch() & 0xFF); if (i == 'n' || i == 'N') { cprintf("No\n"); cprintf("WARNING: This WILL delete everything on the hard disk!\n"); cprintf("Do you want to clear the hard disk MBR?\n"); cprintf("(N/y) "); i = (getch() & 0xFF); if (i == 'y' || i == 'Y') { cprintf("Yes\n"); memset(bs_buf, 0, sizeof(bs_buf)); for(i=0; i<6; i++) if (!(rv = _bios_disk_write(0x80, 0, 0, 1, 1, bs_buf))) break; if (rv) { cprintf("Disk error 0x%2x on disk write:", rv); getch(); cprintf("\n"); } else { cprintf("Hard disk MBR wiped!\n"); } } else cprintf("No -- Disk is still untouched\n"); } else cprintf("Ok -- Disk is untouched\n"); boot_floppy(); } reset_screen() { #asm mov ah,#$0F int $10 cmp al,#$07 je dont_touch mov ax,#$0003 int $10 dont_touch: #endasm } boot_floppy() { _bios_disk_read(0, 0, 0, 1, 1, bs_buf); make_floppy_bb(); #asm mov ax,#$00 push ax pop ds mov bx,#$7c00 mov dx,#$0000 ! Of the floppy drive jmpi $7c00,0 #endasm } boot_hd() { int i; /* If we're booting from a CD we want to turn off the floppy emulation */ buf2[0] = 0x13; /* Sizeof a 'Specification packet' */ #asm mov ax,#$4B01 mov dl,#$7F mov si,#_buf2 int $13 ! Ignore the return value; it's meaningless if we aren't on a CD #endasm /* Now boot the hard disk */ __set_es(0x07c0); for(i=0; i<512; i++) __poke_es(i, bs_buf[i]); #asm mov ax,#$00 push ax pop ds mov bx,#$7c00 mov dx,#$0080 ! Of the hard drive jmpi $7c00,0 #endasm } make_floppy_bb() { int i; __set_es(0x07c0); for(i=0; i> 4); /* if (__deek_es(0) == 0x0301 ) memlen = (__deek_es(24) >> 4); */ if( memlen == 0 ) memlen = 0x1000; memlen += codelen; __set_es(es); } newseg = 0x80; /* If the old area overlaps the new then fail */ if( newseg >= memseg && newseg < memseg+memlen ) return; if( memseg >= newseg && memseg < newseg+memlen ) return; /* Copy segments, done in 32k chunks */ for(moved=0; moved < memlen; ) { unsigned int lump; if( memlen-moved <= 0x800 ) lump = memlen-moved; else lump = 0x800; __movedata(memseg+moved, 0, newseg+moved, 0, (lump<<4)); moved += lump; } /* re-link int 0x80, this one is only an example (used by 'standalone.c') */ /* __set_es(0); __doke_es(0x80*4+2, newseg); __set_es(es); */ /* The actual jump ... */ memseg = newseg; #asm mov ax,ds mov bx,cs sub ax,bx mov bx,[_memseg] add ax,bx push bx call L_x mov ds,ax mov ss,ax mov [_memseg],bx #endasm } #asm L_x: retf #endasm #else } #endif char win95_bb[512] = { 0xeb,0x3c,0x90,0x29,0x69,0x71,0x22,0x5a,0x49,0x48,0x43,0x00,0x02,0x01,0x01,0x00, 0x02,0xe0,0x00,0x40,0x0b,0xf0,0x09,0x00,0x12,0x00,0x02,0x00,0x00,0x00,0x00,0x00, 0x40,0x0b,0x00,0x00,0x00,0x00,0x29,0xfa,0x16,0x58,0x2c,0x4e,0x4f,0x20,0x4e,0x41, 0x4d,0x45,0x20,0x20,0x20,0x20,0x46,0x41,0x54,0x31,0x32,0x20,0x20,0x20,0xfa,0x33, 0xc9,0x8e,0xd1,0xbc,0xfc,0x7b,0x16,0x07,0xbd,0x78,0x00,0xc5,0x76,0x00,0x1e,0x56, 0x16,0x55,0xbf,0x22,0x05,0x89,0x7e,0x00,0x89,0x4e,0x02,0xb1,0x0b,0xfc,0xf3,0xa4, 0x06,0x1f,0xbd,0x00,0x7c,0xc6,0x45,0xfe,0x0f,0x8b,0x46,0x18,0x88,0x45,0xf9,0x38, 0x4e,0x24,0x7d,0x22,0x8b,0xc1,0x99,0xe8,0x77,0x01,0x72,0x1a,0x83,0xeb,0x3a,0x66, 0xa1,0x1c,0x7c,0x66,0x3b,0x07,0x8a,0x57,0xfc,0x75,0x06,0x80,0xca,0x02,0x88,0x56, 0x02,0x80,0xc3,0x10,0x73,0xed,0x33,0xc9,0x8a,0x46,0x10,0x98,0xf7,0x66,0x16,0x03, 0x46,0x1c,0x13,0x56,0x1e,0x03,0x46,0x0e,0x13,0xd1,0x8b,0x76,0x11,0x60,0x89,0x46, 0xfc,0x89,0x56,0xfe,0xb8,0x20,0x00,0xf7,0xe6,0x8b,0x5e,0x0b,0x03,0xc3,0x48,0xf7, 0xf3,0x01,0x46,0xfc,0x11,0x4e,0xfe,0x61,0xbf,0x00,0x07,0xe8,0x23,0x01,0x72,0x39, 0x38,0x2d,0x74,0x17,0x60,0xb1,0x0b,0xbe,0xd8,0x7d,0xf3,0xa6,0x61,0x74,0x39,0x4e, 0x74,0x09,0x83,0xc7,0x20,0x3b,0xfb,0x72,0xe7,0xeb,0xdd,0xbe,0x7f,0x7d,0xac,0x98, 0x03,0xf0,0xac,0x84,0xc0,0x74,0x17,0x3c,0xff,0x74,0x09,0xb4,0x0e,0xbb,0x07,0x00, 0xcd,0x10,0xeb,0xee,0xbe,0x82,0x7d,0xeb,0xe5,0xbe,0x80,0x7d,0xeb,0xe0,0x98,0xcd, 0x16,0x5e,0x1f,0x66,0x8f,0x04,0xcd,0x19,0xbe,0x81,0x7d,0x8b,0x7d,0x1a,0x8d,0x45, 0xfe,0x8a,0x4e,0x0d,0xf7,0xe1,0x03,0x46,0xfc,0x13,0x56,0xfe,0xb1,0x04,0xe8,0xc1, 0x00,0x72,0xd6,0xea,0x00,0x02,0x70,0x00,0xb4,0x42,0xeb,0x2d,0x60,0x66,0x6a,0x00, 0x52,0x50,0x06,0x53,0x6a,0x01,0x6a,0x10,0x8b,0xf4,0x74,0xec,0x91,0x92,0x33,0xd2, 0xf7,0x76,0x18,0x91,0xf7,0x76,0x18,0x42,0x87,0xca,0xf7,0x76,0x1a,0x8a,0xf2,0x8a, 0xe8,0xc0,0xcc,0x02,0x0a,0xcc,0xb8,0x01,0x02,0x8a,0x56,0x24,0xcd,0x13,0x8d,0x64, 0x10,0x61,0x72,0x0a,0x40,0x75,0x01,0x42,0x03,0x5e,0x0b,0x49,0x75,0x77,0xc3,0x03, 0x18,0x01,0x27,0x0d,0x0a,0x49,0x6e,0x76,0x61,0x6c,0x69,0x64,0x20,0x73,0x79,0x73, 0x74,0x65,0x6d,0x20,0x64,0x69,0x73,0x6b,0xff,0x0d,0x0a,0x44,0x69,0x73,0x6b,0x20, 0x49,0x2f,0x4f,0x20,0x65,0x72,0x72,0x6f,0x72,0xff,0x0d,0x0a,0x52,0x65,0x70,0x6c, 0x61,0x63,0x65,0x20,0x74,0x68,0x65,0x20,0x64,0x69,0x73,0x6b,0x2c,0x20,0x61,0x6e, 0x64,0x20,0x74,0x68,0x65,0x6e,0x20,0x70,0x72,0x65,0x73,0x73,0x20,0x61,0x6e,0x79, 0x20,0x6b,0x65,0x79,0x0d,0x0a,0x00,0x00,0x49,0x4f,0x20,0x20,0x20,0x20,0x20,0x20, 0x53,0x59,0x53,0x4d,0x53,0x44,0x4f,0x53,0x20,0x20,0x20,0x53,0x59,0x53,0x7f,0x01, 0x00,0x41,0xbb,0x00,0x07,0x80,0x7e,0x02,0x0e,0xe9,0x40,0xff,0x00,0x00,0x55,0xaa }; dev86-0.16.21/bootblocks/buffer.c000066400000000000000000000065631231050321700163770ustar00rootroot00000000000000 #include "monitor.h" #ifndef MAXTRK #define MAXTRK 18 #endif int disk_drive = 0; int disk_spt = 7; int disk_heads = 0; int disk_cyls = 0; long disk_partition_offset = 0; static long bad_start = -1; static long buf_start = -1; static int buf_sec = 0; static int buf_len = 0; static char buffer[MAXTRK*512]; /* WARNING: This must be DMAable */ void reset_disk() { disk_spt = 7; /* Defaults for reading floppy boot area. */ disk_heads = 0; disk_cyls = 0; bad_start = -1; disk_partition_offset = 0; #ifdef __STANDALONE__ if( disk_drive == __argr.h.dl && __argr.x.si >= 9 && __argr.x.si <= 63 ) { disk_spt = __argr.x.si; disk_heads = 2; disk_cyls = 80; } if( disk_drive & 0x80 ) { /* Hard disk, get parameters from bios */ long dpt; int v; if( disk_drive == __argr.h.dl ) disk_partition_offset = __argr.x.cx + ((long)__argr.h.dh<<16); dpt = _bios_get_dpt(disk_drive); v = ((dpt>>16) & 0xFF); if( v != 0xFF && v > (disk_drive&0x7F) ) { disk_spt = (dpt & 0x3F); /* Max sector number 1-63 */ if( disk_spt == 0 ) disk_spt = 64; /* 1-64 ? */ disk_heads = ((dpt>>24) & 0xFF) + 1; /* Head count 1-256 */ disk_cyls = ((dpt>>8) & 0xFF) + ((dpt<<2) & 0x300) + 1; /* Cyls count, unchecked, only needs != 0, if AMI 386 bios can be * upto 4096 cylinder, otherwise BIOS limit is 1024 cyl. */ } } #endif } char * read_lsector(sectno) long sectno; { int tries; int rv = 0; int phy_s = 1; int phy_h = 0; int phy_c = 0; long bstart; if( sectno == 0 || disk_heads == 0 ) reset_disk(); if( disk_partition_offset > 0 ) sectno += disk_partition_offset; if( disk_spt < 1 || disk_heads < 1 ) phy_s = sectno; else { phy_s = sectno%disk_spt; phy_h = sectno/disk_spt%disk_heads; phy_c = sectno/disk_spt/disk_heads; bstart = (long)phy_c*disk_heads+phy_h; if (disk_spt > MAXTRK) { bstart = bstart * (disk_spt+MAXTRK-1)/MAXTRK; buf_sec = phy_s/MAXTRK; bstart = bstart + buf_sec; buf_sec *= MAXTRK; if (disk_spt > buf_sec+MAXTRK) buf_len = MAXTRK; else buf_len = disk_spt-buf_sec; } else { buf_sec = 0; buf_len = disk_spt; } if( bstart != buf_start && bstart != bad_start && buf_len > 1 ) { rv = _bios_disk_read(disk_drive,phy_c,phy_h,buf_sec+1,buf_len,buffer); if( rv == 0 ) buf_start = bstart; else { bad_start = bstart; buf_start = -1; } #ifdef DEBUG printf("Track read %d,%d,%d,%d,%d,%d -> %d\n", disk_drive,phy_c,phy_h,buf_sec+1,buf_len,buffer, rv); #endif } if( bstart == buf_start ) return buffer + (phy_s-buf_sec) * 512; } tries = 6; do { if( rv && tries<0) { int v; printf("Disk error 0x%02x %d:%d:%d:%d[%2d] -> 0x%04x[]\n", rv, disk_drive, phy_c, phy_h, phy_s+1, 1, buffer); printf("Retry ?"); v = (getch()&0x7F); printf("\n"); if (v == 3 || v == 27 || v == 'n' || v == 'N') return 0; tries = 6; } if (tries == 3) _bios_disk_reset(disk_drive); rv = _bios_disk_read(disk_drive, phy_c, phy_h, phy_s+1, 1, buffer); tries--; } while(rv); #ifdef DEBUG printf("Sector read %d,%d,%d,%d,%d,%d -> %d\n", disk_drive,phy_c,phy_h,phy_s+1,1,buffer, rv); #endif if(rv) return 0; else return buffer; } dev86-0.16.21/bootblocks/bzimage.c000066400000000000000000000377631231050321700165520ustar00rootroot00000000000000/* * Load and execute a bzImage file from the device the 'open_file' and * friends use. */ #define __MINI_MALLOC__ #include "monitor.h" #define MAXRDPART 32 int auto_flag = 1; /* Names of init_ramdisk files to load */ static char *initrd_names[MAXRDPART]; static int initrd_count = 0; static long initrd_start = 0; static long initrd_length = 0; static int vga_mode = -1; /* SVGA_MODE = normal */ static int is_zimage = 0; static char * image_name = 0; static int image_length; /* Length of image in sectors */ static long image_size; /* Length of image file in bytes */ static char * read_cmdfile(); static char * input_cmd(); /* ZIMAGE_LOAD_SEG: Segment that zImage data is loaded * 0x10000 For largest possible zImage * 0x1000 Normal load address, smallest monitor.sys * 0x100 Largest zImage without using extended memory */ #define ZIMAGE_LOAD_SEG 0x10000 #define COMMAND_LINE_POS 0x4000 /* Offset in segment 0x9000 of command line */ static char * linux_command_line = 0; int load_crc = 0; static char buffer[1024]; cmd_bzimage(ptr) register char * ptr; { char * image; int ch; if( (auto_flag=(ptr==0)) ) ptr=""; while(*ptr == ' ') ptr++; image = ptr; while(*ptr != ' ' && *ptr) ptr++; ch = *ptr; *ptr = '\0'; if( ch ) ptr++; while(*ptr == '\n' || *ptr == ' ') ptr++; if( *ptr == '\0' ) ptr = 0; if( *image ) bzimage(image, ptr); else bzimage("vmlinuz", ptr); } bzimage(fname, command_line) char * fname; char * command_line; { long len; char * ptr; int low_sects; unsigned int address; initrd_count = 0; initrd_start = initrd_length = 0; vga_mode = -1; is_zimage = 0; image_name = strdup(fname); /* Ok, deal with the command line */ if( build_linuxarg(fname, command_line) < 0 ) return -1; if( open_file(image_name) < 0 ) { if( auto_flag == 0 ) printf("Cannot find file %s\n", image_name); return -1; } printf("Loading %s\n", image_name); if( read_block(buffer) < 0 || check_magics(image_name, buffer) < 0 ) { printf("Cannot execute file %s\n", image_name); return -1; } #ifndef __ELKS__ if( boot_mem_top < 0x9500 ) { printf("There must be 640k of boot memory to load Linux\n"); return -1; } /* Guestimate how much the uncompressed kernel will use. * I expect we could lookup the size in the gzip header but * this is probably close enough (3*the size of the bzimage) */ len = (image_size=file_length()) * 3 / 1024; if( main_mem_top < len ) { printf("This kernel needs at least %d.%dM of main memory\n", (int)(len/1024), (int)(len*10/1024%10)); return -1; } if( main_mem_top < 3072 ) printf("RTFM warning: Linux needs at least 4MB of memory.\n"); #endif low_sects = buffer[497] + 1; /* setup sects + boot sector */ if (low_sects == 1) low_sects = 5; image_length = (file_length()+511)/512 - low_sects; address = 0x900; #ifndef __ELKS__ #if ZIMAGE_LOAD_SEG == 0x10000 #if 0 /* Don't warn about this limit, the format is old. */ if( is_zimage ) { if( image_length > 0x7FF0/32 ) { printf("This zImage file is too large, maximum is %dk bytes\n", (0x7FF0/32 + low_sects)/2 ); return -1; } } #endif #else if( is_zimage ) { if( image_length > (__get_cs()>>5) - ZIMAGE_LOAD_SEG/32 ) { printf("This zImage file is too large, maximum is %dk bytes\n", ((__get_cs()>>5) - ZIMAGE_LOAD_SEG/32 + low_sects)/2 ); return -1; } } #endif #endif /* load the blocks */ rewind_file(); #ifdef CALC_CRC reset_crc(); #endif for(len = file_length(); len>0; len-=1024) { int v; printf("%dk to go \r", (int)(len/1024)); fflush(stdout); #ifndef NOCOMMAND v = (kbhit()&0x7F); if( v == 3 || v == 27 ) { printf("User interrupt!\n"); getch(); return -1; } #endif if( read_block(buffer) < 0 ) { printf("Error loading %s\n", image_name); return -1; } #ifdef CALC_CRC if( len > 1024 ) addcrc(buffer, 1024); else addcrc(buffer, (int)len); #endif for(v=0; v<1024; v+=512) { int rv; if( (rv=mem_write(buffer+v, 0L, address/2, 1)) != 0 ) { printf("Error 0x%02x while copying to extended memory\n", rv); return -1; } address += 2; if( low_sects ) { low_sects--; if( low_sects == 0 ) { #if ZIMAGE_LOAD_SEG != 0x10000 if( is_zimage ) address = ZIMAGE_LOAD_SEG/16; else #endif address = 0x1000; } } } } close_file(); #ifdef CALC_CRC load_crc = display_crc("Loaded crc ="); #endif #ifdef CALC_CRC if( check_crc() < 0 && !keep_going() ) return -1; #endif printf(" \r"); fflush(stdout); if( initrd_count ) if( load_initrd(address) < 0 ) return -1; #ifdef CALC_CRC if( check_crc() < 0 && !keep_going() ) return -1; #endif #ifndef NOMONITOR if( x86 < 3 || x86_emu ) { if( x86 < 3 ) printf("RTFM error: Linux-i386 needs a CPU >= 80386\n"); else if( x86_emu ) printf("RTFM error: Linux-i386 cannot be run in an emulator.\n"); if( !keep_going() ) return -1; } #endif printf("linux "); if( linux_command_line ) printf("%s", linux_command_line); printf("\n"); fflush(stdout); __set_es(0x9000); /* Save pointer to command line */ if( linux_command_line ) { __doke_es(0x0020, 0xA33F); __doke_es(0x0022, COMMAND_LINE_POS); __movedata(__get_ds(), (unsigned)linux_command_line+1, 0x9000, COMMAND_LINE_POS, strlen(linux_command_line)); free(linux_command_line); } __set_es(0x9000); #if ZIMAGE_LOAD_SEG != 0x10000 #if ZIMAGE_LOAD_SEG != 0x1000 if( is_zimage ) { #if ZIMAGE_LOAD_SEG != 0x100 /* Tell setup that we've loaded the kernel somewhere */ __doke_es(0x20C, ZIMAGE_LOAD_SEG); #else /* Tell setup it's a bzImage _even_ tho it's a _zImage_ because we have * actually loaded it where it's supposed to end up! */ __poke_es(0x211, __peek_es(0x211)|1); __poke_es(0x210, 0xFF); /* Patch setup to deactivate safety switch */ #endif } #endif #endif /* Tell the kernel where ramdisk is */ if( initrd_count ) { __set_es(0x9000); __doke_es(0x218, (unsigned) initrd_start); __doke_es(0x21A, (unsigned)(initrd_start>>16)); __doke_es(0x21C, (unsigned) initrd_length); __doke_es(0x21E, (unsigned)(initrd_length>>16)); } if( !is_zimage || initrd_count ) __poke_es(0x210, 0xFF); /* Patch setup to deactivate safety switch */ /* Set SVGA_MODE if not 'normal' */ if( vga_mode != -1 ) __doke_es(506, vga_mode); /* Default boot drive is auto-detected floppy */ if( __peek_es(508) == 0 ) __poke_es(508, 0x200); printf("Starting ...\n");; #if ZIMAGE_LOAD_SEG == 0x10000 if( is_zimage ) /* Copy 512k from high memory then start */ start_zimage(); else #endif /* Finally do the deed */ { #asm ! Kill the floppy motor, needed in case the kernel has no floppy driver. mov dx,#0x3f2 xor al, al outb ! Setup required registers and go ... mov ax,#$9000 mov bx,#$4000-12 ! Fix this to use boot_mem_top mov es,ax mov fs,ax mov gs,ax mov ds,ax mov ss,ax mov sp,bx jmpi 0,$9020 ! Note SETUPSEG NOT INITSEG #endasm } } check_magics(fname, image_buf) register char * fname; register char * image_buf; { is_zimage = 0; /* Boot sector magic numbers */ if( *(unsigned short*)(image_buf+510) != 0xAA55 || memcmp(image_buf, "\270\300\007\216") != 0 ) { printf("File %s is not a linux Image file\n", fname); return -1; } /* Setup start */ if ( memcmp(image_buf+0x202, "HdrS", 4) == 0 && /* Setup version */ *(unsigned short*)(image_buf+0x206) >= 0x200 ) { /* Code 32 start address for zImage */ if( *(unsigned long*)(image_buf+0x214) == 0x1000 ) { printf("File %s is a zImage file\n", fname); is_zimage = 1; return 0; } else /* Code 32 start address bzImage */ if( *(unsigned long*)(image_buf+0x214) == 0x100000 ) { printf("File %s is a bzImage file\n", fname); return 0; } } is_zimage = 1; printf("File %s is an old Image file\n", fname); #if ZIMAGE_LOAD_SEG == 0x10000 || ZIMAGE_LOAD_SEG == 0x1000 return 0; #else return -1; #endif } static char * read_cmdfile(iname) char * iname; { char * ptr = strchr(iname, '.'); char buf[16]; long len; buf[8] = '\0'; strncpy(buf, iname, 8); strcat(buf, ".cfg"); if( ptr == 0 && open_file(buf) >= 0 ) { /* Ah, a command line ... */ printf("Loading %s\n", buf); len = file_length(); if( len > 1023 ) { printf("Command line file %s truncated to 1023 characters\n", buf); len = 1023; } if( read_block(buffer) >= 0 ) { register int i; for(i=0; i 2048 ) { printf("Linux command line truncated to 2047 characters\n"); ptr[2048] = 0; len = 2048; } #ifdef __ELKS__ fprintf(stderr, "Command line: '%s'\n", ptr+1); #endif linux_command_line = ptr; return 0; } keep_going() { static int burning = 0; char buf[4]; int cc; printf("Keep going ? "); fflush(stdout); #ifdef __STANDALONE__ cc = read(0, buf, 1); #else cc = read(0, buf, 4); #endif if( cc >= 1 && (*buf == 'Y' || *buf == 'y') ) { printf("Yes, Ok%s\n", burning?"":", burn baby burn!"); return burning=1; } printf("No\n"); return 0; } load_initrd(k_top) unsigned int k_top; { char * fname; long baseaddress; long file_len; unsigned sectcount, sectno; int fno; initrd_length = 0; baseaddress = (long)k_top * 256; for(fno = 0; fno = 15360 ) initrd_start = 0x1000000L; else initrd_start = 0x100000 + main_mem_top*1024; sectcount = (initrd_length+511)/512; initrd_start -= (long)sectcount *512; initrd_start &= -4096; printf("Moving ramdisk to 0x%06lx..0x%06lx, (%ld)\n", initrd_start, initrd_start + initrd_length, initrd_length); while(sectcount>0) { sectcount--; if ( mem_read(buffer, baseaddress, sectcount) != 0 || mem_write(buffer, initrd_start, sectcount, 1) != 0) { printf("Error moving ramdisk\n"); return -1; } } return 0; } #ifdef CALC_CRC check_crc() { int low_sects; unsigned int address = 0x900; long len; int re_crc; reset_crc(); __movedata(address*16, 0, __get_ds(), buffer, 512); low_sects = buffer[497] + 1; /* setup sects + boot sector */ if (low_sects == 1) low_sects = 5; for(len=image_size; len>0; len-=512) { if (mem_read(buffer, 0L, address/2) != 0) { printf("Unable to read back for CRC check\n"); return; } if( len > 512 ) addcrc(buffer, 512); else addcrc(buffer, (int)len); address += 2; if( low_sects ) { low_sects--; if( low_sects == 0 ) { #if ZIMAGE_LOAD_SEG != 0x10000 if( is_zimage ) address = ZIMAGE_LOAD_SEG/16; else #endif address = 0x1000; } } } re_crc = display_crc("Images CRC check value ="); if( re_crc != load_crc ) { printf("Error: CRC doesn't match value written to memory!\n"); return -1; } return 0; } #endif #if ZIMAGE_LOAD_SEG == 0x10000 start_zimage() { #include "zimage.v" __movedata(__get_ds(), zimage_data, 0, zimage_start, zimage_size); { #asm callf zimage_start,0 #endasm } } #endif dev86-0.16.21/bootblocks/commands.c000066400000000000000000000116321231050321700167200ustar00rootroot00000000000000 #include "monitor.h" int cmd_type(ptr) char * ptr; { char * fname; char buffer[1024]; long len; while(*ptr == ' ') ptr++; if( (fname=ptr) == 0 ) return 0; while(*ptr & *ptr != ' ') ptr++; if( open_file(fname) >= 0 ) for(len=file_length(); len>0; len-=1024) { if( read_block(buffer) < 0 ) break; if( len > 1024 ) write(1, buffer, 1024); else write(1, buffer, len); } else printf("Cannot open file '%s'\n", fname); close_file(); return 0; } #ifndef NOCOMMAND extern unsigned int current_address; extern int number_base; int cmd_quit(args) char * args; { printf("Bye\n"); exit(0); } int cmd_nop(ptr) char * ptr; { } int cmd_dir(ptr) char * ptr; { open_file("."); return 0; } int cmd_more(ptr) char * ptr; { char * fname; char buffer[1024]; long len; int cc; char * sptr; while(*ptr == ' ') ptr++; if( (fname=ptr) == 0 ) return 0; while(*ptr & *ptr != ' ') ptr++; more_char(-1); if( open_file(fname) >= 0 ) for(len=file_length(); len>0; len-=1024) { if( read_block(buffer) < 0 ) break; if( len > 1024 ) cc = 1024; else cc = len; for(sptr=buffer; cc>0 ; cc--,sptr++) { if( more_char(*sptr & 0xFF) < 0 ) goto break_break; } } else printf("Cannot open file '%s'\n", fname); break_break:; close_file(); return 0; } more_char(ch) int ch; { static int line_number = 0; if( ch == -1 ) { line_number = 0; return 0; } if( (ch & 0xE0 ) || ch == '\n' ) putchar(ch); if( ch == '\n' && ++line_number == 24) { char buf[4]; printf("More ?"); fflush(stdout); if( read(0, buf, 1) <= 0 ) return -1; if( buf[0] == 3 || buf[0] == '\033' || buf[0] == 'q' || buf[0] == 'Q' ) return -1; if( buf[0] == '\r' ) line_number--; if( buf[0] == ' ' ) line_number=2; printf("\r \r"); } return 0; } more_strn(str, len) char * str; int len; { for(; len>0 && *str ; len--,str++) if( more_char( *str & 0xFF ) < 0 ) return -1; return 0; } #endif /**************************************************************************/ #ifndef NOMONITOR cmd_monhelp() { static char * helps[] = { "Monitor help\n", "zimage filename [args] Start Linux-386\n", "bzimage filename [args] Start Linux-386\n", "=filename [args] Start Linux-386\n", "quit Reboot\n", "help Display help file\n", "dir Display directory\n", "type Display file to screen\n", "more Display file to screen\n", "m[em] [address] Hexdump memory\n", "seg [val] Set/show default segment\n", "rel [segment] Relocate this program\n", "base [val] Set default number base (or 'n' cmd)\n", "init Re-init program\n", "r[egs] Display register values\n", 0 }; char **p = helps; more_char(-1); while(*p) if( more_strn(*p, strlen(*p)) <0 ) break; else p++; printf("\n"); return 0; } cmd_regs() { #ifdef __STANDALONE__ printf(": AX=%04x BX=%04x CX=%04x DX=%04x SI=%04x DI=%04x", __argr.x.ax, __argr.x.bx, __argr.x.cx, __argr.x.dx, __argr.x.si, __argr.x.di); printf(" CF=%x", __argr.x.cflag); printf(" CS=%04x DS=%04x ES=%04x\n", __get_cs(), __get_ds(), __get_es()); #else printf("Only in standalone\n"); #endif } int cmd_memdump(ptr) char * ptr; { int count = 128; int i,j; int es = __get_es(); #define rmem(x) __peek_es( (x)+current_address ) getnum(&ptr, ¤t_address); getnum(&ptr, &count); for(i=0; i= ' ' && rmem(j) <= '~' ) putchar(rmem(j)); else putchar('.'); putchar('\n'); current_address += 16; current_address &= 0xFFFF; } #undef rmem } int cmd_seg(ptr) char * ptr; { int es = __get_es(); if( getnum(&ptr, &es) ) { __set_es(es); current_address = 0; } else printf("Current segment 0x%04x\n", es); return 0; } int cmd_set_base(ptr) { int obase = number_base; int nbase; number_base = 10; if( getnum(&ptr, &nbase) ) { if( nbase < 2 || nbase > 36 ) printf("Can't use that base\n"); else obase = nbase; } else printf("Current base is %d\n", obase); number_base = obase; return 0; } int cmd_rel(ptr) char * ptr; { int nseg = 0xFFFF; int cs = __get_cs(); getnum(&ptr, &nseg); relocator(nseg); if( __get_cs() == cs ) printf("Didn't relocate; CS=$%04x DS=$%04x\n", __get_cs(), __get_ds()); else printf("Relocated to CS=$%04x DS=$%04x\n", __get_cs(), __get_ds()); } #endif dev86-0.16.21/bootblocks/freedos.h000066400000000000000000000122471231050321700165560ustar00rootroot00000000000000/* Binaries taken from freedos */ char freedos_fat32lba[512] = { 0xeb,0x58,0x90,0x46,0x72,0x65,0x65,0x44,0x4f,0x53,0x20,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xfa,0x29,0xc0,0x8e,0xd8, 0xbd,0x00,0x7c,0xb8,0xe0,0x1f,0x8e,0xc0,0x89,0xee,0x89,0xef,0xb9,0x00,0x01,0xf3, 0xa5,0xea,0x7a,0x7c,0xe0,0x1f,0x00,0x00,0x60,0x00,0x8e,0xd8,0x8e,0xd0,0x8d,0x66, 0xe0,0xfb,0x88,0x56,0x40,0xbe,0xc1,0x7d,0xe8,0xf4,0x00,0x66,0x31,0xc0,0x66,0x89, 0x46,0x44,0x8b,0x46,0x0e,0x66,0x03,0x46,0x1c,0x66,0x89,0x46,0x48,0x66,0x89,0x46, 0x4c,0x66,0x8b,0x46,0x10,0x66,0xf7,0x6e,0x24,0x66,0x01,0x46,0x4c,0xb8,0x00,0x02, 0x3b,0x46,0x0b,0x74,0x08,0x01,0xc0,0xff,0x06,0x34,0x7d,0xeb,0xf3,0x66,0x8b,0x46, 0x2c,0x66,0x50,0xe8,0x94,0x00,0x72,0x4d,0xc4,0x5e,0x76,0xe8,0xb7,0x00,0x31,0xff, 0xb9,0x0b,0x00,0xbe,0xf1,0x7d,0xf3,0xa6,0x74,0x15,0x83,0xc7,0x20,0x83,0xe7,0xe0, 0x3b,0x7e,0x0b,0x75,0xeb,0x4a,0x75,0xe0,0x66,0x58,0xe8,0x34,0x00,0xeb,0xd2,0x26, 0xff,0x75,0x09,0x26,0xff,0x75,0x0f,0x66,0x58,0x29,0xdb,0x66,0x50,0xe8,0x5a,0x00, 0x72,0x0d,0xe8,0x80,0x00,0x4a,0x75,0xfa,0x66,0x58,0xe8,0x14,0x00,0xeb,0xec,0x8a, 0x5e,0x40,0xff,0x6e,0x76,0xbe,0xee,0x7d,0xe8,0x64,0x00,0x30,0xe4,0xcd,0x16,0xcd, 0x19,0x06,0x57,0x53,0x89,0xc7,0xc1,0xe7,0x02,0x50,0x8b,0x46,0x0b,0x48,0x21,0xc7, 0x58,0x66,0xc1,0xe8,0x07,0x66,0x03,0x46,0x48,0xbb,0x00,0x20,0x8e,0xc3,0x29,0xdb, 0x66,0x3b,0x46,0x44,0x74,0x07,0x66,0x89,0x46,0x44,0xe8,0x38,0x00,0x26,0x80,0x65, 0x03,0x0f,0x26,0x66,0x8b,0x05,0x5b,0x5f,0x07,0xc3,0x66,0x3d,0xf8,0xff,0xff,0x0f, 0x73,0x15,0x66,0x48,0x66,0x48,0x66,0x0f,0xb6,0x56,0x0d,0x66,0x52,0x66,0xf7,0xe2, 0x66,0x5a,0x66,0x03,0x46,0x4c,0xc3,0xf9,0xc3,0x31,0xdb,0xb4,0x0e,0xcd,0x10,0xac, 0x3c,0x00,0x75,0xf5,0xc3,0x52,0x56,0x57,0x66,0x50,0x89,0xe7,0x6a,0x00,0x6a,0x00, 0x66,0x50,0x06,0x53,0x6a,0x01,0x6a,0x10,0x89,0xe6,0x8a,0x56,0x40,0xb4,0x42,0xcd, 0x13,0x89,0xfc,0x66,0x58,0x73,0x08,0x50,0x30,0xe4,0xcd,0x13,0x58,0xeb,0xd9,0x66, 0x40,0x03,0x5e,0x0b,0x73,0x07,0x8c,0xc2,0x80,0xc6,0x10,0x8e,0xc2,0x5f,0x5e,0x5a, 0xc3,0x4c,0x6f,0x61,0x64,0x69,0x6e,0x67,0x20,0x46,0x72,0x65,0x65,0x44,0x4f,0x53, 0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4e,0x6f, 0x20,0x4b,0x45,0x52,0x4e,0x45,0x4c,0x20,0x20,0x53,0x59,0x53,0x00,0x00,0x55,0xaa }; char freedos_fat32chs[512] = { 0xeb,0x58,0x90,0x46,0x72,0x65,0x65,0x44,0x4f,0x53,0x20,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xfa,0x29,0xc0,0x8e,0xd8, 0xbd,0x00,0x7c,0xb8,0xe0,0x1f,0x8e,0xc0,0x89,0xee,0x89,0xef,0xb9,0x00,0x01,0xf3, 0xa5,0xea,0x7a,0x7c,0xe0,0x1f,0x00,0x00,0x60,0x00,0x8e,0xd8,0x8e,0xd0,0x8d,0x66, 0xe0,0xfb,0x88,0x56,0x40,0x8b,0x76,0x1c,0x8b,0x7e,0x1e,0x03,0x76,0x0e,0x83,0xd7, 0x00,0x89,0x76,0x5e,0x89,0x7e,0x60,0x8a,0x46,0x10,0x98,0x50,0xf7,0x66,0x26,0x01, 0xc7,0x58,0xf7,0x66,0x24,0x01,0xf0,0x11,0xfa,0x89,0x46,0x62,0x89,0x56,0x64,0x8b, 0x46,0x0b,0xd1,0xe8,0xd1,0xe8,0x48,0x89,0x46,0x66,0x91,0x41,0x40,0xd1,0xe9,0x81, 0xf9,0x01,0x00,0x75,0xf7,0x88,0x46,0x68,0x49,0x89,0x4e,0x48,0x89,0x4e,0x4a,0x8b, 0x46,0x2c,0x8b,0x56,0x2e,0x52,0x50,0xe8,0x9d,0x00,0x72,0x50,0x53,0xc4,0x5e,0x76, 0xe8,0xcb,0x00,0x52,0x50,0x8b,0x46,0x0b,0xb9,0x0b,0x00,0xbe,0xf1,0x7d,0x89,0xc7, 0x81,0xef,0x20,0x00,0xf3,0xa6,0x74,0x12,0x2d,0x20,0x00,0x75,0xeb,0x58,0x5a,0x5b, 0x4b,0x75,0xd9,0x58,0x5a,0xe8,0x2a,0x00,0xeb,0xcb,0x26,0x8b,0x45,0x0f,0x26,0x8b, 0x55,0x09,0x29,0xdb,0x52,0x50,0x53,0xe8,0x5d,0x00,0x72,0x55,0x89,0xdf,0x5b,0xe8, 0x8c,0x00,0x4f,0x75,0xfa,0x58,0x5a,0xe8,0x08,0x00,0xeb,0xe8,0x30,0xe4,0xcd,0x16, 0xcd,0x19,0x06,0x89,0xc7,0x23,0x7e,0x66,0x8b,0x4e,0x68,0xd1,0xea,0xd1,0xd8,0x49, 0x75,0xf9,0xd1,0xe7,0xd1,0xe7,0x03,0x46,0x5e,0x13,0x56,0x60,0x53,0xbb,0x00,0x20, 0x8e,0xc3,0x29,0xdb,0x3b,0x46,0x48,0x75,0x05,0x3b,0x56,0x4a,0x74,0x09,0x89,0x46, 0x48,0x89,0x56,0x4a,0xe8,0x47,0x00,0x5b,0x26,0x8b,0x05,0x26,0x8b,0x55,0x02,0x07, 0xc3,0x8a,0x5e,0x40,0xff,0x6e,0x76,0x81,0xfa,0xff,0x0f,0x75,0x07,0x3d,0xf8,0xff, 0x72,0x02,0xf9,0xc3,0x89,0xd1,0x2d,0x02,0x00,0x83,0xd9,0x00,0x8a,0x5e,0x0d,0x28, 0xff,0x91,0xf7,0xe3,0x91,0xf7,0xe3,0x01,0xca,0x03,0x46,0x62,0x13,0x56,0x64,0xc3, 0x31,0xdb,0xb4,0x0e,0xcd,0x10,0x5e,0xac,0x56,0x3c,0x00,0x75,0xf3,0xc3,0x52,0x50, 0x91,0x8a,0x46,0x18,0xf6,0x66,0x1a,0x91,0xf7,0xf1,0x92,0xf6,0x76,0x18,0x89,0xd1, 0x88,0xc6,0x86,0xe9,0xd0,0xc9,0xd0,0xc9,0xfe,0xc4,0x08,0xe1,0xb8,0x01,0x02,0x8a, 0x56,0x40,0xcd,0x13,0x58,0x5a,0x73,0x06,0x30,0xe4,0xcd,0x13,0xeb,0xd0,0x03,0x5e, 0x0b,0x73,0x07,0x8c,0xc1,0x80,0xc5,0x10,0x8e,0xc1,0x83,0xc0,0x01,0x83,0xd2,0x00, 0xc3,0x4b,0x45,0x52,0x4e,0x45,0x4c,0x20,0x20,0x53,0x59,0x53,0x00,0x00,0x55,0xaa }; dev86-0.16.21/bootblocks/freedosboot.zip000066400000000000000000000334671231050321700200240ustar00rootroot00000000000000PK šë0boot/UT D ð@%›JHUxèèPK,8:0w³è«vE boot/boot.asmUT D»@%›JHUxèè­<ýsÚH²?“ªü³{»õòÀ6IðË]ajm“r—¼”Ë5H#P,$J#lØÚ?þu÷Œ¤ÉÞ½e÷Ê êîéééïiÝéóg§l袇ÿQó™GQrÈå Á.„tbøQøÚÅxzpN¸W z­w±¿X&ì…ó’µß¿{ZOwzÏÃD°a,vÕ€ý `¤*ÙDHß Ws1[ú’y°k×Í®Ó)Ž'¬Ï>÷'³Ñù—Ëþ„}þ2ù<žáô‰ª^˜Ìb«抄ûLwü ŽPwË–ü^ÀQ:ÂÝ`œ9 ‡ÕÇ„È)qDá‚¶©$xʤ„Gju>þümtýxy,Œ’&â>Ä>(KÕži“ußž°+.%ëß Â;ç«yì» ÑdW}Öê´Þ7Ù—i_oþm¼>П׬=´zo­þþÇÙxª¡Zž˜ñAwd~G–¸é¶z-«¸ò#~þ ÿ9ýÕž 6šÂÊíNæöÚ¥g]óþ#Åb%¤q˜ˆm‚?¤ðgýéÀt¡­í[™yþlß¹Fñ‚þ">„I¼ëåϬÖô, Ük,xpK;~þ¬Ñ£5í -kô?~è'>üßA¬`#¸î2gl.ÇbuÍW"ÃyÝÚ¶ŽÔ—S6\Á¹ÏñtsŒ³]"ägO…“aÌSŒ9>|#…“ ÛΑP΃L2$7ERàò ‚È!s'ï'&>Dš©‚ÊÙ)þ?@*¥¤LT8*i\Dm·rTðKO ¬~ ²—F»€¸ö˜ÁqǾ{[Mṵ̀rlÍ!F.B‚¿â a¸‚ È÷>I ¬è¡«R…óÜé»â=m2‘8‡‡‡9-\ Ä>ä‰I«[fØà(†ê,æÎ]Žú®„ú&Aˆ/ü$¸[’7Ïñ–øÜ„÷]üPÞ1àÕóÒÁ†JΟ6 ‘#vZ–½y쟬{rrÔÍ‘ÝBÛã²sœ"«Çáf5†ƒQŸá¹‘2iÂc¢CļŒIòd'{¾[Zôm€¬­0Ï0Ê,RÀ}å 觃†«AçgB€=œ}šÎIþýÜ“‚’·D¬ÖQÌãvÁý@ÙqU}N™³ä~h:¦i´"aÆœÝóØçó Èp¯S871™Ûf“Ñ¿Ž]MÁËŸóÀÙ` Ua O@¢° ‰¼ÃU¹Î¶à0‰½F£@¡Ñ*ŸË*ºWÃo²‡(vÙwmq7Õ°î>ì뎚»îeÓM[œŒ< ’µöUåbÔƒcÿzÃIaäO#I5³jið]*Þ4¡'CÃÆšÀO}IùwE,{ræÔM`,–;á›|£_{ý¯°Q”£ÁÓη,m<™"çÛz »[›1%œ†1Zq— »^xˆt HBÞE”¡Ÿ&°ŒÀÃ]1Á®ö8Žg³†ø{XÍÁ|Kçgd-5šïÀaŸX½˜ëßC˜eg_1>ê”IÈeœ­ç6gxâ9ï:u`k8úÇÕœ«m©‰eÛHñànñüËÏašÇÇ-J¯ò’7¨m¸ÒÙô8ïâqü·*û§å‚¸¾#Ü“4Ô€ÌóWää`ÉYü=¤Õh$þJÈDíÁÁ/¯ù…¹sVˆÎXÇ@!ø¶Ûj@äÓ?ÜÂ/T ”`÷á) S/Ïú·Ÿûç¿ fFêpÜÁ¨áêô½ÝZR:Å:#ˆ£w")@´Œ°áL?|ÐèùÃÜ£åé.V+®‘¨ì1G­"Ätôiå¤Ô2G»Ùƒœ_¹²BRø2aÇÃ,ÿ1 Ž÷ ~´uK«ÎƓۖmÕwìÆ Œ x ¸Ý²ulÀ;ðñ;ðñÊ:rÈúWSs[XåÏ Û§ý+x¬¹ »ü‡y¼YAõ»4—ÊB­ÆËHu R¶xŸ(ƃ@·D "œifê{Ì´ø>­=?ówºÌþ׳ɷ¿×·äÍ€:'ðÕÿ@dh`AÜh€ïk¸Òø¦ °it&ð |N¡0Äê:I›{!ÈxÅ‘Xë,¥Ð†&ºšH‹ÝTž ›J*’#Á‚lwúž­Ä Ï‹ßs?ÀjËÑþWEN‘o8¢¶he?aœî":|ºà¢³B?³ôؽUT E.¢âêëfž}+Zj«ùBØ[K¦ÃæëL€…oŽf²E¸±Xã¯Ò’¦²SµZ|)õ‹ _^Óyéã/ººCXÄé™Ççy;B)·\cN¶‹¾ÄøºwKÙÙhv †—J_³ ÏÁ&¡Jp{™0DÐ&¥ÄÅÃ2 D)-ã¬"}wTìl>–|[‹ŸšºÅZJ— o3û.ÃBæµM!c¼ÁF”ìÍ· NìyWë Šî—wådžê]ë­ˆcљȌSëÊ®Ÿ­¬0Nµúò¨fÿ!Z/éPÈW¢I× Ÿ]ÝõÐ @'Š-¬Ÿ7Á³B vÞn×·;p\  µÞÈ¥ÚEù¸nr<àÀäÜ‚­Yj¡V#Y`^Õ¿QQ.Õkíg¼8ZíUƒý¡»”žw…¢®ÀÊ (Õ…E#Œ†(ÁÇ×)ºkâÝ5œžïi“GÛ¤Çú&E‹^¿Õ´°þNóãkÐÅbLa¤n©™ú‘Ú*2UÉ\žé²‡‰‡7}ÏŸ)1õªOœo÷=õ÷\OÚùµø­=·{Zéw1ÕNw¯åÎ?õG×½=_‰}sºÃ„<˜š¦dÄŸ¤`‹MúRGV‹6Së³»ù!c³==‘s2Ã+cº–mwæþþæe3'Õ°Ÿ^˶Š~–FƒöV=Å%Ä­{8t? y Ó0JpŽÙä:l›\·ˆm¤ªó9*F‰8 ñ\‡ÿ>iwT/–è„–S³­»FMaG¸Na'çx°¸Å^eD­¥Íìrh¹Œt,r"ì$'Š' 8J‡ùi9³Q#fÛwÀg*;€k!?9ˆ5lBßZ`°ø`fX2Û˜O ”yCö)1ÒlÈþ••ze¾­º…ª1ôb¨ëYüý̧à×ÓÞň•Ò \Ž/D–3e zXdõÖ°¬.&ûßóþÏ#9…ºòÉâ)í^©9p)j¯o”ØöVw¹µóL=¼²ƒýÕ÷ 8OoÛm2¦©"ø—ã6Àðñ6„4µ¦ÝéY{Ò7i¬6Aâ¯!uß ÂØË¥Ó?Û¶L»½ø¼]`È¡ÛÖýbXÀ²© r±4´ív¤‚ëŸXòàÐO³ððžPº¥29pì¡Úmtôý¯‡5ô#×-·‘ËVD¤Ú'*K}´\ú^¡©Á³cÃeíNN”88ÒK‘y¹=>‘5ïÒ¬¾îG¨ 5å•UçA“SÍ»Œ³N€R KU÷A—TÌ{†qy‡÷¢j€  2Ý\u2¥{ ž÷.¿ ι„Áxha_'¹•ÝÖÄQö*ß!tÕ¨ö½=+ê>ÁŠºÊŠ("­øÖ_A¤Nû¾<ͬ½§H¥˜VGPFólÉ’ )䔈0=“[m·gõ.í/ÙwòÕè FƒÛ%¼lsGyAôPë\R‘v«høðPmÂÞ³²Úx¶X±–A_nÞÖ²‹©ºòXG>ˆ8Kã+-“ŠÕ}SSD~La=Caÿù ‡Ãw@CëÄß¡·©Ö¢HBÉìeü^ñøÎô6T%®*õ$}{j¾0Õ0›†Â* ”ñX˜G€­ƒš¸¶¹y¬¤Õ‘¤7iiÏ´äÿ1nÚÓPîÔ„r×ÚÐ9}¤£sš—¿ÑÌTÔ˜úYUÕ?—QÌÂ-‹&’)Q•f'ËP› ª§Ì†pj‚á}UUZYÙƒPC]”}EíÅçh:…ɬ;P—C˜C*Š–²‰¤”í?¦ù½EíëÕCQä×Så+ßÕ…ôîõPßÎ&ÍÆ¤o¹šÓ£Íâ-xaP£éžå³ÓÁÇ›f±%“?‡7M5c… ©Ä„Tè•åC+Ný öªþ“ÝÉ7ÌBï åf½ŽÔKé•^ñ†!£uÜ^Zn ê øÆÖÉ çKóQ)(ºñ4¦¿¹1’_##ÚÞ±[ çÛ§ûé¿7”¢ªÌ[¼qÅ‹{j`O—½˜o‹ÝË|sç“ñÕ½¯uØz½cb…3ô.V•£U£¶«ƒÒò6"iCÇÙ6ÛŠ‰¯JÛ©Øhc¥jkEÏI’œŸœ,Ùk#:ŠI]˜:<ŽwìÝ÷À*/Á8£Ÿ¬ÍÂh9£ÇcÅãM…5þ­©/°¥€j†*O¥{'’^àqœc(ÎQÕ9Ã|%Ø>øx$JóÈó R¯T}i÷¥0ÎD†Qúýøú=Å@í,íãêåš ¸Å0wt«œ]¦ÿ¹åå²ì%‘Õ × êÆG­Ñ´yÐÓ•:´…Gí® "¥Pcm‹Å<”j ÜŒx´4¯°†0¿à¥•àWás™åãÕ‡¨ßÀVœzÑ£L?¯é½öªôÞˆ…³ ||‡³š-µOìUþnINk b²÷*™è6IßTW ê>T-l¸u–‹´q¶¶ 9x¯ßÛÐÿ~`““WÝ#ž»íqD…Sªžãµ/Ix$Bê+eg¼FjîÉÝÚyËà~l ™dûÈAèղ市«À.³•kº+7á<…lUÓÚ‹‚ zÀ0·â¡¿ÖÁI½ ,¨ð ôr2\¡uAìP‰aXµJc±ð±Š´ ·c€×)Ú’R<±wMiìÊÛƒn/ÇÃN6vH+qèsrÐê=*ilˆrëÜ;½•CšAûrÕ(ÈÜdµò9˪)z4|à‡ê¶k§†ÿ¶5ǧÑAåiH tŸþb„ ²e/¸”›•À8¼q·^Öû¡'Ù€ÜÌ3¾´Ö+ä)²8’ÏZ•ê¶Ï²²šSƬ},¥-í꾘SÉÓJÄ‹,‚ÑÉçŽß%‚Ô)Ëšëo–¡ï´Ú8›g„ýž-EzB&[ŸEêü!ëOW÷z.º³€ Hê{§•Ne—yY%Dì14õ­Ê…ã<«8n©A*ʲʨôb±"R¸A×ó ô¹ò…nÂj1ôÌYÚ´qX|÷¦Ñ€Ð@Å7“PX Ø8w>¸Ãv—ýôÂ¥­¾½²«¢e™Bj;eÚÕÝÁb½—¿ƒ’wI5ÓvªëWÙ•¤RP<Üá5Ù‚Œ4%Z3GU:T¶ÁR¬o…l…f‚ëò¤Ç6a· ZÀ—#A@"­í­ô2CZgèÌB‰^y!ýlµ½vñµ—tF¯ÔøLÿo¦ßptUu@ñÚ‚Ìu—¿µí÷ONž?ûPK;:0 $د'.boot/boot32lb.asmUT ®À@%›JHUxèèµZûoÛ¸–þYú?°ÙYÀÙ±]ÙI_æy¸»™¦H2¸Ù€–h›,yE)ŽýãïùI‰v’}`»Å`bQ<‡äy|çAˆË¹6‚þ“¹8=:ì©\N2•Š¥R'gâÃáåÞPLŠ¢F%UQŠŽÑù,SîñÅnÿù³ñgQ‹„XÔF§T$År-LQ—‰¢ß©œè\–ZQç©*E5W¢RåˆbŠðùøåñµžd:§:Q9±ë|üzºÛwª4ºÈÅPÐrµRe_\(%V«U–×ý¢œ‰)½Z¥¢-Ù‘4t¢Q²Ì4­¸*Ê[1Y7‡»Ue®21— ý2]¢MõTÍ\É;­i.øŒKÚÎaM pŠ¿Ã*¯H:oÄK1Œã=Hs?(YÕ¥2#ñ‡¡“’H­úìøì½} ;¨Š,\ý£{`žEã?þtÑ+hË[Òz*ÖäK+™WN_´•R‘ѬA)¾ÑY–Ï‚][¿#¹7ŒXÕ[ÚìºI,¨ßﳦ‹ºr¹ÌÖN,Ò9f’ Üm¨v»÷û~ » ^†Ä_‹¹fé<~ú£×9ÉÙ`5p™KÚiU<8SŸK1T‘œ{Ähk½€#ØÀMs´à\r Í<&iÝ“À¸$«myaqS/—¹Ï„žÙeœÊa 6~úª¨I™%fEa}.ƒéèeš’“Æ1ý®ÖÖ"“k¬‹éå&F{X†?Øí’™$$Ñóˆì¢=ûï‡|Ç£7ã8æá£³³Ë‹ññ~8Ÿž÷£[‚ìãQ) ~¬¤ÈF¦wª²Bn‹.Ž_o‰îù3£f@¥¨_©û QDñ1Šïß$qE ìõ7ýåù³qN >Š¢ï‹edæ0U€Ï ǰɋ¥5§Éô:§P"3:w gû9 ö_S5Õ9Ù¡9S‹/„¢4ÿ×ø>Þ£µÏÆ¿“%Oè4·t–vêÑšÄõU•*qÓ'‚<£/}ò‘®6Hh*gµ©IJ+¸¸ò’PjFè¬i£D=Ù >W`€©ŽXñ¿ÀiUyG'òñi{U2mY’AÌ$„SY·Bxþs’ï‰.I®n‘ÁÀS”=)\ª8/¢uº"¶a >½ ‰ÓìŽõð¹4- L$88I2—ֲĆhÚ“ öxQ ª¨dœA<½.ÌÈ”[nŸjš­î‡ÆÛ­EW©–nÉWÄag‘*“”zI Fbšþ64:Uïh/]¡ª»-6ì“ôúA:­^olŸÏNòþï&³•\»|ã¾åèÒ ^–”º¥Þ†K½¬ð&ÜZþIÉÔKUòÜ9F¶Œ$ÿ¤ÓTåÞJ;‘dzJ7NÙ’ ãÍcO)¾~õjïµ#õ„÷Ûòî¡3€—XP©— ^¿éJL39£M@xåB—%AT> 'JžØ&@> ïÔ¦æœ$·ã<μ+qè "¯7ÕÀîÐmîm/Æ’½Ò'çôy½˜XÊ©é÷t>-Àj¨†ÿU»'¤ÎzéÍ”û›™Å´qüàLi©ï”Óâ>Ôq‚Ǽ\&Ð-¦Ó›×1f»é1¦5ýl ÿÅøcD€ ô_‘áº7C†ôæMD:º¡C˜¹žVüÀŒ1=à‰’”ÈC‹>Œ°ÇMgÿÇû÷|\Ø)ÁâRílÊ5ÏÚªÝoÂ-EŒÜÁ÷AœICIb‚”"…÷”Y¦>òAéu^c.Cø6†cÿ„S]šêÿÄÕÓߤå‹wÿkƘTé…2¤ŽW²÷˯¿ü"Ò‰ˆ1~ÀŦĭ5¼¿1¡ Õ½ ¼. “¥\°³íZ:ÌÞÃì”êQJ6³öÕ¼rñq)SÔRœXÆqW ÍÞÜôW¼îãÝNwohÿ¿9$F®¨qDPÉkDïÕœR±&Dahl5Èg?èýœ\B¹<ÿóg²|þ¬ÍKFQ’¥8\’iü1õ$’÷]!ïñD™x”šði²¤ Á©U1Æ0Ÿpš2\?¢6hŒîŠÉ²á·ñ”0m<ˆ™¶TKŒš„Íe›wA*NKÝB#x¿¥A¶ÅÆàÞ$EÎi[€"QºŠÈtزàL@7zìȆŸ°#’XrË5êÑ×åÁ”ѱO ”$˜ª(ž?[ÿ2%ù¯¡ W“eètÍ¢®´_⊡òº+ÒŒ–áJx) Bo@&b÷Éi+wÈuaf7§tÒ¦qAš¤à-)UVŠÜ—1âð›8ú&.>ûºè¢ãÃÓ㯇燿_P®¡g58j&gê„.8úÉáå¡dAÖÜÑãˆ:Í*cZf|òªEÑ€S¶Ó6qØ[Ðá¹a_7£èžSÁ¤T«‚«U¯ù é³OôÑ騕ŒC­.ý¡5›ŒBk½ ó×kÆ#¨ñ¯{Á+ÜZÙv  K즮\rríØ ·7,ÑlmŽ[57hæÚÏREtïdV«]œœàЦ¥oŽ£ÜyW_GáQpU{Œ‘åâ€o‹xlØ TBÁ¯ÌÄ{Ñô&-¨°Ù§âî$í™VÜͱf–W¿bÏÓùšàzÒaqP~)[ع œè/F‰Ag$Ël:hTq¨ô½wfΈ\ö{Ò«‚J× ¼ p šEŽ×ˆ¢½ÜÞèܯ5Ú†¶!2!o(³¹$.Š%·¡™eö˜ù+zÔR¼Q’ÁÐÏ­—BZ8šP°wY{c–²Ü†æŸ[ º}pxmTG4>ÆðvþÿT°’º"i­mº-ç]9·ùCqÇ„˜Ãà-Í„íaùQ3ëój.Ñ«k:W?ûÐä…mS¹å‰.ùÃÊm¿ŠŸÌ ³²w¶€áfo_|á›­0Y±±Ègòœgè|YW6Ë赦y€’(x± PÏŸ…¶é]Ô40“êæçä¾MRÚ°eæ? Y¸ 'ظÊtmUôDÆ¿³“|q8µæèärʤی™»âë S¨þ¬Ï¹b›ÆrÊÒçÐwÑF|m´Ã¸`‰e©îtQÁ;–²Bà{áš)´ÜàØœ/ÔEXÿ´•W[g±œ˜"«+µÕ±¤`ÞJèk{‚a_br¿‰Îv>i°Œ-5±N`Y7woï]6‘ä7~èÑ"Õ9AÕMbì`RÜò±îXn.(í]wãûxêÕˆº¼"Ýd!f3Ùe‚këœr3„6ÍW¯x+ ú%¼mkÍ *×+ø©Î|ì¢åVXuíÇõ :”³œ“µePý\ ÿzþùË%™ Ç`t…q3$N.Fˆ½OdžK».mDö‰ã¸Ó©*èØ3%šö*Åkán\™Nè*ˆÞ±%“âòòO,¦wŠÜY‘š K^P·*÷†&)¡aJ_«ð®-ÜQÕÔìfP⨳&i$ºD€“üÀ¦ÊŸ/×s YsÁßµàS®ûtéôèð¿ï {ˆ hÑo 962m¤¿T˜èÜÞu[¶^¼ÒY†ïL¨ÐÌüMB󱉖»»!ÌÐ¥ù.uám£ox ÀÜ·›h³ˆ µvQÁ%Î{ðÓè\ÂU šîyí«¼¨gó÷a®a–¬°…bèm|JL²"¹…´eb:!›z;äb©JdI HÜK2MÑÁªö:f·Ím¸šõm'ÛAšËlê34|ýDa E÷Õñµo»uRòÍPUˆ_Ü»e·C;@bñp0ÙJæz6÷ÕXJæêíöÔ¬XmÏ4˜øúºi/ÛOB‚Ô ï÷›÷”íUmn 7‹WÃëÖ`:ˆˆïæ¯âk'ÓéU´D>Ý7íEÊf âa8GÏÂ6`Ø‹‚»ƒ%7lØ pϲ½0{ßw4ÚñŸnqƒÃñ%¸m úrø ˳(’Ø"­¸»ïõb‰X–BÙÊ%ÈpyÁ/|w Ç’s§ÌPlÀ]³ÍØKUY ÷GlÚ€GSæî“·¦¢©ã7œÐ†¨‰» x´3KÊ ªj“òFqeMÇ_LÉ¢ÜÇDNS¸Í0M»‡ÑÛÂ4M£!1ˆãxè_„©jÊ·]ÃVÂMž&<`ðþÿ)œm]0á–`Ï0?¶ÓåÛ@wáÅ·¾|©§Txïky5¥jN_ ±c£¾ë ¡§Ï7";¶–ý4–›Í;\ âÓ+ZÂà#WKŒ/9×eSâ¾_Z#_Duê>Óðm´KVo"ònl—RàKÇþLÏrBÀ•ˆ¡±ÃÃW¯ìrÿÐù»{ûi ¾HÞwÝ}‰ÏŽg:±õ ç1´Æ?PK£8:0ò*ÊÔ ¦1boot/boot32.asmUT "¼@%›JHUxèèµkoÛ8ò³ä?½=`Û8©ì4Ù®|ÝEš8»Á¥Í"Î-‚œAK´ÍF–QNœbüÍð!Q%§Ý=i"‘3Î{†ì¨··¯Ÿ½ÝQïO¢Ÿ?ofæŸäçy>üxN˜ó“›­† ﯮnÈd|ªf]/¯NOnÆu˜Áù¸cÕç¾ø+_]_üvñfï§Sk­*Ì÷®õïñõÇñ¥»¼:9Ÿ59ãyÇm»´eïÿ ٜnj|øÏåÍÅ61½ŸÆŽîî¶X±8ïäl“ã3ÿýÉdL¬ÇÛüàr»;¤ö$ÙBþFÇyöä—ã_V©ü-–I–“ŒÑh*ršÁj½^œ¤’J=u–.yÎiÄ¿²ä Áu—%a3qÅVéŠ0{ÞÆ;T/#r5þ@":c‘ ñþ)gâ–MXP@Ì Ä _ äIfÁd9Ö"/€B¤¦‹×4Š’€æ<‰ÉȶᯢÀY%™ÌÀÿ!Xö[Ô¨lP0Q2P‚¼4™“9Í+×I’Ÿñ x/ ˆA"ƒ$äqgœ‰ÚV ôa ­)aä4ñ¾¢ f#øÀBNk+92d<õÉ<|7aypppPâµ€íç4·q7‰2(²¡z“Ñà¾}Û}ãŒ.þѰÁoZÂ-qÜžÏÃŵù5_7+>ÿ¾^°pè9ö6'¿ã££ÃãxSãŒ~c€µ_ŸÛÙ ÐO#‘Û” J'h†<^•œe¶šHtO%ª0ãŒÔ˜ô¦ ýLÇëÕŒehѽ^ÎWLô¼ÍÝÿaï‡H8#ží`еMÆ¿Yš=¬Àž@WžW¼ÚSA¦Šy6uo‹¹#ð ÀLˆÂæp¿ùR.d#‹7[$óùôØë*ýa _ö¥w|ç'×$MxŒl{GÐ7Ô áGA7G1Øl=básžå.ë.*¤9µ%ìñ°‹óÀšc+*î-àã^o¤¥ˆÌÑz¡­¤ìcü¨¡K>ÏKT6ó­ÅöÀ®ámöÿžGÅ’ñÇ›ëÏ'ÒÝ2n©ÐD!jyñfDëYnú„npÊ*yè…B½Õg˜æ~ߊ° 1€_|Æ|aÂÆ)xàŠ*o„õž„ÍXŠ_Å£µò×׿$!ÃH‹¶ VôѰ ßIšÑ ‰¥Ô,Ãè…=¯ü?øE9ÎEß±õm¬-ãSZëngé>z‡;$Xä¼Û­ôcw}Fš ï/®&$¥à„vrZÿAçÏ.íì¤xˆúø;Í8ò¡1êÜâÅ%pý닾g!:¥Q@þ ]‰â¸íéÄdEFº’å·:ÜÜÙ’®Œì å C ÊÎ?ôp ”Òb©™š^ø!`à-c°0¹;ê¡ó©PL#„Ì]ä‚Áì¥k±ìi­]G¥Ì,ê‘<53MÒ.˜mD‘+··Qä•Äß–>òÎ¶Ú˜ÚØ¦†å¯lk”P•lR)Ü2“ÃÆKÈ‚^uQÍM…[“T]T»Ä 6à)s¶Jñ…âKuF¯· – ¹LÕó=Bç’¤¹ãà 0ÑWp¾ü¢ˆBZCk°JË—/1ëÙ+!ùRqnmþÈì!¥1œ_|<;¿¸û™Ð,X‚uÍ!p ‹™óˆ¡uáßÕtòÀQ‰âšåë,~ÍÂÎ>ù'Ÿ2¸Y© âu(Æö+ü‡åî$ãl—xú ëÃð­ÏGGöÈP¢ì¢Á¨¨³ÉÍîÚg‡ÍÙr•ÝÈMb¨Ø¦zû~ÚÂA:¨e(8=¨ËG¾ýe5͉_tΉáfʲÌäiMbÆW§P¡É3+6QÕŸ’J ¬˜=Zœ’—,#¦Š…Hç¶’,Þµ³ò‡ðŒ£?ù‹‚2‰\—œºõ¯áÂЄGÚN¥•ª&ÄÁäóDk å6ØzÂ+ü£rN-ìƒRLWþf1éN¡ü=âGôFÀÝ dYÅ8ÿæ È{d& ®MÌJùU;Þù4Lb§ë0k¨\̵Ɨø«ARòÀ!$ÕˆÚ„›1rz[¬Q„›ö±ÙVôUånd.,Ðx¶ïÔÐ ï¨[ýѳ9¬³ ØØá’:8aìͦƱ—JOªæLå–P#»ØbYLø!ÇnÀÉþ`pWnmÁÊHeŠä.§_"zƒˆ {~ã·k':"—äÁ›NT‘н›jÅ (ü?ômA ô®W€kY§w»„Y§ÀöŽýïñÆÆBÞnÁq—zÿÿõ58r)f[}™&ˆ.ût©²À¼‡m´:úGÊséæ)¹gOÖðÏr8c²(ÄìlEƒ%Wžq[º† Ngc* Û/tD’uŽ3jpcö,,€0}ÃÖ54äó§äbw§âE\öfÔ‰oÁÌx%ÿCǨVMƒAÙâi”$©ËF—™±jG$Ì‚Ì8A».ÞX¯Ü4}Å Ó¸üÇ%$T ¤l{NÕ@f|¸hº8¿ÃÙE©, J!Û¨€²¶¹5UlJ'2 1h'’;\—,m‹Û¸ª†e˜(«m×Ä  vé],‰$ZçÌ’°+érÎEó VR½Öö9Øzšm¶… Á*­m\_.•fZ¥n±sÕ®•­\[±Ùw¨Fð„Bª`þ¥1÷ƒ˜uä¬QÍ1xà0bdÉKÙôúVŸ}ô€c†|Â<§|Ý/µ€ÁPc%-«–t·Gõ°†´-Ó†Þ–BT’«u½%K°Uw°ÅùÔ‰Ä<ô¼ªÉ)ݾôV`eóuà]†œ-çNÁ’f~{µ‘­¼¶ 6þ cBRº§n …:«Æp ¦È&ÜaEøO†^ ß8%77Ÿ±Ò`zO~=bÞ*6É.tßZ6œ4nZb”è¢$³.%@ÙçÉ=‹ÛµJ@¾Á=Y§@sÎb¼ ƒb]g1jMæ,—•7ÆsÏ“A=”Ì5ldñk›«·¡Ž` „DDuÏJ×m´X}Y ~.ÙÖ¢¥‰‚‡Ãý°gW“jj¤~'¾Œ‡P¥äGûž¿•ÓáR²±í”Lj†ÜW¨Ž´f<9-` ÜØ°.{ŠHœtnלh`ìîN’¼n£<‘dâ‘~2 ¼%?R!Ö+†ýý›ª/])’Jé²»fÜà\jÆD;ÞØ—‚ÖÎëWk¿®Újú)1Z¬$;ÑÈÎØ¬hãô´²Y³O§ýPK šë0 íAboot/UTD ð@UxPK,8:0w³è«vE ¤8boot/boot.asmUTD»@UxPK;:0 $د'. ¤#boot/boot32lb.asmUT®À@UxPK£8:0ò*ÊÔ ¦1 ¤'boot/boot32.asmUT"¼@UxPKË//¹bP ¤_4boot/makefileUTþf?UxPKf»5dev86-0.16.21/bootblocks/fs.c000066400000000000000000000030561231050321700155300ustar00rootroot00000000000000 #include "monitor.h" #ifndef SINGLEFS int fs_type = 0; open_file(fname) char * fname; { #ifdef DEBUG fprintf(stderr, "Open file %s\n", fname); #endif if( fs_type ) close_file(); /* If we can't read the boot sector there is a _real_ problem */ if (read_sector(0) == 0) return -1; if( tar_open_file(fname) >= 0 ) { fs_type = 1; return 0; } if( min_open_file(fname) >= 0 ) { fs_type = 2; return 0; } if( dos_open_file(fname) >= 0 ) { fs_type = 3; return 0; } return -1; } rewind_file() { #ifdef DEBUG fprintf(stderr, "Rewind file (%d)\n", fs_type); #endif switch(fs_type) { case 1: return tar_rewind_file(); case 2: return min_rewind_file(); case 3: return dos_rewind_file(); } return -1; } close_file() { int rv = -1; #ifdef DEBUG fprintf(stderr, "Close file (%d)\n", fs_type); #endif switch(fs_type) { case 1: rv = tar_close_file(); break; case 2: rv = min_close_file(); break; case 3: rv = dos_close_file(); break; } fs_type = 0; return rv; } long file_length() { #ifdef DEBUG fprintf(stderr, "File length (%d)\n", fs_type); #endif switch(fs_type) { case 1: return tar_file_length(); case 2: return min_file_length(); case 3: return dos_file_length(); } return -1; } read_block(buffer) char * buffer; { #ifdef DEBUG fprintf(stderr, "read block into (%d) (%d)\n", buffer, fs_type); #endif switch(fs_type) { case 1: return tar_read_block(buffer); case 2: return min_read_block(buffer); case 3: return dos_read_block(buffer); } return -1; } #endif dev86-0.16.21/bootblocks/fs_dos.c000066400000000000000000000210031231050321700163650ustar00rootroot00000000000000 #include "monitor.h" #ifdef BUFFER_FAT #define read_fat_sector read_sector #endif #define DOS_SECT(P) get_uint(P,0x0B) #define DOS_CLUST(P) get_byte(P,0x0D) #define DOS_RESV(P) get_uint(P,0x0E) #define DOS_NFAT(P) get_byte(P,0x10) #define DOS_NROOT(P) get_uint(P,0x11) #define DOS_MAXSECT(P) get_uint(P,0x13) #define DOS_MEDIA(P) get_byte(P,0x15) #define DOS_FATLEN(P) get_uint(P,0x16) #define DOS_SPT(P) get_uint(P,0x18) #define DOS_HEADS(P) get_uint(P,0x1A) #define DOS_HIDDEN(P) get_long(P,0x1C) #define DOS4_MAXSECT(P) get_long(P,0x20) #define DOS4_PHY_DRIVE(P) get_byte(P,0x24) #define DOS4_SERIAL(P) get_long(P,0x27) #define DOS4_FATTYPE(P) get_uint(P,0x39) /* These assume alignment is not a problem */ #define get_byte(P,Off) *((unsigned char*)((char*)(P)+(Off))) #define get_uint(P,Off) *((unsigned short*)((char*)(P)+(Off))) #define get_long(P,Off) *((long*)((char*)(P)+(Off))) typedef long Tsect; static int read_bootblock(); static int dir_nentry, dir_sect; static Tsect dos_clust0, dos_spc; static int dos_fatpos, dos_fatlen, dos_fattype; static int last_serial = 0; #ifndef BUFFER_FAT static char * read_fat_sector(); static int sector_no = 0; static char sector_buf[512]; #endif #ifdef BUFFER_FAT static char * fat_buf = 0; int use_fatbuf = 0; #endif static struct filestatus { char fname[12]; unsigned short first_cluster; unsigned short cur_cluster; unsigned short sector_no; /* Max filesize = 32M */ long file_length; } cur_file = { "", 0, 0, 0 }; dos_open_file(fname) char * fname; { char conv_name[12]; char *s, *d; int i; int dodir = 0; /* Get the superblock */ if( read_bootblock() < 0 ) return -1; if(strcmp(fname, ".") == 0) dodir = 1; else { /* Convert the name to MSDOS directory format */ strcpy(conv_name, " "); for(s=fname, d=conv_name; *s && *d && *s != '.' && *s != ' '; s++) { if( islower(*s) ) *d++ = toupper(*s); else *d++ = *s; } while( *s && *s != '.' ) s++; strcpy(d=(conv_name+8), " "); if( *s == '.' ) { for(s++; *s && *d; s++) { if( islower(*s) ) *d++ = toupper(*s); else *d++ = *s; } } /* Already opened ? Then just rewind it */ if( cur_file.first_cluster && strcmp(cur_file.fname, conv_name) == 0 ) return dos_rewind_file(); } memset(&cur_file, '\0', sizeof(cur_file)); #ifdef BUFFER_FAT if( !dodir && dos_fattype == 12 ) { /* Read in and buffer the FAT */ if( fat_buf ) free(fat_buf); fat_buf = malloc(dos_fatlen * 512); if( fat_buf == 0 ) use_fatbuf = 0; else { use_fatbuf = 1; for(i=0; i ' ' && *d <= '~' ) switch(d[11]&0x18) { case 0: printf("%-8.8s %-3.3s %10ld", d, d+8, get_long(d,28)); dtime=1; break; case 0x10: printf("%-8.8s %-3.3s ", d, d+8); dtime=1; break; case 8: if( (d[11] & 7) == 0 ) { printf("%-11.11s ", d); dtime=1; } break; } if( dtime ) { printf(" %02d/%02d/%04d %02d:%02d", (get_uint(d,24)&0x1F), ((get_uint(d,24)>>5)&0xF), ((get_uint(d,24)>>9)&0x7F)+1980, ((get_uint(d,22)>>11)&0x1F), ((get_uint(d,22)>>5)&0x3F) ); if( more_char('\n') < 0 ) break; } #endif } else if( memcmp(d, conv_name, 11) == 0 && (d[11]&0x18) == 0 ) { /* Name matches and is normal file */ strcpy(cur_file.fname, conv_name); cur_file.first_cluster = get_uint(d,26); cur_file.file_length = get_long(d,28); cur_file.cur_cluster = cur_file.first_cluster; cur_file.sector_no = 0; #ifdef DEBUG fprintf(stderr, "Opened first cluster %d, len %ld\n", cur_file.first_cluster, cur_file.file_length ); #endif return 0; } } return -1; } dos_rewind_file() { /* Is there an opened file ? */ if( cur_file.fname[0] == 0 ) return -1; cur_file.sector_no = 0; cur_file.cur_cluster = cur_file.first_cluster; return 0; } dos_close_file() { #ifdef BUFFER_FAT if( fat_buf ) free(fat_buf); fat_buf = 0; #endif memset(&cur_file, '\0', sizeof(cur_file)); reset_disk(); return 0; } long dos_file_length() { /* Is there an opened file ? */ if( cur_file.fname[0] == 0 ) return -1; return cur_file.file_length; } dos_read_block(buffer) char * buffer; { int s; char * ptr; /* Is there an opened file ? */ if( cur_file.fname[0] == 0 ) { #ifdef DEBUG fprintf(stderr, "File is not currently open!\n"); #endif return -1; } /* Are we before the EOF ? */ if( ( dos_fattype == 12 && cur_file.cur_cluster >= 0xFF0 ) || ( dos_fattype == 16 && (cur_file.cur_cluster&0xFFF0) == 0xFFF0 ) || cur_file.cur_cluster < 2 ) { #ifdef DEBUG fprintf(stderr, "Hit end of file; cluster 0x%03x\n", cur_file.cur_cluster); #endif return -1; } for(s=0; s<2; s++) { Tsect sectno; if( ( dos_fattype == 12 && cur_file.cur_cluster >= 0xFF0 ) || ( dos_fattype == 16 && (cur_file.cur_cluster&0xFFF0) == 0xFFF0 ) || cur_file.cur_cluster < 2 ) { memset(buffer, '\0', 512); buffer += 512; continue; } sectno = dos_clust0 + cur_file.cur_cluster * dos_spc + cur_file.sector_no % dos_spc; ptr = read_sector(sectno); if( ptr == 0 ) return -1; memcpy(buffer, ptr, 512); cur_file.sector_no++; if( cur_file.sector_no % dos_spc == 0 ) { if( dos_fattype == 12 ) { int odd = (cur_file.cur_cluster&1); unsigned int val, val2; val = cur_file.cur_cluster + (cur_file.cur_cluster>>1); #ifdef BUFFER_FAT if( use_fatbuf ) val2 = get_uint(fat_buf, val); else #endif { ptr = read_fat_sector(dos_fatpos+(val/512)); if( ptr == 0 ) return -1; if( val%512 == 511 ) { val2 = (ptr[511]&0xFF); ptr = read_fat_sector(dos_fatpos+(val/512)+1); if( ptr == 0 ) return -1; val2 |= (ptr[0]<<8); } else val2 = get_uint(ptr, (val%512)); } if( odd ) val2>>=4; val2 &= 0xFFF; cur_file.cur_cluster = val2; } else { ptr = read_fat_sector(dos_fatpos+(cur_file.cur_cluster/256)); if( ptr == 0 ) return -1; cur_file.cur_cluster = get_uint(ptr, (cur_file.cur_cluster%256*2)); } } buffer += 512; } return 0; } static int read_bootblock() { char * sptr; int rv, media_byte = 0; #ifndef BUFFER_FAT sector_no = 0; #endif sptr = read_sector(1); if( sptr == 0 ) return -1; media_byte = *(unsigned char*)sptr; /* Valid media byte ? */ if( (media_byte & 0xF0) != 0xF0 ) return -1; sptr = read_sector(0); if( sptr == 0 ) return -1; if( DOS_MEDIA(sptr) != media_byte ) return -1; if( DOS_SPT(sptr) > 63 ) return -1; if( DOS_SECT(sptr) != 512 ) return -1; if( last_serial != DOS4_SERIAL(sptr) ) dos_close_file(); last_serial = DOS4_SERIAL(sptr); /* Collect important data */ dir_sect = DOS_RESV(sptr) + DOS_NFAT(sptr)*DOS_FATLEN(sptr); dir_nentry = DOS_NROOT(sptr); dos_fatpos = DOS_RESV(sptr); dos_fatlen = DOS_FATLEN(sptr); dos_spc = DOS_CLUST(sptr); dos_fattype = DOS4_FATTYPE(sptr); switch(dos_fattype) { case '1'+'6'*256: dos_fattype = 16; break; case '1'+'2'*256: default: dos_fattype = 12; break; } if( dos_spc < 1 ) dos_spc = 1; dos_clust0 = dir_sect + (dir_nentry+15)/16 - 2*dos_spc; if( disk_cyls == 0 ) { disk_spt = DOS_SPT(sptr); disk_heads = DOS_HEADS(sptr); } return 0; } #ifndef BUFFER_FAT static char * read_fat_sector(sector) int sector; { char * p; if( sector == sector_no ) return sector_buf; p = read_sector(sector); if(p) { memcpy(sector_buf, p, 512); sector_no = sector; return sector_buf; } else return 0; } #endif dev86-0.16.21/bootblocks/fs_min.c000066400000000000000000000122351231050321700163720ustar00rootroot00000000000000 #include "monitor.h" #include "minix.h" /* #define DEBUG 1 /**/ #define SECTOR_SIZE 512 block_nr inode_tbl = 0; /* super.s_imap_blocks+super.s_zmap_blocks+2 */ static int fs_dir32 = 0; /* Using 30 char filenames ? */ struct file_pos { inode_nr inode; zone_nr seek_addr; file_pos i_size; /* current file size in bytes */ mask_bits i_mode; /* File type */ zone_nr i_zone[NR_ZONE_NUMS]; /* block numbers from inode */ } current_file = { 0,0 }; static int first_time = 1; static inode_nr current_dir = ROOT_INODE; static block_nr fs_ind = 0; static block_nr fs_block = 0; static char fs_buf[BLOCK_SIZE]; /* For storing inodes and ind sectors */ static min_inode_open(); #define b_super(x) ((struct super_block *)(x)) #define b_dir(x) ((dir_struct*)(x)) min_open_file(fname) char * fname; { char * sptr; if( disk_heads == 0 ) return -1; if( (sptr = read_sector(SUPER_BLOCK*BLOCK_SIZE/SECTOR_SIZE)) == 0 ) return -1; /* Check super */ if(b_super(sptr)->s_magic == SUPER_MAGIC ) fs_dir32 = 0; else if(b_super(sptr)->s_magic == SUPER_MAGIC2 ) fs_dir32 = 16; else return -1; inode_tbl = b_super(sptr)->s_imap_blocks+b_super(sptr)->s_zmap_blocks+2; /* Check for boot directory */ current_dir = ROOT_INODE; if( min_name_open("boot") >= 0 && current_file.i_mode == I_DIRECTORY ) current_dir = current_file.inode; #ifdef DEBUG fprintf(stderr, "Opening minix file <%d>/%s[1,%d]\n", current_dir,fname,fs_dir32+14); #endif return min_name_open(fname); } static min_name_open(fname) char * fname; { int do_dir = 0; char dirbuf[1024]; long len; int v; inode_nr file_inode = 0; if( strcmp(fname, ".") == 0 ) do_dir = 1; /* open current_dir inode */ if( min_inode_open(current_dir) < 0 ) return -1; /* scan for file */ for(len = min_file_length(); len>0; len-=1024) { if( min_read_block(dirbuf) < 0 ) break; for(v=0; v<1024; v+= 16+fs_dir32) { if( b_dir(dirbuf+v)->d_inum == 0 ) continue; #ifndef NOCOMMAND if( do_dir ) { if( b_dir(dirbuf+v)->d_name[0] == '.' ) continue; if( fs_dir32 ) printf("%.30s\n", b_dir(dirbuf+v)->d_name); else printf("%.14s\n", b_dir(dirbuf+v)->d_name); } else #endif if( strncmp(b_dir(dirbuf+v)->d_name, fname,14+fs_dir32) ==0) { file_inode = b_dir(dirbuf+v)->d_inum; break; } } } /* open */ if( file_inode ) { if( min_inode_open(file_inode) >= 0 ) return 0; } return -1; } static min_inode_open(inode) int inode; { int inode_sector = inode_tbl*BLOCK_SIZE/SECTOR_SIZE; d_inode * sptr = 0; int i; min_close_file(); inode--; inode_sector += inode/(SECTOR_SIZE/sizeof(d_inode)); if( (sptr = read_sector(inode_sector)) == 0 ) return -1; sptr += inode%(SECTOR_SIZE/sizeof(d_inode)); current_file.i_mode = (sptr->i_mode & I_TYPE); if( current_file.i_mode != I_REGULAR && current_file.i_mode != I_DIRECTORY ) return -1; current_file.i_size = sptr->i_size; for(i=0; ii_zone[i]; current_file.inode = inode+1; return 0; } min_rewind_file() { current_file.seek_addr = 0; return 0; } min_close_file() { if( current_file.inode == 0 ) return -1; current_file.inode = 0; current_file.seek_addr = 0; fs_ind = 0; return 0; } long min_file_length() { if( current_file.inode == 0 ) return -1; return current_file.i_size; } min_read_block(buffer) char * buffer; { block_nr block_no; if( current_file.seek_addr < NR_DZONE_NUM ) block_no = current_file.i_zone[current_file.seek_addr]; else if( current_file.seek_addr < NR_DZONE_NUM + NR_INDIRECTS ) { if( fs_block != current_file.i_zone[NR_DZONE_NUM] ) { block_no = current_file.i_zone[NR_DZONE_NUM]; read_fs_block(block_no, fs_buf); fs_block = current_file.i_zone[NR_DZONE_NUM]; fs_ind = 0; } block_no = ((zone_nr*)fs_buf)[current_file.seek_addr-NR_DZONE_NUM]; } else { int ind_block; ind_block = current_file.seek_addr - NR_DZONE_NUM - NR_INDIRECTS; if( fs_ind != ind_block/NR_INDIRECTS + 1 ) { block_no = current_file.i_zone[NR_DZONE_NUM+1]; read_fs_block(block_no, fs_buf); fs_block = current_file.i_zone[NR_DZONE_NUM+1]; block_no = ((zone_nr*)fs_buf)[ind_block/NR_INDIRECTS]; read_fs_block(block_no, fs_buf); fs_block = current_file.i_zone[NR_DZONE_NUM]; fs_ind = ind_block/NR_INDIRECTS + 1; } block_no = ((zone_nr*)fs_buf)[ind_block%NR_INDIRECTS]; } current_file.seek_addr++; read_fs_block(block_no, buffer); return 0; } read_fs_block(block_no, buffer) block_nr block_no; char * buffer; { long sector_no; char * sptr; if( block_no == 0 ) goto zappit; sector_no = ((long)block_no) * BLOCK_SIZE/SECTOR_SIZE; sptr = read_sector(sector_no); if( sptr ) memcpy(buffer, sptr, SECTOR_SIZE); else goto zappit; sptr = read_sector(sector_no+1); if( sptr ) memcpy(buffer+SECTOR_SIZE, sptr, SECTOR_SIZE); else goto zappit; return; zappit:; memset(buffer, '\0', 1024); } dev86-0.16.21/bootblocks/fs_tar.c000066400000000000000000000145441231050321700164020ustar00rootroot00000000000000 #include "monitor.h" #define HEADER_SIZE 512 #define NAME_SIZE 100 #define BLOCK_BOUNDARY 20 typedef union { char hdr_block[HEADER_SIZE]; struct m { char m_name[NAME_SIZE]; char m_mode[8]; char m_uid[8]; char m_gid[8]; char m_size[12]; char m_time[12]; char m_checksum[8]; char m_linked; char m_link[NAME_SIZE]; char m_ustar[8]; char m_uname[32]; char m_gname[32]; char m_major[8]; /* GNU fields */ char m_minor[8]; char m_atime[12]; char m_ctime[12]; char m_offset[12]; /* An so forth */ } member; } HEADER; long tar_convert(); int valid_tar_checksum(); void tar_set_drive(); static int disk_size = 0; struct tx { char name[NAME_SIZE]; int first_sectno; int cur_sectno; int sectcount; int diskoffset; long file_length; } tar_status; tar_open_file(fname) char * fname; { HEADER * sptr; #ifndef NOCOMMAND int dodir = 0; #endif int sectno; sptr = read_sector(0); /* Is it a tar disk ? */ if( !valid_tar_checksum(sptr) ) return -1; tar_set_drive(); #ifndef NOCOMMAND if( strcmp(fname, ".") == 0 ) dodir=1; else #endif { if( tar_status.diskoffset == 0 && strcmp(fname, tar_status.name) == 0 ) return tar_rewind_file(); } tar_close_file(); for(sectno=0;;) { long fl, v; if(sectno) sptr = read_sector(sectno); if(!sptr || !*sptr->member.m_name) break; if( !valid_tar_checksum(sptr) ) { printf("Checksum error on tar header\n"); return -1; } fl = tar_convert(sptr->member.m_size, 12); v = (fl+511)/512 + 1; if( sptr->member.m_linked != 0 && sptr->member.m_linked != '0' ) ; #ifndef NOCOMMAND else if( dodir ) printf("%s %d tape blocks\n", sptr->member.m_name, (int)v-1); #endif else if( strcmp(fname, sptr->member.m_name, NAME_SIZE) == 0 ) { strncpy(tar_status.name, sptr->member.m_name, NAME_SIZE); tar_status.first_sectno = sectno+1; tar_status.cur_sectno = sectno+1; tar_status.file_length = fl; tar_status.sectcount = v-1; tar_status.diskoffset = 0; return 0; } if( v < 1 || (sectno += v) > disk_size ) break; } return -1; } tar_rewind_file() { if( tar_status.name[0] == '\0' || tar_status.diskoffset != 0 ) { tar_close_file(); return -1; } tar_status.cur_sectno = tar_status.first_sectno; return 0; } tar_close_file() { tar_status.name[0] = 0; tar_status.first_sectno = -1; tar_status.cur_sectno = -1; tar_status.file_length = -1; tar_status.diskoffset = -1; return 0; } long tar_file_length() { if( tar_status.name[0] == '\0' ) return -1; return tar_status.file_length; } tar_read_block(buffer) char * buffer; { char * ptr; HEADER * sptr; int i; if( tar_status.name[0] == '\0' ) return -1; for(i=0; i<2; i++) { if( tar_status.cur_sectno - tar_status.first_sectno >= tar_status.sectcount ) { memset(buffer, '\0', 512); } else { if( tar_status.cur_sectno >= tar_status.diskoffset+disk_size ) { int k; tar_status.diskoffset += disk_size-2; for(;;) { printf("Please insert next disk and press return:"); fflush(stdout); while( (k=(getch() & 0x7F)) != '\r' && k != '\n') if( k == 27 || k == 3 ) { printf("... Aborting\n"); return -1; } printf("\n"); sptr = read_sector(0); if( !valid_tar_checksum(sptr) ) { printf("Checksum failed reading volume label\n"); continue; } tar_set_drive(); sptr = read_sector(1); if( !valid_tar_checksum(sptr) || sptr->member.m_linked != 'M' || 512*(long)(tar_status.cur_sectno-tar_status.first_sectno) != tar_convert(sptr->member.m_offset, 12) ) { printf("Wrong disk inserted, "); continue; } break; } ptr = read_sector(tar_status.cur_sectno-tar_status.diskoffset); } else ptr = read_sector(tar_status.cur_sectno-tar_status.diskoffset); if( ptr == 0 ) return -1; memcpy(buffer, ptr, 512); } buffer+=512; tar_status.cur_sectno++; } return 0; } long tar_convert(str, type) char str[]; int type; { register long ac = 0L; register int i; for (i = 0; i < type; i++) { if (str[i] >= '0' && str[i] <= '7') { ac <<= 3; ac += (long) (str[i] - '0'); } } return ac; } valid_tar_checksum(sptr) register HEADER * sptr; { register char *ptr; int ac = 0; ptr = sptr->hdr_block; while (ptr < sptr->hdr_block+sizeof(sptr->hdr_block)) if( ptr < sptr->member.m_checksum || ptr >= sptr->member.m_checksum+sizeof(sptr->member.m_checksum)) ac += (*ptr++ & 0xFF); else ptr++, (ac += ' '); ac -= tar_convert(sptr->member.m_checksum, sizeof(sptr->member.m_checksum)); return ac == 0; } void tar_set_drive() { #ifdef __STANDALONE__ disk_spt = __argr.x.si; /* Choose some formats, note Boot block only sees a few SPT. * 9x40=360k, 15x80=1200k, 18x80=1440k, 21x82=1722k, 36x80=2880k */ if( disk_spt <= 9 ) disk_cyls = 40; if( disk_spt == 21 || disk_spt > 36 ) disk_cyls = 82; else if( disk_spt == 32 ) disk_cyls = 1024; else disk_cyls = 80; #else disk_spt = 18; /* Testing only */ disk_cyls= 80; #endif disk_heads=2; disk_size = disk_spt*disk_cyls*disk_heads; } #if 0 #asm !-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ! ! These are the number of sectors per track that will be scanned for. ! For 3.5 inch floppies 36 is 2.88 Mb, 18 is 1.44Mb, 21 is 1.68Mb on ! a 1.44Mb floppy drive. 15 and 9 are for 5.25 inch floppies. disksizes: .byte 36,21,18,15,9 ! It seems that there is no BIOS call to get the number of sectors. Guess ! 36 sectors if sector 36 can be read, 18 sectors if sector 18 can be read, ! 15 if sector 15 can be read. Otherwise guess 9. export _probe_sectors _probe_sectors: mov si,#disksizes ! table of sizes to try probe_loop: lodsb cbw ! extend to word mov _disk_spt, ax cmp al,#9 je got_sectors ! if all else fails, try 9 xchg ax, cx ! cx = track and sector xor dx, dx ! drive 0, head 0 mov bx,#probe_buf ! address after setup (es = cs) mov ax,#0x0201 ! service 2, 1 sector int 0x13 jc probe_loop ! try next value got_sectors: ret #endasm #endif dev86-0.16.21/bootblocks/help.c000066400000000000000000000037501231050321700160510ustar00rootroot00000000000000 /* * Display a page from help.txt, the argument is the scan code of a function * key. F1..F10 display pages 1..10, HOME is page zero, PGUP and PGDN are * previous and next page. */ #include "monitor.h" #ifndef NOCOMMAND struct keys { int key; int rel; int abs; } keys[] = { {0xC7, 0, 0}, /* HOME page 0*/ {0xBB, 0, 1}, /* F1 page 1 */ {0xBC, 0, 2}, /* F2 page 2 */ {0xBD, 0, 3}, /* F3 page 3 */ {0xBE, 0, 4}, /* F4 page 4 */ {0xBF, 0, 5}, /* F5 page 5 */ {0xC0, 0, 6}, /* F6 page 6 */ {0xC1, 0, 7}, /* F7 page 7 */ {0xC2, 0, 8}, /* F8 page 8 */ {0xC3, 0, 9}, /* F9 page 9 */ {0xC4, 0, 10}, /* F10 page 10 */ {0xC9, -1,0}, /* PGUP page-- */ {0xD1, 1,0}, /* PGDN page++ */ {0,0,1} }; cmd_help(ptr) char * ptr; { int helpkey = 1; getnum(&ptr, &helpkey); return help_key(helpkey); } help_key(helpkey) int helpkey; { static int lastpage = 0; int i; for(i=0; keys[i].key; i++) if( keys[i].key == helpkey || i == helpkey ) break; if( keys[i].key == 0 ) { printf("Unbound key, press F1 for general help\n"); return -1; } if( keys[i].rel ) lastpage += keys[i].rel; else lastpage = keys[i].abs; if( lastpage < 0 ) { lastpage=0; return 0; } return display_help(lastpage); } display_help(page) int page; { char buffer[1024]; long length= -1; int left = 0; int ch,lastch = '\n'; int flg = 0; if( open_file("help.txt") < 0 ) { if( page == 1 ) printf("Help file 'help.txt' is not available, sorry.\n"); return -1; } for(length = file_length(); length>0; length--) { if( left==0 ) { if( read_block(buffer) < 0 ) break; left = 1024; } ch = buffer[1024-left]; left--; if( ch == '%' && lastch == '\n' ) { flg = 1; page--; } if( page < 0 ) break; if( page == 0 && flg == 0 ) putchar(ch); if( ch == '\n' ) flg = 0; lastch = ch; } return 0; } #endif dev86-0.16.21/bootblocks/i86_funcs.c000066400000000000000000000101251231050321700167170ustar00rootroot00000000000000 #include "monitor.h" #ifndef NOMONITOR int x86 = 3; /* CPU major number */ char *x86_name = ""; /* and it's name */ int x86_emu = 0; /* Is this a PC emulator ? */ int x86_fpu = 0; #endif int x86_test = 0; /* In test mode */ unsigned boot_mem_top = 0x2000; /* Default 128k, the minimum */ long main_mem_top = 0; /* K of extended memory */ void cpu_check() { #ifndef NOMONITOR static char *name_808x[] = { "8088", "8086", "80C88", "80C86", "NEC V20", "NEC V30", "808x Clone" }; static char *name_8018x[] = { "80188", "80186", "8018x Clone" }; static char cpubuf[] = "80x86+"; int c, major; c = cputype(0); x86_fpu = (c < 0); major = ((c >> 8) & 0x1F); c &= 0xFF; x86 = (major&0xF); if (major == 0) { if (c > 6) c = 6; x86_name = name_808x[c]; } else if (major == 1) { if (c > 3) c = 3; x86_name = name_8018x[c]; } else { cpubuf[2] = (major&0xF)+'0'; cpubuf[5] = (major > 15 ? '+' : '\0'); x86_name = cpubuf; if (c & 0x01) x86_emu = 1; /* Already in protected mode !!! */ } x86_test = x86_emu; if (x86<3) x86_test = 1; #endif #ifdef __STANDALONE__ if (__argr.x.cflag) x86_test = 1; #else x86_test = 1; #endif } void mem_check() { if (x86_test) { main_mem_top = 0; return; } #asm int 0x12 ! Amount of boot memory mov cl,#6 sal ax,cl ! In segments mov [_boot_mem_top],ax mov ah,#0x88 ! Next check for extended int 0x15 jnc got_ext ! Error! is_xt: xor ax,ax got_ext: mov word ptr [_main_mem_top+2],#0 mov [_main_mem_top],ax #endasm /* Try int $15 EAX=$E820 */ { struct e820_dat { unsigned long base_lo, base_hi; unsigned long len_lo, len_hi; long addr_type; } e820_item; long epoll = 0; do { e820_item.addr_type = 0; #asm mov eax,#$E820 mov ebx,.mem_check.epoll[bp] mov ecx,#20 mov edx,#$534D4150 push ds pop es lea di,.mem_check.e820_item[bp] int $15 jnc got_e820 xor ebx,ebx got_e820: mov .mem_check.epoll[bp],ebx #endasm if (e820_item.addr_type == 1 && e820_item.base_hi == 0 && e820_item.base_lo == 0x100000L) { /* XXX Later ... */ if (e820_item.len_hi) main_mem_top = 0x40000; else main_mem_top = (e820_item.len_lo >> 10); return; } } while(epoll); } /* Try int $15 EAX=$E801 */ { unsigned int mem_64, mem_16; /* For int $15,AX=$E801 */ #asm mov ax,#$E801 int $15 jc no_e801 mov .mem_check.mem_16[bp],ax mov .mem_check.mem_64[bp],bx #endasm main_mem_top = ((unsigned long)mem_64<<6) + mem_16; #asm no_e801: #endasm } } #define RIGHTS (0x93000000L) static struct { char gdt0[8]; char gdt1[8]; unsigned short src_len; long src_seg; unsigned short spad; unsigned short dst_len; long dst_seg; unsigned short dpad; char gdt4[8]; char gdt5[8]; } GDT = { "","", 0xFFFF, RIGHTS, 0, 0xFFFF, RIGHTS, 0, "" }; mem_write(buffer, baseaddr, sectno, sectcount) void * buffer; long baseaddr; unsigned sectno, sectcount; { if(x86_test) return 0; /* In an EMU we can't write to high mem but we'll pretend we can for debuggering */ baseaddr += ((long)sectno<<9); if( baseaddr < 0xA0000L ) { __movedata(__get_ds(), buffer, (unsigned)(baseaddr>>4), (unsigned)(baseaddr&0xF), sectcount * 512); return 0; } GDT.src_seg = RIGHTS + (unsigned)buffer + ((long)__get_ds()<<4); GDT.dst_seg = RIGHTS + baseaddr; return asm_copy(sectcount << 8); } mem_read(buffer, baseaddr, sectno) void * buffer; long baseaddr; int sectno; { if(x86_test) return 3; baseaddr += ((long)sectno<<9); GDT.dst_seg = RIGHTS + (unsigned)buffer + ((long)__get_ds()<<4); GDT.src_seg = RIGHTS + baseaddr; return asm_copy(256); } static asm_copy(length) { #asm #if !__FIRST_ARG_IN_AX__ mov bx,sp mov ax,[bx+2] #endif push es push si mov cx,ax mov ah,#$87 push ds pop es mov si,#_GDT int $15 jc err xor ax,ax err: mov al,ah xor ah,ah pop si pop es #endasm } dev86-0.16.21/bootblocks/i86_funcs.h000066400000000000000000000007271231050321700167330ustar00rootroot00000000000000/* * These are bios and hardware functions for the 8086 IBM PC */ extern int x86; /* CPU major number (0-3) */ extern char *x86_name; /* and it's name */ extern int x86_emu; /* Is this a PC emulator ? */ extern int x86_fpu; extern int x86_test; /* Running in test mode ? */ extern unsigned boot_mem_top; /* Top of RAM below 1M */ extern long main_mem_top; /* Top of RAM above 1M */ void cpu_check(); void mem_check(); int ext_put(); int ext_get(); dev86-0.16.21/bootblocks/killhd.s000066400000000000000000000021221231050321700164000ustar00rootroot00000000000000! ! This program destroys the MBR and the start of the first partition of ! the hard disk. IT DOES NOT HAVE AN 'ARE YOU SURE?' ! org $7c00 include sysboot.s org dos_sysid .ascii "DEATH" ! System ID org codestart cld xor ax,ax mov es,ax mov ds,ax mov ss,ax mov sp,ax mov di,#$8000 mov cx,#$0800 rep stosw ! Zap a space. mov dx,#$0080 mov cx,#$0001 mov bx,#$8000 mov ax,#$0308 int $13 ! Zap the MBR (and a disk manager?) mov dx,#$0180 mov cx,#$0001 mov bx,#$8000 mov ax,#$0308 int $13 ! Zap the first partition boot and super. !---------------------------------------------------------------- prtmsg: ! SI = pointer to error message mov si,#boot_message nextc: lodsb cmp al,#0 jz eos mov bx,#7 mov ah,#$E ! Can't use $13 cause that's AT+ only! int $10 jmp nextc !---------------------------------------------------------------- eos: ! Wait for a key then reboot reboot: xor ax,ax int $16 jmpi $0,$FFFF ! Wam! Try or die! export boot_message boot_message: .asciz "PANIC! OS Destroyed!\r\n" dev86-0.16.21/bootblocks/lsys.c000066400000000000000000000054661231050321700161210ustar00rootroot00000000000000 #include "msdos.v" #include "msdos16.v" #define DOS_SYSID 0x03 #define DOS_SECT 0x0B #define DOS_CLUST 0x0D #define DOS_RESV 0x0E #define DOS_NFAT 0x10 #define DOS_NROOT 0x11 #define DOS_MAXSECT 0x13 #define DOS_MEDIA 0x15 #define DOS_FATLEN 0x16 #define DOS_SPT 0x18 #define DOS_HEADS 0x1A #define DOS_HIDDEN 0x1C #define DOS4_MAXSECT 0x20 #define DOS4_PHY_DRIVE 0x24 #define DOS4_SERIAL 0x27 #define DOS4_LABEL 0x2B #define DOS4_FATTYPE 0x36 unsigned char buffer[1024]; int drive = 0; main(argc, argv) int argc; char ** argv; { int tries, rv, i; if( argc > 1 ) { static char * s = "Usage: lsys [a:]\n"; if( argc == 2 && argv[1][1] == ':' && argv[1][2] <= ' ' ) { if( argv[1][0] == 'a' || argv[1][0] == 'A' ) drive = 0; else if( argv[1][0] == 'b' || argv[1][0] == 'B' ) drive = 1; else fatal(s); } else fatal(s); } for(tries=0; tries<6; tries++) if( (rv = dos_sect_read(drive, 0, 0, 1, buffer)) == 0 ) break; if( rv == 0 ) for(tries=0; tries<6; tries++) if( (rv = dos_sect_read(drive, 0, 0, 2, buffer+512)) == 0 ) break; if( rv ) fatal("Cannot read bootsector"); if( buffer[DOS_MEDIA] != buffer[512] || buffer[DOS_MEDIA] < 0xF0 || buffer[DOS_NFAT] > 2 || buffer[DOS_SECT+1] != 2 ) fatal("Floppy has invalid format"); if( memcmp(buffer+DOS4_FATTYPE, "FAT16", 5) ) { for(i=0; i #include #include #include #ifndef __MSDOS__ #include #endif #include "sysboot.v" #include "sysboot16.v" #include "noboot.v" #include "msdos.v" #include "msdos16.v" #include "skip.v" #include "killhd.v" #include "tarboot.v" #include "minix.v" #include "minixhd.v" #include "mbr.v" #include "mbr_dm.v" #include "mbr_chs.v" #include "mbr_lin.v" #include "mbr_lba.v" #include "pbr.v" #include "nombr.v" /* Binary bootblocks */ #include "freedos.h" #ifdef USE_WIN95BB #include "win95.h" #endif unsigned char buffer[1024]; #define FS_NONE 0 /* Bootsector is complete */ #define FS_DOS 1 /* Bootsector needs 'normal' DOS FS */ #define FS_ADOS 2 /* Bootsector likes any DOS FS */ #define FS_TAR 3 /* Bootsector needs GNU-tar volume label */ #define FS_STAT 4 /* Any bootsector is checked */ #define FS_ZERO 5 /* Boot sector must be already Zapped */ #define FS_MBR 6 /* Boot sector is an MBR */ #ifndef __MSDOS__ #define X_HAS_2M20 #endif struct bblist { char * name; char * desc; char * data; int size; int name_type; int boot_name; int fstype; int fsmod; } bblocks[] = { /* Default */ { "stat", "Display dosfs superblock", 0, 0, 0, 0, FS_STAT}, { "copy", "Copy boot block to makeboot.sav or named file", 0, 0, 0, 0, FS_STAT}, { "Zap", "Clear boot block to NULs", 0, 1024, 0, 0, FS_NONE}, { "none", "No OS bootblock, just display message", noboot_data, noboot_size, 2, noboot_boot_message-noboot_start, FS_ADOS}, { "skip", "Bypasses floppy boot with message", skip_data, skip_size, 2, skip_mesg-skip_start, FS_ADOS}, #if __STDC__ { "mbr", "Master boot record for HD" #if defined(mbr_Banner) || mbr_diskman || mbr_linear || mbr_mbrkey || mbr_preboot || mbr_direct || mbr_pbr ", Options:" #ifdef mbr_Banner " Banner" #endif #if mbr_diskman " DiskMan" #endif #if mbr_linear " LBA" #if !mbr_useCHS "-Only" #endif #endif #if mbr_useCHS && mbr_linCHS " linCHS" #endif #if mbr_mbrkey " BootKeys" #endif #if mbr_preboot " PreBoot" #endif #if mbr_direct " Direct" #endif #if mbr_pbr " PBR" #endif #endif , mbr_data,mbr_size, #ifdef mbr_Banner 2, mbr_Banner-mbr_start, FS_MBR}, #else 0, 0, FS_MBR}, #endif #else { "mbr", "Master boot record for HD", mbr_data,mbr_size, 0, 0, FS_MBR}, #endif { "pbr", "LBA-Only Partition boot record", pbr_data,pbr_size, 0, 0, FS_ADOS}, { "mbrchs","MBR using CHS addressing and BIOS", mbr_chs_data,mbr_chs_size, 0, 0, FS_MBR}, { "mbrlin","MBR using Linear addressing and CHS BIOS", mbr_lin_data,mbr_lin_size, 0, 0, FS_MBR}, { "mbrlba","MBR using Linear addressing and LBA BIOS", mbr_lba_data,mbr_lba_size, 0, 0, FS_MBR}, { "nombr", "Boot failure message for MBR", nombr_data,nombr_size, 2, nombr_message-nombr_start, FS_MBR}, #ifdef mbr_dm_size { "mbrdm", "DM Master boot record for HD", mbr_dm_data,mbr_dm_size, 0, 0, FS_MBR}, #endif { "minix","Minix floppy FS booter", minix_data, minix_size, 2, minix_bootfile-minix_start, FS_ZERO}, { "hdmin","Minix Hard disk FS booter", minixhd_data, minixhd_size, 2, minixhd_bootfile-minixhd_start, FS_ZERO}, { "tar", "Bootable GNU tar volume label", tarboot_data, tarboot_size, 0, 0, FS_TAR}, { "dos12","Boot file BOOTFILE.SYS from dos floppy", msdos_data, msdos_size, 1, msdos_boot_name-msdos_start, FS_DOS, 12}, { "dos16","Boot file BOOTFILE.SYS from FAT16 hard disk or floppy", msdos16_data, msdos16_size, 1, msdos16_boot_name-msdos16_start, FS_DOS, 16}, { "fd32l","Freedos FAT32 LBA Bootblock", freedos_fat32lba, 512, 0, 0, FS_DOS, 32}, { "fd32c","Freedos FAT32 CHS Bootblock", freedos_fat32chs, 512, 0, 0, FS_DOS, 32}, #ifdef USE_WIN95BB { "win95","The Windows 95 bootblock, (C) Microsoft.", win95_bootblock, 512, 0, 0, FS_DOS, 12}, #endif { "killhd", "Deletes MBR from hard disk when booted", killhd_data, killhd_size, 2, killhd_boot_message-killhd_start, FS_ADOS}, 0 }; char * progname = ""; int disktype = 0; FILE * diskfd; int disk_sect = 63; /* These are initialised to the maximums */ int disk_head = 256; /* Set to the correct values when an MSDOS disk is */ int disk_trck = 256; /* successfully identified */ int force = 0; int write_zero = 1; /* Write sector 0 */ int write_one = 0; /* Write sector 1 */ int copy_zero = 0; /* Copy of sector zero */ char * boot_id = 0; /* Overrides for bpb in dos bootblocks. */ unsigned char bpb_buffer[100]; unsigned char bpb_flags[100]; int has_bpb_overrides = 0; main(argc, argv) int argc; char ** argv; { FILE * fd; struct bblist *ptr = bblocks; int i; int ar, opton=1; char *p; char * bbname = 0; char * devname = 0; progname = argv[0]; /* Traditional option processing. */ for(ar=1; ar=argc) Usage(); ap = argv[++ar]; } switch(ch) { case 'S': set_superfield(ap); break; default: Usage(); } break; } else { if (bbname) Usage(); bbname = devname; devname = argv[ar]; } if( devname == 0 ) Usage(); /* First bootblock is default */ if( bbname == 0 ) bbname = bblocks->name; boot_id = strchr(bbname, '='); if( boot_id ) *boot_id++ = '\0'; if( (i=strlen(bbname)) < 2 ) Usage(); for(ptr = bblocks; ptr->name; ptr++) if( strncmp(bbname, ptr->name, i) == 0 ) break; if( ptr->name == 0 ) Usage(); if (has_bpb_overrides && ptr != bblocks && ptr->fstype != FS_DOS && ptr->fstype != FS_ADOS) Usage(); open_disk(devname); if( read_sector(0, buffer) != 0 ) exit(1); read_sector(1, buffer+512); write_zero = (ptr->size >= 512); write_one = (ptr->size >= 1024); switch(ptr->fstype) { case FS_NONE: /* override */ case FS_STAT: case FS_ADOS: if ( has_bpb_overrides ) check_msdos(); break; case FS_DOS: check_msdos(); if(ptr->fsmod) check_simpledos(ptr->fsmod); break; case FS_TAR: check_tar(); break; case FS_ZERO: check_zapped(); break; case FS_MBR: check_mbr(); break; default: fprintf(stderr, "Program error, unknown filesystem requirement\n"); exit(2); } switch(ptr->fstype) { case FS_DOS: case FS_ADOS: if (ptr->fsmod == 12 || ptr->fsmod == 16) { for(i=0; idata[i]; for(i=sysboot16_codestart; i<512; i++) buffer[i] = ptr->data[i]; } else { for(i=0; idata[i]; for(i=sysboot_codestart; i<512; i++) buffer[i] = ptr->data[i]; } break; case FS_TAR: copy_tarblock(); break; case FS_MBR: copy_mbr(ptr->data, ptr->size); break; case FS_ZERO: case FS_NONE: if( ptr->data ) memcpy(buffer, ptr->data, ptr->size); else { memset(buffer, '\0', 1024); write_one = 1; } break; } if ( has_bpb_overrides ) { copy_superfields(buffer); write_zero = 1; } switch(ptr->fstype) { case FS_STAT: if( strcmp(ptr->name, "copy") == 0 ) save_super(buffer); else print_super(buffer); if ( !has_bpb_overrides ) { close_disk(); exit(0); } break; } if( boot_id ) switch(ptr->name_type) { case 1: set_dosname(ptr->boot_name); break; case 2: set_asciz(ptr->boot_name); break; default: fprintf(stderr, "Cannot specify boot name for this block\n"); exit(1); } if( write_zero ) { write_sector(0, buffer); if (copy_zero) write_sector(copy_zero, buffer); /* FAT32 backup */ } if( write_one ) write_sector(1, buffer+512); close_disk(); exit(0); } Usage() { struct bblist *ptr = bblocks; if( progname == 0 || *progname == 0 || progname[1] == 0 ) progname = "makeboot"; #ifdef __MSDOS__ fprintf(stderr, "Usage: %s [-f] [-S var=val] bootblock[=bootname] a:\n\n", progname); fprintf(stderr, "The 'a:' can be any drive or file or @: for the MBR.\n"); #else fprintf(stderr, "Usage: %s [-f] [-S var=val] bootblock[=bootname] /dev/fd0\n\n", progname); #endif fprintf(stderr, "-S sets BPB fields in the msdos filesystem superblock.\n"); fprintf(stderr, "The bootname is a filename or message to use with the block,\n"); fprintf(stderr, "the blocks are:\n"); for(;ptr->name; ptr++) fprintf(stderr, "\t%s\t%s\n", ptr->name, ptr->desc); exit(1); } /**************************************************************************/ int open_disk(diskname) char * diskname; { #ifdef __MSDOS__ /* Freedos fix */ if( diskname[2] == '\r' ) diskname[2] = 0; if( diskname[2] == 0 && diskname[1] == ':' ) { if (isalpha(diskname[0])) { disktype = toupper(diskname[0])-'A'+1; return 0; } if (diskname[0] =='@') { disktype = 129; return 0; } } #endif disktype = 0; diskfd = fopen(diskname, "r+b"); if( diskfd == 0 ) diskfd = fopen(diskname, "rb"); if( diskfd == 0 && force ) diskfd = fopen(diskname, "w+b"); if( diskfd == 0 ) { fprintf(stderr, "Cannot open '%s'\n", diskname); exit(1); } return 0; } close_disk() { if( diskfd && disktype == 0 ) fclose(diskfd); diskfd = 0; disktype = 0; } int write_sector(sectno, loadaddr) int sectno; char * loadaddr; { #ifdef __MSDOS__ if( disktype == 1 || disktype == 2 || disktype == 129 ) { int tries, rv; int s,h,c; s = sectno%disk_sect + 1; h = sectno/disk_sect%disk_head; c = sectno/disk_sect/disk_head; for(tries=0; tries<6; tries++) if( (rv = bios_sect_write(disktype-1, c, h, s, loadaddr)) == 0 ) break; if( rv ) { if (rv/256 == 3) fprintf(stderr, "Write protect error writing sector %d\n", sectno); else fprintf(stderr, "Error writing sector %d, (%d)\n", sectno, rv/256); return -1; } return 0; } if( disktype ) { int tries, rv; for(tries=0; tries<6; tries++) if( (rv = dos_sect_write(disktype-1, sectno, loadaddr)) == 0 ) break; if( rv ) { fprintf(stderr, "Error writing sector %d, (0x%04d)\n", sectno, rv); memset(loadaddr, '\0', 512); return -1; } return 0; } #endif if( disktype ) { fprintf(stderr, "Cannot write sector %d\n", sectno); return -1; } fseek(diskfd, (long)sectno*512, 0); if( fwrite(loadaddr, 512, 1, diskfd) != 1 ) { fprintf(stderr, "Cannot write sector %d\n", sectno); return -1; } printf("Wrote sector %d\n", sectno); return 0; } int read_sector(sectno, loadaddr) int sectno; char * loadaddr; { int cc; #ifdef __MSDOS__ if( disktype == 1 || disktype == 2 || disktype == 129 ) { int tries, rv; int s,h,c; s = sectno%disk_sect + 1; h = sectno/disk_sect%disk_head; c = sectno/disk_sect/disk_head; for(tries=0; tries<6; tries++) if( (rv = bios_sect_read(disktype-1, c, h, s, loadaddr)) == 0 ) break; if( rv ) { fprintf(stderr, "Error reading sector %d, (%d)\n", sectno, rv/256); memset(loadaddr, '\0', 512); return -1; } return 0; } if( disktype ) { int tries, rv; for(tries=0; tries<6; tries++) if( (rv = dos_sect_read(disktype-1, sectno, loadaddr)) == 0 ) break; if( rv ) { fprintf(stderr, "Error reading sector %d, (0x%04d)\n", sectno, rv); memset(loadaddr, '\0', 512); return -1; } return 0; } #endif if( disktype ) { fprintf(stderr, "Cannot read sector %d\n", sectno); return -1; } fseek(diskfd, (long)sectno*512, 0); if( (cc=fread(loadaddr, 1, 512, diskfd)) != 512 ) { fprintf(stderr, "Cannot read sector %d, clearing\n", sectno); if(cc<0) cc=0; memset(loadaddr+cc, '\0', 512-cc); } return 0; } /**************************************************************************/ #ifdef __MSDOS__ bios_sect_read(drv, track, head, sector, loadaddr) { #asm push bp mov bp,sp push ds pop es mov dh,[bp+2+_bios_sect_read.head] mov dl,[bp+2+_bios_sect_read.drv] mov cl,[bp+2+_bios_sect_read.sector] mov ch,[bp+2+_bios_sect_read.track] mov bx,[bp+2+_bios_sect_read.loadaddr] mov ax,#$0201 int $13 jc bios_read_err mov ax,#0 bios_read_err: pop bp #endasm } bios_sect_write(drv, track, head, sector, loadaddr) { #asm push bp mov bp,sp push ds pop es mov dh,[bp+2+_bios_sect_write.head] mov dl,[bp+2+_bios_sect_write.drv] mov cl,[bp+2+_bios_sect_write.sector] mov ch,[bp+2+_bios_sect_write.track] mov bx,[bp+2+_bios_sect_write.loadaddr] mov ax,#$0301 int $13 jc bios_write_err mov ax,#0 bios_write_err: pop bp #endasm } #endif /**************************************************************************/ #ifdef __MSDOS__ /* All this mess just to read one sector!! */ struct disk_packet { long sector; int count; long addr; } disk_packet; dos_sect_read(drv, sector, loadaddr) { #asm push bp mov bp,sp mov al,[bp+2+_dos_sect_read.drv] mov cx,#1 mov dx,[bp+2+_dos_sect_read.sector] mov bx,[bp+2+_dos_sect_read.loadaddr] int $25 pop bx jnc dos_read_ok mov bp,sp ! Fill the disk packet mov ax,[bp+2+_dos_sect_read.sector] mov [_disk_packet],ax xor ax,ax mov [_disk_packet+2],ax inc ax mov [_disk_packet+4],ax mov ax,[bp+2+_dos_sect_read.loadaddr] mov [_disk_packet+6],ax mov ax,ds mov [_disk_packet+8],ax mov dl,[bp+2+_dos_sect_read.drv] inc dl mov bx,#_disk_packet mov cx,#0xFFFF mov si,#0 mov ax,#0x7305 int $21 jc dos_read_err dos_read_ok: mov ax,#0 dos_read_err: pop bp #endasm } dos_sect_write(drv, sector, loadaddr) { #asm push bp mov bp,sp mov al,[bp+2+_dos_sect_write.drv] mov cx,#1 mov dx,[bp+2+_dos_sect_write.sector] mov bx,[bp+2+_dos_sect_write.loadaddr] int $26 pop bx jnc dos_write_ok mov bp,sp ! Fill the disk packet mov ax,[bp+2+_dos_sect_write.sector] mov [_disk_packet],ax xor ax,ax mov [_disk_packet+2],ax inc ax mov [_disk_packet+4],ax mov ax,[bp+2+_dos_sect_write.loadaddr] mov [_disk_packet+6],ax mov ax,ds mov [_disk_packet+8],ax mov dl,[bp+2+_dos_sect_write.drv] inc dl mov bx,#_disk_packet mov cx,#0xFFFF mov si,#1 mov ax,#0x7305 int $21 jc dos_write_err dos_write_ok: mov ax,#0 dos_write_err: pop bp #endasm } #endif /**************************************************************************/ check_zapped() { int i; for(i=0; i<512; i++) if( buffer[i] ) break; if( i != 512 ) { fprintf(stderr, "Boot block isn't empty, zap it first\n"); if(!force) exit(1); } } /**************************************************************************/ struct tar_head { char name[100]; char mode[8]; char uid[8]; char gid[8]; char size[12]; char mtime[12]; char chksum[8]; char linkflag; char linkname[100]; char magic[8]; char uname[32]; char gname[32]; char devmajor[8]; char devminor[8]; char padding[167]; } ; #define buff_tar (*(struct tar_head*) buffer) #define boot_tar (*(struct tar_head*) tarboot_data) unsigned int oct(s) char *s; { unsigned int val = 0; int i; for(i=0; i<8; i++) if( s[i] >= '0' && s[i] <= '7' ) val = (val<<3) + s[i] - '0'; return val; } check_tar() { char vbuf[100]; unsigned char *p; unsigned int csum = 0; long osum = -1; for(p=buffer; p= 0; i++) { if( i>= DOS4_MAXSECT && (fat_len==0) != (i>=DOS7_MAXSECT) ) continue; if( dosflds[i].length <= 4 ) { long v = 0; int j; for(j=dosflds[i].length-1; j>=0; j--) { v = v*256 + (0xFF&( bootsect[dosflds[i].offset+j] )); } if( i==DOS_FATLEN ) fat_len = v; if (v==0 && (i==DOS_FATLEN || i==DOS_MAXSECT || i==DOS4_MAXSECT || i==DOS_NROOT)) continue; if ( i==DOS7_SERIAL ) printf("%-35s%08x\n", fieldnames[i], v); else printf("%-35s%ld\n", fieldnames[i], v); if (i==DOS_SECT && v!=512 && v!=1024 && v!=2048) break; } else { int ch, j; printf("%-35s", fieldnames[i]); for(j=0; j '~' ) putchar('.'); else putchar(ch); } putchar('\n'); } } } decode_super(bootsect) char * bootsect; { int i; for(i=0; dosflds[i].offset >= 0; i++) { if( i>= DOS4_MAXSECT && (dosflds[DOS_FATLEN].value==0) != (i>=DOS7_MAXSECT) ) { dosflds[i].lvalue = dosflds[i].value = 0; continue; } if( dosflds[i].length <= 4 ) { long v = 0; int j; for(j=dosflds[i].length-1; j>=0; j--) { v = v*256 + (0xFF&( bootsect[dosflds[i].offset+j] )); } dosflds[i].value = v; dosflds[i].lvalue = v; } else dosflds[i].lvalue = dosflds[i].value = 0; } if (dosflds[DOS_FATLEN].value == 0) copy_zero = dosflds[DOS7_BOOT2].value; else copy_zero = 0; } save_super(bootsect) char * bootsect; { FILE * fd; char * fname = "makeboot.sav"; if( boot_id ) fname = boot_id; printf("Copying boot block to '%s'\n", fname); fd = fopen(fname, "wb"); fwrite(bootsect, 1024, 1, fd); fclose(fd); } set_superfield(setstr) char * setstr; { int i, l; char * av; has_bpb_overrides = 1; av = strchr(setstr, '='); if (av == 0) Usage(); l = av++ - setstr; for(i=0; dosflds[i].offset >= 0; i++) { if ( dosflds[i].label && l == strlen(dosflds[i].label) && strncmp(dosflds[i].label, setstr, l) == 0) dosflds[i].new_value = av; } } copy_superfields(bootsect) char * bootsect; { int i, j; for(i=0; dosflds[i].offset >= 0; i++) { if (dosflds[i].new_value == 0) continue; if( i>= DOS4_MAXSECT && (dosflds[DOS_FATLEN].value==0) != (i>=DOS7_MAXSECT) ) { continue; } if( dosflds[i].length <= 4 ) { long v = 0; v = strtol(dosflds[i].new_value, 0, 0); for(j=0; j>= 8; } } else { char * p = dosflds[i].new_value; for(j=0; j 0 && disk_head > 0 ) disk_trck = dosflds[DOS_MAXSECT].value/disk_head/disk_sect; return; } if(!force) exit(2); } check_simpledos(bb_fatbits) int bb_fatbits; { long numclust = 0xFFFF; char * err = 0; int fatbits = 0; /* Work out how many real clusters there are */ if( dosflds[DOS_MAXSECT].value + 2 > 2 ) numclust = ( dosflds[DOS_MAXSECT].value - dosflds[DOS_RESV].value - dosflds[DOS_NFAT].value * dosflds[DOS_FATLEN].value - ((dosflds[DOS_NROOT].value+15)/16) ) / dosflds[DOS_CLUST].value + 2; else if( dosflds[DOS4_MAXSECT].value > 0 ) numclust = ( dosflds[DOS4_MAXSECT].lvalue - dosflds[DOS_RESV].value - dosflds[DOS_NFAT].value * dosflds[DOS_FATLEN].value - ((dosflds[DOS_NROOT].value+15)/16) ) / dosflds[DOS_CLUST].value + 2; else numclust = ( dosflds[DOS7_MAXSECT].lvalue - dosflds[DOS_RESV].value - dosflds[DOS_NFAT].value * dosflds[DOS7_FAT32LEN].value ) / dosflds[DOS_CLUST].value; if( memcmp(buffer+dosflds[DOS4_FATTYPE].offset, "FAT12", 5) == 0 ) fatbits=12; else if( memcmp(buffer+dosflds[DOS4_FATTYPE].offset, "FAT16", 5) == 0 ) fatbits=16; else if(dosflds[DOS_FATLEN].value == 0) fatbits=32; else fatbits=12+4*(numclust > 0xFF0) + 16*(numclust > 0xFFF0L); if( dosflds[DOS_NFAT].value > 2 ) err = "Too many fat copies on disk"; else if( dosflds[DOS_SECT].value != 512 ) err = "Drive sector size isn't 512 bytes sorry no-go."; else if( fatbits == 16 && numclust < 0xFF0 ) err = "Weirdness, FAT16 but less than $FF0 clusters"; else if( fatbits != bb_fatbits ) err = "Filesystem has the wrong fat type for this bootblock."; if( !err && (bb_fatbits == 12 || bb_fatbits == 16)) { if( dosflds[DOS_NROOT].value < 15 ) err = "Root directory has unreasonable size."; else if( numclust * dosflds[DOS_CLUST].lvalue / dosflds[DOS_SPT].value > 65535 ) err = "Boot sector untested with more than 65535 tracks"; } if( !err && bb_fatbits == 12 ) { if( dosflds[DOS4_PHY_DRIVE].value != 0 ) err = "This boot sector is only for floppies"; else if( (0x7C00-msdos_start-512)/512 < dosflds[DOS_FATLEN].value ) err = "The FAT is too large to load in the available space."; else if( dosflds[DOS_RESV].value + dosflds[DOS_FATLEN].value > dosflds[DOS_SPT].value ) err = "The bootblock needs all of fat1 on the first track."; else if( msdos_heads == 2 && dosflds[DOS_HEADS].value != 2 ) err = "Drive doesn't have two heads, this is required."; else if( dosflds[DOS_HIDDEN].lvalue != 0 ) err = "MSDOS floppies shouldn't have hidden sectors."; } if( err ) { fprintf(stderr, "ERROR: %s\n\n", err); print_super(buffer); if(!force) exit(2); } } set_dosname(boot_name) int boot_name; { char dos_name[20]; int i,j; strcpy(dos_name, " "); for(i=0; boot_id[i] && boot_id[i] != '.' && i<16; i++) dos_name[i] = toupper(boot_id[i]); if( boot_id[i] == '.' ) { for(j=8,i++; boot_id[i] && boot_id[i] != '.' && j<16; i++,j++) dos_name[j] = toupper(boot_id[i]); } printf("Bootfile set to '%11.11s'\n", dos_name); memcpy(buffer+boot_name, dos_name, 11); } set_asciz(boot_name) int boot_name; { int i, j; for(i=boot_name; buffer[i]; i++) ; for( ; !buffer[i]; i++) ; i = i - boot_name -1; if( strlen(boot_id) > i ) { fprintf(stderr, "Name '%s' is too long for bootblock\n", boot_name); exit(1); } else { for(i=0,j=boot_name; boot_id[i]; i++) { if( boot_id[i] == '\\' && boot_id[i+1] ) { i++; switch(boot_id[i]) { case 'n': buffer[j++] = '\n'; break; case 'r': buffer[j++] = '\r'; break; case 'b': buffer[j++] = '\b'; break; case 't': buffer[j++] = '\t'; break; case 'a': buffer[j++] = '\007'; break; case 'e': buffer[j++] = '\033'; break; default: buffer[j++] = boot_id[i]; break; } } #ifdef __MSDOS__ else if(boot_id[i] == '_') buffer[j++] = ' '; else if(boot_id[i] == '^') { buffer[j++] = '\r'; buffer[j++] = '\n'; } #endif else buffer[j++] = boot_id[i]; } buffer[j] = 0; } } check_mbr() { int i = 0; if( buffer[510] == 0x55 && buffer[511] == 0xAA ) i = 512; for(; i<512; i++) if( buffer[i] ) break; /* Check for Disk Manager partition tables */ if( buffer[252] == 0x55 && buffer[253] == 0xAA ) { if( (unsigned char)mbr_data[252] != 0x55 || (unsigned char)mbr_data[253] != 0xAA ) i = 252; } if( i != 512 ) { if(force) fprintf(stderr, "That doesn't look like a compatible MBR but ...\n"); else { fprintf(stderr, "That doesn't look like a compatible MBR\n"); exit(1); } } } copy_mbr(boot_data, boot_size) char * boot_data; int boot_size; { int boot_to_copy = 446; if (boot_size < boot_to_copy) boot_to_copy = boot_size; if ( boot_to_copy > 254 && buffer[252] == 0xAA && buffer[253] == 0x55 && (unsigned char)boot_data[252] == 0xAA && boot_data[253] == 0x55 ) boot_to_copy = 254; memcpy(buffer, boot_data, boot_to_copy); buffer[510] = 0x55; buffer[511] = 0xAA; write_zero = 1; } dev86-0.16.21/bootblocks/mbr.s000066400000000000000000000263771231050321700157330ustar00rootroot00000000000000! ! This is a 'Master Boot Record' following the MSDOS 'standards'. ! This BB successfully boots MSDOS, Windows or Linux in CHS or Linear. ! ! Copyright GPL2, Robert de Bath, 1996-2008. ! ! NB: This needs as86 0.16.0 or later ! ! Lowest available is $0500, MSDOS appears to use $0600 ... I wonder why? ORGADDR=$0600 BOOTADDR=0x7c00 pbr=0 ! Make this a partition boot record for ldboot. direct=1 ! Direct boot from MBR to any sector. copyright=0 ! Add in the copyright message; if room. mbrkey=0 ! Option to choose the boot record based on keystroke (107) message=1 ! Display boot message (6+message space) markptab=1 ! Put an end marker just below the partition table. use512=0 ! Put the end marker at byte 510..512 linear=1 ! Use the LBA BIOS addresses. useCHS=1 ! Disable CHS if you need space. linCHS=1 ! Calculate CHS from linear mbr values. (41 bytes) preboot=0 ! Include the pre-boot loader. (40 bytes) if linCHS ! Allow immediate shifts etc. use16 186 endif mbr_extras=ORGADDR+0x1B6 partition_start=ORGADDR+0x1BE partition_size=0x10 partition_end=ORGADDR+0x1FE if pbr|direct table_start=ORGADDR+0x1A2 ! Space for special table. else table_start=mbr_extras endif export pbr export direct export linear export useCHS export linCHS export mbrkey export end_of_code if preboot export preboot endif org ORGADDR if pbr ! Skip a potential MSDOS BPB. boot_start: j code nop ! DOS appears to _require_ this to identify an MSDOS disk!! .blkb boot_start+3-* .ascii "LINUX" ! System ID .byte 0,0,0 .blkb boot_start+0x5A-* code: endif cli ! Assume _nothing_! (needed for NT 4) cld mov bx,#BOOTADDR ! Pointer to start of BB. xor ax,ax ! Segs all to zero mov ss,ax mov sp,bx ! SP Just below BB if pbr push [si+10] ! Save the inbound disk offset and drive push [si+8] ! As if called pbr(drive, offset) push dx endif mov ds,ax mov es,ax mov cx,#$100 ! Move 256 words mov si,bx ! From default BB mov di,#ORGADDR ! To the correct address. rep movsw jmpi cont,#0 ! Set CS:IP correct. cont: sti ! Let the interrupts back in. if pbr pop [boot_drive] pop [boot_part] pop [boot_part+2] endif !-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ! Next check for a pre-boot message, load or keypress if message call disp_message endif if preboot call preboot_code endif if mbrkey call key_wait endif !-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ! if (linear|useCHS) if pbr=0 ! Now check the partition table, must use SI as pointer cause that's what the ! partition boot blocks expect. ! Normal active partition check, (Order: 1,2,3,4) mov si,#partition_start check_active: cmp byte [si],#$80 ! Flag for activated partition jz found_active if direct=0 try_next_part: ! Only if no direct. endif add si,#partition_size cmp si,#partition_end jnz check_active endif if pbr|direct mov si,#table_start cmp byte [si],#0 jnz found_active try_next_part: endif jmp no_partition !-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ! Active partition found, boot it. found_active: mov di,#6 ! Max retries, int doc says 3 ... double it movb [$7DFE],#0 ! Clear magic for dosemu retry: !-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ! If the BIOS has LBA extensions use them. ! If we have no CHS don't check for LBA just use it. if linear mov dx,[si] ! dh = Drive head, dl = $80 ie HD drive 0 if useCHS mov ah,#$41 mov bx,#$55AA if mbrkey test dl,#$80 jz do_CHS endif int $13 jc do_CHS ! Unknown call cmp bx,#$AA55 jnz do_CHS ! Wrong call test cl,#1 jz do_CHS ! EDD basic functions OK. endif push si ! Save SI on read. if pbr|direct mov ax,[si+8] ! 32bit disk address mov cx,[si+10] cmp si,#table_start jnz normal_part add ax,[boot_offset] adc cx,[boot_offset+2] normal_part: endif xor bx,bx push bx ! 64bit disk address push bx if pbr|direct push cx ! 32bit disk address push ax else push [si+10] ! 32bit disk address push [si+8] endif push bx ! Load segment push #BOOTADDR ! Load address push #1 ! Number of sectors push #16 ! Packet size mov si,sp mov ah,#$42 int $13 lea sp,[si+16] pop si jc retry_error j sector_loaded endif !linear if useCHS do_CHS: if linCHS call calc_chs else mov dx,[si] ! dh = Drive head, dl = $80 ie HD drive 0 mov cx,[si+2] ! cx = Sector & head encoded for int $13 endif mov bx,#BOOTADDR ! Pointer to start of BB. mov ax,#$0201 ! Read 1 sector int $13 ! Disk read. jnc sector_loaded endif ! Error, reset and retry retry_error: xor ax,ax int $13 ! Disk reset dec di jnz retry ! Try again mov si,#disk_read_error jmp no_boot ! Sorry it ain't gonna work. sector_loaded: mov di,#$7DFE ! End of sector loaded cmp [di],#$AA55 ! Check for magic jnz try_next_part ! No? Try next partition. mov bp,si ! LILO says some BBs use bp rather than si jmpi #BOOTADDR,#0 ! Go! no_partition: mov si,#no_bootpart no_boot: ! SI now has pointer to error message call puts endif !(linear|useCHS) ! Fatal errors ........... if mbrkey mov si,#crlf call puts j key_pause else mov si,#press_key call puts keyboot: ! Wait for a key then reboot xor ax,ax int $16 jmpi $0,$FFFF ! Reboot. endif if useCHS if linCHS calc_chs: ! From lilo. mov ah,#8 int $13 ! Drive Geom shr dx,#8 xchg ax,dx inc ax ! AX = No. Heads dec cx ! Davide BIOS bug: CX=0 => Sectors=64 and cx,#$3f ! CX = Sectors inc cx mul cx xchg ax,bx ! BX = Cylinder size mov ax,[si+8] ! Linear partition address. mov dx,[si+10] if pbr|direct cmp si,#table_start jnz std_part add ax,[boot_offset] adc dx,[boot_offset+2] std_part: endif div bx ! AX = Cyl, DX = head & sect shl ah,#6 xchg ah,al xchg dx,ax div cl ! AH = sect-1, AL = Head or dl,ah ! merge for CX arg. mov cx,dx inc cx ! Adjust sector No. mov dx,[si] ! dh = Orig Drive head, dl = $80 ie HD drive 0 mov dh,al ! Head No. ; CX & DX ready for int $13 ret endif endif !-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ! if message disp_message: mov si,#Banner endif ! Display message uses SI,AX,BX puts: ! This is smaller than using $13 lodsb cmp al,#0 jz .EOS mov bx,#7 mov ah,#$E int $10 jmp puts .EOS: ret !-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ! if mbrkey=0 press_key: .asciz "\r\nPress return:" endif !-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ! if (linear|useCHS) if mbrkey disk_read_error: no_bootpart: .asciz "Boot error" else disk_read_error: .asciz "Disk read error" no_bootpart: .asciz "No bootable partition" endif endif !(linear|useCHS) !-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ! Choose the partition based on a pressed key ... if mbrkey key_wait: mov si,#Prompt call puts call wait_key jnz key_pause mov si,#Unprompt ! Nothing has happened, return. call puts ret key_pause: mov si,#Pause call puts key_tick: call wait_key jz key_tick j Got_key wait_key: mov di,#19 ! Wait for 18-19 ticks next_loop: mov ah,#1 int $16 jnz done_wait mov ah,#0 int $1A ! Get current tick cmp dx,si ! If changed DEC our counter. jz next_loop mov si,dx dec di jnz next_loop done_wait: ret Got_key: mov ah,#0 ! Clean the kbd buffer. int $16 cmp al,#0x20 jz key_tick push ax mov Showkey,al mov si,#Showkey call puts pop ax ! ... Now we use our key ... ! 0 => Floppy ! 1 .. 4 => Hard disk partition. if useCHS cmp al,#'F jz is_floppy cmp al,#'f jz is_floppy endif cmp al,#'1 jb key_pause cmp al,#'4 ja key_pause and ax,#0x7 dec ax mov cl,#4 shl ax,cl add ax,#partition_start mov si,ax ! Set active flag for disk interrupt. or byte [si],#$80 br found_active if useCHS is_floppy: mov si,#floppy_part br found_active endif Prompt: .asciz "\rMBR: " Unprompt: .asciz "\r \r" Pause: if useCHS .asciz "\rMBR F1234> " else .asciz "\rMBR 1234> " endif Showkey: .ascii " " crlf: .asciz "\r\n" floppy_part: .word 0,1 endif !-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ! This is the pre-boot loader it uses CHS but that's ok for track 0 ! if preboot public preboot_code preboot_code: mov si,#pre_boot_table lodsw mov di,ax ! First word is execute address more_boot: lodsw test ah,ah jz load_done mov bx,ax ! word 1 address lodsw mov cx,ax ! word 2 CX, cylinder/sector lodsw mov dx,ax ! word 3 DX, drive, head lodsw ! word 4 AX, $02, sector count int $13 jnc more_boot ! This doesn't retry, with a HD it shouldn't be bad. mov si,#disk_read_error br no_boot ! Sorry it ain't gonna work. load_done: call di exec_done: return: ret export pre_boot_table pre_boot_table: ! Example: Do nothing. .word return,0 ! If the message is in use, preallocate some extents if message .blkb 64 endif ! Labels ! .word ! Then repeat .. ! .word , , , ! Or. ! .word ! .byte + ( & $300)>>2), & $FF ! .byte , , , 2 ! Finally ! .word 0 ! Example: Load rest of H0,C0 into mem at BOOTADDR ! .word BOOTADDR ! .word BOOTADDR,$0002,$8000,$0210 ! .word $0000 endif !-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ! end_of_code: !-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ! if message export Banner Banner: if (linear|useCHS) if *table_start fail! Partition table overlaps endif !-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ! And a copyright message if there's room. if copyright if *table_start fail! Partition table overlaps endif !-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ! The diskman magic number and empty DM partitions. if diskman org table_start public diskman_magic diskman_magic: .word 0xAA55 .blkb 12*partition_size-1 endif !-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ! Clear the sector to the bottom of the partition table. if markptab if * #include "minix.h" /* #define DOTS /* define to have dots printed */ /* #define HARDDISK /* Define for hard disk version */ /* #define TRY_FLOPPY /* To do trial reads to find floppy size */ /* #define MIN_SPACE */ #define zone_shift 0 /* for any < 32M (!= 0 not supported yet, if ever) */ #define seg_at(k) ((k)*64) #define seg_of(p) ((unsigned int)p >>4) #define BOOTSEG (0x07c0) #define LOADSEG (0x1000) #define ORGADDR (0x0500) #ifdef HARDDISK #define get_now() #endif #ifdef zone_shift #if zone_shift == 0 #define load_zone load_block #endif #else static short zone_shift; #endif #asm BOOTADDR = 0x7c00 .text ! Apparently on startup the only things we can assume are that we start at ! `start` (ABS addr $07C00) and the boot sector is in the segment. ! So first set CS=DS=ES=SS=0 ! The we move this to $0500 and put the stack at the top of the first 64k. ! The directory 'file' is loaded $1500 and scanned there. ! The final executable will be loaded in the 2nd 64k chunk. ! org ORGADDR ! The lowest available address. start: #ifndef MIN_SPACE include sysboot16.s org start ! The lowest available address, again. j skip_vars org dos_sysid .ascii "MINIXFS BOOT (C) 1990-1999, Robert de Bath" org codestart #endif ! A few variables we need to know the positions of for patching, so export ! them and as86_encaps will make some variables. Put them here at the start ! so they're in the same place for both Floppy and harddisk versions as they ! will be used by helper programs. export inode ! Inode to search inode: _inode: .word 1 ! ROOT_INODE #ifndef MIN_SPACE export dinode ! Inode of directory file was found in. dinode: _dinode: .word 1 ! ROOT_INODE #endif export bootfile ! File to boot, make this whatever you like, bootfile: ! 'boot' is good, 'linux' too. _bootfile: .ascii "boot" .byte 0,0,0,0,0,0,0,0,0,0 skip_vars: #ifdef HARDDISK mov bx,[si+8] ! Fetch the linear address of part from DS:SI mov dh,[si+10] ! DL is drive number #endif xor ax,ax ! All segments are zero, first 64k of mem. mov ds,ax mov es,ax mov ss,ax mov sp,ax #ifndef HARDDISK loopy: mov ax,#$0203 ! Read 3 sectors, code + superblock. mov bx,#start ! Where this _should_ be mov cx,#$0001 ! From sector 1 xor dx,dx ! Of the floppy drive head zero int $13 jc loopy #else mov cx,#$100 ! Move 256 words mov si,#BOOTADDR ! From default BB mov di,#ORGADDR ! To the correct address. rep movsw xchg dl,dh mov [bootpart],bx ! Save the partition sector offset (and drive) mov [bootpart+2],dx ! Read next 2 sectors of hd. xor dx,dx mov cx,#1 mov bx,#ORGADDR+$200 mov al,#2 call load_sect #endif jmpi code,#0 #endasm /* /* */ /****************************************************************************/ /* Section cdef */ /****************************************************************************/ /* The name of the file and inode to start */ extern char bootfile[]; extern inode_nr inode; extern inode_nr dinode; /* For multi-sector reads */ extern sect_nr lastsect; extern sect_nr firstsect; extern unsigned loadaddr; extern unsigned loadcount; /* Keep track of zones to load */ extern zone_nr * next_zone; extern zone_nr * end_zone; extern zone_nr indirect; /* Where to load zones */ extern unsigned ldaddr; /* Directory reading */ extern dir_struct * dirptr; extern unsigned flength; extern unsigned dir_32; #ifndef HARDDISK /* The 'shape' of the floppy - intuit from superblock or try to read max */ extern unsigned n_sectors; #endif extern struct super_block b_super; extern d_inode b_inode[INODES_PER_BLOCK]; extern zone_nr b_zone[NR_INDIRECTS]; extern dir_struct directory[]; /* /* */ /****************************************************************************/ /* Section adef */ /****************************************************************************/ #asm .text #ifdef HARDDISK bootpart: .long 0 #else _loadcount: .word 0 _firstsect: .word 0 _loadaddr: .word 0 _lastsect: .word 0 #endif block start+0x400 _b_super: .blkb 512 #ifndef MIN_SPACE export helper helper: .blkb 1024 export helper_end helper_end: #endif _b_inode: .blkb 1024 _b_zone: .blkb 1024 #ifdef MIN_SPACE temp_space: .blkb 512 #endif probe_buf: _directory: .blkb 32768 endb #endasm /* /* */ /****************************************************************************/ /* Section nogood */ /****************************************************************************/ /* #if defined(HARDDISK) && !defined(SKIPBOOT) */ #ifndef SKIPBOOT static nogood() { #asm mov si,#fail_fs min_nextc: lodsb cmp al,#0 jz min_eos mov bx,#7 mov ah,#$E ! Can't use $13 cause that's AT+ only! int $10 jmp min_nextc min_eos: ! Wait for a key then reboot xor ax,ax int $16 jmpi $0,$FFFF ! Reboot. fail_fs: .byte 13,10 #if defined(HARDDISK) .asciz "Initial boot failed, press return to reboot\r\n" #else .asciz "Boot failed:" #endif #endasm } #else static nogood() { /* This didn't work, chain the boot sector of the HD */ #asm push cs pop es hcode: mov ax,#$0201 ! Read 1 sector mov bx,#BOOTADDR ! In the boot area mov cx,#$0001 ! From sector 1 mov dx,#$0080 ! Of the hard drive head zero int $13 jc hcode ! Keep trying forever! jmpi BOOTADDR,0 #endasm } #endif /* /* */ /****************************************************************************/ /* Section hd_sect */ /****************************************************************************/ #ifdef HARDDISK #asm ! ! Load AL sectors from linear sector DX:CX into location ES:BX ! Linear sector zero is at [bootpart] ! This loads one sector at a time, but that's OK cause even in the _very_ ! worst case it'll take no more that 5 seconds to load a 16 bit executable. ! load_sect: add cx,[bootpart] adc dx,[bootpart+2] moresect: cmp al,#0 jnz onesect clc ret ! Load one sector... onesect: push ax ! Save lots push di push si push cx ! Drive and sector. push dx push es ! Load location push bx push cx ! Drive and sector again. push dx ! Fetch drive 'shape' mov ah,#8 mov dl,dh int $13 ! DX:CX = drive specification jc _nogood and cx,#$3F ! Get sector count => DI mov di,cx xor dl,dl ! Get head count => SI xchg dl,dh inc dx mov si,dx pop dx ! Get back drive and sector pop ax mov bl,dh ! Save drive xor dh,dh div di ! DX=sector, AX=track number mov cx,dx inc cl ! CL=sector number xor dx,dx div si ! DX=head, AX=cylinder mov dh,dl mov dl,bl ! DX for int 1302 xchg al,ah ror al,#1 ror al,#1 or cx,ax ! CX for int 1302 pop bx ! ES:BX for int 1302 pop es mov di,#5 ! Lots of retries for a hd retry: mov ax,#$0201 int $13 jnc got_hd_sect xor ax,ax ! Reset between each try. int $13 dec di jnz retry br _nogood got_hd_sect: pop dx pop cx pop si pop di pop ax dec al add cx,#1 adc dh,#0 add bh,#2 jmp moresect #endasm #endif /****************************************************************************/ /* This is the end of the parts that MUST be in the first sector */ /* From here down the functions can safely be in any order. */ /****************************************************************************/ /* /* */ /****************************************************************************/ /* Section fd_block */ /****************************************************************************/ #ifndef HARDDISK static load_block(address, blkno) unsigned address, blkno; { register sect_nr sectno; if(blkno == 0) { zero_block(address); return; } #ifdef DOTS prt_dot(); #endif sectno = (sect_nr)blkno * 2; load_sect(address, sectno); load_sect(address+32, sectno+1); } #endif /****************************************************************************/ /* Section fd_bpb */ /****************************************************************************/ #ifndef HARDDISK #asm _set_bpb: #ifdef MIN_SPACE bios_tabl=temp_space ! Temp space. bios_disk=temp_space+4 ! #else bios_tabl=dosfs_stat ! Temp space. bios_disk=dosfs_stat+4 ! #endif #ifndef __CALLER_SAVES__ push si push di #endif mov di,#bios_disk mov bx,#0x78 ! 0:bx is parameter table address push ds push di mov si,[bx] mov ax,[bx+2] mov [bios_tabl],si mov [bios_tabl+2],ax push ax pop ds ! ds:si is source ! copy 12 bytes mov cl,#6 cld rep movsw pop di pop ds mov ax,[_n_sectors] movb 4[di],al ! patch sector count mov [bx],di mov 2[bx],es #ifndef __CALLER_SAVES__ pop si pop di #endif ret _unset_bpb: ! 0:0x78 is parameter table address mov ax,[bios_tabl] mov [0x78],ax mov ax,[bios_tabl+2] mov [0x78+2],ax ret #endasm #endif /****************************************************************************/ /* Section fd_get_now */ /****************************************************************************/ #ifndef HARDDISK static get_now() { #asm mov si,#5 retry_get: xor dx,dx mov cx,[_firstsect] shr ch,#1 adc dh,#0 mov es,[_loadaddr] xor bx,bx mov ax,[_loadcount] test ax,ax jz no_load mov ah,#2 int $13 ! Try fetch jnc no_load xor ax,ax ! Bad, retry. int $13 dec si jnz retry_get br _nogood no_load: xor ax,ax mov [_loadcount],ax #endasm } #endif /****************************************************************************/ /* Section fd_probe */ /****************************************************************************/ #ifndef HARDDISK #ifdef TRY_FLOPPY #asm !-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ! ! These are the number of sectors per track that will be scanned for. ! For 3.5 inch floppies 36 is 2.88 Mb, 18 is 1.44Mb, 21 is 1.68Mb on ! a 1.44Mb floppy drive. 15 and 9 are for 5.25 inch floppies. disksizes: .byte 36,21,18,15,9 ! It seems that there is no BIOS call to get the number of sectors. Guess ! 36 sectors if sector 36 can be read, 18 sectors if sector 18 can be read, ! 15 if sector 15 can be read. Otherwise guess 9. _probe_sectors: mov si,#disksizes ! table of sizes to try probe_loop: lodsb cbw ! extend to word mov _n_sectors, ax cmp al,#9 je got_sectors ! if all else fails, try 9 xchg ax, cx ! cx = track and sector xor dx, dx ! drive 0, head 0 mov bx,#probe_buf ! address after setup (es = cs) mov ax,#0x0201 ! service 2, 1 sector int 0x13 jc probe_loop ! try next value got_sectors: ret #endasm #else probe_sectors() { /* Guess the number of sectors based on the size of the file system */ if( (n_sectors = b_super.s_nzones / 40) > 11 ) n_sectors /= 2; } #endif #endif /****************************************************************************/ /* Section fd_sect */ /****************************************************************************/ #ifndef HARDDISK static load_sect(address, sectno) unsigned address; sect_nr sectno; { register sect_nr nsect; nsect = sectno%n_sectors +1; sectno /= n_sectors; nsect |= (sectno<<8); if( loadcount ) { lastsect++; if( ( address & 4095 ) && nsect == lastsect ) { loadcount++; return; } get_now(); } lastsect = firstsect = nsect; loadaddr = address; loadcount = 1; } #endif /****************************************************************************/ /* Section fd_zeroblk */ /****************************************************************************/ #ifndef HARDDISK static zero_block(address) { #asm #if __FIRST_ARG_IN_AX__ mov es,ax #else mov bx,sp mov es,[bx+2] #endif push di mov cx,#512 xor ax,ax mov di,ax rep stosw pop di #endasm } #endif /****************************************************************************/ /* Section hd_block */ /****************************************************************************/ #ifdef HARDDISK /*----------------------------------*/ /* Hard disk block driver */ /*----------------------------------*/ #asm _load_block: push bp mov bp,sp #if __FIRST_ARG_IN_AX__ ! Fetch load location mov es,ax ! Test for block zero mov ax,4[bp] #else ! Fetch load location mov ax,[bp+4] mov es,ax ! Test for block zero mov ax,6[bp] #endif test ax,ax jne real_block ! Iff block zero, zap memory push di mov cx,#512 xor ax,ax mov di,ax rep stosw pop di func_exit: mov sp,bp pop bp ret real_block: #ifdef DOTS push ax call _prt_dot pop ax #endif ! Load a real block. mov cx,ax xor dx,dx shl cx,#1 rcl dx,#1 xor bx,bx mov al,#2 call load_sect j func_exit #endasm #endif /****************************************************************************/ /* Section main */ /****************************************************************************/ #asm code: call _loadprog call _runprog br _nogood #endasm /****************************************************************************/ /* Section prt_dots */ /****************************************************************************/ #ifdef DOTS #asm _prt_crlf: mov al,#13 call outch mov al,#10 j outch _prt_dot: mov al,#'. outch: mov ah,#$0E mov bx,#7 int $10 ret #endasm #endif /****************************************************************************/ /* Section end_1 */ /****************************************************************************/ #if defined(HARDDISK) || !defined(MIN_SPACE) #asm end_of_part1: #ifdef HARDDISK if *>start+0x1FE ! Leave space for magic #else if *>start+0x200 #endif fail! Part 1 too large! endif .blkb 0x200+start-* #endasm #endif /****************************************************************************/ /* Section prog_load */ /****************************************************************************/ loadprog() { #ifdef DOTS prt_dot(); #endif if( b_super.s_magic == SUPER_MAGIC2 ) dir_32 = 1; else if( b_super.s_magic == SUPER_MAGIC ) dir_32 = 0; else nogood(); #ifdef zone_shift if( zone_shift != b_super.s_log_zone_size) nogood(); #else zone_shift = b_super.s_log_zone_size; #endif #ifndef HARDDISK probe_sectors(); /* if( (n_sectors = b_super.s_nzones / 40) > 11 ) n_sectors /= 2; */ set_bpb(); #endif try_again:; inode--; load_block(seg_of(b_inode), inode/INODES_PER_BLOCK + b_super.s_imap_blocks + b_super.s_zmap_blocks + 2); get_now(); ldaddr = LOADSEG; /* Load at 64k mark */ { register d_inode * i_ptr; i_ptr = b_inode + inode%INODES_PER_BLOCK; next_zone = i_ptr->i_zone; flength = i_ptr->i_size; if( (i_ptr->i_mode & I_TYPE) == I_DIRECTORY ) { ldaddr = seg_of(directory); #ifndef MIN_SPACE dinode = inode+1; /* Remember current directory */ #endif inode = 0; /* Mark - we've no _file_ inode yet */ } } end_zone = next_zone+NR_DZONE_NUM; load_zone(seg_of(b_zone), (indirect = next_zone[NR_DZONE_NUM])); get_now(); for(;;) { if( next_zone >= end_zone ) { if( indirect != 0 ) { next_zone = b_zone; end_zone = next_zone + NR_INDIRECTS; indirect = 0; continue; } break; } load_zone(ldaddr, *next_zone); next_zone++; ldaddr += (seg_at(1) << zone_shift); } get_now(); #ifdef DOTS prt_crlf(); #endif if(!inode) { dirptr = directory; while(flength > 0) { register char * s = bootfile; register char * p = dirptr->d_name; if( dirptr->d_inum ) { for(;;) { if( *s == '\0') { if(*p == '\0') { inode = dirptr->d_inum; goto try_again; } break; } if( *s++ != *p++ ) break; } } flength -= 16; dirptr++; if( dir_32 ) { flength -= 16; dirptr++; } } nogood(); } #ifndef HARDDISK unset_bpb(); #endif } /****************************************************************************/ /* Section prog_run */ /****************************************************************************/ static runprog() { /* It all worked, run the loaded executable */ #asm #ifdef HARDDISK mov dx,[bootpart+2] xchg dh,dl ! DX => hard drive push [bootpart] ! CX => partition offset xor si,si #else xor dx,dx ! DX=0 => floppy drive push dx ! CX=0 => partition offset = 0 mov si,[_n_sectors] ! Save for monitor.out #endif mov bx,#LOADSEG mov ds,bx ! DS = loadaddress xor di,di ! Zero mov ax,[di] cmp ax,#0x0301 ! Right magic ? jnz binfile ! Yuk ... assume .SYS inc bx inc bx ! bx = initial CS mov ax,[di+2] and ax,#$20 ! Is it split I/D ? jz impure ! No ... mov cl,#4 mov ax,[di+8] shr ax,cl impure: pop cx add ax,bx mov ss,ax mov sp,[di+24] ! Chmem value mov ds,ax binfile: push bx push di ! jmpi 0,#LOADSEG+2 retf #endasm } /****************************************************************************/ /* Section sys_libs */ /****************************************************************************/ #asm ! These functions are pulled from the C library. libstuff: imodu: xor dx,dx div bx mov ax,dx ! instruction queue full so xchg slower ret idiv_u: xor dx,dx div bx ret #ifndef zone_shift isl: islu: mov cl,bl shl ax,cl ret #endif libend: #endasm /****************************************************************************/ /* Section sys_vars */ /****************************************************************************/ #asm #ifdef MIN_SPACE block temp_space+64 #endif vars: #ifndef HARDDISK _n_sectors: .blkw 1 #endif _next_zone: .blkw 1 _end_zone: .blkw 1 _indirect: .blkw 1 _ldaddr: .blkw 1 _dirptr: .blkw 1 _flength: .blkw 1 _dir_32: .blkw 1 varend: #ifdef MIN_SPACE endb #endif #endasm /****************************************************************************/ /* Section end_2 */ /****************************************************************************/ #asm end_of_prog: if *>start+0x400 fail! Part 2 too large! endif if end_of_prog DMA is simple. */ relocator(0x1000-__get_ds()+__get_cs()); #else relocator(-1); /* Top of available memory */ #endif printf("Relocated to CS=$%04x DS=$%04x\n", __get_cs(), __get_ds()); #endif disk_drive = __argr.h.dl; #endif #ifdef NOCOMMAND cmd_type("help.txt"); #else display_help(0); #endif cmd_bzimage((void*)0); } #ifdef NOCOMMAND printf("Unable to boot, sorry\nreboot:"); fflush(stdout); read(0, command_buf, sizeof(command_buf)-1) ; #else for (;;) { #ifdef COLOUR printf("\033S \033R+\033Sa\033Rc"); #endif printf(">"); fflush(stdout); ch = read(0, command_buf, sizeof(command_buf)-1) ; if( ch <= 0 ) break; command_buf[ch] = '\0'; if( ch == 1 && command_buf[0] != '\n' ) { putchar('\n'); help_key(command_buf[0]&0xFF); continue; } if( command_buf[ch-1] == '\n' ) command_buf[ch-1] = 0; for(ptr=command_buf; *ptr; ptr++) { if(*ptr=='"') do { ptr++; } while(*ptr && *ptr != '"'); if( isupper(*ptr) ) *ptr = tolower(*ptr); } cmd = command_buf; while(*cmd == ' ') cmd++; if( !isalpha(cmd[0]) || !isalpha(cmd[1]) ) { minibuf[0] = cmd[0]; args = cmd+1; cmd = minibuf; } else { args = strchr(cmd, ' '); if( args ) *args++ = 0; else args = cmd + strlen(cmd); } if( *cmd == 0 ) continue; for(cptr = cmd_list; cptr->command; cptr++) { if( strcmp(cptr->command, cmd) == 0 ) break; } #ifdef COLOUR printf("\033S \033Sa\033Rg"); #endif fflush(stdout); if( cptr->command ) (void) (*cptr->func)(args); else printf("Command not found.\n"); } #endif } /****************************************************************************/ void init_prog() { char offt; #ifdef COLOUR vt52_putch(0); printf("\033E\033Rg\033Sa\033J"); #endif printf("Linux x86"); #ifdef NOCOMMAND #ifdef TARFLOPPY printf(" TAR floppy booter"); #else #ifdef DOSFLOPPY printf(" DOS floppy booter"); #else printf(" floppy booter"); #endif #endif #else printf(" boot monitor"); #endif printf(", Version %s", VERSION); printf(".\n"); cpu_check(); mem_check(); #ifndef NOMONITOR printf("Processor: %s", x86_name); if(x86_fpu) printf(" with FPU"); if(x86_emu) printf(" in protected mode"); printf("\n"); #endif printf("There is %u bytes available", &offt-sbrk(0)); printf(", %dk of boot memory", boot_mem_top/64); if( main_mem_top ) { printf(", %d.%dM of main memory", (int)(main_mem_top/1024), (int)((10*main_mem_top)/1024%10)); } printf(".\n"); } /****************************************************************************/ int getnum(numptr, valptr) char ** numptr; unsigned int * valptr; { char * ptr = *numptr; unsigned int val = 0; int base = number_base; int flg = 0; while( *ptr && *ptr <= ' ' ) ptr++; switch(*ptr) { case '$': case '&': case 'X': base=16; ptr++; break; case '#': base=10; ptr++; break; case '%': base=2; ptr++; break; case '0': if( ptr[1] == 'X' ) { base=16; ptr+=2; } break; case '-': *numptr = ptr+1; return 0; } while(*ptr) { int d = -1, ch; ch = *ptr; if( ch >= '0' && ch <= '9' ) d = ch - '0'; if( ch >= 'a' && ch <= 'z' ) d = ch - 'a' + 10; if( ch >= 'A' && ch <= 'Z' ) d = ch - 'A' + 10; if( d>=0 && d #include #include #include #include #include "i86_funcs.h" #include "readfs.h" #define X_TARFLOPPY #define X_DOSFLOPPY #define X_CALC_CRC #ifdef __STANDALONE__ #define NO_COLOUR extern union REGS __argr; #endif #ifdef TARFLOPPY #define SINGLEFS #define open_file tar_open_file #define rewind_file tar_rewind_file #define close_file tar_close_file #define file_length tar_file_length #define read_block tar_read_block #endif #ifdef MINFLOPPY #define SINGLEFS #define open_file min_open_file #define rewind_file min_rewind_file #define close_file min_close_file #define file_length min_file_length #define read_block min_read_block #endif #ifdef DOSFLOPPY #define SINGLEFS #define open_file dos_open_file #define rewind_file dos_rewind_file #define close_file dos_close_file #define file_length dos_file_length #define read_block dos_read_block #endif #ifdef SINGLEFS /* #define NOCOMMAND */ #define NOMONITOR #endif #ifdef __STANDALONE__ #undef putchar #define putchar putch #define printf cprintf #define fflush(x) #endif dev86-0.16.21/bootblocks/msdos.s000066400000000000000000000205751231050321700162720ustar00rootroot00000000000000!--------------------------------------------------------------------------- !! This is a bootblock to load an execute a standalone program from an !! MSDOS filesystem on a floppy disk. !! !! The file loaded is called 'BOOTFILE.SYS' and is loaded at address $7C00. !--------------------------------------------------------------------------- ! The filename can be changed at install time by following the label ! boot_name, because the file is loaded at address $7C00 it can be the ! image of a boot block (eg LILO). It's also checked for the magic number ! associated with a Linux-8086 standalone executable and this is used if ! it's found. ! ! There are a number of assumptions made by the code concerning the layout ! of the msdos files system: ! ! 1) All of the first 12 bit FAT must be on the first track. ! 2) The FAT must be 12 bit or 16 bit. (known at install time) ! 3) The value of the hidden sectors field must be zero ! ! All these are true for mtools created floppies on normal PC drives. ! ! In addition this now has a compile time option for FAT16 partitions. ! TODO: Auto detect disk type ! FAT32 ! !--------------------------------------------------------------------------- ORGADDR=$0500 use16 ! Some configuration values LOADSEG= $7C0 export fatbits fatbits=12 ! Set to 12 or 16 (16 for LS-120 disks) export heads heads=0 ! This can be 0,1 or 2. 0 is dynamic. export harddisk if fatbits=12 harddisk=0 else harddisk=1 ! Allow for hard disks, but will only work with endif ! disks formatted >= MSDOS 4.0 !--------------------------------------------------------------------------- ! Absolute position macro, fails if code before it is too big. macro locn if *-start>?1 fail! *-start>?1 endif .blkb ?1 + start-* mend org ORGADDR start: include sysboot16.s org dos_sysid .ascii "DOSFS" ! System ID !--------------------------------------------------------------------------- ! Data into the temp area, 30 clear bytes org floppy_temp root_count: .blkw 1 !--------------------------------------------------------------------------- locn(codestart-start) cld ! Assume _nothing_! mov bx,#$7C00 ! Pointer to start of BB. xor ax,ax ! Segs all to zero mov ds,ax mov es,ax mov ss,ax mov sp,bx ! SP Just below BB mov cx,#$100 ! Move 256 words mov si,bx ! From default BB mov di,#ORGADDR ! To the correct address. rep movsw jmpi cont,#0 ! Set CS:IP correct. cont: sti ! Let the interrupts back in. ! DONT Need to fix BPB for fd0 to correct sectors (Like linux bootblock does) ! as we only ever read one sector at a time. ! For each sector in root dir ! For each dir entry ! If entry name is == boot_name ! then load and run ! First dir = dos_fatlen*dos_nfat+dos_resv mov ax,[dos_fatlen] mov dl,[dos_nfat] xor dh,dh mul dx add ax,[dos_resv] mov di,ax ! DI is sector number of first root dir sector. mov ax,[dos_nroot] mov [root_count],ax add ax,#15 mov cl,#4 shr ax,cl add ax,di mov bp,ax ! bp is first data sector. nextsect: call linsect mov ax,#$0201 int $13 jc floppy_error ! ... foreach dir entry mov si,bx nextentry: ! TODO: Test attributes for !dir !label here ? ! test entry name push si push di mov di,#boot_name mov cx,#11 rep cmpsb pop di pop si jne bad_entry mov ax,[si+26] ! Cluster number of start of file test ax,ax ! Make sure we have a block. jnz load_system bad_entry: add si,#32 ! skip to next entry cmp si,#512 jnz nextentry inc di ! Load next sector sub [root_count],#16 jp nextsect jmp no_system !--------------------------------------------------------------------------- ! Convert a cluster number in DI into a CHS in CX:DX linclust: mov ax,di sub ax,#2 mov dl,[dos_clust] xor dh,dh mul dx add ax,bp ! Add sector number of first data sector. adc dx,#0 jmp linsect2 ! ! This function converts a linear sector number in DI ! into a CHS representation in CX:DX ! linsect: mov ax,di linsect1: xor dx,dx linsect2: ! Add partition offset in. if fatbits =16 add ax,[dos_hidden] adc dx,[dos_hidden+2] endif div [dos_spt] inc dx mov cl,dl ! Sector num xor dx,dx ! Drive 0 if heads =2 shr ax,#1 ! Assume dos_heads == 2 adc dh,#0 ! Head num endif if heads =0 div [dos_heads] xchg dh,dl endif mov ch,al ! Cylinder bits 0-7 if heads =0 sar ax,#1 ! Cylinder bits 8&9 sar ax,#1 and al,#$C0 or cl,al endif if harddisk mov dl,[dos4_phy_drive] endif ret !--------------------------------------------------------------------------- ! Error processing. no_system: floppy_error: mov si,#error_msg no_boot: ! SI now has pointer to error message lodsb cmp al,#0 jz EOS mov bx,#7 mov ah,#$E ! Can't use $13 cause that's AT+ only! int $10 jmp no_boot EOS: xor ax,ax int $16 jmpi $0,$FFFF ! Reboot. !--------------------------------------------------------------------------- ! This loads the boot program 1 sector at a time, funny thing is it actually ! loads at exactly the same speed as loading a track at a time, at least on ! my slow old 286/8Mhz. Oh well, we need the space so if you're worried just ! tell superformat to give you an interleave of 2 (-i 2). ! load_system: if fatbits =12 push ax ! Save cluster we're loading ! 1) Load FAT ! This assumes all of FAT1 is on the first track, this is normal mov ax,[dos_fatlen] mov ah,#2 mov bx,#fat_table mov cx,[dos_resv] ! Fat starts past bootblock inc cx xor dx,dx ! Head zero int $13 jc floppy_error pop di ! Cluster to start load. else mov di,ax endif mov ax,#LOADSEG mov es,ax ! load whole cluster next_cluster: mov si,[dos_clust] ! How big is a cluster and si,#255 call linclust ! Find it's physical address next: mov ax,#$0201 xor bx,bx int $13 ! Load 1 sector at a time jc floppy_error mov ax,es add ax,#512/16 mov es,ax cmp cl,[dos_spt] ! Does cluster straddle tracks ? jnz sectok mov cl,#0 if heads=2 inc dh cmp dh,#2 ! Does cluster straddle cylinders ? jnz sectok xor dh,dh endif if heads=0 inc dh cmp dh,[dos_heads] ! Nb low byte only. jnz sectok xor dh,dh endif inc ch sectok: inc cl dec si jnz next call next_fat jc next_cluster jmp maincode next_fat: if fatbits =12 mov ax,di shr ax,#1 pushf ! Save if odd number add di,ax mov di,fat_table[di] popf jnc noshift ! Odd in high nibbles. mov cl,#4 shr di,cl noshift: and di,#$FFF cmp di,#$FF0 ! FFF is EOF, clear carry flag. ! FF0+ are badblocks etc. endif if fatbits =16 mov ax,di ! load fat sector AH (if it's not already loaded) xchg ah,al xor ah,ah add ax,[dos_resv] cmp ax,[fatsect] jz got_fsect mov [fatsect],ax call linsect1 push es mov bx,#fat_table xor ax,ax mov es,ax mov ax,#$0201 int $13 pop es jnc got_fsect br floppy_error got_fsect: ! Load di with cluster number in di and di,#$FF shl di,#1 mov di,fat_table[di] cmp di,#$FFF0 endif ret !--------------------------------------------------------------------------- ! File is now loaded, execute it. maincode: mov bx,#7 mov ax,#$0E + ': int $10 ! Marker printed to say bootblock succeeded. xor dx,dx ! DX=0 => floppy drive if harddisk mov dl,[dos4_phy_drive] endif push dx ! CX=0 => partition offset = 0 mov si,[dos_spt] ! SI=Sectors per track mov bx,#LOADSEG mov ds,bx ! DS = loadaddress xor di,di ! Zero mov ax,[di] cmp ax,#0x0301 ! Right magic ? jnz bad_magic ! Yuk ... mov ax,[di+2] and ax,#$20 ! Is it split I/D ? jz impure ! No ... mov cl,#4 mov ax,[di+8] shr ax,cl impure: pop cx ! Partition offset. inc bx inc bx ! bx = initial CS add ax,bx mov ss,ax mov sp,[di+24] ! Chmem value mov ds,ax ! AX=ds, BX=cs, CX=X, DX=X, SI=X, DI=0, BP=X, ES=X, DS=*, SS=*, CS=* bad_magic: push bx ! jmpi 0,#LOADSEG+2 push di retf !--------------------------------------------------------------------------- ! initilised data fatsect: .word 0 error_msg: .asciz "\r\nError during initial boot\r\nPress a key:" export boot_name boot_name: .ascii "BOOTFILESYS" name_end: ! NNNNNNNNEEE locn(510) .word $AA55 ! This is a floppy so it should not need the magic _but_ ! the debian MBR requires the magic even on floppies fat_table: ! This is the location that the fat table is loaded. ! Note: The fat must be entirely on track zero if 12 bit. !--------------------------------------------------------------------------- dev86-0.16.21/bootblocks/noboot.s000066400000000000000000000007671231050321700164460ustar00rootroot00000000000000 org $7c00 include sysboot.s org dos_sysid .ascii "PANIC" ! System ID org codestart xor ax,ax mov ds,ax mov ss,ax mov sp,ax jmpi code,#0 code: ! SI = pointer to error message mov si,#boot_message nextc: lodsb cmp al,#0 jz eos mov bx,#7 mov ah,#$E ! Can't use $13 cause that's AT+ only! int $10 jmp nextc eos: ! Wait for a key then reboot xor ax,ax int $16 jmpi $0,$FFFF ! Wam! Try or die! export boot_message boot_message: .asciz "PANIC! NO OS Found!\r\n" dev86-0.16.21/bootblocks/nombr.s000066400000000000000000000005461231050321700162560ustar00rootroot00000000000000 include sysmbr.s org codestart mov si,#message nextc: lodsb cmp al,#0 jz eos mov bx,#7 mov ah,#$E ! Can't use $13 cause that's AT+ only! int $10 jmp nextc eos: ! Wait for a key then reboot xor ax,ax int $16 jmpi $0,$FFFF ! Wam! Try or die! export message message: .asciz "MBR loaded but not bootable.\r\n" include sysmbrtail.s dev86-0.16.21/bootblocks/readfs.h000066400000000000000000000020571231050321700163710ustar00rootroot00000000000000 /* Functions for reading from one file at a time in the root directory * of a raw filesystem. */ #ifdef __STDC__ #define P(x) x #else #define P(x) () #endif int open_file P((char * fname)); int rewind_file P((void)); int close_file P((void)); long file_length P((void)); int read_block P((char * buffer)); int tar_open_file P((char * fname)); int tar_rewind_file P((void)); int tar_close_file P((void)); long tar_file_length P((void)); int tar_read_block P((char * buffer)); int min_open_file P((char * fname)); int min_rewind_file P((void)); int min_close_file P((void)); long min_file_length P((void)); int min_read_block P((char * buffer)); int dos_open_file P((char * fname)); int dos_rewind_file P((void)); int dos_close_file P((void)); long dos_file_length P((void)); int dos_read_block P((char * buffer)); #define read_sector(__sect) read_lsector((unsigned long)(__sect)) char * read_lsector P((long sector)); void reset_disk P((void)); extern char * track_buffer; extern int disk_drive; extern int disk_cyls; extern int disk_heads; extern int disk_spt; dev86-0.16.21/bootblocks/relocate.c000066400000000000000000000041651231050321700167200ustar00rootroot00000000000000 #include "monitor.h" static unsigned memseg = 0, memlen = 0; char buf[1]; /* If newseg == 0x0000 => Lowest address CS=$50 * If newseg == 0x0001 => DS to 64k position * If newseg == 0x0002 => DS to 128k position * ... * If newseg == 0x0009 => DS to 576k position * If newseg == 0xFFFF => Highest address leaving Linux-i386 clear. * * All others are literal, will fail if would overlap with something important. */ void relocator(newseg) unsigned newseg; { #ifdef __STANDALONE__ unsigned moved, codelen; unsigned es = __get_es(); /* If running under DOS don't relocate */ if (__argr.x.cflag) return; /* Where do we start */ if(memseg == 0) { extern int _heap_top; memseg = __get_cs(); codelen = __get_ds()-memseg; __set_es(memseg-2); memlen = (((int)&_heap_top) >> 4); /* if (__deek_es(0) == 0x0301 ) memlen = (__deek_es(24) >> 4); */ if( memlen == 0 ) memlen = 0x1000; memlen += codelen; __set_es(es); } if( newseg == 0 ) newseg = 0x50; if( newseg > 0 && newseg < 10 ) { newseg = (newseg<<12) - (__get_ds() - __get_cs()); } if( newseg < 0x50 ) return; if( newseg == 0xFFFF ) { newseg = boot_mem_top; if( newseg > 0x9000 ) newseg = 0x9000; newseg -= memlen; } /* If the old area overlaps the new then fail */ if( newseg >= memseg && newseg < memseg+memlen ) return; if( memseg >= newseg && memseg < newseg+memlen ) return; /* Copy segments, done in 32k chunks */ for(moved=0; moved < memlen; ) { unsigned int lump; if( memlen-moved <= 0x800 ) lump = memlen-moved; else lump = 0x800; __movedata(memseg+moved, 0, newseg+moved, 0, (lump<<4)); moved += lump; } /* re-link int 0x80, this one is only an example (used by 'standalone.c') */ /* __set_es(0); __doke_es(0x80*4+2, newseg); __set_es(es); */ /* The actual jump ... */ memseg = newseg; #asm mov ax,ds mov bx,cs sub ax,bx mov bx,[_memseg] add ax,bx push bx call L_x mov ds,ax mov ss,ax mov [_memseg],bx #endasm } #asm L_x: retf #endasm #else } #endif dev86-0.16.21/bootblocks/skip.s000066400000000000000000000025301231050321700161020ustar00rootroot00000000000000! ! This floppy bootblock bypasses the floppy boot ... ! BOOTDISK = 0x80 ORGADDR = $0600 use16 org ORGADDR start: include sysboot.s org dos_sysid .ascii "BOOT C" ! System ID org codestart cli ! Assume _nothing_! cld mov bx,#$7C00 ! Pointer to start of BB. xor ax,ax ! Segs all to zero mov ds,ax mov es,ax mov ss,ax mov sp,bx ! SP Just below BB mov cx,#$100 ! Move 256 words mov si,bx ! From default BB mov di,#ORGADDR ! To the correct address. rep movsw jmpi cont,#0 ! Set CS:IP correct. cont: sti ! Let the interrupts back in. mov si,#mesg call prtmsg mov di,#5 hcode: mov bx,#$7C00 ! Pointer to start of BB. mov ax,#$0201 ! Read 1 sector mov cx,#$0001 ! From sector 1 mov dx,#BOOTDISK ! Of the hard drive head zero int $13 jc error jmpi $7c00,0 error: mov si,#mesg2 call prtmsg dec di jz reboot mov si,#mesg3 call prtmsg jmp hcode prtmsg: lodsb cmp al,#0 jz EOS mov bx,#7 mov ah,#$E ! Can't use $13 cause that's AT+ only! int $10 jmp prtmsg EOS: ret reboot: mov si,#mesg4 call prtmsg xor ax,ax int $16 jmpi $0,$FFFF ! Reboot. mesg2: .asciz "Disk error\r\n" mesg3: .asciz "Retrying\r\n" mesg4: .asciz "Press a key:" export mesg if BOOTDISK = 0x80 mesg: .asciz "Bypassing floppy boot\r\n" else mesg: .asciz "Booting drive two\r\n" endif dev86-0.16.21/bootblocks/sysboot.s000066400000000000000000000045711231050321700166450ustar00rootroot00000000000000 ! The master boot sector will have setup a stack, ! this is normally at 0:7c00 down. ! DS, SS, CS and ES will all have value 0 so the execution address is 0:7c00 ! On entry the register SI will be pointer to the partition entry that ! this sector was loaded from, DL is the drive. ! Also if it's a standard Master boot DH will be the head, CX will be the ! sector and cylinder, BX=7C00, AX=1, DI=7DFE, BP=SI. There's a reasonable ! chance that this isn't true though. ! The Master boot itself will have been loaded and run at $07c00 ! The BIOS must have setup a stack because interrupts are enabled ! Little else can be assumed because DOS doesn`t assume anything either sysboot_start: j codestart nop ! DOS appears to _require_ this to identify an MSDOS disk!! .blkb sysboot_start+3-* public dosfs_stat dos_sysid: .ascii "LINUX" ! System ID .byte 0,0,0 dosfs_stat: dos_sect: .blkw 1 ! Sector size dos_clust: .blkb 1 ! Cluster size dos_resv: .blkw 1 ! Res-sector dos_nfat: .blkb 1 ! FAT count dos_nroot: .blkw 1 ! Root dir entries dos_maxsect: .blkw 1 ! Sector count (=0 if large FS) dos_media: .blkb 1 ! Media code dos_fatlen: .blkw 1 ! FAT length dos_spt: .blkw 1 ! Sect/Track dos_heads: .blkw 1 ! Heads dos_hidden: .blkw 2 ! Hidden sectors ! Here down is DOS 4+ and probably not needed for floppy boots. dos4_maxsect: .blkw 2 ! Large FS sector count dos4_phy_drive: .blkb 1 ! Phys drive .blkb 1 ! Reserved .blkb 1 ! DOS 4 floppy_temp: dos4_serial: .blkw 2 ! Serial number dos4_label: .blkb 11 ! Disk Label (DOS 4+) dos4_fattype: .blkb 8 ! FAT type ! ! This is where the code will be overlaid, the default is a hang ! The 0x5A offset clears the FAT32 header. .blkb sysboot_start+0x5A-* public codestart codestart: j codestart ! Partition table public bootblock_magic .blkb sysboot_start+0x1BE-* partition_1: .blkb 8 ! IN,SH,SS,ST,OS,EH,ES,ET .blkw 2 ! Linear position (0 based) .blkw 2 ! Linear length .blkb sysboot_start+0x1CE-* partition_2: .blkb 8 ! IN,SH,SS,ST,OS,EH,ES,ET .blkw 2 ! Linear position (0 based) .blkw 2 ! Linear length .blkb sysboot_start+0x1DE-* partition_3: .blkb 8 ! IN,SH,SS,ST,OS,EH,ES,ET .blkw 2 ! Linear position (0 based) .blkw 2 ! Linear length .blkb sysboot_start+0x1EE-* partition_4: .blkb 8 ! IN,SH,SS,ST,OS,EH,ES,ET .blkw 2 ! Linear position (0 based) .blkw 2 ! Linear length .blkb sysboot_start+0x1FE-* bootblock_magic: .word 0xAA55 dev86-0.16.21/bootblocks/sysboot16.s000066400000000000000000000045161231050321700170130ustar00rootroot00000000000000 ! The master boot sector will have setup a stack, ! this is normally at 0:7c00 down. ! DS, SS, CS and ES will all have value 0 so the execution address is 0:7c00 ! On entry the register SI will be pointer to the partition entry that ! this sector was loaded from, DL is the drive. ! Also if it's a standard Master boot DH will be the head, CX will be the ! sector and cylinder, BX=7C00, AX=1, DI=7DFE, BP=SI. There's a reasonable ! chance that this isn't true though. ! The Master boot itself will have been loaded and run at $07c00 ! The BIOS must have setup a stack because interrupts are enabled ! Little else can be assumed because DOS doesn`t assume anything either sysboot_start: j codestart nop ! DOS appears to _require_ this to identify an MSDOS disk!! .blkb sysboot_start+3-* public dosfs_stat dos_sysid: .ascii "LINUX" ! System ID .byte 0,0,0 dosfs_stat: dos_sect: .blkw 1 ! Sector size dos_clust: .blkb 1 ! Cluster size dos_resv: .blkw 1 ! Res-sector dos_nfat: .blkb 1 ! FAT count dos_nroot: .blkw 1 ! Root dir entries dos_maxsect: .blkw 1 ! Sector count (=0 if large FS) dos_media: .blkb 1 ! Media code dos_fatlen: .blkw 1 ! FAT length dos_spt: .blkw 1 ! Sect/Track dos_heads: .blkw 1 ! Heads dos_hidden: .blkw 2 ! Hidden sectors ! Here down is DOS 4+ and probably not needed for floppy boots. dos4_maxsect: .blkw 2 ! Large FS sector count dos4_phy_drive: .blkb 1 ! Phys drive .blkb 1 ! Reserved .blkb 1 ! DOS 4 floppy_temp: dos4_serial: .blkw 2 ! Serial number dos4_label: .blkb 11 ! Disk Label (DOS 4+) dos4_fattype: .blkb 8 ! FAT type ! ! This is where the code will be overlaid, the default is a hang .blkb sysboot_start+0x3E-* public codestart codestart: j codestart ! Partition table public bootblock_magic .blkb sysboot_start+0x1BE-* partition_1: .blkb 8 ! IN,SH,SS,ST,OS,EH,ES,ET .blkw 2 ! Linear position (0 based) .blkw 2 ! Linear length .blkb sysboot_start+0x1CE-* partition_2: .blkb 8 ! IN,SH,SS,ST,OS,EH,ES,ET .blkw 2 ! Linear position (0 based) .blkw 2 ! Linear length .blkb sysboot_start+0x1DE-* partition_3: .blkb 8 ! IN,SH,SS,ST,OS,EH,ES,ET .blkw 2 ! Linear position (0 based) .blkw 2 ! Linear length .blkb sysboot_start+0x1EE-* partition_4: .blkb 8 ! IN,SH,SS,ST,OS,EH,ES,ET .blkw 2 ! Linear position (0 based) .blkw 2 ! Linear length .blkb sysboot_start+0x1FE-* bootblock_magic: .word 0xAA55 dev86-0.16.21/bootblocks/sysmbr.s000066400000000000000000000042141231050321700164540ustar00rootroot00000000000000 ! The master boot sector will have setup a stack, ! this is normally at 0:7c00 down. ! DS, SS, CS and ES will all have value 0 so the execution address is 0:7c00 ! On entry the register SI will be pointer to the partition entry that ! this sector was loaded from, DL is the drive. ! Also if it's a standard Master boot DH will be the head, CX will be the ! sector and cylinder, BX=7C00, AX=1, DI=7DFE, BP=SI. There's a reasonable ! chance that this isn't true though. ! The Master boot itself will have been loaded and run at $07c00 ! The BIOS must have setup a stack because interrupts are enabled ! Little else can be assumed because DOS doesn`t assume anything either ! Lowest available is $0500, MSDOS appears to use $0600 ... I wonder why? ORGADDR=$0500 org ORGADDR sysboot_start: cli ! Assume _nothing_! cld mov bx,#$7C00 ! Pointer to start of BB. xor ax,ax ! Segs all to zero mov ds,ax mov es,ax mov ss,ax mov sp,bx ! SP Just below BB mov cx,#$100 ! Move 256 words mov si,bx ! From default BB mov di,#ORGADDR ! To the correct address. rep movsw jmpi cont,#0 ! Set CS:IP correct. cont: sti ! Let the interrupts back in. ! This is where the code will be overlaid, the default is a hang public codestart codestart: j codestart ! Partition table public bootblock_magic .blkb sysboot_start+0x1B6-* table_start: .blkb 2 ! Dirty bits .blkb 4 ! Volume Serial Number .blkb 2 ! Possible Magic number .blkb sysboot_start+0x1BE-* partition_1: .blkb 8 ! IN,SH,SS,ST,OS,EH,ES,ET .blkw 2 ! Linear position (0 based) .blkw 2 ! Linear length .blkb sysboot_start+0x1CE-* partition_2: .blkb 8 ! IN,SH,SS,ST,OS,EH,ES,ET .blkw 2 ! Linear position (0 based) .blkw 2 ! Linear length .blkb sysboot_start+0x1DE-* partition_3: .blkb 8 ! IN,SH,SS,ST,OS,EH,ES,ET .blkw 2 ! Linear position (0 based) .blkw 2 ! Linear length .blkb sysboot_start+0x1EE-* partition_4: .blkb 8 ! IN,SH,SS,ST,OS,EH,ES,ET .blkw 2 ! Linear position (0 based) .blkw 2 ! Linear length .blkb sysboot_start+0x1FE-* bootblock_magic: .blkb 2 dev86-0.16.21/bootblocks/sysmbrtail.s000066400000000000000000000004531231050321700173270ustar00rootroot00000000000000 ! Now make sure this isn't too big! end_of_code: if *>table_start fail! Partition table overlaps endif !-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ! Clear the sector to the bottom of the partition table. if *?1 fail! ?1 endif .blkb ?1 + start-* mend ! On startup from a floppy boot it`s probably best if we assume _nothing_ ! that we don`t have to ... ! ! So, `start` is, erm, right here :-) ! The boot block is re-loaded from the floppy for relocation. !-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- use16 org RELADDR start: ! Don't even _think_ of changing this unless you're 110% sure! .byte 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90 .byte 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90 block start .asciz "ENIAC" .byte $C0 endb ! All right, I'll help, you can use any of these chars: ! "/?@ABCDEFGHIJKLMNO" ! Others are likely to cause ... problems. !-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ! Beware; the assumption is this code is relocatable. xor ax,ax mov ds,ax mov es,ax mov ss,ax if STACK = 0 mov sp,ax else mov sp,#STACK ! Stack location endif cld ! ASSUME ds=ss=es=cs=0 keep_trying1: ! Get the tar block after this program, and relocate this code. mov ax,#$0202 ! Read 2 sectors mov bx,#start ! Where this _should_ be mov cx,#$0001 ! From sector 1 xor dx,dx ! Of the floppy drive head zero int $13 jc keep_trying1 jmpi going,#0 going: ! OK. Code will now be run at correct address. if DEBUG call pboot endif mov al,tar_link cmp al,#'0 jnz nogood ! Make sure next item is file. call probe_floppy call get_size ! Get number of clicks in di test di,di jz nogood ! If it`s zero .. Hmm if STACK = 0 mov sp,#overstack ! Real bad magic :-) endif call load_sectors ! This requires that we have been relocated, so we can't call it too soon. nogood: push cs pop es hcode: mov ax,#$0201 ! Read 1 sector mov bx,#BOOTADDR ! into the boot area mov cx,#1 ! sector 1 mov dx,#$0080 ! hard drive head zero int $13 jc hcode ! Keep trying forever! jmpi BOOTADDR,#0 !-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ! ! These are the number of sectors per track that will be scanned for. ! For 3.5 inch floppies 36 is 2.88 Mb, 18 is 1.44Mb, 21 is 1.68Mb on ! a 1.44Mb floppy drive. 15 and 9 are for 5.25 inch floppies. disksizes: .byte 36,32,21,18,15,9 ! End of part 1 !-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ! This is important bits of the TAR Block. ! The chksum field will need to be changed if any mods are done to this ! file so that the bare header is a TAR file. If it's installed using ! makeboot that program will correct the sum as it also changes the time. locn(100) blk_mode: .asciz " 4111" blk_uid: .blkb 8 blk_gid: .blkb 8 blk_size: .blkb 12 blk_mtime: .asciz "6141567743 " if DEBUG blk_chksum: .asciz " 142273" else blk_chksum: .asciz " 127270" endif blk_link: .byte 'V ! Sneaks here, overlay zero init vars on tar data. block blk_mode public sectors sectors: .blkw 1 ! bios_disk: .blkb 12 ! BPB for FD0 head: .word 0 ! current head track: .word 0 ! current track endb !-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ! ! This code taken from the Linux bootsector and adjusted to suit ! ! Many BIOS's default disk parameter tables will not ! recognize multi-sector reads beyond the maximum sector number ! specified in the default diskette parameter tables - this may ! mean 7 sectors in some cases. ! ! Since single sector reads are slow and out of the question, ! we must take care of this by creating new parameter tables ! (for the first disk) in RAM. We will set the maximum sector ! count to 36 - the most we will encounter on an ED 2.88. ! ! High doesn't hurt. Low does. ! ! Segments are as follows: ds=es=ss=cs=0 ! probe_floppy: mov di,#bios_disk mov bx,#0x78 ! 0:bx is parameter table address push ds lds si,[bx] ! ds:si is source mov cl,#6 ! copy 12 bytes cld push di rep movsw pop di pop ds movb 4[di],*36 ! patch sector count mov [bx],di mov 2[bx],es ! It seems that there is no BIOS call to get the number of sectors. Guess ! 36 sectors if sector 36 can be read, 18 sectors if sector 18 can be read, ! 15 if sector 15 can be read. Otherwise guess 9. mov si,#disksizes ! table of sizes to try probe_loop: lodsb cbw ! extend to word mov sectors, ax cmp al,#9 je got_sectors ! if all else fails, try 9 xchg ax, cx ! cx = track and sector xor dx, dx ! drive 0, head 0 mov bx,#probe_buf ! address after setup (es = cs) mov ax,#0x0201 ! service 2, 1 sector int 0x13 jc probe_loop ! try next value got_sectors: ret !-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ! ! This function reads the size of the first file in the TAR image. It's ! stored in octal in the tar header that was loaded just after this block. get_size: mov di,#tar_size xor dx,dx xor bx,bx xor cx,cx next_dig: mov al,[di] and al,#$F8 cmp al,#'0 jne no_dig mov al,[di] and al,#$07 mov cl,#3 mul_loop: sal bx,#1 ! Double prec * 8 rcl dx,#1 loop mul_loop or bl,al no_dig: inc di cmp di,#tar_mtime jne next_dig add bx,#15 ! How many clicks ? adc dx,cx ! AKA zero mov cl,#4 div_loop: shr dx,#1 rcr bx,#1 loop div_loop mov di,bx ret overstack: !-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ! ! This is good so far, is it an 8086 a.out file ? ! If so start it. go_go_go: xor dx,dx ! DX=0 => floppy drive push dx ! CX=0 => partition offset = 0 mov si,[sectors] ! Save for monitor.out mov bx,#LOADSEG mov ds,bx ! DS = loadaddress xor di,di ! Zero mov ax,[di] cmp ax,#0x0301 ! Right magic ? jnz bad_magic ! Yuk ... mov ax,[di+2] and ax,#$20 ! Is it split I/D ? jz impure ! No ... mov cl,#4 mov ax,[di+8] shr ax,cl impure: pop cx ! Partition offset. inc bx inc bx ! bx = initial CS add ax,bx mov ss,ax mov sp,[di+24] ! Chmem value mov ds,ax ! AX=ds, BX=cs, CX=X, DX=X, SI=X, DI=0, BP=X, ES=X, DS=*, SS=*, CS=* bad_magic: push bx ! jmpi 0,#LOADSEG+2 push di retf !-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ! This isn't in a normal volume lable, no problem it leaves more space. ! ! locn(257) ! blk_magic: .ascii "ustar " ! .blkb 1 ! blk_uname: .ascii "TarBoot/Copyright" ! blk_uname_end: ! .blkb 32+blk_uname-blk_uname_end ! blk_gname: .ascii "R de Bath" ! blk_gname_end: ! .blkb 32+blk_gname-blk_gname_end ! blk_devmaj: .blkb 8 ! blk_devmin: .blkb 8 ! !-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- if DEBUG dot: mov al,#'. putc: push bx mov bx,#7 mov ah,#$E int $10 pop bx ret endif !-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ! ! This code taken from the Linux bootsector and adjusted to suit ! ! This routine loads the system at address LOADSEG, making sure ! no 64kB boundaries are crossed. We try to load it as fast as ! possible, loading whole tracks whenever we can. ! ! LOADSEG must be sector aligned and sectors will be loaded upto ! the next 64k boundry past the segment specified by DI. load_sectors: if LOADSEG & $F000 = 0 xor ax,ax else mov ax,#LOADSEG & $F000 ! segment to load to endif mov es,ax ! dx=sectors read of current track ! bx=offset in memory of block ! si=sectors read to block ! al=number to read read_it: mov dx,#2 ! Volume lable + tar header if LOADSEG & $0FFF = 0 xor si,si else mov si,#(LOADSEG & $FFF)>>5 endif add di,#LOADSEG rp_read: if DEBUG call dot endif mov ax,es cmp ax,di ! have we loaded all yet? jbe ok1_read jmp go_go_go ! Loaded, run it. ok1_read: mov ax,sectors ! nr of sectors/track sub ax,dx ! remaining of track mov cx,ax ! cx= remaining add cx,si ! boundary check cmp cl,#128 jbe ok2_read ! ! to much-> fill block mov ax,#128 ! ax=0 sub ax,si ! so much may be read ok2_read: mov bx,si mov cx,#9 shl bx,cl call read_track ! do it mov cx,ax ! cl=read blocks add ax,dx ! ax=new sectors cmp ax,sectors ! track done? jne ok3_read mov ax,#1 ! yes sub ax,head jne ok4_read ! next head inc track ! next track ok4_read: mov head,ax xor ax,ax ok3_read: mov dx,ax add si,cx cmp si,#128 jne rp_read mov ax,es add ah,#0x10 mov es,ax xor si,si jmp rp_read read_track: push dx push ax push bx mov cx,dx mov dx,track inc cx mov ch,dl mov dx,head mov dh,dl and dx,#0x0100 mov ah,#2 int 0x13 ! ah=02h al=nr sectors to read ! ch=cylinder ! cl=sector ! dh=head ! dl=drive ! es:bx=buffer jc bad_rt pop bx pop ax pop dx ret bad_rt: xor ah,ah xor dl,dl int 0x13 pop bx pop ax pop dx jmp read_track !-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ! ! This is the GNU-TAR 'isextended' field. It must be zero or gtar goes apeshit. locn(482) .byte 0 !-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- if DEBUG pboot: mov si,#blk_load nextc: lodsb call putc cmp al,#0 jnz nextc ret endif !-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ! This isn't a hard disk boot sector but give it an HD magic anyway. locn(510) .word 0xAA55 ! From here down is where we load stuff. locn(512) blk_load: ! Address of block load tar_name: .blkb 100 tar_mode: .blkb 8 tar_uid: .blkb 8 tar_gid: .blkb 8 tar_size: .blkb 12 tar_mtime: .blkb 12 tar_chksum: .blkb 8 tar_link: .blkb 1 ! "0" tar_linkname: .blkb 100 tar_magic: .blkb 8 ! "ustar " tar_uname: .blkb 32 tar_gname: .blkb 32 tar_devmaj: .blkb 8 tar_devmin: .blkb 8 tar_padd: locn(1024) probe_buf: .blkb 512 dev86-0.16.21/bootblocks/unix.c000066400000000000000000000111141231050321700160750ustar00rootroot00000000000000 #include "monitor.h" #ifdef __ELKS__ kbhit() { return 0; } getch() { return 3; } static int phy_fd = -1; static open_fd() { phy_fd = open("/tmp/ramdisk", 0); if( phy_fd < 0 ) { fprintf(stderr, "Cannot open /dev/ramdisk\n"); phy_fd= -2; } } _bios_disk_read(drive, cyl, head, sect, len, buffer) int drive, cyl, head, sect, len; char *buffer; { extern long lseek(); int rv = 0; long offset; int i; extern int disk_spt; int spt = 18; if( phy_fd == -1 ) open_fd(); if( phy_fd < 0 ) return -1; if( len <= 0 ) return -1; if( disk_spt > 1 ) spt = disk_spt; offset = (((cyl*2 + head)*(long)spt + sect-1)*512L); fprintf(stderr, "PHY_READ(d%d, c%d, h%d, s%d, l%d, b%d) (Sect=%ld)\n", drive, cyl, head, sect, len, buffer, offset/512); if( lseek(phy_fd, offset, 0) < 0 ) perror("Phyread lseek error\n"); for(i=0; i< len; i++) { rv = read(phy_fd, buffer, 512); if( rv < 0 ) perror("Phyread read error\n"); buffer+=512; } if( rv < 0 ) return -1; return 0; } _bios_disk_reset() { } motor_running() { return 1; } #if 0 putsect(buffer, address) char * buffer; int address; { fprintf(stderr, "Sector write from DS:%04x to 0000:%04x00\n", buffer, address); return 0; } #endif #endif /* crctab calculated by Mark G. Mendel, Network Systems Corporation */ static unsigned short crctab[256] = { 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49, 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067, 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634, 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3, 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0 }; /* * updcrc macro derived from article Copyright (C) 1986 Stephen Satchell. * NOTE: First srgument must be in range 0 to 255. * Second argument is referenced twice. * * Programmers may incorporate any or all code into their programs, * giving proper credit within the source. Publication of the * source routines is permitted so long as proper credit is given * to Stephen Satchell, Satchell Evaluations and Chuck Forsberg, * Omen Technology. */ #define updcrc(cp, crc) ( crctab[((crc >> 8) & 255)] ^ (crc << 8) ^ cp) static unsigned short crc = 0; reset_crc() { crc = 0; } addcrc(buffer, len) unsigned char * buffer; int len; { while(len>0) { crc = updcrc((*buffer++), crc); len--; } } display_crc(str) char * str; { if( str ) printf("%s 0x%04x\n", str, crc); return crc; } dev86-0.16.21/bootblocks/zimage.s000066400000000000000000000020111231050321700164020ustar00rootroot00000000000000! ! This is a short helper to copy a zImage from high memory to low memory ! then call it. ! org $1000 Start: xor ax,ax mov ds,ax mov es,ax mov ss,ax mov sp,#Start mov di,#8 nextpg: mov cx,#$8000 mov ah,#$87 mov si,#GDT int $15 jnc no_err ! If there's an error reset. jmpi $0000,$FFFF no_err: inc srcaddr inc destaddr dec di jnz nextpg ! Call the Image (same as bzImage) go: ! Kill the floppy motor, needed in case the kernel has no floppy driver. mov dx,#0x3f2 xor al, al outb ! Setup required registers and go ... mov ax,#$9000 mov bx,#$4000-12 ! Fix this to use boot_mem_top mov es,ax mov fs,ax mov gs,ax mov ds,ax mov ss,ax mov sp,bx jmpi 0,$9020 ! Note SETUPSEG NOT INITSEG ! The global descriptor table. GDT: .word $0000,$0000 .word $0000,$0000 .word $0000,$0000 .word $0000,$0000 .word $FFFF,$0000 srcaddr: .word $9310,$0000 .word $FFFF,$0000 destaddr: .word $9301,$0000 .word $0000,$0000 .word $0000,$0000 .word $0000,$0000 .word $0000,$0000 dev86-0.16.21/copt/000077500000000000000000000000001231050321700135545ustar00rootroot00000000000000dev86-0.16.21/copt/Makefile000066400000000000000000000001421231050321700152110ustar00rootroot00000000000000 copt: copt.c $(CC) $(ANSI) $(CFLAGS) $(LDFLAGS) -o $@ copt.c realclean clean: rm -f *.o copt dev86-0.16.21/copt/README000066400000000000000000000014231231050321700144340ustar00rootroot00000000000000 From gero@gkminix.han.de Thu Jan 30 19:54:34 1997 Date: Wed, 29 Jan 1997 23:46:50 +0100 (MET) From: Gero Kuhlmann Subject: Re: 8086 Development environment Hello again, And one hint for using the optimizer I sent you in an earlier mail: the order of the rules files matters! You should try: copt -c! -h"use16 386" rules.start rules.386 rules.86 rules.end If you don't want to optimize for 386 long integer operations, you can leave out the -h option and the rules.386 file. The rules.net file is only necessary for my bootrom code, and does some optimizations I can't do with preprocessor commands. gero. >-- Life sucks, but it's better than the alternative. - Peter da Silva -- Gero Kuhlmann, Hannover 0511/6497525 (Voice) gero@gkminix.han.de dev86-0.16.21/copt/copt.c000066400000000000000000000451271231050321700146760ustar00rootroot00000000000000/* ************************************************************************** * * Utility program to optimize the output of the BCC compiler * * Module: copt.c * Purpose: Optimize BCC assembler output * Entries: main * * This program is based on an idea from Christopher W. Fraser. * ************************************************************************** * * Copyright (C) 1995,1996,1997 Gero Kuhlmann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* #include "utility.h" #include "../../headers/general.h" #include "../../headers/version.h" */ #include #include #include #include #define KEEPCOMMENTS #define MAXLINE 1024 #ifdef __BCC__ #define HASHSIZE 107 #else #define HASHSIZE 1999 #endif #define NOCHAR '\177' #define VARNUM 10 /* Struct containing each string of an input file */ struct line_s { char *text; struct line_s *prev; struct line_s *next; int comment_flg; }; /* Struct containing one rule */ struct rule_s { struct line_s *old; struct line_s *new; struct rule_s *next; }; /* Hash table to store strings in a space saving way */ struct hash_s { char *text; struct hash_s *next; }; /* * Global variables */ static struct rule_s *first = NULL; /* first rule */ static struct rule_s *last = NULL; /* last rule */ static struct line_s *infile = NULL; /* list of strings in input file */ static struct hash_s *htab[HASHSIZE]; /* string hash table */ static int hash_init = 0; /* flag if hash table initialized */ static char *vars[VARNUM]; /* variable table */ static char *progname; /* program name */ /* * Allocate memory and print error if none available */ static void *mymalloc(int size) { void *p; if ((p = malloc(size)) == NULL) { fprintf(stderr, "%s: no memory\n", progname); exit(1); } return(p); } /* * Insert a string into the hash table. If the string is already in there * just return the pointer to that string. */ static char *install(char *str, int slen) { struct hash_s *hp; char *chkstr; char *cp; unsigned int hashval; /* Clear the hashing table if not already done */ if (!hash_init) { for (hashval = 0; hashval < HASHSIZE; hashval++) htab[hashval] = NULL; hash_init++; } /* Get check string */ if (slen < 0) slen = strlen(str); chkstr = mymalloc(slen + 1); strncpy(chkstr, str, slen); chkstr[slen] = '\0'; /* Determine hashing value of string */ hashval = 0; for (cp = chkstr; *cp; cp++) hashval = hashval*75 + *cp; hashval %= HASHSIZE; /* Check if the string is already in the hashing table */ for (hp = htab[hashval]; hp != NULL; hp = hp->next) if (!strcmp(chkstr, hp->text)) { free(chkstr); return(hp->text); } /* String is not in hash table, so create a new entry */ hp = (struct hash_s *)mymalloc(sizeof(struct hash_s)); hp->text = chkstr; hp->next = htab[hashval]; htab[hashval] = hp; return(hp->text); } /* * Read one line from input file and skip all blanks at the beginning */ static char *readline(FILE *fp) { static char buf[MAXLINE]; char *cp; /* Read line from input file */ if (fgets(buf, MAXLINE-1, fp) == NULL) return(NULL); buf[MAXLINE-1] = '\0'; /* Delete trailing newline */ if ((cp = strchr(buf, '\n')) != NULL) *cp = '\0'; /* Delete leading white spaces */ for (cp = buf; *cp && isspace(*cp); cp++) ; if (cp != buf && *cp) memmove(buf, cp, strlen(cp) + 1); return(buf); } /* * Read a list of input lines. Terminate reading when the 'quit' character * has been found in the first column of the input line. All lines with the * 'comment' character in the first position will be skipped. */ static struct line_s *readlist(FILE *fp, int quit, int comment) { struct line_s *lp; struct line_s *first_line = NULL; struct line_s *last_line = NULL; char *cp; while ((cp = readline(fp)) != NULL) { if (quit != NOCHAR && quit == *cp) break; if (comment != NOCHAR && comment == *cp) if (quit != NOCHAR) continue; if (*cp == '\0') continue; lp = mymalloc(sizeof(struct line_s)); lp->text = install(cp, -1); lp->prev = last_line; lp->next = NULL; lp->comment_flg = (comment != NOCHAR && *cp == comment); if (first_line == NULL) first_line = lp; if (last_line != NULL) last_line->next = lp; last_line = lp; } return(first_line); } /* * Read pattern file */ static void readpattern(char *rulesdir, char *filename) { static char path[MAXLINE]; struct rule_s *rp; FILE *fp; /* Open pattern file */ if (rulesdir != NULL) sprintf(path, "%s/%s", rulesdir, filename); else sprintf(path, "%s", filename); if ((fp = fopen(path, "r")) == NULL) { fprintf(stderr, "%s: can't open pattern file %s\n", progname, path); exit(1); } /* Read every line of the pattern file */ while (!feof(fp)) { rp = (struct rule_s *)mymalloc(sizeof(struct rule_s)); rp->old = readlist(fp, '=', '#'); rp->new = readlist(fp, '\0', '#'); if (rp->old == NULL || rp->new == NULL) { free(rp); break; } /* This put the rules into the table in reverse order; this is confusing * rp->next = first; first = rp; if (last == NULL) last = rp; */ rp->next = NULL; if (last) { last->next = rp; last = rp; } else { first = last = rp; } } /* Close pattern file */ (void)fclose(fp); } /* * Clear pattern list to allow for another run */ static void clearpattern(void) { struct rule_s *rp1, *rp2; struct line_s *lp1, *lp2; rp1 = first; while (rp1 != NULL) { /* Clear old rule text list */ lp1 = rp1->old; while (lp1 != NULL) { lp2 = lp1; lp1 = lp1->next; free(lp2); } /* Clear new rule text list */ lp1 = rp1->new; while (lp1 != NULL) { lp2 = lp1; lp1 = lp1->next; free(lp2); } /* Clear rule itself */ rp2 = rp1; rp1 = rp1->next; free(rp2); } first = NULL; last = NULL; } /* * Read input file */ static void readinfile(char *filename, int comment) { FILE *fp; fp = stdin; if (filename != NULL && (fp = fopen(filename, "r")) == NULL) { fprintf(stderr, "%s: can't open input file %s\n", progname, filename); exit(1); } infile = readlist(fp, NOCHAR, comment); if (fp != stdin) (void)fclose(fp); } #define NO_OP 0 #define ADD_OP 1 #define SUB_OP 2 #define MUL_OP 3 #define DIV_OP 4 #define SHL_OP 5 #define SHR_OP 6 long retval = 0; long num = 0; int sign = 1; int base = 10; int op = NO_OP; /* Apply operation to current numeric value */ static void doretval(void) { switch (op) { case NO_OP: retval = num * sign; break; case ADD_OP: retval += num * sign; break; case SUB_OP: retval -= num * sign; break; case MUL_OP: retval *= num * sign; break; case DIV_OP: retval /= num * sign; break; case SHL_OP: retval <<= num; break; case SHR_OP: retval >>= num; break; } op = NO_OP; num = 0; sign = 1; base = 10; } /* * Eval an expression into an integer number */ static long eval(char *str, int len) { char *cp, c; int state = 0; int i, varnum; retval = 0; num = 0; sign = 1; base = 10; op = NO_OP; /* Scan through whole string and decode it */ for (cp = str, i = 0; *cp && i < len; cp++, i++) { c = toupper(*cp); if (c == '-' && (state == 0 || state == 5)) { state = 1; sign = -1; } else if (c == '+' && (state == 0 || state == 5)) { state = 1; sign = 1; } else if (c == '%' && isdigit(*(cp + 1)) && (state < 2 || state == 5)) { state = 4; varnum = *(cp + 1) - '0'; if (vars[varnum] == NULL || i >= len) return(0); num = eval(vars[varnum], strlen(vars[varnum])); doretval(); cp++; i++; } else if (c == '$' && (state < 2 || state == 5)) { state = 2; base = 16; } else if (base == 10 && (c >= '0' && c <= '9') && (state <= 3 || state == 5)) { state = 3; num = num * 10 + (c - '0'); } else if (base == 16 && ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F')) && (state <= 3 || state == 5)) { state = 3; num = num * 16 + (c >= 'A' ? c - '0' - 7 : c - '0'); } else if (c == ' ' && (state == 3 || state == 4 || state == 5)) { if (state == 3) { doretval(); state = 4; } } else if (strchr("+-*/<>", c) != NULL && (state == 3 || state == 4)) { if (state == 3) doretval(); state = 5; switch (c) { case '+': op = ADD_OP; break; case '-': op = SUB_OP; break; case '*': op = MUL_OP; break; case '/': op = DIV_OP; break; case '<': op = SHL_OP; break; case '>': op = SHR_OP; break; } } else return(0); } /* Check if the string has been terminated correctly */ if (state != 3 && state != 4) return(0); if (state == 3) doretval(); return(retval); } /* * Compare an infile string with a pattern string. If there is any variable * defined, it will be inserted into the variable list from the pattern * string. */ static int match(char *ins, char *pat) { char *cp, *oldpat; long val; int varnum; int len = 0; while (*ins && *pat) { if (pat[0] != '%') { if (*pat++ != *ins++) return(0); else continue; } if (pat[1] == '%') { /* '%%' actually means '%' */ if (*ins != '%') return(0); pat += 2; } else if ((pat[1] == '*' || isdigit(pat[1]))) { /* Copy variable text into vars array */ pat += 2; for (cp = ins; *ins && !match(ins, pat); ins++) ; if (pat[-1] == '*') continue; len = ins - cp; varnum = pat[-1] - '0'; if (vars[varnum] == NULL) vars[varnum] = install(cp, len); else if (strlen(vars[varnum]) != len || strncmp(vars[varnum], cp, len)) return(0); } else if (pat[1] == '[') { /* Copy only specific variable text into vars array */ if ((cp = strchr(pat + 2, ']')) == NULL || (*(cp + 1) != '*' && !isdigit(*(cp + 1)))) { if (*ins != '[') return(0); pat += 2; continue; } oldpat = pat + 1; pat = cp + 2; /* Seperate allowable patterns and compare them with ins */ while (*oldpat && *oldpat != ']') { oldpat++; len = strcspn(oldpat, "|]"); if (!strncmp(ins, oldpat, len)) break; oldpat += len; } if (!*oldpat || *oldpat == ']') return(0); ins += len; if (!match(ins, pat)) return(0); /* Install new string into variable table */ if (*(cp + 1) == '*') continue; varnum = *(cp + 1) - '0'; if (vars[varnum] == NULL) vars[varnum] = install(oldpat, len); else if (strlen(vars[varnum]) != len || strncmp(vars[varnum], oldpat, len)) return(0); } else if (pat[1] == '!') { /* Match only if the pattern string is not found */ if (pat[2] != '[' || (cp = strchr(pat + 3, ']')) == NULL) { if (*ins != '!') return(0); pat += 3; continue; } oldpat = pat + 2; pat = cp + 1; /* Seperate allowable patterns and compare them with ins */ while (*oldpat && *oldpat != ']') { oldpat++; len = strcspn(oldpat, "|]"); if (!strncmp(ins, oldpat, len)) return(0); oldpat += len; } } else if (pat[1] == '(') { /* Match ins with expression */ if ((cp = strchr(pat + 2, ')')) == NULL) { if (*ins != '(') return(0); pat += 2; continue; } oldpat = pat + 2; pat = cp + 1; len = cp - oldpat; val = eval(oldpat, len); for (cp = ins; *ins && !match(ins, pat); ins++) ; len = ins - cp; if (val != eval(cp, len)) return(0); } else /* Bad % format cannot match */ return(0); } return(*ins == *pat); } /* * Substitute variables in a string */ static char *subst(char *pat) { char buf[MAXLINE]; char *cp, *cp1, *cp2, *varptr; long num; int i = 0; int j, pos; while (*pat) if (pat[0] == '%' && isdigit(pat[1])) { /* Substitute with value of variable */ cp = vars[pat[1] - '0']; while (cp != NULL && *cp) { buf[i++] = *cp++; if (i >= MAXLINE - 1) { fprintf(stderr, "%s: line too long\n", progname); exit(1); } } pat += 2; } else if (pat[0] == '%' && pat[1] == '(') { /* Substitute with expression */ cp = pat + 2; if ((pat = strchr(cp, ')')) == NULL || pat - cp <= 0) num = 0; else num = eval(cp, pat - cp); if (i >= MAXLINE - 20) { fprintf(stderr, "%s: line too long\n", progname); exit(1); } i += sprintf(&buf[i], "%s$%lx", num < 0 ? "-" : "", labs(num)); pat++; } else if (pat[0] == '%' && pat[1] == '=') { /* Substitute with converted variable */ /* First seperate all parts of the pattern string */ cp = pat + 2; cp1 = cp2 = varptr = NULL; if (*cp == '[') { cp1 = ++cp; while (*cp && *cp != ']') cp++; if (cp[0] == ']' && cp[1] == '[') { cp += 2; cp2 = cp; while (*cp && *cp != ']') cp++; if (cp[0] == ']' && isdigit(cp[1])) varptr = vars[cp[1] - '0']; } } if (cp1 == NULL || cp2 == NULL || varptr == NULL) { buf[i++] = *pat++; if (i >= MAXLINE - 1) { fprintf(stderr, "%s: line too long\n", progname); exit(1); } continue; } pat = cp + 2; /* Now scan through the first string to find variable value */ cp1--; pos = 0; while (*cp1 != ']') { cp1++; j = strcspn(cp1, "|]"); if (strlen(varptr) == j && !strncmp(cp1, varptr, j)) break; pos++; cp1 += j; } if (*cp1 == ']') continue; /* Scan through the second string to find the conversion */ cp2--; while (*cp2 != ']' && pos > 0) { cp2++; j = strcspn(cp2, "|]"); pos--; cp2 += j; } if (*cp2 == ']' || pos != 0) continue; /* Insert conversion string into destination */ cp2++; while (*cp2 != '|' && *cp2 != ']') { buf[i++] = *cp2++; if (i >= MAXLINE - 1) { fprintf(stderr, "%s: line too long\n", progname); exit(1); } } } else { buf[i++] = *pat++; if (i >= MAXLINE - 1) { fprintf(stderr, "%s: line too long\n", progname); exit(1); } } buf[i] = '\0'; return(install(buf, i)); } /* * Optimize one line of the input file */ static struct line_s *optline(struct line_s *cur) { struct rule_s *rp; struct line_s *ins, *pat; struct line_s *lp1, *lp2; int i; for (rp = first; rp != NULL; rp = rp->next) { /* Clear variable array */ for (i = 0; i < VARNUM; i++) vars[i] = NULL; /* Scan through pattern texts and match them against the input file */ ins = cur; pat = rp->old; while (ins != NULL && pat != NULL && ( ins->comment_flg || ( /* (pat->text[0]=='%' || ins->text[0]==pat->text[0]) && */ match(ins->text, pat->text)))) { if (!ins->comment_flg) pat = pat->next; else if (ins->text[0]==pat->text[0]) /* Matching a comment! */ { if (match(ins->text, pat->text)) pat = pat->next; } ins = ins->next; } /* Current pattern matched input line, so replace input with new */ if (pat == NULL) { /* Clear all lines in the source file for this pattern */ lp1 = cur; cur = cur->prev; while (lp1 != ins) { #if 0 if( lp1->comment_flg ) { lp2 = lp1; lp1 = lp1->next; lp2->next = cur->next; cur->next = lp2; lp2->prev = cur; cur=cur->next; } else #endif { lp2 = lp1; lp1 = lp1->next; free(lp2); } } /* Insert new lines into list */ pat = rp->new; lp1 = cur; lp2 = NULL; while (pat != NULL) { lp2 = mymalloc(sizeof(struct line_s)); lp2->text = subst(pat->text); lp2->next = NULL; lp2->prev = lp1; lp2->comment_flg = 0; if (lp1 != NULL) lp1->next = lp2; else infile = lp2; lp1 = lp2; pat = pat->next; } if (ins != NULL) ins->prev = lp2; if (lp2 != NULL) lp2->next = ins; else if (lp1 != NULL) lp1->next = NULL; else infile = NULL; return(cur); } } return(cur->next); } /* * Actually optimize all strings in the input file */ static void optimize(int backup) { struct line_s *cur, *lp; int i; int in_asm = 0; /* Scan through all lines in the input file */ cur = infile; while (cur != NULL) { if (cur->comment_flg || in_asm) { lp=cur->next; if (memcmp(cur->text, "!BCC_", 5) == 0) in_asm = (memcmp(cur->text+5, "ASM", 3) == 0); } else if ((lp = optline(cur)) != NULL && lp != cur->next) { for (i = 0; i < backup && lp != NULL; i++) lp = lp->prev; if (lp == NULL) lp = infile; } cur = lp; } } /* * Write out into destination file */ static void writeoutf(char *filename, char *headstr) { FILE *fp; struct line_s *lp; fp = stdout; if (filename != NULL && (fp = fopen(filename, "w")) == NULL) { fprintf(stderr, "%s: can't open output file %s\n", progname, filename); exit(1); } if (headstr != NULL) { fprintf(fp, "%s", headstr); fprintf(fp, "\n"); } for (lp = infile; lp != NULL; lp = lp->next) fprintf(fp, "%s\n", lp->text); if (fp != stdout) (void)fclose(fp); } /* * Print usage */ static void usage(void) { fprintf(stderr, "usage: %s [-c] [-f] [-o]\n" "\t\t[-b] [-h] [-d] " " ...\n", progname); exit(1); } /* * Main program */ int main(int argc, char **argv) { char comment = NOCHAR; char *srcfile = NULL; char *outfile = NULL; char *headstr = NULL; char *rulesdir = NULL; int backup = 0; int i; /* Get program name */ if ((progname = strrchr(argv[0], '/')) == NULL) progname = argv[0]; else progname++; /* Make life easy for bcc */ if ( argc > 4 && strcmp(argv[2], "-o") == 0 && argv[1][0] != '-' ) { srcfile = argv[1]; argv++,argc--; } /* Get options from command line */ for (i = 1; i < argc; i++) if (!strncmp(argv[i], "-c", 2)) comment = argv[i][2]; else if (!strncmp(argv[i], "-b", 2)) backup = atoi(&(argv[i][3])); else if (!strncmp(argv[i], "-f", 2)) srcfile = &(argv[i][2]); else if (!strncmp(argv[i], "-o", 2)) { if(argv[i][2]) outfile = &(argv[i][2]); else if(++i> 8) mov ax,%[#|*]0%1 push ax call __htons inc sp inc sp = mov ax,#((%1 & $00FF) << 8) + ((%1 & $FF00) >> 8) push %0[%1] call __htons inc sp inc sp = mov ax,%0[%1] xchg al,ah push ax call __htons inc sp inc sp = xchg al,ah push %[bx|cx|dx]1 call __htons inc sp inc sp = mov ax,%1 xchg al,ah call ___get_ds = mov ax,ds call ___get_es = mov ax,es call ___get_cs = mov ax,cs push word %[#|*]0%1 call ___set_es inc sp inc sp = mov ax,%0%1 mov es,ax mov ax,%[#|*]0%1 push ax call ___set_es inc sp inc sp = mov ax,%0%1 mov es,ax push %0[%1] call ___set_es inc sp inc sp = mov ax,%0[%1] mov es,ax push %[ax|bx|cx|dx]1 call ___set_es inc sp inc sp = mov es,%1 push word %[#|*]0%1 call ___deek_es inc sp inc sp = seg es mov ax,[%1] mov ax,%[#|*]0%1 push ax call ___deek_es inc sp inc sp = seg es mov ax,[%1] push %0[%1] call ___deek_es inc sp inc sp = mov bx,%0[%1] seg es mov ax,[bx] push bx call ___deek_es inc sp inc sp = seg es mov ax,[bx] push %[ax|cx|dx]1 call ___deek_es inc sp inc sp = mov bx,%1 seg es mov ax,[bx] push word %[#|*]0%1 call ___peek_es inc sp inc sp = seg es mov al,[%1] xor ah,ah mov ax,%[#|*]0%1 push ax call ___peek_es inc sp inc sp = seg es mov al,[%1] xor ah,ah push %0[%1] call ___peek_es inc sp inc sp = mov bx,%0[%1] seg es mov al,[bx] xor ah,ah push bx call ___peek_es inc sp inc sp = seg es mov al,[bx] xor ah,ah push %[ax|cx|dx]1 call ___peek_es inc sp inc sp = mov bx,%1 seg es mov al,[bx] xor ah,ah push word %[#|*]0%1 call ___poke_es add sp,*4 = pop ax seg es mov [%1],al mov ax,%[#|*]0%1 push ax call ___poke_es add sp,*4 = pop ax seg es mov [%1],al pmov ax,%[#|*]0%1 push ax call ___poke_es add sp,*4 = seg es mov [%1],al push %0[%1] call ___poke_es add sp,*4 = mov bx,%0[%1] pop ax seg es mov [bx],al push bx call ___poke_es add sp,*4 = pop ax seg es mov [bx],al push %[ax|cx|dx]1 call ___poke_es add sp,*4 = mov bx,%1 pop ax seg es mov [bx],al push word %[#|*]0%1 call ___doke_es add sp,*4 = pop ax seg es mov [%1],ax mov ax,%[#|*]0%1 push ax call ___doke_es add sp,*4 = pop ax seg es mov [%1],ax pmov ax,%[#|*]0%1 push ax call ___doke_es add sp,*4 = seg es mov [%1],ax push %0[%1] call ___doke_es add sp,*4 = mov bx,%0[%1] pop ax seg es mov [bx],ax push bx call ___doke_es add sp,*4 = pop ax seg es mov [bx],ax push %[ax|cx|dx]1 call ___doke_es add sp,*4 = mov bx,%1 pop ax seg es mov [bx],ax push ax mov bx,%1 pop ax = mov bx,%1 push %1 pop ax = mov ax,%1 mov ax,ax = !mov ax,ax dev86-0.16.21/copt/rules.net000066400000000000000000000007631231050321700154240ustar00rootroot00000000000000# Rules for optimizing BCC assembler output # Rules for converting short number from host to network order push word %[#|*]0%1 call __htons inc sp inc sp = mov ax,#((%1 & $00FF) << 8) + ((%1 & $FF00) >> 8) mov ax,%[#|*]0%1 push ax call __htons inc sp inc sp = mov ax,#((%1 & $00FF) << 8) + ((%1 & $FF00) >> 8) push %0[%1] call __htons inc sp inc sp = mov ax,%0[%1] xchg al,ah push ax call __htons inc sp inc sp = xchg al,ah push %[bx|cx|dx]1 call __htons inc sp inc sp = mov ax,%1 xchg al,ah dev86-0.16.21/copt/rules.start000066400000000000000000000003551231050321700157700ustar00rootroot00000000000000# Rules to optimize BCC assembler output # The following rules protect the procedure prolog and epilogue from # getting optimized away in later steps push bp mov bp,sp push di push si = proc_start pop si pop di pop bp ret = proc_end dev86-0.16.21/cpp/000077500000000000000000000000001231050321700133715ustar00rootroot00000000000000dev86-0.16.21/cpp/Makefile000066400000000000000000000010731231050321700150320ustar00rootroot00000000000000CFLAGS=-Wall -Wstrict-prototypes all: bcc-cpp bcc-cpp: main.o cpp.o hash.o token1.o token2.o $(CC) $(CFLAGS) -o bcc-cpp main.o cpp.o hash.o token1.o token2.o clean realclean: rm -f bcc-cpp main.o cpp.o hash.o token1.o token2.o tmp.h maintclean: realclean rm -f token1.h token2.h main.o: cc.h cpp.o: cc.h hash.o: cc.h tree.o: cc.h token1.o: token1.h token2.o: token2.h token1.h: token1.tok gperf -aptTc -N is_ctok -H hash1 token1.tok > tmp.h mv tmp.h token1.h token2.h: token2.tok gperf -aptTc -k1,3 -N is_ckey -H hash2 token2.tok > tmp.h mv tmp.h token2.h dev86-0.16.21/cpp/cc.h000066400000000000000000000060321231050321700141300ustar00rootroot00000000000000 #ifndef P #if __STDC__ #define P(x) x #else #define P(x) () #endif #endif extern void cfatal P((char*)); extern void cerror P((char*)); extern void cwarn P((char*)); extern FILE * open_include P((char*, char*, int)); extern FILE * curfile; extern char curword[]; extern char * c_fname; extern int c_lineno; extern int alltok; extern int dialect; #define DI_KNR 1 #define DI_ANSI 2 extern int gettok P((void)); struct token_trans { char * name; int token; }; struct token_trans * is_ctok P((const char *str, unsigned int len)); struct token_trans * is_ckey P((const char *str, unsigned int len)); #define WORDSIZE 128 #define TK_WSPACE 256 #define TK_WORD 257 #define TK_NUM 258 #define TK_FLT 259 #define TK_QUOT 260 #define TK_STR 261 #define TK_FILE 262 #define TK_LINE 263 #define TK_COPY 264 #define TKS_CTOK 0x200 #define TKS_CKEY 0x300 #define TK_NE_OP (TKS_CTOK+ 0) #define TK_MOD_ASSIGN (TKS_CTOK+ 1) #define TK_AND_OP (TKS_CTOK+ 2) #define TK_AND_ASSIGN (TKS_CTOK+ 3) #define TK_MUL_ASSIGN (TKS_CTOK+ 4) #define TK_INC_OP (TKS_CTOK+ 5) #define TK_ADD_ASSIGN (TKS_CTOK+ 6) #define TK_DEC_OP (TKS_CTOK+ 7) #define TK_SUB_ASSIGN (TKS_CTOK+ 8) #define TK_PTR_OP (TKS_CTOK+ 9) #define TK_ELLIPSIS (TKS_CTOK+10) #define TK_DIV_ASSIGN (TKS_CTOK+11) #define TK_LEFT_OP (TKS_CTOK+12) #define TK_LEFT_ASSIGN (TKS_CTOK+13) #define TK_LE_OP (TKS_CTOK+14) #define TK_EQ_OP (TKS_CTOK+15) #define TK_GE_OP (TKS_CTOK+16) #define TK_RIGHT_OP (TKS_CTOK+17) #define TK_RIGHT_ASSIGN (TKS_CTOK+18) #define TK_XOR_ASSIGN (TKS_CTOK+19) #define TK_OR_ASSIGN (TKS_CTOK+20) #define TK_OR_OP (TKS_CTOK+21) #define TK_AUTO (TKS_CKEY+ 0) #define TK_BREAK (TKS_CKEY+ 1) #define TK_CASE (TKS_CKEY+ 2) #define TK_CHAR (TKS_CKEY+ 3) #define TK_CONST (TKS_CKEY+ 4) #define TK_CONTINUE (TKS_CKEY+ 5) #define TK_DEFAULT (TKS_CKEY+ 6) #define TK_DO (TKS_CKEY+ 7) #define TK_DOUBLE (TKS_CKEY+ 8) #define TK_ELSE (TKS_CKEY+ 9) #define TK_ENUM (TKS_CKEY+10) #define TK_EXTERN (TKS_CKEY+11) #define TK_FLOAT (TKS_CKEY+12) #define TK_FOR (TKS_CKEY+13) #define TK_GOTO (TKS_CKEY+14) #define TK_IF (TKS_CKEY+15) #define TK_INT (TKS_CKEY+16) #define TK_LONG (TKS_CKEY+17) #define TK_REGISTER (TKS_CKEY+18) #define TK_RETURN (TKS_CKEY+19) #define TK_SHORT (TKS_CKEY+20) #define TK_SIGNED (TKS_CKEY+21) #define TK_SIZEOF (TKS_CKEY+22) #define TK_STATIC (TKS_CKEY+23) #define TK_STRUCT (TKS_CKEY+24) #define TK_SWITCH (TKS_CKEY+25) #define TK_TYPEDEF (TKS_CKEY+26) #define TK_UNION (TKS_CKEY+27) #define TK_UNSIGNED (TKS_CKEY+28) #define TK_VOID (TKS_CKEY+29) #define TK_VOLATILE (TKS_CKEY+30) #define TK_WHILE (TKS_CKEY+31) #define MAX_INCLUDE 64 /* Nested includes */ #define MAX_DEFINE 64 /* Nested defines */ extern char * set_entry P((int,char*,void*)); extern void * read_entry P((int,char*)); struct define_item { struct define_arg * next; char * name; int arg_count; /* -1 = none; >=0 = brackets with N args */ int in_use; /* Skip this one for looking up #defines */ int varargs; /* No warning if unexpected arguments. */ char value[1]; /* [arg,]*value */ }; dev86-0.16.21/cpp/cpp.c000066400000000000000000001061251231050321700143240ustar00rootroot00000000000000 #include #include #ifdef __STDC__ #include #else #include #endif #include "cc.h" #define CPP_DEBUG 0 /* LOTS of junk to stderr. */ /* * This file comprises the 'guts' of a C preprocessor. * * Functions exported from this file: * gettok() Returns the next token from the source * curword contains the text of the token * * Variables * curword Contains the text of the last token parsed. * curfile Currently open primary file * c_fname Name of file being parsed * c_lineno Current line number in file being parsed. * * alltok Control flag for the kind of tokens you want (C or generic) * dialect Control flag to change the preprocessor for Ansi C. * * TODO: * #asm -> asm("...") translation. * ?: in #if expressions * Complete #line directive. * \n in "\n" in a stringized argument. * Comments in stringized arguments should be deleted. * * Poss: Seperate current directory for #include from errors (#line). * (For editors that hunt down source files) * Poss: C99 Variable macro args. */ #define KEEP_SPACE 0 #define SKIP_SPACE 1 #define EOT 4 #define SYN 22 char curword[WORDSIZE]; int alltok = 0; int dialect = 0; FILE * curfile; char * c_fname; int c_lineno = 0; #ifdef __BCC__ typedef long int_type; /* Used for preprocessor expressions */ #else typedef int int_type; /* Used for preprocessor expressions */ #endif static int curtok = 0; /* Used for preprocessor expressions */ static int fi_count = 0; static FILE * saved_files[MAX_INCLUDE]; static char * saved_fname[MAX_INCLUDE]; static int saved_lines[MAX_INCLUDE]; static char * def_ptr = 0; static char * def_start = 0; static struct define_item * def_ref = 0; static int def_count =0; static char * saved_def[MAX_DEFINE]; static char * saved_start[MAX_DEFINE]; static long saved_unputc[MAX_DEFINE]; static struct define_item * saved_ref[MAX_DEFINE]; static long unputc = 0; static int last_char = '\n'; static int in_preproc = 0; static int dont_subst = 0; static int quoted_str = 0; static int if_count = 0; static int if_false = 0; static int if_has_else = 0; static int if_hidden = 0; static unsigned int if_stack = 0; struct arg_store { char * name; char * value; int in_define; }; static int chget P((void)); static int chget_raw P((void)); static void unchget P((int)); static int gettok_nosub P((void)); static int get_onetok P((int)); static int pgetc P((void)); static int do_preproc P((void)); static int do_proc_copy_hashline P((void)); static int do_proc_if P((int)); static void do_proc_include P((void)); static void do_proc_define P((void)); static void do_proc_undef P((void)); static void do_proc_else P((void)); static void do_proc_endif P((void)); static void do_proc_tail P((void)); static int get_if_expression P((void)); static int_type get_expression P((int)); static int_type get_exp_value P((void)); static void gen_substrings P((char *, char *, int, int)); static char * insert_substrings P((char *, struct arg_store *, int)); int gettok() { int ch; for(;;) { /* Tokenised C-Preprocessing */ if (!quoted_str) { if (alltok) ch = get_onetok(KEEP_SPACE); else ch = get_onetok(SKIP_SPACE); if( ch == '"' || ch == '\'' ) quoted_str = ch; if( ch == TK_WORD ) { struct token_trans *p = is_ckey(curword, strlen(curword)) ; if( p ) return p->token; } if (ch == '\n') continue; return ch; } /* Special for quoted strings */ *curword = '\0'; ch = chget(); if( ch == EOF ) return ch; *curword = ch; curword[1] = '\0'; if( ch == quoted_str ) { if( ch == '"' ) { if (dialect == DI_ANSI) { /* Found a terminator '"' check for ansi continuation */ while( (ch = pgetc()) <= ' ' && ch != EOF) ; if( ch == '"' ) continue; unchget(ch); *curword = '"'; curword[1] = '\0'; } quoted_str = 0; return '"'; } else { quoted_str = 0; return ch; } } if( ch == '\n' ) { quoted_str = 0; unchget(ch); /* Make sure error line is right */ return ch; } if( ch == '\\' ) { unchget(ch); ch = get_onetok(KEEP_SPACE); return ch; } return TK_STR; } } static int gettok_nosub() { int rv; dont_subst++; rv=get_onetok(SKIP_SPACE); dont_subst--; return rv; } static int get_onetok(keep) int keep; { char * p; int state; int ch, cc; Try_again: *(p=curword) = '\0'; state=cc=ch=0; /* First skip whitespace, if the arg says so then we need to keep it */ while( (ch = pgetc()) == ' ' || ch == '\t' ) { if (keep == KEEP_SPACE) { if( p < curword + WORDSIZE-1 ) { *p++ = ch; /* Clip to WORDSIZE */ *p = '\0'; } } } if( ch > 0xFF ) return ch; if( p != curword ) { unchget(ch); return TK_WSPACE; } if( ch == '\n') return ch; if( ch == EOF ) return ch; if( ch >= 0 && ch < ' ' ) goto Try_again; for(;;) { switch(state) { case 0: if( (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || ch == '_' || ch == '$' ) state = 1; else if(ch == '0') state = 2; else if(ch >= '1' && ch <= '9') state = 5; else goto break_break; break; case 1: if( (ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || ch == '_' || ch == '$' ) break; else goto break_break; case 2: if( ch >= '0' && ch <= '7') state = 3; else if( ch == 'x' || ch == 'X' ) state = 4; else goto break_break; break; case 3: if( ch >= '0' && ch <= '7') break; else goto break_break; case 4: if( (ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'F') || (ch >= 'a' && ch <= 'f') ) break; else goto break_break; case 5: case 6: if( ch >= '0' && ch <= '9') ; else if( ch == '.' && state != 6 ) state = 6; else if( ch == 'e' || ch == 'E' ) state = 7; else goto break_break; break; case 7: if( ch == '+' || ch == '-' ) break; state = 8; /* FALLTHROUGH */ case 8: if( ch >= '0' && ch <= '9') break; else goto break_break; } if( cc < WORDSIZE-1 ) *p++ = ch; /* Clip to WORDSIZE */ *p = '\0'; cc++; ch = chget(); if (ch == SYN) ch = chget(); } break_break: /* Numbers */ if( state >= 2 ) { if( state < 6 ) { if( ch == 'u' || ch == 'U' ) { if( cc < WORDSIZE-1 ) *p++ = ch; /* Clip to WORDSIZE */ *p = '\0'; cc++; ch = chget(); } if( ch == 'l' || ch == 'L' ) { if( cc < WORDSIZE-1 ) *p++ = ch; /* Clip to WORDSIZE */ *p = '\0'; cc++; } else unchget(ch); return TK_NUM; } unchget(ch); return TK_FLT; } /* Words */ if( state == 1 ) { struct define_item * ptr; unchget(ch); if( !dont_subst && (ptr = read_entry(0, curword)) != 0 && !ptr->in_use ) { if ( def_count >= MAX_DEFINE ) { cwarn("Preprocessor recursion overflow"); return TK_WORD; } else if( ptr->arg_count >= 0 ) { /* An open bracket must follow the word */ int ch1 = 0; while ((ch = chget()) == ' ' || ch == '\t' ) ch1 = ch; if (ch != '(') { unchget(ch); if (ch1) unchget(ch1); return TK_WORD; } /* We have arguments to process so lets do so. */ gen_substrings(ptr->name, ptr->value, ptr->arg_count, ptr->varargs); /* Don't mark macros with arguments as in use, it's very * difficult to say what the correct result would be so * I'm letting the error happen. Also if I do block * recursion then it'll also block 'pseudo' recursion * where the arguments have a call to this macro. * def_ref = ptr; ptr->in_use = 1; */ } else if (ptr->value[0]) { /* Simple direct substitution; note the shortcut (above) for * macros that are defined as null */ saved_ref[def_count] = def_ref; saved_def[def_count] = def_ptr; saved_start[def_count] = def_start; saved_unputc[def_count] = unputc; def_count++; unputc = 0; def_ref = ptr; def_ptr = ptr->value; def_start = 0; ptr->in_use = 1; } goto Try_again; } return TK_WORD; } /* Quoted char for preprocessor expressions */ if(in_preproc && ch == '\'' ) { *p++ = ch; ch = chget(); for(;;) { if( cc < WORDSIZE-1 ) *p++ = ch; /* Clip to WORDSIZE */ *p = '\0'; cc++; if( ch == '\'' || ch == '\n' ) break; if( ch == '\\' ) { ch = chget(); if( cc < WORDSIZE-1 ) *p++ = ch; /* Clip to WORDSIZE */ *p = '\0'; cc++; } ch = chget(); } ch = TK_QUOT; } /* Collect and translate \xyx strings, (should probably translate these * all to some standard form (eg \ooo plus \N ) * * ___________________________________________________________________ * | new-line NL (LF) \n| audible alert BEL \a | * | horizontal tab HT \t| question mark ? \? | * | vertical tab VT \v| double quote " \" | * | backspace BS \b| octal escape ooo \ooo| * | carriage return CR \r| hexadecimal escape hh \xhh| * | formfeed FF \f| backslash \ \\ | * | single quote ' \'| | * |_______________________________|_________________________________| */ if( ch == '\\' ) { int i; *p++ = ch; ch = chget(); if (ch >= '0' && ch <= '7' ) { for(i=0; i<3; i++) { if (ch >= '0' && ch <= '7' ) { *p++ = ch; ch = chget(); } } unchget(ch); } else if (ch == 'x' || ch == 'X') { *p++ = ch; ch = chget(); for(i=0; i<2; i++) { if ( (ch >= '0' && ch <= '9' ) || (ch >= 'A' && ch <= 'F' ) || (ch >= 'a' && ch <= 'f' ) ) { *p++ = ch; ch = chget(); } } unchget(ch); } else if (ch == '?') { p[-1] = '?'; } else if (ch != '\n' && ch != EOF) { *p++ = ch; } else unchget(ch); *p = '\0'; return TK_STR; } /* Possible composite tokens */ if( ch > ' ' && ch <= '~' ) { struct token_trans *tt; *curword = cc = ch; for(state=1; ; state++) { curword[state] = ch = chget(); if( !(tt=is_ctok(curword, state+1)) ) { unchget(ch); curword[state] = '\0'; return cc; } cc=tt->token; } } return ch; } static int pgetc() { int ch, ch1; for(;;) { if ((ch = chget()) == EOF) return ch; if( !in_preproc && last_char == '\n' && ch == '#' ) { in_preproc = 1; ch = do_preproc(); in_preproc = 0; if(if_false || ch == 0) continue; last_char = '\n'; return ch; } if( last_char != '\n' || (ch != ' ' && ch != '\t') ) last_char = ch; /* Remove comments ... */ if( ch != '/' ) { if(if_false && !in_preproc) continue; return ch; } ch1 = chget(); /* Allow "/\\\n*" as comment start too!? */ if( ch1 == '/' ) /* Double slash style comments */ { do { ch = chget(); } while(ch != '\n' && ch != EOF); return ch; /* Keep the return. */ } if( ch1 != '*' ) { unchget(ch1); if(if_false && !in_preproc) continue; return ch; } for(;;) { if( ch == '*' ) { ch = chget(); if( ch == EOF ) return EOF; if( ch == '/' ) break; } else ch = chget(); } if (dialect == DI_ANSI) return ' '; /* If comments become " " */ else return SYN; /* Comments become nulls, but we need a * marker so I can do token concat properly. */ } } /* This function handles the first and second translation phases of Ansi-C */ static int chget() { int ch, ch1; for(;;) { ch = chget_raw(); if (ch == '\\') { ch1 = chget_raw(); if (ch1 == '\n') continue; unchget(ch1); } /* Ansi trigraphs -- Ewww, it needs lots of 'unchget' space too. */ if (dialect == DI_ANSI && ch == '?') { ch1 = chget_raw(); if (ch1 != '?') unchget(ch1); else { static char trig1[] = "()<>/!'-="; static char trig2[] = "[]{}\\|^~#"; char * s; ch1 = chget_raw(); s = strchr(trig1, ch1); if (s) { unchget(trig2[s-trig1]); /* Unchget so that ??/ can be used as */ continue; /* a real backslash at EOL. */ } else { unchget(ch1); unchget('?'); } } } return ch; } } static void unchget(ch) { #if CPP_DEBUG fprintf(stderr, "\b", ch); #endif if(ch == 0) return; /* Hummm */ if(ch == EOF) ch=EOT; /* EOF is pushed back as a normal character. */ ch &= 0xFF; if(unputc&0xFF000000) cerror("Internal character pushback stack overflow"); else unputc = (unputc<<8) + (ch); if( ch == '\n' ) c_lineno--; } static int chget_raw() #if CPP_DEBUG { int ch; static int last_def = 0; static int last_fi = 0; if (last_fi != fi_count) fprintf(stderr, "", fi_count); if (last_def != def_count) fprintf(stderr, "", def_count); last_def = def_count; last_fi = fi_count; ch = realchget(); if (ch == EOF) fprintf(stderr, ""); else fprintf(stderr, "%c", ch); if (last_def != def_count) fprintf(stderr, "", def_count); if (last_fi != fi_count) fprintf(stderr, "", fi_count); last_def = def_count; last_fi = fi_count; return ch; } static int realchget() #endif { int ch; for(;;) { if( unputc ) { if((unputc&0xFF)==EOT && in_preproc) return '\n'; ch=(unputc&0xFF); unputc>>=8; if( ch == EOT ) ch = EOF; if( ch == '\n' ) c_lineno++; return ch; } if( def_ptr ) { ch = *def_ptr++; if(ch) return (unsigned char)ch; if( def_start ) free(def_start); if( def_ref ) def_ref->in_use = 0; def_count--; def_ref = saved_ref[def_count]; def_ptr = saved_def[def_count]; def_start = saved_start[def_count]; unputc = saved_unputc[def_count]; continue; } ch = getc(curfile); if( ch == EOF && fi_count != 0) { fclose(curfile); fi_count--; curfile = saved_files[fi_count]; if(c_fname) free(c_fname); c_fname = saved_fname[fi_count]; c_lineno = saved_lines[fi_count]; ch = '\n'; /* Ensure end of line on end of file */ } else if( ch == '\n' ) c_lineno++; /* Treat all control characters, except the standard whitespace * characters of TAB and NL as completely invisible. */ if( ch >= 0 && ch < ' ' && ch!='\n' && ch!='\t' && ch!=EOF ) continue; if( ch == EOF ) { unchget(ch); return '\n'; } /* Ensure EOL before EOF */ return (unsigned char)ch; } } static int do_preproc() { int val, no_match=0; if( (val=get_onetok(SKIP_SPACE)) == TK_WORD ) { if( strcmp(curword, "ifdef") == 0 ) do_proc_if(0); else if( strcmp(curword, "ifndef") == 0 ) do_proc_if(1); else if( strcmp(curword, "if") == 0 ) do_proc_if(2); else if( strcmp(curword, "elif") == 0 ) do_proc_if(3); else if( strcmp(curword, "else") == 0 ) do_proc_else(); else if( strcmp(curword, "endif") == 0 ) do_proc_endif(); else if(if_false) no_match=1; else { if( strcmp(curword, "include") == 0 ) do_proc_include(); else if( strcmp(curword, "define") == 0 ) do_proc_define(); else if( strcmp(curword, "undef") == 0 ) do_proc_undef(); else if( strcmp(curword, "error") == 0 ) { strcpy(curword, "#error"); do_proc_copy_hashline(); pgetc(); cerror(curword); } else if( strcmp(curword, "warning") == 0 ) { strcpy(curword, "#warning"); do_proc_copy_hashline(); pgetc(); cwarn(curword); } else if( strcmp(curword, "pragma") == 0 ) { do_proc_copy_hashline(); pgetc(); /* Ignore #pragma ? */ } else if( strcmp(curword, "line") == 0 ) { do_proc_copy_hashline(); pgetc(); /* Ignore #line for now. */ } else if( strcmp(curword, "asm") == 0 ) { alltok |= 0x100; return do_proc_copy_hashline(); } else if( strcmp(curword, "endasm") == 0 ) { alltok &= ~0x100; return do_proc_copy_hashline(); } else no_match=1; } } else if (!val) { /* Empty directives used to denote that a file is to be run through * the preprocessor in K&R. Do not complain if we got no token. */ no_match=1; } if( no_match ) { if(!if_false) cerror("Unknown preprocessor directive"); while( val != '\n' ) val = pgetc(); } *curword = 0; /* Just in case */ return 0; } static int do_proc_copy_hashline() { int off, ch; off = strlen(curword); while( (ch=pgetc()) != '\n' ) { if( off < WORDSIZE ) curword[off++] = ch; } if( off == WORDSIZE ) { cerror("Preprocessor directive too long"); curword[WORDSIZE-1] = '\0'; } else curword[off] = '\0'; unchget('\n'); return TK_COPY; } static void do_proc_include() { int ch, ch1; char * p; FILE * fd; ch = get_onetok(SKIP_SPACE); if( ch == '<' || ch == '"' ) { if( ch == '"' ) ch1 = ch; else ch1 = '>'; p = curword; while(p< curword+WORDSIZE-1) { ch = pgetc(); if( ch == '\n' ) break; if( ch == ch1 ) { *p = '\0'; p = strdup(curword); do { ch1 = pgetc(); } while(ch1 == ' ' || ch1 == '\t'); unchget(ch1); do_proc_tail(); saved_files[fi_count] = curfile; saved_fname[fi_count] = c_fname; saved_lines[fi_count] = c_lineno; fd = open_include(p, "r", (ch=='"')); if( fd ) { fi_count++; curfile = fd; } else cerror("Cannot open include file"); return; } *p++ = ch; } } cerror("Bad #include command"); while(ch != '\n') ch = pgetc(); return; } static void do_proc_define() { int ch, ch1; struct define_item * ptr, * old_value = 0; int cc, len; char name[WORDSIZE]; if( (ch=gettok_nosub()) == TK_WORD ) { strcpy(name, curword); ptr = read_entry(0, name); if(ptr) { set_entry(0, name, (void*)0); /* Unset var */ if (ptr->in_use) /* Eeeek! This shouldn't happen; so just let it leak. */ cwarn("macro redefined while it was in use!?"); else old_value = ptr; } /* Skip blanks */ for(ch=ch1=pgetc(); ch == ' ' || ch == '\t' ; ch=pgetc()) ; len = WORDSIZE; ptr = malloc(sizeof(struct define_item) + WORDSIZE); if(ptr==0) cfatal("Preprocessor out of memory"); ptr->value[cc=0] = '\0'; /* Add in arguments */ if( ch1 == '(' ) { ptr->arg_count=0; for(;;) { ch=gettok_nosub(); if( ptr->arg_count==0 && ch == ')' ) break; if( ch == TK_WORD ) { if( cc+strlen(curword)+4 >= len) { len = cc + WORDSIZE; ptr = (struct define_item *) realloc(ptr, sizeof(struct define_item) + len); if(ptr==0) cfatal("Preprocessor out of memory"); } if( cc+strlen(curword) < len) { strcpy(ptr->value+cc, curword); cc+=strlen(curword); strcpy(ptr->value+cc, ","); cc++; ptr->arg_count++; ch=gettok_nosub(); if( ch == TK_ELLIPSIS ) { ptr->varargs = 1; ch=gettok_nosub(); if (ch == ',') ch = '*'; /* Force error if not ')' */ } if( ch == ')' ) break; if( ch == ',' ) continue; } } cerror("Bad #define command"); free(ptr); while(ch != '\n') ch = pgetc(); set_entry(0, name, (void*)old_value); /* Return var to old. */ return; } while((ch=pgetc())==' ' || ch=='\t'); } else ptr->arg_count = -1; /* And the substitution string */ while(ch != '\n') { if( cc+4 > len ) { len = cc + WORDSIZE; ptr = (struct define_item *) realloc(ptr, sizeof(struct define_item) + len); if(ptr==0) cfatal("Preprocessor out of memory"); } ptr->value[cc++] = ch; ch = pgetc(); } if (cc) ptr->value[cc++] = ' ';/* Byte of lookahead for recursive macros */ ptr->value[cc++] = '\0'; #if CPP_DEBUG if (cc == 1) fprintf(stderr, "\n### Define '%s' as null\n", name); else if (ptr->arg_count<0) fprintf(stderr, "\n### Define '%s' as '%s'\n", name, ptr->value); else fprintf(stderr, "\n### Define '%s' as %d args '%s'\n", name, ptr->arg_count, ptr->value); #endif /* Clip to correct size and save */ ptr = (struct define_item *) realloc(ptr, sizeof(struct define_item) + cc); ptr->name = set_entry(0, name, ptr); ptr->in_use = 0; ptr->next = 0; if (old_value) { if (strcmp(old_value->value, ptr->value) != 0) cwarn("#define redefined macro"); free(old_value); } } else cerror("Bad #define command"); while(ch != '\n') ch = pgetc(); } static void do_proc_undef() { int ch; struct define_item * ptr; if( (ch=gettok_nosub()) == TK_WORD ) { ptr = read_entry(0, curword); if(ptr) { set_entry(0, curword, (void*)0); /* Unset var */ if (ptr->in_use) /* Eeeek! This shouldn't happen; so just let it leak. */ cwarn("macro undefined while it was in use!?"); else free(ptr); } do_proc_tail(); } else { cerror("Bad #undef command"); while(ch != '\n') ch = pgetc(); } } static int do_proc_if(type) int type; { int ch = 0; if(if_false && if_hidden) { if( type != 3 ) if_hidden++; do_proc_tail(); return 0; } if( type == 3 ) { if( if_count == 0 ) cerror("#elif without matching #if"); else { if( if_has_else ) cerror("#elif following #else for one #if"); if( if_has_else || if_false != 1 ) { if_false=2; while(ch != '\n') ch = pgetc(); return 0; } if_false=0; } if_has_else = 0; } if(if_false) { if( type != 3 ) if_hidden++; do_proc_tail(); } else { if( type != 3 ) { if_count++; if_stack <<= 1; if_stack |= if_has_else; if_has_else = 0; } if(type > 1) { ch = get_if_expression(); if_false=!ch; } else { ch = gettok_nosub(); if( ch == TK_WORD ) { do_proc_tail(); if_false = (read_entry(0, curword) == 0); if(type == 1) if_false = !if_false; } else { cerror("Bad #if command"); if_false = 0; while(ch != '\n') ch = pgetc(); } } } return 0; } static void do_proc_else() { if( if_hidden == 0 ) { if( if_count == 0 ) cerror("#else without matching #if"); else if_false = (if_false^1); if( if_has_else ) cerror("Multiple #else's for one #if"); if_has_else = 1; } do_proc_tail(); } static void do_proc_endif() { if( if_hidden ) if_hidden--; else { if( if_count == 0 ) cerror("Unmatched #endif"); else { if_count--; if_false=0; if_has_else = (if_stack&1); if_stack >>=1; } } do_proc_tail(); } static void do_proc_tail() { int ch, flg=1; while((ch = pgetc()) != '\n') if(ch > ' ') { if (!if_false && flg) cwarn("Unexpected text following preprocessor command"); flg=0; } } static int get_if_expression() { int value = get_expression(0); if (curtok != '\n') do_proc_tail(); return value; } static int_type get_expression(prio) int prio; { int_type lvalue; int_type rvalue; int no_op = 0; curtok = get_onetok(SKIP_SPACE); lvalue = get_exp_value(); do { switch(curtok) { case '*': case '/': case '%': if (prio >= 10) return lvalue; break; case '+': case '-': if (prio >= 9) return lvalue; break; case TK_RIGHT_OP: case TK_LEFT_OP: if (prio >= 8) return lvalue; break; case '<': case '>': case TK_LE_OP: case TK_GE_OP: if (prio >= 7) return lvalue; break; case TK_EQ_OP: case TK_NE_OP: if (prio >= 6) return lvalue; break; case '&': if (prio >= 5) return lvalue; break; case '^': if (prio >= 4) return lvalue; break; case '|': if (prio >= 3) return lvalue; break; case TK_AND_OP: if (prio >= 2) return lvalue; break; case TK_OR_OP: if (prio >= 1) return lvalue; break; } switch(curtok) { case '*': rvalue = get_expression(10); lvalue *= rvalue; break; case '/': rvalue = get_expression(10); if (rvalue) lvalue /= rvalue; break; case '%': rvalue = get_expression(10); if (rvalue) lvalue %= rvalue; break; case '+': rvalue = get_expression(9); lvalue += rvalue; break; case '-': rvalue = get_expression(9); lvalue -= rvalue; break; case TK_RIGHT_OP: rvalue = get_expression(8); lvalue >>= rvalue; break; case TK_LEFT_OP: rvalue = get_expression(8); lvalue <<= rvalue; break; case '<': rvalue = get_expression(7); lvalue = (lvalue < rvalue); break; case '>': rvalue = get_expression(7); lvalue = (lvalue > rvalue); break; case TK_LE_OP: rvalue = get_expression(7); lvalue = (lvalue <= rvalue); break; case TK_GE_OP: rvalue = get_expression(7); lvalue = (lvalue >= rvalue); break; case TK_EQ_OP: rvalue = get_expression(6); lvalue = (lvalue == rvalue); break; case TK_NE_OP: rvalue = get_expression(6); lvalue = (lvalue != rvalue); break; case '&': rvalue = get_expression(5); lvalue = (lvalue & rvalue); break; case '^': rvalue = get_expression(4); lvalue = (lvalue ^ rvalue); break; case '|': rvalue = get_expression(3); lvalue = (lvalue | rvalue); break; case TK_AND_OP: rvalue = get_expression(2); lvalue = (lvalue && rvalue); break; case TK_OR_OP: rvalue = get_expression(1); lvalue = (lvalue || rvalue); break; case '?': /* XXX: To add */ default: no_op = 1; } } while(prio == 0 && !no_op); return lvalue; } static int_type get_exp_value() { int_type value = 0; int sign = 1; if (curtok == '!') { curtok = get_onetok(SKIP_SPACE); return !get_exp_value(); } if (curtok == '~') { curtok = get_onetok(SKIP_SPACE); return ~get_exp_value(); } while (curtok == '+' || curtok == '-') { if (curtok == '-') sign = -sign; curtok = get_onetok(SKIP_SPACE); } if (curtok == TK_NUM) { value = strtoul(curword, (void*)0, 0); curtok = get_onetok(SKIP_SPACE); } else if (curtok == TK_QUOT) { value = curword[1]; if (value == '\\') { if (curword[2] >= '0' && curword[2] <= '7') { value = curword[2] - '0'; if (curword[3] >= '0' && curword[3] <= '7') { value = (value<<3) + curword[3] - '0'; if (curword[4] >= '0' && curword[4] <= '7') { value = (value<<3) + curword[4] - '0'; } } } else switch(curword[2]) { case 'n': value = '\n'; break; case 'f': value = '\f'; break; case 't': value = '\t'; break; default: value = curword[2]; break; } } #ifdef NATIVE_CPP value = (char) value; /* Fix range */ #elif SIGNED_CHAR value = (signed char) value; #else value = (unsigned char) value; #endif curtok = get_onetok(SKIP_SPACE); } else if (curtok == TK_WORD) { value = 0; if (strcmp("defined", curword) == 0) { curtok = gettok_nosub(); if (curtok == '(' && gettok_nosub() != TK_WORD) cerror("'defined' keyword requires argument"); else { value = (read_entry(0, curword) != 0); if (curtok == '(' && gettok_nosub() != ')') cerror("'defined' keyword requires closing ')'"); else curtok = get_onetok(SKIP_SPACE); } } else curtok = get_onetok(SKIP_SPACE); } else if (curtok == '(') { value = get_expression(0); if (curtok == ')') curtok = get_onetok(SKIP_SPACE); else { curtok = '$'; cerror("Expected ')'"); } } return sign<0 ? -value: value; } void gen_substrings(macname, data_str, arg_count, is_vararg) char * macname; char * data_str; int arg_count; int is_vararg; { char * mac_text = 0; struct arg_store *arg_list; int ac, ch, cc, len; int paren_count = 0; int in_quote = 0; int quote_char = 0; int commas_found = 0; int args_found = 0; arg_list = malloc(sizeof(struct arg_store) * arg_count); memset(arg_list, 0, sizeof(struct arg_store) * arg_count); for(ac=0; *data_str && ac < arg_count; data_str++) { if( *data_str == ',' ) { ac++; continue; } if (arg_list[ac].name == 0) cc = len = 0; if (cc+2 >= len) { len += 20; arg_list[ac].name = realloc(arg_list[ac].name, len); } arg_list[ac].name[cc++] = *data_str; arg_list[ac].name[cc] = '\0'; } for(;;) { if ((ch = chget()) == EOF) break; if(in_quote == 2) { in_quote = 1; } else if (in_quote) { if ( ch == quote_char ) in_quote = 0; if ( ch == '\\') in_quote = 2; } else { if ( ch == '(' ) paren_count++; if ( ch == '"' || ch == '\'' ) { in_quote = 1; quote_char = ch; } if (paren_count == 0 && ch == ',' ) { commas_found++; if (commas_found < arg_count) continue; } if ( ch == ')' ) { if (paren_count == 0) break; paren_count--; } } args_found = 1; /* Too many args, deal with, or ignore, the rest. */ if (commas_found >= arg_count) { if(arg_count == 0) continue; ac = arg_count-1; } else ac = commas_found; if (arg_list[ac].value == 0) { cc = len = 0; arg_list[ac].in_define = def_count; } if (cc+2 >= len) { len += 20; arg_list[ac].value = realloc(arg_list[ac].value, len); } #if 0 if (ch == '\n' && cc>0 && arg_list[ac].value[cc-1] == '\n' ) { ... ? } #endif arg_list[ac].value[cc++] = ch; arg_list[ac].value[cc] = '\0'; } if (commas_found || args_found) args_found = commas_found+1; if( arg_count == 0 && args_found != 0 ) cerror("Arguments given to macro without them."); else if( !is_vararg && arg_count != args_found ) cwarn("Incorrect number of macro arguments"); mac_text = insert_substrings(data_str, arg_list, arg_count); /* * At this point 'mac_text' contains the full expansion of the macro. * * So we could scan this for calls to this macro and if we find one * that _exactly_ matches this call (including arguments) then we mark * this call's in_use flag. * * OTOH, it would probably be best to throw away this expansion and * pretend we never noticed this macro expansion in the first place. * * Still this is mostly academic as the error trapping works and * recursive macros _with_arguments_ are both rare and unpredictable. */ if (arg_list) { for (ac=0; ac\n", def_count, mac_text); #endif } static char * insert_substrings(data_str, arg_list, arg_count) char * data_str; struct arg_store *arg_list; int arg_count; { int ac, ch; char * p, * s; char * rv = 0; int len = 0; int cc = 0; int in_quote = 0; int quote_char = 0; int ansi_stringize = 0; #if CPP_DEBUG fprintf(stderr, "\n### Macro substitution in '%s'\n", data_str); for (ac=0; ac= '0' && ch <= '9') || (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || ch == '_' || ch == '$' ) *p++ = *data_str++; else break; } if (p == curword) { /* Ansi Stringize and concat */ if (*data_str == '#' && dialect != DI_KNR) { if (data_str[1] == '#') { while(cc>0 && (rv[cc-1] == ' ' || rv[cc-1] == '\t')) cc--; data_str+=2; while(*data_str == ' ' || *data_str == '\t') data_str++; if (*data_str == '\0') { /* Hummm */ data_str--; cerror("'##' operator at end of macro"); } continue; } data_str++; ansi_stringize = 1; continue; } if (ansi_stringize) { ansi_stringize = 0; cerror("'#' operator should be followed by a macro argument name"); } /* Other characters ... */ if (cc+2 > len) { len += 20; rv = realloc(rv, len); } rv[cc++] = *data_str++; continue; } *p = '\0'; s = curword; for (ac=0; acarg_count == -1) { s = ptr->value; } } rv[cc++] = '"'; while(*s == ' ' || *s == '\t') s++; while (*s) { if (cc+4 > len) { len += 20; rv = realloc(rv, len); } if (*s == '"') rv[cc++] = '\\'; rv[cc++] = *s++; } while(cc>0 && (rv[cc-1] == ' ' || rv[cc-1] == '\t')) cc--; rv[cc++] = '"'; rv[cc++] = '\0'; ansi_stringize = 0; s = ""; break; } break; } } if (ansi_stringize) { ansi_stringize = 0; cerror("'#' operator should be followed by a macro argument name"); } if (cc+2+strlen(s) > len) { len += strlen(s)+20; rv = realloc(rv, len); } strcpy(rv+cc, s); cc = strlen(rv); } rv[cc] = '\0'; return rv; } dev86-0.16.21/cpp/hash.c000066400000000000000000000052101231050321700144560ustar00rootroot00000000000000 #include #ifdef __STDC__ #include #include #else #include #endif #include "cc.h" /* * Two functions: * char * set_entry(int namespace, char * name, void * value); * returns a pointer to the copy of the name; * * void * read_entry(int namespace, char * name); * returns the value; */ struct hashentry { struct hashentry * next; void * value; int namespace; char word[1]; }; struct hashentry ** hashtable; int hashsize = 0xFF; /* 2^X -1 */ int hashcount = 0; static int hashvalue P((int namespace, char * word)); void * read_entry(namespace, word) int namespace; char * word; { int hash_val; struct hashentry * hashline; if( hashtable == 0 ) return 0; hash_val = hashvalue(namespace, word); hashline = hashtable[hash_val]; for(; hashline; hashline = hashline->next) { if(namespace != hashline->namespace) continue; if(word[0] != hashline->word[0]) continue; if(strcmp(word, hashline->word) ) continue; return hashline->value; } return 0; } char * set_entry(namespace, word, value) int namespace; char * word; void * value; { int hash_val, i; struct hashentry * hashline, *prev; hash_val = hashvalue(namespace, word); if( hashtable ) { hashline = hashtable[hash_val]; for(prev=0; hashline; prev=hashline, hashline = hashline->next) { if(namespace != hashline->namespace) continue; if(word[0] != hashline->word[0]) continue; if(strcmp(word, hashline->word) ) continue; if( value ) hashline->value = value; else { if( prev == 0 ) hashtable[hash_val] = hashline->next; else prev->next = hashline->next; free(hashline); return 0; } return hashline->word; } } if( value == 0 ) return 0; if( hashtable == 0 ) { hashtable = malloc((hashsize+1)*sizeof(char*)); if( hashtable == 0 ) cfatal("Out of memory"); for(i=0; i<=hashsize; i++) hashtable[i] = 0; } /* Add record */ hashline = malloc(sizeof(struct hashentry)+strlen(word)); if( hashline == 0 ) cfatal("Out of memory"); else { hashline->next = hashtable[hash_val]; hashline->namespace = namespace; hashline->value = value; strcpy(hashline->word, word); hashtable[hash_val] = hashline; } return hashline->word; } static int hashvalue(namespace, word) int namespace; char * word; { int val = namespace; char *p = word; while(*p) { val = ((val<<4)^((val>>12)&0xF)^((*p++)&0xFF)); } val &= hashsize; return val; } dev86-0.16.21/cpp/main.c000066400000000000000000000302121231050321700144570ustar00rootroot00000000000000 #include #if __STDC__ #include #include #else #include #endif #include #include #include #include "cc.h" #define MAXINCPATH 5 int main P((int argc, char ** argv)); void undefine_macro P((char * name)); void define_macro P((char * name)); void print_toks_cpp P((void)); void print_toks_raw P((void)); void define_macro P((char *)); void undefine_macro P((char *)); void cmsg P((char * mtype, char * str)); char * token_txn P((int)); void pr_indent P((int)); void hash_line P((void)); char * include_paths[MAXINCPATH]; char last_name[512] = ""; int last_line = -1; int debug_mode = 0; int p_flag = 0; int exit_code = 0; char * outfile = 0; FILE * ofd = 0; int main(argc, argv) int argc; char ** argv; { int ar, i; char * p; static char Usage[] = "Usage: cpp -E -0 -Dxxx -Uxxx -Ixxx infile -o outfile"; #ifdef LC_CTYPE setlocale(LC_CTYPE, ""); #endif alltok = 1; /* Get all tokens from the cpp. */ for(ar=1; ar=argc) cfatal(Usage); p = argv[ar]; } for(i=0; i=MAXINCPATH) cfatal("Too many items in include path for CPP"); break; case 'D': if (argv[ar][2]) p=argv[ar]+2; else { ar++; if (ar>=argc) cfatal(Usage); p = argv[ar]; } define_macro(p); break; case 'U': if (argv[ar][2]) p=argv[ar]+2; else { ar++; if (ar>=argc) cfatal(Usage); p = argv[ar]; } undefine_macro(p); break; case 'o': if (argv[ar][2]) p=argv[ar]+2; else { ar++; if (ar>=argc) cfatal(Usage); p = argv[ar]; } if (outfile) cfatal(Usage); outfile = p; break; default: fprintf(stderr, "CPP Unknown option %s\n", argv[ar]); cfatal(Usage); } else if (!curfile) { /* Input file */ curfile = fopen(argv[ar], "r"); c_fname = argv[ar]; c_lineno = 1; if (!curfile) cfatal("Cannot open input file"); } else cfatal(Usage); if (!curfile) cfatal(Usage); /* Define date and time macros. */ if (dialect != DI_KNR) { time_t now; char * timep; char buf[128]; time(&now); timep = ctime(&now); /* Yes, well */ sprintf(buf, "__TIME__=\"%.8s\"", timep + 11); define_macro(buf); /* US order; Seems to be mandated by standard. */ sprintf(buf, "__DATE__=\"%.3s %.2s %.4s\"", timep + 4, timep + 8, timep + 20); define_macro(buf); } if (outfile) ofd = fopen(outfile, "w"); else ofd = stdout; if (!ofd) cfatal("Cannot open output file"); if (debug_mode) print_toks_raw(); else print_toks_cpp(); if (outfile) fclose(ofd); exit(exit_code); } void undefine_macro(name) char * name; { struct define_item * ptr; ptr = read_entry(0, name); if (ptr) { set_entry(0, name, (void*)0); if (!ptr->in_use) free(ptr); } } void define_macro(name) char * name; { char * p; char * value; struct define_item * ptr; if ((p=strchr(name, '=')) != 0) { *p = 0; value = p+1; } else value = "1"; undefine_macro(name); ptr = malloc(sizeof(struct define_item) + strlen(value)); ptr->name = set_entry(0, name, ptr); strcpy(ptr->value, value); ptr->arg_count = -1; ptr->in_use = 0; ptr->next = 0; } FILE * open_include(fname, mode, checkrel) char * fname; char * mode; int checkrel; { FILE * fd = 0; int i; char buf[256], *p; if( checkrel ) { strcpy(buf, c_fname); p = strrchr(buf, '/'); if (p) *++p = 0; else *(p=buf) = 0; strcpy(p, fname); fd=fopen(buf, mode); } if (!fd) { for(i=0; i10) count=10; while(count>0) {fprintf(ofd, "\t"); count--; } } void hash_line() { if( strcmp(last_name, c_fname) != 0 ) last_line = -1; if( c_lineno != last_line || last_line <= 0 ) { if( outpos != 0 ) { fputc('\n', ofd); outpos=0; if (last_line > 0) last_line++; } while( c_lineno > last_line && (p_flag || c_lineno < last_line+4) && last_line > 0 && !debug_mode ) { fputc('\n', ofd); last_line++; } if( !p_flag && (c_lineno != last_line || last_line <= 0 )) { fprintf(ofd, "# %d", c_lineno); if( last_line <= 0 ) fprintf(ofd, " \"%s\"", c_fname); fprintf(ofd, "\n"); } strcpy(last_name, c_fname); last_line = c_lineno; } } void print_toks_cpp() { int i; int indent=0; int paren=0; hash_line(); while( (i=gettok()) != EOF ) { hash_line(); switch(i) { case '\n': cwarn("newline received from tokeniser!"); break; case TK_STR: outpos += fprintf(ofd, "%s", curword); break; case TK_COPY: if( outpos ) { fputc('\n', ofd); last_line++; } outpos = 0; last_line++; fprintf(ofd, "#%s\n", curword); break; case TK_FILE: sprintf(curword, "\"%s\"", c_fname); if(0) { case TK_LINE: sprintf(curword, "%d", c_lineno); } /*FALLTHROUGH*/ default: if (!alltok) { if(i == '}' || i == TK_CASE || i == TK_DEFAULT ) indent--; if(i ==')') paren--; if(outpos) { fputc(' ', ofd); outpos++; } else pr_indent(indent+(paren!=0)); if(i == '{' || i == TK_CASE || i == TK_DEFAULT ) indent++; if(i ==';') paren=0; if(i =='(') paren++; } outpos += fprintf(ofd, "%s", curword); if ( i == '"' || i == '\'' ) { while((i=gettok()) == TK_STR) { outpos += fprintf(ofd, "%s", curword); } if (i != '\n') outpos += fprintf(ofd, "%s", curword); } break; } } if( outpos ) fputc('\n', ofd); outpos = 0; } void print_toks_raw() { int i; long val; hash_line(); while( (i=gettok()) != EOF ) { hash_line(); switch(i) { case '"': case '\'': if (debug_mode < 2) { fprintf(ofd, "%-16s: %s", "Quoted string", curword); while((i=gettok()) == TK_STR) outpos+= fprintf(ofd, "%s", curword); if ( i == '\n' ) fprintf(ofd, " --> EOL!!\n"); else outpos+= fprintf(ofd, "%s\n", curword); break; } /*FALLTHROUGH*/ default: fprintf(ofd, "%-16s: '", token_txn(i)); { char *p; for(p=curword; *p; p++) if(isprint(*p) && *p != '\'' && *p != '\\') fputc(*p, ofd); else if (*p == '\n') fprintf(ofd, "\\n"); else if (*p == '\t') fprintf(ofd, "\\t"); else if (*p == '\v') fprintf(ofd, "\\v"); else if (*p == '\b') fprintf(ofd, "\\b"); else if (*p == '\r') fprintf(ofd, "\\r"); else if (*p == '\f') fprintf(ofd, "\\f"); else if (*p == '\a') fprintf(ofd, "\\a"); else fprintf(ofd, "\\x%02x", (unsigned char)*p); } fprintf(ofd, "'\n"); break; case TK_NUM: val = strtoul(curword, (void*)0, 0); fprintf(ofd, "%-16s: ", token_txn(i)); fprintf(ofd, "%s => %ld\n", curword, val); break; case TK_COPY: fprintf(ofd, "%-16s: ", token_txn(i)); fprintf(ofd, "#%s\n", curword); break; case '\n': fprintf(ofd, "%-16s:\n", "Newline char"); break; } } } char * token_txn(token) int token; { char * s = "UNKNOWN"; static char buf[17]; if (token> ' ' && token <= '~') { sprintf(buf, "TK_CHAR('%c')", token); return buf; } if (token >= 0 && token < 0x100) { sprintf(buf, "TK_CHAR(%d)", token); return buf; } switch(token) { case TK_WSPACE : s="TK_WSPACE"; break; case TK_WORD : s="TK_WORD"; break; case TK_NUM : s="TK_NUM"; break; case TK_FLT : s="TK_FLT"; break; case TK_QUOT : s="TK_QUOT"; break; case TK_STR : s="TK_STR"; break; case TK_FILE : s="TK_FILE"; break; case TK_LINE : s="TK_LINE"; break; case TK_COPY : s="TK_COPY"; break; case TK_NE_OP : s="TK_NE_OP"; break; case TK_MOD_ASSIGN : s="TK_MOD_ASSIGN"; break; case TK_AND_OP : s="TK_AND_OP"; break; case TK_AND_ASSIGN : s="TK_AND_ASSIGN"; break; case TK_MUL_ASSIGN : s="TK_MUL_ASSIGN"; break; case TK_INC_OP : s="TK_INC_OP"; break; case TK_ADD_ASSIGN : s="TK_ADD_ASSIGN"; break; case TK_DEC_OP : s="TK_DEC_OP"; break; case TK_SUB_ASSIGN : s="TK_SUB_ASSIGN"; break; case TK_PTR_OP : s="TK_PTR_OP"; break; case TK_ELLIPSIS : s="TK_ELLIPSIS"; break; case TK_DIV_ASSIGN : s="TK_DIV_ASSIGN"; break; case TK_LEFT_OP : s="TK_LEFT_OP"; break; case TK_LEFT_ASSIGN : s="TK_LEFT_ASSIGN"; break; case TK_LE_OP : s="TK_LE_OP"; break; case TK_EQ_OP : s="TK_EQ_OP"; break; case TK_GE_OP : s="TK_GE_OP"; break; case TK_RIGHT_OP : s="TK_RIGHT_OP"; break; case TK_RIGHT_ASSIGN : s="TK_RIGHT_ASSIGN"; break; case TK_XOR_ASSIGN : s="TK_XOR_ASSIGN"; break; case TK_OR_ASSIGN : s="TK_OR_ASSIGN"; break; case TK_OR_OP : s="TK_OR_OP"; break; case TK_AUTO : s="TK_AUTO"; break; case TK_BREAK : s="TK_BREAK"; break; case TK_CASE : s="TK_CASE"; break; case TK_CHAR : s="TK_CHAR"; break; case TK_CONST : s="TK_CONST"; break; case TK_CONTINUE : s="TK_CONTINUE"; break; case TK_DEFAULT : s="TK_DEFAULT"; break; case TK_DO : s="TK_DO"; break; case TK_DOUBLE : s="TK_DOUBLE"; break; case TK_ELSE : s="TK_ELSE"; break; case TK_ENUM : s="TK_ENUM"; break; case TK_EXTERN : s="TK_EXTERN"; break; case TK_FLOAT : s="TK_FLOAT"; break; case TK_FOR : s="TK_FOR"; break; case TK_GOTO : s="TK_GOTO"; break; case TK_IF : s="TK_IF"; break; case TK_INT : s="TK_INT"; break; case TK_LONG : s="TK_LONG"; break; case TK_REGISTER : s="TK_REGISTER"; break; case TK_RETURN : s="TK_RETURN"; break; case TK_SHORT : s="TK_SHORT"; break; case TK_SIGNED : s="TK_SIGNED"; break; case TK_SIZEOF : s="TK_SIZEOF"; break; case TK_STATIC : s="TK_STATIC"; break; case TK_STRUCT : s="TK_STRUCT"; break; case TK_SWITCH : s="TK_SWITCH"; break; case TK_TYPEDEF : s="TK_TYPEDEF"; break; case TK_UNION : s="TK_UNION"; break; case TK_UNSIGNED : s="TK_UNSIGNED"; break; case TK_VOID : s="TK_VOID"; break; case TK_VOLATILE : s="TK_VOLATILE"; break; case TK_WHILE : s="TK_WHILE"; break; } return s; } dev86-0.16.21/cpp/token1.c000066400000000000000000000002731231050321700147400ustar00rootroot00000000000000 #include #include #include "cc.h" #ifdef __GNUC__ __inline #endif static unsigned int hash1 P((register const char *, register unsigned int)); #include "token1.h" dev86-0.16.21/cpp/token1.h000066400000000000000000000063111231050321700147440ustar00rootroot00000000000000/* C code produced by gperf version 2.7.1 (19981006 egcs) */ /* Command-line: gperf -aptTc -N is_ctok -H hash1 token1.tok */ #define TOTAL_KEYWORDS 23 #define MIN_WORD_LENGTH 2 #define MAX_WORD_LENGTH 3 #define MIN_HASH_VALUE 2 #define MAX_HASH_VALUE 63 /* maximum key range = 62, duplicates = 0 */ #ifdef __GNUC__ __inline #endif static unsigned int hash1 (str, len) register const char *str; register unsigned int len; { static unsigned char asso_values[] = { 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 1, 64, 64, 64, 3, 25, 64, 64, 64, 13, 18, 64, 8, 30, 15, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 5, 0, 20, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 30, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 23, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64 }; return len + asso_values[(unsigned char)str[len - 1]] + asso_values[(unsigned char)str[0]]; } #ifdef __GNUC__ __inline #endif struct token_trans * is_ctok (str, len) register const char *str; register unsigned int len; { static struct token_trans wordlist[] = { {""}, {""}, {"==", TK_EQ_OP}, {"!=", TK_NE_OP}, {""}, {"%=", TK_MOD_ASSIGN}, {""}, {"<=", TK_LE_OP}, {"<<=", TK_LEFT_ASSIGN}, {""}, {"-=", TK_SUB_ASSIGN}, {""}, {"<<", TK_LEFT_OP}, {""}, {""}, {"*=", TK_MUL_ASSIGN}, {""}, {"/=", TK_DIV_ASSIGN}, {"--", TK_DEC_OP}, {""}, {"+=", TK_ADD_ASSIGN}, {""}, {">=", TK_GE_OP}, {">>=", TK_RIGHT_ASSIGN}, {""}, {"|=", TK_OR_ASSIGN}, {""}, {"&=", TK_AND_ASSIGN}, {""}, {""}, {"->", TK_PTR_OP}, {""}, {"^=", TK_XOR_ASSIGN}, {""}, {""}, {""}, {""}, {""}, {"++", TK_INC_OP}, {""}, {""}, {""}, {">>", TK_RIGHT_OP}, {""}, {""}, {""}, {""}, {""}, {"||", TK_OR_OP}, {""}, {""}, {""}, {"&&", TK_AND_OP}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {"..", TK_WORD}, {"...", TK_ELLIPSIS} }; if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) { register int key = hash1 (str, len); if (key <= MAX_HASH_VALUE && key >= 0) { register const char *s = wordlist[key].name; if (*str == *s && !strncmp (str + 1, s + 1, len - 1)) return &wordlist[key]; } } return 0; } dev86-0.16.21/cpp/token1.tok000066400000000000000000000006401231050321700153110ustar00rootroot00000000000000struct token_trans { char * name; int token; }; %% ..., TK_ELLIPSIS >>=, TK_RIGHT_ASSIGN <<=, TK_LEFT_ASSIGN +=, TK_ADD_ASSIGN -=, TK_SUB_ASSIGN *=, TK_MUL_ASSIGN /=, TK_DIV_ASSIGN %=, TK_MOD_ASSIGN &=, TK_AND_ASSIGN ^=, TK_XOR_ASSIGN |=, TK_OR_ASSIGN >>, TK_RIGHT_OP <<, TK_LEFT_OP ++, TK_INC_OP --, TK_DEC_OP ->, TK_PTR_OP &&, TK_AND_OP ||, TK_OR_OP <=, TK_LE_OP >=, TK_GE_OP ==, TK_EQ_OP !=, TK_NE_OP .., TK_WORD dev86-0.16.21/cpp/token2.c000066400000000000000000000002731231050321700147410ustar00rootroot00000000000000 #include #include #include "cc.h" #ifdef __GNUC__ __inline #endif static unsigned int hash2 P((register const char *, register unsigned int)); #include "token2.h" dev86-0.16.21/cpp/token2.h000066400000000000000000000072321231050321700147500ustar00rootroot00000000000000/* C code produced by gperf version 2.7.1 (19981006 egcs) */ /* Command-line: gperf -aptTc -k1,3 -N is_ckey -H hash2 token2.tok */ #define TOTAL_KEYWORDS 34 #define MIN_WORD_LENGTH 2 #define MAX_WORD_LENGTH 8 #define MIN_HASH_VALUE 2 #define MAX_HASH_VALUE 69 /* maximum key range = 68, duplicates = 0 */ #ifdef __GNUC__ __inline #endif static unsigned int hash2 (str, len) register const char *str; register unsigned int len; { static unsigned char asso_values[] = { 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 5, 70, 70, 70, 70, 70, 0, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 0, 70, 5, 5, 10, 10, 20, 20, 25, 70, 0, 70, 70, 50, 70, 0, 15, 0, 70, 15, 0, 40, 20, 0, 0, 70, 70, 10, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70 }; register int hval = len; switch (hval) { default: case 3: hval += asso_values[(unsigned char)str[2]]; case 2: case 1: hval += asso_values[(unsigned char)str[0]]; break; } return hval; } #ifdef __GNUC__ __inline #endif struct token_trans * is_ckey (str, len) register const char *str; register unsigned int len; { static struct token_trans wordlist[] = { {""}, {""}, {"if", TK_IF}, {""}, {"void", TK_VOID}, {"while", TK_WHILE}, {"switch", TK_SWITCH}, {""}, {"__LINE__", TK_LINE}, {""}, {""}, {"static", TK_STATIC}, {"do", TK_DO}, {"__FILE__", TK_FILE}, {"case", TK_CASE}, {"const", TK_CONST}, {"sizeof", TK_SIZEOF}, {""}, {"continue", TK_CONTINUE}, {"char", TK_CHAR}, {"short", TK_SHORT}, {"struct", TK_STRUCT}, {""}, {""}, {"else", TK_ELSE}, {"union", TK_UNION}, {""}, {""}, {"unsigned", TK_UNSIGNED}, {""}, {"break", TK_BREAK}, {"signed", TK_SIGNED}, {""}, {""}, {""}, {""}, {"double", TK_DOUBLE}, {"default", TK_DEFAULT}, {"for", TK_FOR}, {""}, {"float", TK_FLOAT}, {""}, {""}, {"int", TK_INT}, {"enum", TK_ENUM}, {""}, {""}, {"typedef", TK_TYPEDEF}, {"register", TK_REGISTER}, {"auto", TK_AUTO}, {""}, {""}, {""}, {""}, {"long", TK_LONG}, {""}, {""}, {""}, {"volatile", TK_VOLATILE}, {""}, {""}, {"return", TK_RETURN}, {""}, {""}, {""}, {""}, {"extern", TK_EXTERN}, {""}, {""}, {"goto", TK_GOTO} }; if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) { register int key = hash2 (str, len); if (key <= MAX_HASH_VALUE && key >= 0) { register const char *s = wordlist[key].name; if (*str == *s && !strncmp (str + 1, s + 1, len - 1)) return &wordlist[key]; } } return 0; } dev86-0.16.21/cpp/token2.tok000066400000000000000000000011751231050321700153160ustar00rootroot00000000000000struct token_trans { char * name; int token; }; %% auto, TK_AUTO break, TK_BREAK case, TK_CASE char, TK_CHAR const, TK_CONST continue, TK_CONTINUE default, TK_DEFAULT do, TK_DO double, TK_DOUBLE else, TK_ELSE enum, TK_ENUM extern, TK_EXTERN float, TK_FLOAT for, TK_FOR goto, TK_GOTO if, TK_IF int, TK_INT long, TK_LONG register, TK_REGISTER return, TK_RETURN short, TK_SHORT signed, TK_SIGNED sizeof, TK_SIZEOF static, TK_STATIC struct, TK_STRUCT switch, TK_SWITCH typedef, TK_TYPEDEF union, TK_UNION unsigned, TK_UNSIGNED void, TK_VOID volatile, TK_VOLATILE while, TK_WHILE __FILE__, TK_FILE __LINE__, TK_LINE dev86-0.16.21/cpp/torture.c000066400000000000000000000004051231050321700152400ustar00rootroot00000000000000/\ * \ This _evil_ little file is compilable Ansi C. * / There are NO extensions ... Waddya think ? \/ // ***/ func() { printf("Hello /* world */ %d ???/?=\n" ??/ , 1? '\\ 007': '??/"'/*"*/ );} main() { func(); } dev86-0.16.21/dis88/000077500000000000000000000000001231050321700135465ustar00rootroot00000000000000dev86-0.16.21/dis88/Makefile000066400000000000000000000032211231050321700152040ustar00rootroot00000000000000# Makefile for dis # @(#) Makefile, Ver. 2.1 created 00:00:00 87/09/01 # Makefile for 8088 symbolic disassembler # Copyright (C) 1987 G. M. Harding, all rights reserved. # Permission to copy and redistribute is hereby granted, # provided full source code, with all copyright notices, # accompanies any redistribution. # This Makefile automates the process of compiling and linking # a symbolic object-file disassembler program for the Intel # 8088 CPU. Relatively machine-independent code is contained in # the file dismain.c; lookup tables and handler routines, which # are by their nature machine-specific, are contained in two # files named distabs.c and dishand.c, respectively. (A third # machine-specific file, disfp.c, contains handler routines for # floating-point coprocessor opcodes.) A header file, dis.h, # attempts to mediate between the machine-specific and machine- # independent portions of the code. An attempt has been made to # isolate machine dependencies and to deal with them in fairly # straightforward ways. Thus, it should be possible to target a # different CPU by rewriting the handler routines and changing # the initialization data in the lookup tables. It should not # be necessary to alter the formats of the tables. #CC=bcc CFLAGS=-O LDFLAGS= PREFIX=/usr OBJ = disrel.o dismain.o distabs.o dishand.o disfp.o all: dis88 dis88: $(OBJ) $(CC) $(LDFLAGS) -o dis88 $(OBJ) install: dis88 install -m 755 -s dis88 $(DIST)$(PREFIX)/bin/dis86 install -m 644 dis88.1 $(DIST)$(PREFIX)/man/man1/dis86.1 $(OBJ): dis.h a.out.h a.out.h: ln -s ../libc/include/a.out.h . clean realclean: rm -f *.bak *.lst *.o core dis88 a.out.h dev86-0.16.21/dis88/README000066400000000000000000000114411231050321700144270ustar00rootroot00000000000000 dis88 Beta Release 87/09/01 --- G. M. HARDING POB 4142 Santa Clara CA 95054-0142 "Dis88" is a symbolic disassembler for the Intel 8088 CPU, designed to run under the PC/IX operating system on an IBM XT or fully-compatible clone. Its output is in the format of, and is completely compatible with, the PC/IX assembler, "as". The program is copyrighted by its author, but may be copied and re- distributed freely provided that complete source code, with all copyright notices, accompanies any distribution. This provision also applies to any modifications you may make. You are urged to comment such changes, giving, as a miminum, your name and complete address. This release of the program is a beta release, which means that it has been extensively, but not exhaustively, tested. User comments, recommendations, and bug fixes are welcome. The principal features of the current release are: (a) The ability to disassemble any file in PC/IX object format, making full use of symbol and relocation information if it is present, regardless of whether the file is executable or linkable, and regardless of whether it has continuous or split I/D space; (b) Automatic generation of synthetic labels when no sym- bol table is available; and (c) Optional output of address and object-code informa- tion as assembler comment text. Limitations of the current release are: (a) Numeric co-processor (i.e., 8087) mnemonics are not supported. Instructions for the co-processor are disassembled as CPU escape sequences, or as interrupts, depending on how they were assembled in the first place. This limitation will be addressed in a future release. (b) Symbolic references within the object file's data segment are not supported. Thus, for example, if a data segment location is initialized to point to a text segment address, no reference to a text segment symbol will be detected. This limi- tation is likely to remain in future releases, because object code does not, in most cases, contain sufficient information to allow meaningful interpretation of pure data. (Note, however, that symbolic references to the data segment from within the text segment are always supported.) As a final caveat, be aware that the PC/IX assembler does not recognize the "esc" mnemonic, even though it refers to a completely valid CPU operation which is documented in all the Intel literature. Thus, the corresponding opcodes (0xd8 through 0xdf) are disassembled as .byte directives. For reference, how- ever, the syntactically-correct "esc" instruction is output as a comment. To build the disassembler program, transfer all the source files, together with the Makefile, to a suitable (preferably empty) PC/IX directory. Then, simply type "make". To use dis88, place it in a directory which appears in your $PATH list. It may then be invoked by name from whatever directory you happen to be in. As a minimum, the program must be invoked with one command-line argument: the name of the ob- ject file to be disassembled. (Dis88 will complain if the file specified is not an object file.) Optionally, you may specify an output file; stdout is the default. One command-line switch is available: "-o", which makes the program display addresses and object code along with its mnemonic disassembly. The "-o" option is useful primarily for verifying the cor- rectness of the program's output. In particular, it may be used to check the accuracy of local relative jump opcodes. These jumps often target local labels, which are lost at assembly time; thus, the disassembly may contain cryptic instructions like "jnz .+39". As a user convenience, all relative jump and call opcodes are output with a comment which identifies the physical target address. By convention, the release level of the program as a whole is the SID of the file disrel.c, and this SID string appears in each disassembly. Release 2.1 of the program is the first beta release to be distributed on Usenet. dev86-0.16.21/dis88/ansi.h000066400000000000000000000033131231050321700146510ustar00rootroot00000000000000/* The header attempts to decide whether the compiler has enough * conformance to Standard C for Minix to take advantage of. If so, the * symbol _ANSI is defined (as 31415). Otherwise _ANSI is not defined * here, but it may be defined by applications that want to bend the rules. * The magic number in the definition is to inhibit unnecessary bending * of the rules. (For consistency with the new '#ifdef _ANSI" tests in * the headers, _ANSI should really be defined as nothing, but that would * break many library routines that use "#if _ANSI".) * If _ANSI ends up being defined, a macro * * _PROTOTYPE(function, params) * * is defined. This macro expands in different ways, generating either * ANSI Standard C prototypes or old-style K&R (Kernighan & Ritchie) * prototypes, as needed. Finally, some programs use _CONST, _VOIDSTAR etc * in such a way that they are portable over both ANSI and K&R compilers. * The appropriate macros are defined here. */ #ifndef _ANSI_H #define _ANSI_H #if __STDC__ == 1 #define _ANSI 31459 /* compiler claims full ANSI conformance */ #endif #ifdef __GNUC__ #define _ANSI 31459 /* gcc conforms enough even in non-ANSI mode */ #endif #ifdef _ANSI /* Keep everything for ANSI prototypes. */ #define _PROTOTYPE(function, params) function params #define _ARGS(params) params #define _VOIDSTAR void * #define _VOID void #define _CONST const #define _VOLATILE volatile #define _SIZET size_t #else /* Throw away the parameters for K&R prototypes. */ #define _PROTOTYPE(function, params) function() #define _ARGS(params) () #define _VOIDSTAR void * #define _VOID void #define _CONST #define _VOLATILE #define _SIZET int #endif /* _ANSI */ #endif /* ANSI_H */ dev86-0.16.21/dis88/dis.h000066400000000000000000000133171231050321700145030ustar00rootroot00000000000000 /* ** @(#) dis.h, Ver. 2.1 created 00:00:00 87/09/01 */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Copyright (C) 1987 G. M. Harding, all rights reserved * * * * Permission to copy and redistribute is hereby granted, * * provided full source code, with all copyright notices, * * accompanies any redistribution. * * * * This file contains declarations and definitions used by * * the 8088 disassembler program. The program was designed * * for execution on a machine of its own type (i.e., it is * * not designed as a cross-disassembler); consequently, A * * SIXTEEN-BIT INTEGER SIZE HAS BEEN ASSUMED. This assump- * * tion is not particularly important, however, except in * * the machine-specific portions of the code (i.e., the * * handler routines and the optab[] array). It should be * * possible to override this assumption, for execution on * * 32-bit machines, by use of a pre-processor directive * * (see below); however, this has not been tested. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include #include /* System file-control definitions */ #include #include #include #include /* System standard I/O definitions */ #include "a.out.h" /* Object file format definitions */ #include "ansi.h" #define MAXSYM ((sizeof(int)-1)*32400/ \ (sizeof(struct nlist)+sizeof(struct reloc))) /* Maximum entries in symbol table */ extern struct nlist /* Array to hold the symbol table */ symtab[MAXSYM]; extern struct reloc /* Array to hold relocation table */ relo[MAXSYM]; extern int symptr; /* Index into the symtab[] array */ extern int relptr; /* Index into the relo[] array */ struct opcode /* Format for opcode data records */ { char *text; /* Pointer to mnemonic text */ void (*func)(); /* Pointer to handler routine */ unsigned min; /* Minimum # of object bytes */ unsigned max; /* Maximum # of object bytes */ }; extern struct opcode /* Array to hold the opcode table */ optab[256]; extern char *REGS[]; /* Table of register names */ extern char *REGS0[]; /* Mode 0 register name table */ extern char *REGS1[]; /* Mode 1 register name table */ #define AL REGS[0] /* CPU register manifests */ #define CL REGS[1] #define DL REGS[2] #define BL REGS[3] #define AH REGS[4] #define CH REGS[5] #define DH REGS[6] #define BH REGS[7] #define AX REGS[8] #define CX REGS[9] #define DX REGS[10] #define BX REGS[11] #define SP REGS[12] #define BP REGS[13] #define SI REGS[14] #define DI REGS[15] #define ES REGS[16] #define CS REGS[17] #define SS REGS[18] #define DS REGS[19] #define BX_SI REGS0[0] #define BX_DI REGS0[1] #define BP_SI REGS0[2] #define BP_DI REGS0[3] extern int symrank[6][6]; /* Symbol type/rank matrix */ extern unsigned long PC; /* Current program counter */ extern int segflg; /* Flag: segment override in effect */ extern int objflg; /* Flag: output object as a comment */ #define OBJMAX 8 /* Size of the object code buffer */ extern unsigned char /* Internal buffer for object code */ objbuf[OBJMAX]; extern int objptr; /* Index into the objbuf[] array */ extern char ADD[], /* Opcode family mnemonic strings */ OR[], ADC[], SBB[], AND[], SUB[], XOR[], CMP[], NOT[], NEG[], MUL[], DIV[], MOV[], ESC[], TEST[], AMBIG[]; extern char *OPFAM[]; /* Indexed mnemonic family table */ extern struct exec HDR; /* Holds the object file's header */ #define LOOK_ABS 0 /* Arguments to lookup() function */ #define LOOK_REL 1 #define LOOK_LNG 2 #define TR_STD 0 /* Arguments to mtrans() function */ #define TR_SEG 8 /* Macro for byte input primitive */ /* #define FETCH(p) ++PC; p = getchar() & 0xff; objbuf[objptr++] = p */ static int _F_; #define FETCH(p) (p)=_F_ = Fetch(); if(_F_<0) {printf("???\n"); return FRV; } #define FRV /* disfp.c */ _PROTOTYPE(void eshand, (int j )); _PROTOTYPE(void fphand, (int j )); _PROTOTYPE(void inhand, (int j )); /* dishand.c */ _PROTOTYPE(void objini, (int j )); _PROTOTYPE(void objout, (void)); _PROTOTYPE(void badseq, (int j, int k )); _PROTOTYPE(void dfhand, (int j )); _PROTOTYPE(void sbhand, (int j )); _PROTOTYPE(void aohand, (int j )); _PROTOTYPE(void sjhand, (int j )); _PROTOTYPE(void imhand, (int j )); _PROTOTYPE(void mvhand, (int j )); _PROTOTYPE(void mshand, (int j )); _PROTOTYPE(void pohand, (int j )); _PROTOTYPE(void cihand, (int j )); _PROTOTYPE(void mihand, (int j )); _PROTOTYPE(void mqhand, (int j )); _PROTOTYPE(void tqhand, (int j )); _PROTOTYPE(void rehand, (int j )); _PROTOTYPE(void mmhand, (int j )); _PROTOTYPE(void srhand, (int j )); _PROTOTYPE(void aahand, (int j )); _PROTOTYPE(void iohand, (int j )); _PROTOTYPE(void ljhand, (int j )); _PROTOTYPE(void mahand, (int j )); _PROTOTYPE(void mjhand, (int j )); /* dismain.c */ _PROTOTYPE(void main, (int argc, char **argv )); /* distabs.c */ _PROTOTYPE(char *getnam, (int k )); _PROTOTYPE(int lookext, (long off, long loc, char *buf )); _PROTOTYPE(char *lookup, (long addr, int type, int kind, long ext )); _PROTOTYPE(char *mtrans, (int c, int m, int type )); _PROTOTYPE(void mtrunc, (char *a )); dev86-0.16.21/dis88/dis88.1000066400000000000000000000142571231050321700146000ustar00rootroot00000000000000.TH dis88 1 LOCAL .SH "NAME" dis88 \- 8088 symbolic disassembler .SH "SYNOPSIS" \fBdis88\fP [ -f -o ] ifile [ ofile ] .SH "DESCRIPTION" Dis88 reads ifile, which must be in PC/IX a.out format. It interprets the binary opcodes and data locations, and writes corresponding assembler source code to stdout, or to ofile if specified. The program's output is in the format of, and fully compatible with, the PC/IX assembler, as(1). If a symbol table is present in ifile, labels and references will be symbolic in the output. If the input file lacks a symbol table, the fact will be noted, and the disassembly will proceed, with the disassembler generating synthetic labels as needed. If the input file has split I/D space, or if it is executable, the disassembler will make all necessary adjustments in address-reference calculations. .PP If the "-o" option appears, object code will be included in comments during disassembly of the text segment. This feature is used primarily for debugging the disassembler itself, but may provide information of passing interest to users. .PP If the "-f" option appears, dis88 will attempt to disassemble any file whatsoever. It has to assume that the file begins at address zero. .PP The program always outputs the current machine address before disassembling an opcode. If a symbol table is present, this address is output as an assembler comment; otherwise, it is incorporated into the synthetic label which is generated internally. Since relative jumps, especially short ones, may target unlabelled locations, the program always outputs the physical target address as a comment, to assist the user in following the code. .PP The text segment of an object file is always padded to an even machine address. In addition, if the file has split I/D space, the text segment will be padded to a paragraph boundary (i.e., an address divisible by 16). As a result of this padding, the disassembler may produce a few spurious, but harmless, instructions at the end of the text segment. .PP Disassembly of the data segment is a difficult matter. The information to which initialized data refers cannot be inferred from context, except in the special case of an external data or address reference, which will be reflected in the relocation table. Internal data and address references will already be resolved in the object file, and cannot be recreated. Therefore, the data segment is disassembled as a byte stream, with long stretches of null data represented by an appropriate ".zerow" pseudo-op. This limitation notwithstanding, labels (as opposed to symbolic references) are always output at appropriate points within the data segment. .PP If disassembly of the data segment is difficult, disassembly of the bss segment is quite easy, because uninitialized data is all zero by definition. No data is output in the bss segment, but symbolic labels are output as appropriate. .PP For each opcode which takes an operand, a particular symbol type (text, data, or bss) is appropriate. This tidy correspondence is complicated somewhat, however, by the existence of assembler symbolic constants and segment override opcodes. Therefore, the disassembler's symbol lookup routine attempts to apply a certain amount of intelligence when it is asked to find a symbol. If it cannot match on a symbol of the preferred type, it may return a symbol of some other type, depending on preassigned (and somewhat arbitrary) rankings within each type. Finally, if all else fails, it returns a string containing the address sought as a hex constant; this behavior allows calling routines to use the output of the lookup function regardless of the success of its search. .PP It is worth noting, at this point, that the symbol lookup routine operates linearly, and has not been optimized in any way. Execution time is thus likely to increase geometrically with input file size. The disassembler is internally limited to 1500 symbol table entries and 1500 relocation table entries; while these limits are generous (/unix, itself, has fewer than 800 symbols), they are not guaranteed to be adequate in all cases. If the symbol table or the relocation table overflows, the disassembly aborts. .PP Finally, users should be aware of a bug in the assembler, which causes it not to parse the "esc" mnemonic, even though "esc" is a completely legitimate opcode which is documented in all the Intel literature. To accommodate this deficiency, the disassembler translates opcodes of the "esc" family to .byte directives, but notes the correct mnemonic in a comment for reference. .PP In all cases, it should be possible to submit the output of the disassembler program to the assembler, and assemble it without error. In most cases, the resulting object code will be identical to the original; in any event, it will be functionally equivalent. .SH "SEE ALSO" adb(1), as(1), cc(1), ld(1). .br "Assembler Reference Manual" in the PC/IX Programmer's Guide. .SH "DIAGNOSTICS" "can't access input file" if the input file cannot be found, opened, or read. .sp "can't open output file" if the output file cannot be created. .sp "warning: host/cpu clash" if the program is run on a machine with a different CPU. .sp "input file not in object format" if the magic number does not correspond to that of a PC/IX object file. .sp "not an 8086/8088 object file" if the CPU ID of the file header is incorrect. .sp "reloc table overflow" if there are more than 1500 entries in the relocation table. .sp "symbol table overflow" if there are more than 1500 entries in the symbol table. .sp "lseek error" if the input file is corrupted (should never happen). .sp "warning: no symbols" if the symbol table is missing. .sp "can't reopen input file" if the input file is removed or altered during program execution (should never happen). .SH "BUGS" Numeric co-processor (i.e., 8087) mnemonics are not currently supported. Instructions for the co-processor are disassembled as CPU escape sequences, or as interrupts, depending on how they were assembled in the first place. .sp Despite the program's best efforts, a symbol retrieved from the symbol table may sometimes be different from the symbol used in the original assembly. .sp The disassembler's internal tables are of fixed size, and the program aborts if they overflow. dev86-0.16.21/dis88/disfp.c000066400000000000000000000127301231050321700150220ustar00rootroot00000000000000static char *sccsid = "@(#) disfp.c, Ver. 2.1 created 00:00:00 87/09/01"; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Copyright (C) 1987 G. M. Harding, all rights reserved * * * * Permission to copy and redistribute is hereby granted, * * provided full source code, with all copyright notices, * * accompanies any redistribution. * * * * This file contains handler routines for the numeric op- * * codes of the 8087 co-processor, as well as a few other * * opcodes which are related to 8087 emulation. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "dis.h" /* Disassembler declarations */ #define FPINT0 0xd8 /* Floating-point interrupts */ #define FPINT1 0xd9 #define FPINT2 0xda #define FPINT3 0xdb #define FPINT4 0xdc #define FPINT5 0xdd #define FPINT6 0xde #define FPINT7 0xdf /* Test for floating opcodes */ #define ISFLOP(x) \ (((x) >= FPINT0) && ((x) <= FPINT7)) /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * This is the handler for the escape family of opcodes. * * These opcodes place the contents of a specified memory * * location on the system bus, for access by a peripheral * * or by a co-processor such as the 8087. (The 8087 NDP is * * accessed only via bus escapes.) Due to a bug in the * * PC/IX assembler, the "esc" mnemonic is not recognized; * * consequently, escape opcodes are disassembled as .byte * * directives, with the appropriate mnemonic and operand * * included as a comment. FOR NOW, those escape sequences * * corresponding to 8087 opcodes are treated as simple * * escapes. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void eshand(j) register int j; /* Pointer to optab[] entry */ {/* * * * * * * * * * START OF eshand() * * * * * * * * * */ register char *a; register int k; objini(j); FETCH(k); a = mtrans((j & 0xfd),(k & 0xc7),TR_STD); mtrunc(a); printf("\t.byte\t0x%02.2x\t\t| esc\t%s\n",j,a); for (k = 1; k < objptr; ++k) printf("\t.byte\t0x%02.2x\n",objbuf[k]); }/* * * * * * * * * * * END OF eshand() * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * This is the handler routine for floating-point opcodes. * * Since PC/IX must accommodate systems with and without * * 8087 co-processors, it allows floating-point operations * * to be initiated in either of two ways: by a software * * interrput whose type is in the range 0xd8 through 0xdf, * * or by a CPU escape sequence, which is invoked by an op- * * code in the same range. In either case, the subsequent * * byte determines the actual numeric operation to be per- * * formed. However, depending on the method of access, * * either one or two code bytes will precede that byte, * * and the fphand() routine has no way of knowing whether * * it was invoked by interrupt or by an escape sequence. * * Therefore, unlike all of the other handler routines ex- * * cept dfhand(), fphand() does not initialize the object * * buffer, leaving that chore to the caller. * * * * FOR NOW, fphand() does not disassemble floating-point * * opcodes to floating mnemonics, but simply outputs the * * object code as .byte directives. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void fphand(j) register int j; /* Pointer to optab[] entry */ {/* * * * * * * * * * START OF fphand() * * * * * * * * * */ register int k; segflg = 0; FETCH(k); printf("\t.byte\t0x%02.2x\t\t| 8087 code sequence\n", objbuf[0]); for (k = 1; k < objptr; ++k) printf("\t.byte\t0x%02.2x\n",objbuf[k]); /* objout(); FOR NOW */ }/* * * * * * * * * * * END OF fphand() * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * This is the handler for variable software interrupt * * opcodes. It is included in this file because PC/IX im- * * plements its software floating-point emulation by means * * of interrupts. Any interrupt in the range 0xd8 through * * 0xdf is an NDP-emulation interrupt, and is specially * * handled by the assembler. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void inhand(j) register int j; /* Pointer to optab[] entry */ {/* * * * * * * * * * START OF inhand() * * * * * * * * * */ register int k; objini(j); FETCH(k); if (ISFLOP(k)) { fphand(k); return; } printf("%s\t$%02x\n",optab[j].text,k); objout(); }/* * * * * * * * * * * END OF inhand() * * * * * * * * * * */ dev86-0.16.21/dis88/dishand.c000066400000000000000000000637571231050321700153460ustar00rootroot00000000000000static char *sccsid = "@(#) dishand.c, Ver. 2.1 created 00:00:00 87/09/01"; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Copyright (C) 1987 G. M. Harding, all rights reserved * * * * Permission to copy and redistribute is hereby granted, * * provided full source code, with all copyright notices, * * accompanies any redistribution. * * * * This file contains the source code for most of the spe- * * cialized handler routines of the disassembler program. * * (The file disfp.c contains handler routines specific to * * the 8087 numeric co-processor.) Each handler routine * * interprets the opcode byte (and subsequent data bytes, * * if any) of a particular family of opcodes, and is re- * * sponsible for generating appropriate output. All of the * * code in this file is highly MACHINE-SPECIFIC, and would * * have to be rewritten for a different CPU. The handler * * routines are accessed only via pointers in the optab[] * * array, however, so machine dependencies are confined to * * this file, its sister file "disfp.c", and the data file * * "distabs.c". * * * * All of the code in this file is based on the assumption * * of sixteen-bit integers. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "dis.h" /* Disassembler declarations */ int segflg; /* Segment-override flag */ unsigned char objbuf[OBJMAX]; /* Buffer for object code */ int objptr; /* Index into objbuf[] */ unsigned long PC; /* Current program counter */ /* * * * * * MISCELLANEOUS SUPPORTING ROUTINES * * * * * */ void objini(j) /* Object code init routine */ register int j; { if ((segflg == 1) || (segflg == 2)) segflg *= 3; else segflg = 0; objptr = 0; objbuf[objptr++] = (unsigned char)(j); } void objout() /* Object-code output routine */ { register int k; if ( ! objflg ) return; else { printf("\t|"); if (symptr >= 0) printf(" %05.5lx:",(PC + 1L - (long)(objptr))); for (k = 0; k < objptr; ++k) printf(" %02.2x",objbuf[k]); putchar('\n'); } } void badseq(j,k) /* Invalid-sequence routine */ register int j, k; { printf("\t.byte\t$%02.2x\t\t| invalid code sequence\n",j); printf("\t.byte\t$%02.2x\n",k); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * This routine is the first of several opcode-specific * * handlers, each of which is dedicated to a particular * * opcode family. A pointer to a handler routine is con- * * tained in the second field of each optab[] entry. The * * dfhand() routine is the default handler, invoked when * * no other handler is appropriate (generally, when an in- * * valid opcode is encountered). * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void dfhand(j) register int j; /* Pointer to optab[] entry */ {/* * * * * * * * * * START OF dfhand() * * * * * * * * * */ segflg = 0; printf("\t.byte\t$%02.2x",j); if (optab[j].min || optab[j].max) putchar('\n'); else printf("\t\t| unimplemented opcode\n"); }/* * * * * * * * * * * END OF dfhand() * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * This is the single-byte handler, invoked whenever a * * one-byte opcode is encountered. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void sbhand(j) register int j; /* Pointer to optab[] entry */ {/* * * * * * * * * * START OF sbhand() * * * * * * * * * */ objini(j); if (j == 0x2e) /* seg cs */ segflg = 1; if ((j == 0x26) /* seg es */ || (j == 0x36) /* seg ss */ || (j == 0x3e)) /* seg ds */ segflg = 2; printf("%s\n",optab[j].text); objout(); }/* * * * * * * * * * * END OF sbhand() * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * This is the handler for most of the processor's regular * * arithmetic operations. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void aohand(j) register int j; /* Pointer to optab[] entry */ {/* * * * * * * * * * START OF aohand() * * * * * * * * * */ register int k; int m, n; char b[80]; objini(j); switch (j & 7) { case 0 : case 1 : case 2 : case 3 : printf("%s\t",optab[j].text); FETCH(k); printf("%s\n",mtrans(j,k,TR_STD)); break; case 4 : FETCH(k); if( k < 16 ) printf("%s\tal,*%d\n",optab[j].text,k); else printf("%s\tal,*$%02.2x\n",optab[j].text,k); break; case 5 : FETCH(m); FETCH(n); k = (n << 8) | m; if (lookext((long)(k),(PC - 1),b)) printf("%s\tax,#%s\n",optab[j].text,b); else { if( k < 100 || k > 65436 ) printf("%s\tax,#%d\n",optab[j].text, (short)k); else printf("%s\tax,#$%04x\n",optab[j].text,k); } break; default : dfhand(j); break; } objout(); }/* * * * * * * * * * * END OF aohand() * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * This is the handler for opcodes which perform short * * (eight-bit) relative jumps. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void sjhand(j) register int j; /* Pointer to optab[] entry */ {/* * * * * * * * * * START OF sjhand() * * * * * * * * * */ register int k; int m; unsigned short dest; objini(j); FETCH(m); if (m & 0x80) k = 0xff00; else k = 0; k |= m; dest = (PC + k + 1); printf("%s\t%s\t\t| loc %05.5lx\n",optab[j].text, lookup((long) dest,N_TEXT,LOOK_REL,-1L), (long) dest); objout(); }/* * * * * * * * * * * END OF sjhand() * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * This is the handler for a loosely-knit family of op- * * codes which perform arithmetic and logical operations, * * and which take immediate data. The routine's logic is * * rather complex, so, in an effort to avoid additional * * complexity, the search for external references in the * * relocation table has been dispensed with. Eager hackers * * can try their hand at coding such a search. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void imhand(j) register int j; /* Pointer to optab[] entry */ {/* * * * * * * * * * START OF imhand() * * * * * * * * * */ unsigned long pc; register int k; int offset, oflag, immed, iflag, mod, opi, w, rm; int m, n; static char a[100], b[30]; objini(j); FETCH(k); pc = PC + 1; offset = 0; mod = (k & 0xc0) >> 6; opi = (k & 0x38) >> 3; w = j & 1; rm = k & 7; if ((j & 2) && ((opi == 1) || (opi == 4) || (opi == 6))) { badseq(j,k); return; } strcpy(a,OPFAM[opi]); if ( ! w ) strcat(a,"b"); if ((oflag = mod) > 2) oflag = 0; if ((mod == 0) && (rm == 6)) { FETCH(m); FETCH(n); offset = (n << 8) | m; } else if (oflag) if (oflag == 2) { FETCH(m); FETCH(n); offset = (n << 8) | m; } else { FETCH(m); if (m & 0x80) n = -0xFF; else n = 0; offset = n | m; } switch (j & 3) { case 0 : case 2 : FETCH(immed); iflag = 0; break; case 1 : FETCH(m); FETCH(n); immed = (n << 8) | m; iflag = 1; break; case 3 : FETCH(immed); if (immed & 0x80) immed &= 0xff00; iflag = 0; break; } strcat(a,"\t"); switch (mod) { case 0 : if (rm == 6) strcat(a, lookup((long)(offset),N_DATA,LOOK_ABS,pc)); else { sprintf(b,"(%s)",REGS0[rm]); strcat(a,b); } break; case 1 : case 2 : if (mod == 1) { strcat(a,"*"); sprintf(b,"%d(", (short)offset); } else { strcat(a,"#"); if( offset < 100 || offset > 65436 ) sprintf(b,"%d(", (short)offset); else sprintf(b,"$%04x(",offset); } strcat(a,b); strcat(a,REGS1[rm]); strcat(a,")"); break; case 3 : strcat(a,REGS[(w << 3) | rm]); break; } strcat(a,","); if (iflag) { strcat(a,"#"); if( immed < 100 || immed > 65436 ) sprintf(b,"%d", (short)immed); else sprintf(b,"$%04x",immed); } else { strcat(a,"*"); sprintf(b,"%d",immed); } strcat(a,b); printf("%s\n",a); objout(); }/* * * * * * * * * * * END OF imhand() * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * This is the handler for various "mov"-type opcodes * * which use the mod, reg, and r/m fields of the second * * code byte in a standard, straightforward way. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void mvhand(j) int j; /* Pointer to optab[] entry */ {/* * * * * * * * * * START OF mvhand() * * * * * * * * * */ register int k, m = j; objini(j); FETCH(k); if ((m == 0x84) || (m == 0x85) /* Kind of kludgey */ || (m == 0xc4) || (m == 0xc5) || (m == 0x8d)) if (m & 0x40) m |= 0x03; else m |= 0x02; printf("%s\t%s\n",optab[j].text,mtrans(m,k,TR_STD)); objout(); }/* * * * * * * * * * * END OF mvhand() * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * This is the handler for segment-register "mov" opcodes. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void mshand(j) register int j; /* Pointer to optab[] entry */ {/* * * * * * * * * * START OF mshand() * * * * * * * * * */ register int k; objini(j); FETCH(k); if (k & 0x20) { badseq(j,k); return; } printf("%s\t%s\n",optab[j].text,mtrans(j,k,TR_SEG)); objout(); }/* * * * * * * * * * * END OF mshand() * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * This is the handler for pops, other than single-byte * * pops. (The 8088 allows popping into any register, or * * directly into memory, accessed either immediately or * * through a register and an index.) * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void pohand(j) register int j; /* Pointer to optab[] entry */ {/* * * * * * * * * * START OF pohand() * * * * * * * * * */ char *a; register int k; objini(j); FETCH(k); if (k & 0x38) { badseq(j,k); return; } printf("%s\t",optab[j].text); a = mtrans((j & 0xfd),k,TR_STD); mtrunc(a); printf("%s\n",a); objout(); }/* * * * * * * * * * * END OF pohand() * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * This is the handler routine for intersegment calls and * * jumps. Its output is never symbolic, because the host * * linker does not allow symbolic intersegment address * * references except by means of symbolic constants, and * * any such constants in the symbol table, even if they * * are of the appropriate value, may be misleading. In * * compiled code, intersegment references should not be * * encountered, and even in assembled code, they should * * occur infrequently. If and when they do occur, however, * * they will be disassembled in absolute form. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void cihand(j) int j; /* Pointer to optab[] entry */ {/* * * * * * * * * * START OF cihand() * * * * * * * * * */ register int m, n; objini(j); printf("%s\t",optab[j].text); FETCH(m); FETCH(n); printf("#$%04.4x,",((n << 8) | m)); FETCH(m); FETCH(n); printf("#$%04.4x\n",((n << 8) | m)); objout(); }/* * * * * * * * * * * END OF cihand() * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * This is the handler for "mov" opcodes with immediate * * data. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void mihand(j) register int j; /* Pointer to optab[] entry */ {/* * * * * * * * * * START OF mihand() * * * * * * * * * */ register int k; int m, n; char b[80]; objini(j); printf("%s",optab[j].text); if (j & 8) { FETCH(m); FETCH(n); k = ((n << 8) | m); if (lookext((long)(k),(PC - 1),b)) printf("#%s\n",b); else { if( k < 100 || k > 65436 ) printf("#%d\n",(short)k); else printf("#$%04x\n",k); } } else { FETCH(m); printf("*%d\n",m); } objout(); }/* * * * * * * * * * * END OF mihand() * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * This is the handler for a family of quick-move opcodes. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void mqhand(j) int j; /* Pointer to optab[] entry */ {/* * * * * * * * * * START OF mqhand() * * * * * * * * * */ unsigned long pc; register int m, n; objini(j); pc = PC + 1; FETCH(m); FETCH(n); m = (n << 8) | m; printf("%s\t",optab[j].text); if (j & 2) printf("%s,%s\n", lookup((long)(m),N_DATA,LOOK_ABS,pc), REGS[(j & 1) << 3]); else printf("%s,%s\n", REGS[(j & 1) << 3], lookup((long)(m),N_DATA,LOOK_ABS,pc)); objout(); }/* * * * * * * * * * * END OF mqhand() * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * This is the handler for a family of quick-test opcodes. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void tqhand(j) int j; /* Pointer to optab[] entry */ {/* * * * * * * * * * START OF tqhand() * * * * * * * * * */ register int m, n; int k; char b[80]; objini(j); printf("%s\t%s,",optab[j].text,REGS[(j & 1) << 3]); FETCH(m); if (j & 1) { FETCH(n); k = ((n << 8) | m); if (lookext((long)(k),(PC - 1),b)) printf("#%s\n",b); else { if( k < 100 || k > 65436 ) printf("#%d\n",(short)k); else printf("#$%04x\n",k); } } else { if (m & 80) m |= -0xFF; printf("*%d\n",m); } objout(); }/* * * * * * * * * * * END OF tqhand() * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * This is the handler for multiple-byte "return" opcodes. * * The 8088 allows returns to take an optional 16-bit ar- * * gument, which reflects the amount to be added to SP * * after the pop of the return address. The idea is to * * facilitate the use of local parameters on the stack. * * After some rumination, it was decided to disassemble * * any such arguments as absolute quantities, rather than * * rummaging through the symbol table for possible corre- * * sponding constants. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void rehand(j) int j; /* Pointer to optab[] entry */ {/* * * * * * * * * * START OF rehand() * * * * * * * * * */ register int m, n; objini(j); FETCH(m); FETCH(n); m = (n << 8) | m; printf("%s\t#0x%04.4x\n",optab[j].text,m); objout(); }/* * * * * * * * * * * END OF rehand() * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * This is the handler for "mov" opcodes involving memory * * and immediate data. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void mmhand(j) register int j; /* Pointer to optab[] entry */ {/* * * * * * * * * * START OF mmhand() * * * * * * * * * */ char *a; register int k; char b[80]; objini(j); FETCH(k); if (k & 0x38) { badseq(j,k); return; } printf("%s",optab[j].text); if ( ! (j & 1) ) putchar('b'); a = mtrans((j & 0xfd),(k & 0xc7),TR_STD); mtrunc(a); printf("\t%s,",a); if (j & 1) { FETCH(j); FETCH(k); k = (k << 8) | j; if (lookext((long)(k),(PC - 1),b)) printf("#%s\n",b); else { if( k < 100 || k > 65436 ) printf("#%d\n",(short)k); else printf("#$%04x\n",k); } } else { FETCH(k); printf("*%d\n",k); } objout(); }/* * * * * * * * * * * END OF mmhand() * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * This is the handler for the 8088 family of shift and * * rotate instructions. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void srhand(j) register int j; /* Pointer to optab[] entry */ {/* * * * * * * * * * START OF srhand() * * * * * * * * * */ char *a; register int k; objini(j); FETCH(k); if ((k & 0x38) == 0x30) { badseq(j,k); return; } printf("%s",OPFAM[((k & 0x38) >> 3) + 16]); if ( ! (j & 1) ) putchar('b'); a = mtrans((j & 0xfd),(k & 0xc7),TR_STD); mtrunc(a); printf("\t%s",a); if (j & 2) printf(",cl\n"); else printf(",*1\n"); objout(); }/* * * * * * * * * * * END OF srhand() * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * This is the handler for the ASCII-adjust opcodes. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void aahand(j) register int j; /* Pointer to optab[] entry */ {/* * * * * * * * * * START OF aahand() * * * * * * * * * */ register int k; objini(j); FETCH(k); if (k != 0x0a) { badseq(j,k); return; } printf("%s\n",optab[j].text); objout(); }/* * * * * * * * * * * END OF aahand() * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * This is the handler for port I/O opcodes which specify * * the port address as an immediate operand. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void iohand(j) register int j; /* Pointer to optab[] entry */ {/* * * * * * * * * * START OF iohand() * * * * * * * * * */ register int k; objini(j); FETCH(k); printf("%s\t$%02.2x\n",optab[j].text,k); objout(); }/* * * * * * * * * * * END OF iohand() * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * This is the handler for opcodes which perform long * * (sixteen-bit) relative jumps and calls. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void ljhand(j) register int j; /* Pointer to optab[] entry */ {/* * * * * * * * * * START OF ljhand() * * * * * * * * * */ register int k; int m, n; unsigned short dest; objini(j); FETCH(m); FETCH(n); k = (n << 8) | m; dest = PC + k + 1; printf("%s\t%s\t\t| loc %05.5lx\n",optab[j].text, lookup((long)dest,N_TEXT,LOOK_LNG,(PC - 1L)), (long)dest); objout(); }/* * * * * * * * * * * END OF ljhand() * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * This is the handler for a pair of oddball opcodes (0xf6 * * and 0xf7) which perform miscellaneous arithmetic opera- * * tions not dealt with elsewhere. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void mahand(j) register int j; /* Pointer to optab[] entry */ {/* * * * * * * * * * START OF mahand() * * * * * * * * * */ char *a; register int k; char b[80]; objini(j); FETCH(k); a = mtrans((j & 0xfd),(k & 0xc7),TR_STD); mtrunc(a); switch (((k = objbuf[1]) & 0x38) >> 3) { case 0 : printf("\ttest"); break; case 1 : badseq(j,k); return; case 2 : printf("\tnot"); break; case 3 : printf("\tneg"); break; case 4 : printf("\tmul"); break; case 5 : printf("\timul"); break; case 6 : printf("\tdiv"); break; case 7 : printf("\tidiv"); break; } if ( ! (j & 1) ) putchar('b'); printf("\t%s",a); if (k & 0x38) putchar('\n'); else if (j & 1) { FETCH(j); FETCH(k); k = (k << 8) | j; if (lookext((long)(k),(PC - 1),b)) printf(",#%s\n",b); else printf(",#$%04x\n",k); } else { FETCH(k); printf(",*%d\n",k); } objout(); }/* * * * * * * * * * * END OF mahand() * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * This is the handler for miscellaneous jump, call, push, * * and increment/decrement opcodes (0xfe and 0xff) which * * are not dealt with elsewhere. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void mjhand(j) register int j; /* Pointer to optab[] entry */ {/* * * * * * * * * * START OF mjhand() * * * * * * * * * */ char *a; register int k; objini(j); FETCH(k); a = mtrans((j & 0xfd),(k & 0xc7),TR_STD); mtrunc(a); switch (((k = objbuf[1]) & 0x38) >> 3) { case 0 : printf("\tinc"); if ( ! (j & 1) ) putchar('b'); putchar('\t'); break; case 1 : printf("\tdec"); if ( ! (j & 1) ) putchar('b'); putchar('\t'); break; case 2 : if (j & 1) printf("\tcall\t@"); else goto BAD; break; case 3 : if (j & 1) printf("\tcalli\t@"); else goto BAD; break; case 4 : if (j & 1) printf("\tjmp\t@"); else goto BAD; break; case 5 : if (j & 1) printf("\tjmpi\t@"); else goto BAD; break; case 6 : if (j & 1) printf("\tpush\t"); else goto BAD; break; case 7 : BAD : badseq(j,k); return; } printf("%s\n",a); objout(); }/* * * * * * * * * * * END OF mjhand() * * * * * * * * * * */ dev86-0.16.21/dis88/dismain.c000066400000000000000000000447131231050321700153470ustar00rootroot00000000000000static char *sccsid = "@(#) dismain.c, Ver. 2.1 created 00:00:00 87/09/01"; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Copyright (C) 1987 G. M. Harding, all rights reserved * * * * Permission to copy and redistribute is hereby granted, * * provided full source code, with all copyright notices, * * accompanies any redistribution. * * * * This file contains the source code for the machine- * * independent portions of a disassembler program to run * * in a Unix (System III) environment. It expects, as its * * input, a file in standard a.out format, optionally con- * * taining symbol table information. If a symbol table is * * present, it will be used in the disassembly; otherwise, * * all address references will be literal (absolute). * * * * The disassembler program was originally written for an * * Intel 8088 CPU. However, all details of the actual CPU * * architecture are hidden in three machine-specific files * * named distabs.c, dishand.c, and disfp.c (the latter * * file is specific to the 8087 numeric co-processor). The * * code in this file is generic, and should require mini- * * mal revision if a different CPU is to be targeted. If a * * different version of Unix is to be targeted, changes to * * this file may be necessary, and if a completely differ- * * ent OS is to be targeted, all bets are off. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "dis.h" /* Disassembler declarations */ extern char *release; /* Contains release string */ static char *IFILE = NULL; /* Points to input file name */ static char *OFILE = NULL; /* Points to output file name */ static char *PRG; /* Name of invoking program */ static unsigned long zcount; /* Consecutive "0" byte count */ int objflg = 0; /* Flag: output object bytes */ int force = 0; /* Flag: override some checks */ #define unix 1 #define i8086 1 #define ibmpc 1 #if unix && i8086 && ibmpc /* Set the CPU identifier */ static int cpuid = 1; #else static int cpuid = 0; #endif _PROTOTYPE(static void usage, (char *s )); _PROTOTYPE(static void fatal, (char *s, char *t )); _PROTOTYPE(static void zdump, (unsigned long beg )); _PROTOTYPE(static void prolog, (void)); _PROTOTYPE(static void distext, (void)); _PROTOTYPE(static void disdata, (void)); _PROTOTYPE(static void disbss, (void)); _PROTOTYPE(static char *invoker, (char *s)); _PROTOTYPE(static int objdump, (char *c)); _PROTOTYPE(static char *getlab, (int type)); _PROTOTYPE(static void prolog, (void)); /* * * * * * * MISCELLANEOUS UTILITY FUNCTIONS * * * * * * */ static void usage(s) register char *s; { fprintf(stderr,"Usage: %s [-o] ifile [ofile]\n",s); exit(-1); } static void fatal(s,t) register char *s, *t; { fprintf(stderr,"%s: %s\n",s,t); exit(-1); } static void zdump(beg) unsigned long beg; { beg = PC - beg; if (beg > 1L) printf("\t.zerow\t%ld\n",(beg >> 1)); if (beg & 1L) printf("\t.byte\t0\n"); } static char * invoker(s) register char *s; { register int k; k = strlen(s); while (k--) if (s[k] == '/') { s += k; ++s; break; } return (s); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * This rather tricky routine supports the disdata() func- * * tion. Its job is to output the code for a sequence of * * data bytes whenever the object buffer is full, or when * * a symbolic label is to be output. However, it must also * * keep track of consecutive zero words so that lengthy * * stretches of null data can be compressed by the use of * * an appropriate assembler pseudo-op. It does this by * * setting and testing a file-wide flag which counts suc- * * cessive full buffers of null data. The function returns * * a logical TRUE value if it outputs anything, logical * * FALSE otherwise. (This enables disdata() to determine * * whether to output a new synthetic label when there is * * no symbol table.) * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ static int objdump(c) register char *c; {/* * * * * * * * * * START OF objdump() * * * * * * * * * */ register int k,j; int retval = 0; if (objptr == OBJMAX) { for (k = 0; k < OBJMAX; ++k) if (objbuf[k]) break; if (k == OBJMAX) { zcount += k; objptr = 0; if (c == NULL) return (retval); } } if (zcount) { printf("\t.zerow\t%ld\n",(zcount >> 1)); ++retval; zcount = 0L; } if (objptr) { printf("\t.byte\t"); ++retval; } else return (retval); for (k = 0; k < objptr; ++k) { printf("$%02.2x",objbuf[k]); if (k < (objptr - 1)) putchar(','); } for (k = objptr; k < OBJMAX; ++k) printf(" "); printf(" | \""); for (k = 0; k < objptr; ++k) { if (objbuf[k] > ' ' && objbuf[k] <= '~' ) putchar(objbuf[k]); else switch(objbuf[k]) { case '\t': printf("\\t"); break; case '\n': printf("\\n"); break; case '\f': printf("\\f"); break; case '\r': printf("\\r"); break; default: putchar('.'); break; } } printf("\"\n"); objptr = 0; return (retval); }/* * * * * * * * * * END OF objdump() * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * This routine, called at the beginning of the input * * cycle for each object byte, and before any interpreta- * * tion is attempted, searches the symbol table for any * * symbolic name with a value corresponding to the cur- * * rent PC and a type corresponding to the segment type * * (i.e., text, data, or bss) specified by the function's * * argument. If any such name is found, a pointer to it is * * returned; otherwise, a NULL pointer is returned. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ static char * getlab(type) register int type; {/* * * * * * * * * * START OF getlab() * * * * * * * * * */ register int k; static char b[48], c[32]; if (symptr < 0) if ((type == N_TEXT) || ((type == N_DATA) && ( ! objptr ) && ( ! zcount ))) { if (type == N_TEXT) sprintf(b,"T%05.5lx:",PC); else sprintf(b,"D%05.5lx:",PC); return (b); } else return (NULL); for (k = 0; k <= symptr; ++k) if ((symtab[k].n_value == PC) && ((symtab[k].n_sclass & N_SECT) == type)) { sprintf(b,"%s:\n",getnam(k)); if (objflg && (type != N_TEXT)) sprintf(c,"| %05.5lx\n",PC); strcat(b,c); return (b); } return (NULL); }/* * * * * * * * * * * END OF getlab() * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * This routine performs a preliminary scan of the symbol * * table, before disassembly begins, and outputs declara- * * tions of globals and constants. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ static void prolog() {/* * * * * * * * * * START OF prolog() * * * * * * * * * */ register int j, flag; fflush(stdout); if (symptr < 0) return; for (j = flag = 0; j <= symptr; ++j) if ((symtab[j].n_sclass & N_CLASS) == C_EXT) if (((symtab[j].n_sclass & N_SECT) > N_UNDF) && ((symtab[j].n_sclass & N_SECT) < N_COMM)) { char *c = getnam(j); printf("\t.globl\t%s",c); if (++flag == 1) { putchar('\t'); if (strlen(c) < 8) putchar('\t'); printf("| Internal global\n"); } else putchar('\n'); } else if (symtab[j].n_value) { char *c = getnam(j); printf("\t.comm\t%s,0x%08.8lx",c, symtab[j].n_value); if (++flag == 1) printf("\t| Internal global\n"); else putchar('\n'); } if (flag) putchar('\n'); fflush(stdout); for (j = flag = 0; j <= relptr; ++j) if (relo[j].r_symndx < S_BSS) { char *c = getnam(relo[j].r_symndx); ++flag; printf("\t.globl\t%s",c); putchar('\t'); if (strlen(c) < 8) putchar('\t'); printf("| Undef: %05.5lx\n",relo[j].r_vaddr); } if (flag) putchar('\n'); fflush(stdout); for (j = flag = 0; j <= symptr; ++j) if ((symtab[j].n_sclass & N_SECT) == N_ABS) { char *c = getnam(j); printf("%s=0x%08.8lx",c,symtab[j].n_value); if (++flag == 1) { printf("\t\t"); if (strlen(c) < 5) putchar('\t'); printf("| Literal\n"); } else putchar('\n'); } if (flag) putchar('\n'); fflush(stdout); }/* * * * * * * * * * * END OF prolog() * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * This function is responsible for disassembly of the * * object file's text segment. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ static void distext() {/* * * * * * * * * * START OF distext() * * * * * * * * * */ char *c; register int j; register void (*f)(); for (j = 0; j < (int)(HDR.a_hdrlen); ++j) getchar(); printf("| %s, %s\n\n",PRG,release); printf("| @("); printf("#)\tDisassembly of %s",IFILE); if (symptr < 0) printf(" (no symbols)\n\n"); else printf("\n\n"); if (HDR.a_flags & A_EXEC) printf("| File is executable\n\n"); if (HDR.a_flags & A_SEP) printf("| File has split I/D space\n\n"); prolog(); printf("\t.text\t\t\t| loc = %05.5lx, size = %05.5lx\n\n", PC,HDR.a_text); fflush(stdout); segflg = 0; for (PC = 0L; PC < HDR.a_text; ++PC) { j = getchar(); if( j == EOF ) break; j &= 0xFF; if ((j == 0) && ((PC + 1L) == HDR.a_text)) { ++PC; break; } if ((c = getlab(N_TEXT)) != NULL) printf("%s",c); if( j>=0 && j<256 ) { f = optab[j].func; (*f)(j); } fflush(stdout); } }/* * * * * * * * * * END OF distext() * * * * * * * * * */ Fetch() { int p; ++PC; if( symptr>=0 && getlab(N_TEXT) != NULL ) { --PC; return -1; } /* #define FETCH(p) ++PC; p = getchar() & 0xff; objbuf[objptr++] = p */ p = getchar(); objbuf[objptr++] = p; return p; } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * This function handles the object file's data segment. * * There is no good way to disassemble a data segment, be- * * cause it is impossible to tell, from the object code * * alone, what each data byte refers to. If it refers to * * an external symbol, the reference can be resolved from * * the relocation table, if there is one. However, if it * * refers to a static symbol, it cannot be distinguished * * from numeric, character, or other pointer data. In some * * cases, one might make a semi-educated guess as to the * * nature of the data, but such guesses are inherently * * haphazard, and they are bound to be wrong a good por- * * tion of the time. Consequently, the data segment is * * disassembled as a byte stream, which will satisfy no * * one but which, at least, will never mislead anyone. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ static void disdata() {/* * * * * * * * * * START OF disdata() * * * * * * * * * */ register char *c; register int j; unsigned long end; putchar('\n'); if( HDR.a_data == 0 ) return; if (HDR.a_flags & A_SEP) { PC = 0L; end = HDR.a_data; } else end = HDR.a_text + HDR.a_data; printf("\t.data\t\t\t| loc = %05.5lx, size = %05.5lx\n\n", PC,HDR.a_data); segflg = 0; for (objptr = 0, zcount = 0L; PC < end; ++PC) { if ((c = getlab(N_DATA)) != NULL) { objdump(c); printf("%s",c); } if (objptr >= OBJMAX) if (objdump(NULL) && (symptr < 0)) printf("D%05.5lx:",PC); j = getchar() & 0xff; objbuf[objptr++] = j; } objdump(""); }/* * * * * * * * * * END OF disdata() * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * This function handles the object file's bss segment. * * Disassembly of the bss segment is easy, because every- * * thing in it is zero by definition. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ static void disbss() {/* * * * * * * * * * START OF disbss() * * * * * * * * * */ register int j; register char *c; unsigned long beg, end; putchar('\n'); if( HDR.a_bss == 0 ) return; if (HDR.a_flags & A_SEP) end = HDR.a_data + HDR.a_bss; else end = HDR.a_text + HDR.a_data + HDR.a_bss; printf("\t.bss\t\t\t| loc = %05.5lx, size = %05.5lx\n\n", PC,HDR.a_bss); segflg = 0; for (beg = PC; PC < end; ++PC) if ((c = getlab(N_BSS)) != NULL) { if (PC > beg) { zdump(beg); beg = PC; } printf("%s",c); } if (PC > beg) zdump(beg); }/* * * * * * * * * * * END OF disbss() * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * This is the program entry point. The command line is * * searched for an input file name, which must be present. * * An optional output file name is also permitted; if none * * is found, standard output is the default. One command- * * line option is available: "-o", which causes the pro- * * gram to include object code in comments along with its * * mnemonic output. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void main(argc,argv) int argc; /* Command-line args from OS */ register char **argv; {/* * * * * * * * * * * START OF main() * * * * * * * * * * */ char a[1024]; register int fd; long taboff, tabnum; long reloff, relnum; PRG = invoker(*argv); while (*++argv != NULL) /* Process command-line args */ if (**argv == '-') switch (*++*argv) { case 'o' : if (*++*argv) usage(PRG); else ++objflg; break; case 'f' : force++; break; default : usage(PRG); } else if (IFILE == NULL) IFILE = *argv; else if (OFILE == NULL) OFILE = *argv; else usage(PRG); if (IFILE == NULL) usage(PRG); else if ((fd = open(IFILE,0)) < 0) { sprintf(a,"can't access input file %s",IFILE); fatal(PRG,a); } if (OFILE != NULL) if (freopen(OFILE,"w",stdout) == NULL) { sprintf(a,"can't open output file %s",OFILE); fatal(PRG,a); } if ( ! cpuid ) fprintf(stderr,"%s: warning: host/cpu clash\n",PRG); read(fd, (char *) &HDR,sizeof(struct exec)); if (BADMAG(HDR)) { if (!force) { sprintf(a,"input file %s not in object format",IFILE); fatal(PRG,a); } memset(&HDR, '\0', sizeof(struct exec)); HDR.a_text = 0x10000L; } if (HDR.a_cpu != A_I8086 && !force) { sprintf(a,"%s is not an 8086/8088 object file",IFILE); fatal(PRG,a); } if (HDR.a_hdrlen <= A_MINHDR) { HDR.a_trsize = HDR.a_drsize = 0L; HDR.a_tbase = HDR.a_dbase = 0L; /* HDR.a_lnums = HDR.a_toffs = 0L; */ } reloff = HDR.a_text /* Compute reloc data offset */ + HDR.a_data + (long)(HDR.a_hdrlen); relnum = (HDR.a_trsize + HDR.a_drsize) / sizeof(struct reloc); taboff = reloff /* Compute name table offset */ + HDR.a_trsize + HDR.a_drsize; tabnum = HDR.a_syms / sizeof(struct nlist); if (relnum > MAXSYM) fatal(PRG,"reloc table overflow"); if (tabnum > MAXSYM) fatal(PRG,"symbol table overflow"); if (relnum) /* Get reloc data */ if (lseek(fd,reloff,0) != reloff) fatal(PRG,"lseek error"); else { for (relptr = 0; relptr < relnum; ++relptr) read(fd, (char *) &relo[relptr],sizeof(struct reloc)); relptr--; } if (tabnum) /* Read in symtab */ if (lseek(fd,taboff,0) != taboff) fatal(PRG,"lseek error"); else { for (symptr = 0; symptr < tabnum; ++symptr) read(fd, (char *) &symtab[symptr],sizeof(struct nlist)); symptr--; } close(fd); if (freopen(IFILE,"r",stdin) == NULL) { sprintf(a,"can't reopen input file %s",IFILE); fatal(PRG,a); } distext(); disdata(); disbss(); exit(0); }/* * * * * * * * * * * END OF main() * * * * * * * * * * */ dev86-0.16.21/dis88/disrel.c000066400000000000000000000015571231050321700152040ustar00rootroot00000000000000static char *copyright = "@(#) Copyright (C) 1987 G. M. Harding, all rights reserved"; #ifdef __linux__ char *release = "released with Dev86 for Linux, based on minix 2.1"; #else static char *sccsid = "@(#) disrel.c, Ver. 2.1 created 00:00:00 87/09/01"; char *release = "release 2.1 (MINIX)"; #endif /* ** ** This file documents the major revisions to the 8088 sym- ** bolic disassembler. It also contains the release string ** which is output at the head of each disassembly, and the ** copyright string which must be incorporated in any code ** distribution. ** ** Permission to copy and redistribute is hereby granted, ** provided full source code, with all copyright notices, ** accompanies any redistribution. ** ** REVISION HISTORY: ** ** SEP 87: ** After internal shakeout, released on Usenet. ** ** JUN 88: ** Ported to MINIX */ dev86-0.16.21/dis88/distabs.c000066400000000000000000000733711231050321700153560ustar00rootroot00000000000000static char *sccsid = "@(#) distabs.c, Ver. 2.1 created 00:00:00 87/09/01"; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Copyright (C) 1987 G. M. Harding, all rights reserved * * * * Permission to copy and redistribute is hereby granted, * * provided full source code, with all copyright notices, * * accompanies any redistribution. * * * * This file contains the lookup tables and other data * * structures for the Intel 8088 symbolic disassembler. It * * also contains a few global routines which facilitate * * access to the tables, for use primarily by the handler * * functions. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "dis.h" /* Disassembler declarations */ struct exec HDR; /* Used to hold header info */ struct nlist symtab[MAXSYM]; /* Array of symbol table info */ struct reloc relo[MAXSYM]; /* Array of relocation info */ int symptr = -1, /* Index into symtab[] */ relptr = -1; /* Index into relo[] */ char *REGS[] = /* Table of register names */ { "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh", "ax", "cx", "dx", "bx", "sp", "bp", "si", "di", "es", "cs", "ss", "ds" }; char *REGS0[] = /* Mode 0 register name table */ { "bx_si", "bx_di", "bp_si", "bp_di", "si", "di", "", "bx" }; char *REGS1[] = /* Mode 1 register name table */ { "bx_si", "bx_di", "bp_si", "bp_di", "si", "di", "bp", "bx" }; int symrank[6][6] = /* Symbol type/rank matrix */ { /* UND ABS TXT DAT BSS COM */ /* UND */ 5, 4, 1, 2, 3, 0, /* ABS */ 1, 5, 4, 3, 2, 0, /* TXT */ 4, 1, 5, 3, 2, 0, /* DAT */ 3, 1, 2, 5, 4, 0, /* BSS */ 3, 1, 2, 4, 5, 0, /* COM */ 2, 0, 1, 3, 4, 5 }; /* * * * * * * * * * * * OPCODE DATA * * * * * * * * * * * */ char ADD[] = "\tadd", /* Mnemonics by family */ OR[] = "\tor", ADC[] = "\tadc", SBB[] = "\tsbb", AND[] = "\tand", SUB[] = "\tsub", XOR[] = "\txor", CMP[] = "\tcmp", NOT[] = "\tnot", NEG[] = "\tneg", MUL[] = "\tmul", DIV[] = "\tdiv", MOV[] = "\tmov", ESC[] = "\tesc", TEST[] = "\ttest", AMBIG[] = "", ROL[] = "\trol", ROR[] = "\tror", RCL[] = "\trcl", RCR[] = "\trcr", SAL[] = "\tsal", SHR[] = "\tshr", SHL[] = "\tshl", SAR[] = "\tsar"; char *OPFAM[] = /* Family lookup table */ { ADD, OR, ADC, SBB, AND, SUB, XOR, CMP, NOT, NEG, MUL, DIV, MOV, ESC, TEST, AMBIG, ROL, ROR, RCL, RCR, SAL, SHR, SHL, SAR }; struct opcode optab[] = /* Table of opcode data */ { ADD, aohand, 2, 4, /* 0x00 */ ADD, aohand, 2, 4, /* 0x01 */ ADD, aohand, 2, 4, /* 0x02 */ ADD, aohand, 2, 4, /* 0x03 */ ADD, aohand, 2, 2, /* 0x04 */ ADD, aohand, 3, 3, /* 0x05 */ "\tpush\tes", sbhand, 1, 1, /* 0x06 */ "\tpop\tes", sbhand, 1, 1, /* 0x07 */ OR, aohand, 2, 4, /* 0x08 */ OR, aohand, 2, 4, /* 0x09 */ OR, aohand, 2, 4, /* 0x0a */ OR, aohand, 2, 4, /* 0x0b */ OR, aohand, 2, 2, /* 0x0c */ OR, aohand, 3, 3, /* 0x0d */ "\tpush\tcs", sbhand, 1, 1, /* 0x0e */ "\t.code\t386", sbhand, 1, 1, /* 0x0f */ ADC, aohand, 2, 4, /* 0x10 */ ADC, aohand, 2, 4, /* 0x11 */ ADC, aohand, 2, 4, /* 0x12 */ ADC, aohand, 2, 4, /* 0x13 */ ADC, aohand, 2, 2, /* 0x14 */ ADC, aohand, 3, 3, /* 0x15 */ "\tpush\tss", sbhand, 1, 1, /* 0x16 */ "\tpop\tss", sbhand, 1, 1, /* 0x17 */ SBB, aohand, 2, 4, /* 0x18 */ SBB, aohand, 2, 4, /* 0x19 */ SBB, aohand, 2, 4, /* 0x1a */ SBB, aohand, 2, 4, /* 0x1b */ SBB, aohand, 2, 2, /* 0x1c */ SBB, aohand, 3, 3, /* 0x1d */ "\tpush\tds", sbhand, 1, 1, /* 0x1e */ "\tpop\tds", sbhand, 1, 1, /* 0x1f */ AND, aohand, 2, 4, /* 0x20 */ AND, aohand, 2, 4, /* 0x21 */ AND, aohand, 2, 4, /* 0x22 */ AND, aohand, 2, 4, /* 0x23 */ AND, aohand, 2, 2, /* 0x24 */ AND, aohand, 3, 3, /* 0x25 */ "\tseg\tes", sbhand, 1, 1, /* 0x26 */ "\tdaa", sbhand, 1, 1, /* 0x27 */ SUB, aohand, 2, 4, /* 0x28 */ SUB, aohand, 2, 4, /* 0x29 */ SUB, aohand, 2, 4, /* 0x2a */ SUB, aohand, 2, 4, /* 0x2b */ SUB, aohand, 2, 2, /* 0x2c */ SUB, aohand, 3, 3, /* 0x2d */ "\tseg\tcs", sbhand, 1, 1, /* 0x2e */ "\tdas", sbhand, 1, 1, /* 0x2f */ XOR, aohand, 2, 4, /* 0x30 */ XOR, aohand, 2, 4, /* 0x31 */ XOR, aohand, 2, 4, /* 0x32 */ XOR, aohand, 2, 4, /* 0x33 */ XOR, aohand, 2, 2, /* 0x34 */ XOR, aohand, 3, 3, /* 0x35 */ "\tseg\tss", sbhand, 1, 1, /* 0x36 */ "\taaa", sbhand, 1, 1, /* 0x37 */ CMP, aohand, 2, 4, /* 0x38 */ CMP, aohand, 2, 4, /* 0x39 */ CMP, aohand, 2, 4, /* 0x3a */ CMP, aohand, 2, 4, /* 0x3b */ CMP, aohand, 2, 2, /* 0x3c */ CMP, aohand, 3, 3, /* 0x3d */ "\tseg\tds", sbhand, 1, 1, /* 0x3e */ "\taas", sbhand, 1, 1, /* 0x3f */ "\tinc\tax", sbhand, 1, 1, /* 0x40 */ "\tinc\tcx", sbhand, 1, 1, /* 0x41 */ "\tinc\tdx", sbhand, 1, 1, /* 0x42 */ "\tinc\tbx", sbhand, 1, 1, /* 0x43 */ "\tinc\tsp", sbhand, 1, 1, /* 0x44 */ "\tinc\tbp", sbhand, 1, 1, /* 0x45 */ "\tinc\tsi", sbhand, 1, 1, /* 0x46 */ "\tinc\tdi", sbhand, 1, 1, /* 0x47 */ "\tdec\tax", sbhand, 1, 1, /* 0x48 */ "\tdec\tcx", sbhand, 1, 1, /* 0x49 */ "\tdec\tdx", sbhand, 1, 1, /* 0x4a */ "\tdec\tbx", sbhand, 1, 1, /* 0x4b */ "\tdec\tsp", sbhand, 1, 1, /* 0x4c */ "\tdec\tbp", sbhand, 1, 1, /* 0x4d */ "\tdec\tsi", sbhand, 1, 1, /* 0x4e */ "\tdec\tdi", sbhand, 1, 1, /* 0x4f */ "\tpush\tax", sbhand, 1, 1, /* 0x50 */ "\tpush\tcx", sbhand, 1, 1, /* 0x51 */ "\tpush\tdx", sbhand, 1, 1, /* 0x52 */ "\tpush\tbx", sbhand, 1, 1, /* 0x53 */ "\tpush\tsp", sbhand, 1, 1, /* 0x54 */ "\tpush\tbp", sbhand, 1, 1, /* 0x55 */ "\tpush\tsi", sbhand, 1, 1, /* 0x56 */ "\tpush\tdi", sbhand, 1, 1, /* 0x57 */ "\tpop\tax", sbhand, 1, 1, /* 0x58 */ "\tpop\tcx", sbhand, 1, 1, /* 0x59 */ "\tpop\tdx", sbhand, 1, 1, /* 0x5a */ "\tpop\tbx", sbhand, 1, 1, /* 0x5b */ "\tpop\tsp", sbhand, 1, 1, /* 0x5c */ "\tpop\tbp", sbhand, 1, 1, /* 0x5d */ "\tpop\tsi", sbhand, 1, 1, /* 0x5e */ "\tpop\tdi", sbhand, 1, 1, /* 0x5f */ NULL, dfhand, 0, 0, /* 0x60 */ NULL, dfhand, 0, 0, /* 0x61 */ NULL, dfhand, 0, 0, /* 0x62 */ NULL, dfhand, 0, 0, /* 0x63 */ "\tseg\tfs", sbhand, 1, 1, /* 0x64 */ "\tseg\tgs", sbhand, 1, 1, /* 0x65 */ "\tuse\top32", sbhand, 1, 1, /* 0x66 */ "\tuse\tadr32", sbhand, 1, 1, /* 0x67 */ "\tpush\t", mihand, 3, 3, /* 0x68 */ /* NULL, dfhand, 0, 0, /* 0x68 */ NULL, dfhand, 0, 0, /* 0x69 */ "\tpush\t", mihand, 2, 2, /* 0x6a */ /* NULL, dfhand, 0, 0, /* 0x6a */ NULL, dfhand, 0, 0, /* 0x6b */ NULL, dfhand, 0, 0, /* 0x6c */ NULL, dfhand, 0, 0, /* 0x6d */ NULL, dfhand, 0, 0, /* 0x6e */ NULL, dfhand, 0, 0, /* 0x6f */ "\tjo", sjhand, 2, 2, /* 0x70 */ "\tjno", sjhand, 2, 2, /* 0x71 */ "\tjc", sjhand, 2, 2, /* 0x72 */ "\tjnc", sjhand, 2, 2, /* 0x73 */ "\tjz", sjhand, 2, 2, /* 0x74 */ "\tjnz", sjhand, 2, 2, /* 0x75 */ "\tjna", sjhand, 2, 2, /* 0x76 */ "\tja", sjhand, 2, 2, /* 0x77 */ "\tjs", sjhand, 2, 2, /* 0x78 */ "\tjns", sjhand, 2, 2, /* 0x79 */ "\tjp", sjhand, 2, 2, /* 0x7a */ "\tjnp", sjhand, 2, 2, /* 0x7b */ "\tjl", sjhand, 2, 2, /* 0x7c */ "\tjnl", sjhand, 2, 2, /* 0x7d */ "\tjng", sjhand, 2, 2, /* 0x7e */ "\tjg", sjhand, 2, 2, /* 0x7f */ AMBIG, imhand, 3, 5, /* 0x80 */ AMBIG, imhand, 4, 6, /* 0x81 */ AMBIG, imhand, 3, 5, /* 0x82 */ AMBIG, imhand, 3, 5, /* 0x83 */ TEST, mvhand, 2, 4, /* 0x84 */ TEST, mvhand, 2, 4, /* 0x85 */ "\txchg", mvhand, 2, 4, /* 0x86 */ "\txchg", mvhand, 2, 4, /* 0x87 */ MOV, mvhand, 2, 4, /* 0x88 */ MOV, mvhand, 2, 4, /* 0x89 */ MOV, mvhand, 2, 4, /* 0x8a */ MOV, mvhand, 2, 4, /* 0x8b */ MOV, mshand, 2, 4, /* 0x8c */ "\tlea", mvhand, 2, 4, /* 0x8d */ MOV, mshand, 2, 4, /* 0x8e */ "\tpop", pohand, 2, 4, /* 0x8f */ "\tnop", sbhand, 1, 1, /* 0x90 */ "\txchg\tax,cx", sbhand, 1, 1, /* 0x91 */ "\txchg\tax,dx", sbhand, 1, 1, /* 0x92 */ "\txchg\tax,bx", sbhand, 1, 1, /* 0x93 */ "\txchg\tax,sp", sbhand, 1, 1, /* 0x94 */ "\txchg\tax,bp", sbhand, 1, 1, /* 0x95 */ "\txchg\tax,si", sbhand, 1, 1, /* 0x96 */ "\txchg\tax,di", sbhand, 1, 1, /* 0x97 */ "\tcbw", sbhand, 1, 1, /* 0x98 */ "\tcwd", sbhand, 1, 1, /* 0x99 */ "\tcalli", cihand, 5, 5, /* 0x9a */ "\twait", sbhand, 1, 1, /* 0x9b */ "\tpushf", sbhand, 1, 1, /* 0x9c */ "\tpopf", sbhand, 1, 1, /* 0x9d */ "\tsahf", sbhand, 1, 1, /* 0x9e */ "\tlahf", sbhand, 1, 1, /* 0x9f */ MOV, mqhand, 3, 3, /* 0xa0 */ MOV, mqhand, 3, 3, /* 0xa1 */ MOV, mqhand, 3, 3, /* 0xa2 */ MOV, mqhand, 3, 3, /* 0xa3 */ "\tmovb", sbhand, 1, 1, /* 0xa4 */ "\tmovw", sbhand, 1, 1, /* 0xa5 */ "\tcmpb", sbhand, 1, 1, /* 0xa6 */ "\tcmpw", sbhand, 1, 1, /* 0xa7 */ TEST, tqhand, 2, 2, /* 0xa8 */ TEST, tqhand, 3, 3, /* 0xa9 */ "\tstob", sbhand, 1, 1, /* 0xaa */ "\tstow", sbhand, 1, 1, /* 0xab */ "\tlodb", sbhand, 1, 1, /* 0xac */ "\tlodw", sbhand, 1, 1, /* 0xad */ "\tscab", sbhand, 1, 1, /* 0xae */ "\tscaw", sbhand, 1, 1, /* 0xaf */ "\tmov\tal,", mihand, 2, 2, /* 0xb0 */ "\tmov\tcl,", mihand, 2, 2, /* 0xb1 */ "\tmov\tdl,", mihand, 2, 2, /* 0xb2 */ "\tmov\tbl,", mihand, 2, 2, /* 0xb3 */ "\tmov\tah,", mihand, 2, 2, /* 0xb4 */ "\tmov\tch,", mihand, 2, 2, /* 0xb5 */ "\tmov\tdh,", mihand, 2, 2, /* 0xb6 */ "\tmov\tbh,", mihand, 2, 2, /* 0xb7 */ "\tmov\tax,", mihand, 3, 3, /* 0xb8 */ "\tmov\tcx,", mihand, 3, 3, /* 0xb9 */ "\tmov\tdx,", mihand, 3, 3, /* 0xba */ "\tmov\tbx,", mihand, 3, 3, /* 0xbb */ "\tmov\tsp,", mihand, 3, 3, /* 0xbc */ "\tmov\tbp,", mihand, 3, 3, /* 0xbd */ "\tmov\tsi,", mihand, 3, 3, /* 0xbe */ "\tmov\tdi,", mihand, 3, 3, /* 0xbf */ NULL, dfhand, 0, 0, /* 0xc0 */ NULL, dfhand, 0, 0, /* 0xc1 */ "\tret", rehand, 3, 3, /* 0xc2 */ "\tret", sbhand, 1, 1, /* 0xc3 */ "\tles", mvhand, 2, 4, /* 0xc4 */ "\tlds", mvhand, 2, 4, /* 0xc5 */ MOV, mmhand, 3, 5, /* 0xc6 */ MOV, mmhand, 4, 6, /* 0xc7 */ NULL, dfhand, 0, 0, /* 0xc8 */ NULL, dfhand, 0, 0, /* 0xc9 */ "\treti", rehand, 3, 3, /* 0xca */ "\treti", sbhand, 1, 1, /* 0xcb */ "\tint", sbhand, 1, 1, /* 0xcc */ "\tint", inhand, 2, 2, /* 0xcd */ "\tinto", sbhand, 1, 1, /* 0xce */ "\tiret", sbhand, 1, 1, /* 0xcf */ AMBIG, srhand, 2, 4, /* 0xd0 */ AMBIG, srhand, 2, 4, /* 0xd1 */ AMBIG, srhand, 2, 4, /* 0xd2 */ AMBIG, srhand, 2, 4, /* 0xd3 */ "\taam", aahand, 2, 2, /* 0xd4 */ "\taad", aahand, 2, 2, /* 0xd5 */ NULL, dfhand, 0, 0, /* 0xd6 */ "\txlat", sbhand, 1, 1, /* 0xd7 */ ESC, eshand, 2, 2, /* 0xd8 */ ESC, eshand, 2, 2, /* 0xd9 */ ESC, eshand, 2, 2, /* 0xda */ ESC, eshand, 2, 2, /* 0xdb */ ESC, eshand, 2, 2, /* 0xdc */ ESC, eshand, 2, 2, /* 0xdd */ ESC, eshand, 2, 2, /* 0xde */ ESC, eshand, 2, 2, /* 0xdf */ "\tloopne", sjhand, 2, 2, /* 0xe0 */ "\tloope", sjhand, 2, 2, /* 0xe1 */ "\tloop", sjhand, 2, 2, /* 0xe2 */ "\tjcxz", sjhand, 2, 2, /* 0xe3 */ "\tin", iohand, 2, 2, /* 0xe4 */ "\tinw", iohand, 2, 2, /* 0xe5 */ "\tout", iohand, 2, 2, /* 0xe6 */ "\toutw", iohand, 2, 2, /* 0xe7 */ "\tcall", ljhand, 3, 3, /* 0xe8 */ "\tjmp", ljhand, 3, 3, /* 0xe9 */ "\tjmpi", cihand, 5, 5, /* 0xea */ "\tj", sjhand, 2, 2, /* 0xeb */ "\tin", sbhand, 1, 1, /* 0xec */ "\tinw", sbhand, 1, 1, /* 0xed */ "\tout", sbhand, 1, 1, /* 0xee */ "\toutw", sbhand, 1, 1, /* 0xef */ "\tlock", sbhand, 1, 1, /* 0xf0 */ NULL, dfhand, 0, 0, /* 0xf1 */ "\trepnz", sbhand, 1, 1, /* 0xf2 */ "\trepz", sbhand, 1, 1, /* 0xf3 */ "\thlt", sbhand, 1, 1, /* 0xf4 */ "\tcmc", sbhand, 1, 1, /* 0xf5 */ AMBIG, mahand, 2, 5, /* 0xf6 */ AMBIG, mahand, 2, 6, /* 0xf7 */ "\tclc", sbhand, 1, 1, /* 0xf8 */ "\tstc", sbhand, 1, 1, /* 0xf9 */ "\tcli", sbhand, 1, 1, /* 0xfa */ "\tsti", sbhand, 1, 1, /* 0xfb */ "\tcld", sbhand, 1, 1, /* 0xfc */ "\tstd", sbhand, 1, 1, /* 0xfd */ AMBIG, mjhand, 2, 4, /* 0xfe */ AMBIG, mjhand, 2, 4 /* 0xff */ }; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * This simple routine returns the name field of a symbol * * table entry as a printable string. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ char * getnam(k) register int k; {/* * * * * * * * * * START OF getnam() * * * * * * * * * */ register int j; static char a[sizeof(symtab->n_name)+1]; for (j = 0; j < sizeof(symtab[k].n_name); ++j) if ( ! symtab[k].n_name[j] ) break; else a[j] = symtab[k].n_name[j]; a[j] = '\0'; return (a); }/* * * * * * * * * * * END OF getnam() * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * This function is responsible for mucking through the * * relocation table in search of externally referenced * * symbols to be output as operands. It accepts two long * * arguments: the code-segment location at which an extern * * reference is expected, and the offset value which is * * embedded in the object code and used at link time to * * bias the external value. In the most typical case, the * * function will be called by lookup(), which always makes * * a check for external names before searching the symbol * * table proper. However, it may also be called directly * * by any function (such as the move-immediate handler) * * which wants to make an independent check for externals. * * The caller is expected to supply, as the third argument * * to the function, a pointer to a character buffer large * * enough to hold any possible output string. Lookext() * * will fill this buffer and return a logical TRUE if it * * finds an extern reference; otherwise, it will return a * * logical FALSE, leaving the buffer undisturbed. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ int lookext(off,loc,buf) long off, loc; char *buf; {/* * * * * * * * * * START OF lookext() * * * * * * * * * */ register int k; char c[32]; if ((loc != -1L) && (relptr >= 0)) for (k = 0; k <= relptr; ++k) if ((relo[k].r_vaddr == loc) && (relo[k].r_symndx < S_BSS)) { strcpy(buf,getnam(relo[k].r_symndx)); if (off) { if (off < 0) sprintf(c,"%ld",off); else sprintf(c,"+%ld",off); strcat(buf,c); } return (1); } return (0); }/* * * * * * * * * * END OF lookext() * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * This function finds an entry in the symbol table by * * value. Its input is a (long) machine address, and its * * output is a pointer to a string containing the corre- * * sponding symbolic name. The function first searches the * * relocation table for a possible external reference; if * * none is found, a linear search of the symbol table is * * undertaken. If no matching symbol has been found at the * * end of these searches, the function returns a pointer * * to a string containing the ASCII equivalent of the ad- * * dress which was to be located, so that, regardless of * * the success of the search, the function's return value * * is suitable for use as a memory-reference operand. The * * caller specifies the type of symbol to be found (text, * * data, bss, undefined, absolute, or common) by means of * * the function's second parameter. The third parameter * * specifies the format to be used in the event of a nu- * * meric output: zero for absolute format, one for short * * relative format, two for long relative format. The * * fourth parameter is the address which would appear in * * the relocation table for the reference in question, or * * -1 if the relocation table is not to be searched. The * * function attempts to apply a certain amount of intelli- * * gence in its selection of symbols, so it is possible * * that, in the absence of a type match, a symbol of the * * correct value but different type will be returned. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ char * lookup(addr,type,kind,ext) long addr; /* Machine address to be located */ int type, /* Type of symbol to be matched */ kind; /* Addressing output mode to use */ long ext; /* Value for extern ref, if any */ {/* * * * * * * * * * START OF lookup() * * * * * * * * * */ register int j, k; static char b[80]; struct { int i; int t; } best; if (lookext(addr,ext,b)) return (b); if (segflg) if (segflg & 1) type = N_TEXT; else type = N_DATA; for (k = 0, best.i = -1; k <= symptr; ++k) if (symtab[k].n_value == addr) if ((j = symtab[k].n_sclass & N_SECT) == type) { best.t = j; best.i = k; break; } else if (segflg || (HDR.a_flags & A_SEP)) continue; else if (best.i < 0) best.t = j, best.i = k; else if (symrank[type][j] > symrank[type][best.t]) best.t = j, best.i = k; if (best.i >= 0) return (getnam(best.i)); if (kind == LOOK_ABS) sprintf(b,"$%04lx",addr); else { long x = addr - (PC - kind); if (x < 0) sprintf(b,".%ld",x); else sprintf(b,".+%ld",x); } return (b); }/* * * * * * * * * * * END OF lookup() * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * This function translates an 8088 addressing mode byte * * to an equivalent assembler string, returning a pointer * * thereto. If necessary, it performs successive inputs * * of bytes from the object file in order to obtain offset * * data, adjusting PC accordingly. (The addressing mode * * byte appears in several 8088 opcodes; it is used to * * specify source and destination operand locations.) The * * third argument to the function is zero if the standard * * registers are to be used, or eight if the segment reg- * * isters are to be used; these constants are defined sym- * * bolically in dis.h. NOTE: The mtrans() function must * * NEVER be called except immediately after fetching the * * mode byte. If any additional object bytes are fetched * * after the fetch of the mode byte, mtrans() will not * * produce correct output! * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #undef FRV #define FRV "" char * mtrans(c,m,type) register int c; /* Primary instruction byte */ register int m; /* Addressing mode byte */ int type; /* Type code: standard or seg */ {/* * * * * * * * * * START OF mtrans() * * * * * * * * * */ unsigned long pc; int offset, oflag, dir, w, mod, reg, rm; static char a[100]; static char b[30]; offset = 0; dir = c & 2; w = c & 1; mod = (m & 0xc0) >> 6; reg = (m & 0x38) >> 3; rm = m & 7; pc = PC + 1; if (type) w = 1; if ((oflag = mod) > 2) oflag = 0; if (oflag) { int j, k; if (oflag == 2) { FETCH(j); FETCH(k); offset = (k << 8) | j; } else { FETCH(j); if (j & 0x80) k = 0xff00; else k = 0; offset = k | j; } } if (dir) { strcpy(a,REGS[type + ((w << 3) | reg)]); strcat(a,","); switch (mod) { case 0 : if (rm == 6) { int j, k; FETCH(j); FETCH(k); offset = (k << 8) | j; strcat(a, lookup((long)(offset),N_DATA,LOOK_ABS,pc)); } else { sprintf(b,"(%s)",REGS0[rm]); strcat(a,b); } break; case 1 : case 2 : if (mod == 1) strcat(a,"*"); else strcat(a,"#"); sprintf(b,"%d(", (short)offset); strcat(a,b); strcat(a,REGS1[rm]); strcat(a,")"); break; case 3 : strcat(a,REGS[(w << 3) | rm]); break; } } else { switch (mod) { case 0 : if (rm == 6) { int j, k; FETCH(j); FETCH(k); offset = (k << 8) | j; strcpy(a, lookup((long)(offset),N_DATA,LOOK_ABS,pc)); } else { sprintf(b,"(%s)",REGS0[rm]); strcpy(a,b); } break; case 1 : case 2 : if (mod == 1) strcpy(a,"*"); else strcpy(a,"#"); sprintf(b,"%d(", (short)offset); strcat(a,b); strcat(a,REGS1[rm]); strcat(a,")"); break; case 3 : strcpy(a,REGS[(w << 3) | rm]); break; } strcat(a,","); strcat(a,REGS[type + ((w << 3) | reg)]); } return (a); }/* * * * * * * * * * * END OF mtrans() * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * This simple routine truncates a string returned by the * * mtrans() function, removing its source operand. This is * * useful in handlers which ignore the "reg" field of the * * mode byte. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void mtrunc(a) register char *a; /* Ptr. to string to truncate */ {/* * * * * * * * * * START OF mtrunc() * * * * * * * * * */ register int k; for (k = strlen(a) - 1; k >= 0; --k) if (a[k] == ',') { a[k] = '\0'; break; } }/* * * * * * * * * * * END OF mtrunc() * * * * * * * * * * */ dev86-0.16.21/dis88/old_a.out.h000066400000000000000000000077071231050321700156160ustar00rootroot00000000000000/* The header file describes the format of executable files. */ #ifndef _AOUT_H #define _AOUT_H struct exec { /* a.out header */ unsigned char a_magic[2]; /* magic number */ unsigned char a_flags; /* flags, see below */ unsigned char a_cpu; /* cpu id */ unsigned char a_hdrlen; /* length of header */ unsigned char a_unused; /* reserved for future use */ unsigned short a_version; /* version stamp (not used at present) */ long a_text; /* size of text segement in bytes */ long a_data; /* size of data segment in bytes */ long a_bss; /* size of bss segment in bytes */ long a_entry; /* entry point */ long a_total; /* total memory allocated */ long a_syms; /* size of symbol table */ /* SHORT FORM ENDS HERE */ long a_trsize; /* text relocation size */ long a_drsize; /* data relocation size */ long a_tbase; /* text relocation base */ long a_dbase; /* data relocation base */ }; #define A_MAGIC0 (unsigned char) 0x01 #define A_MAGIC1 (unsigned char) 0x03 #define BADMAG(X) ((X).a_magic[0] != A_MAGIC0 ||(X).a_magic[1] != A_MAGIC1) /* CPU Id of TARGET machine (byte order coded in low order two bits) */ #define A_NONE 0x00 /* unknown */ #define A_I8086 0x04 /* intel i8086/8088 */ #define A_M68K 0x0B /* motorola m68000 */ #define A_NS16K 0x0C /* national semiconductor 16032 */ #define A_I80386 0x10 /* intel i80386 */ #define A_SPARC 0x17 /* Sun SPARC */ #define A_BLR(cputype) ((cputype&0x01)!=0) /* TRUE if bytes left-to-right */ #define A_WLR(cputype) ((cputype&0x02)!=0) /* TRUE if words left-to-right */ /* Flags. */ #define A_UZP 0x01 /* unmapped zero page (pages) */ #define A_PAL 0x02 /* page aligned executable */ #define A_NSYM 0x04 /* new style symbol table */ #define A_EXEC 0x10 /* executable */ #define A_SEP 0x20 /* separate I/D */ #define A_PURE 0x40 /* pure text */ /* not used */ #define A_TOVLY 0x80 /* text overlay */ /* not used */ /* Offsets of various things. */ #define A_MINHDR 32 #define A_TEXTPOS(X) ((long)(X).a_hdrlen) #define A_DATAPOS(X) (A_TEXTPOS(X) + (X).a_text) #define A_HASRELS(X) ((X).a_hdrlen > (unsigned char) A_MINHDR) #define A_HASEXT(X) ((X).a_hdrlen > (unsigned char) (A_MINHDR + 8)) #define A_HASLNS(X) ((X).a_hdrlen > (unsigned char) (A_MINHDR + 16)) #define A_HASTOFF(X) ((X).a_hdrlen > (unsigned char) (A_MINHDR + 24)) #define A_TRELPOS(X) (A_DATAPOS(X) + (X).a_data) #define A_DRELPOS(X) (A_TRELPOS(X) + (X).a_trsize) #define A_SYMPOS(X) (A_TRELPOS(X) + (A_HASRELS(X) ? \ ((X).a_trsize + (X).a_drsize) : 0)) struct reloc { long r_vaddr; /* virtual address of reference */ unsigned short r_symndx; /* internal segnum or extern symbol num */ unsigned short r_type; /* relocation type */ }; /* r_tyep values: */ #define R_ABBS 0 #define R_RELLBYTE 2 #define R_PCRBYTE 3 #define R_RELWORD 4 #define R_PCRWORD 5 #define R_RELLONG 6 #define R_PCRLONG 7 #define R_REL3BYTE 8 #define R_KBRANCHE 9 /* r_symndx for internal segments */ #define S_ABS ((unsigned short)-1) #define S_TEXT ((unsigned short)-2) #define S_DATA ((unsigned short)-3) #define S_BSS ((unsigned short)-4) struct nlist { /* symbol table entry */ char n_name[8]; /* symbol name */ long n_value; /* value */ unsigned char n_sclass; /* storage class */ unsigned char n_numaux; /* number of auxiliary entries (not used) */ unsigned short n_type; /* language base and derived type (not used) */ }; /* Low bits of storage class (section). */ #define N_SECT 07 /* section mask */ #define N_UNDF 00 /* undefined */ #define N_ABS 01 /* absolute */ #define N_TEXT 02 /* text */ #define N_DATA 03 /* data */ #define N_BSS 04 /* bss */ #define N_COMM 05 /* (common) */ /* High bits of storage class. */ #define N_CLASS 0370 /* storage class mask */ #define C_NULL #define C_EXT 0020 /* external symbol */ #define C_STAT 0030 /* static */ /* Function prototypes. */ #ifndef _ANSI_H #include "ansi.h" #endif _PROTOTYPE( int nlist, (char *_file, struct nlist *_nl) ); #endif /* _AOUT_H */ dev86-0.16.21/doselks/000077500000000000000000000000001231050321700142535ustar00rootroot00000000000000dev86-0.16.21/doselks/Makefile000066400000000000000000000014061231050321700157140ustar00rootroot00000000000000 CC=$(BCC) BCC=bcc CFLAGS=-Md LDFLAGS=-Md -s DISTFILES=Makefile syscalls.h doselks.h coroutine.c doselks.c syscalls.c # NB coroutine.o first then we can find it easily for breakpoints in CV.EXE OBJ=coroutine.o doselks.o syscalls.o all: doselks.com install: # Err, Ok, but where do I install a dos program ? doselks.com: $(OBJ) $(CC) $(LDFLAGS) -o doselks.com $(OBJ) syscalls.o: call_tab.v $(OBJ): doselks.h call_tab.v: dummy -cp -p ../libc/syscall/call_tab.v . 2>/dev/null -cp -p ../libc/syscall/defn_tab.v . 2>/dev/null distribution: tar czf /tmp/doselks.tar.gz $(DISTFILES) dummy: clean: rm -f $(OBJ) doselks.com realclean: rm -f call_tab.v defn_tab.v rm -f $(OBJ) doselks.com VVV=xx $(VVV).o: $(VVV).c $(CC) $(CFLAGS) -A-l -A$(VVV).lst -c $(VVV).c dev86-0.16.21/doselks/coroutine.c000066400000000000000000000054151231050321700164330ustar00rootroot00000000000000 #include "doselks.h" int in_process = 0; int intr_pending = 0; unsigned int current_ds, current_stack; struct process * proc; /*************************************************************************** * These two routines to make doselks and the user program into co-routines. * * The Server calls run_cpu which runs the client. * The client then does an int $80 which calls elks_int. * Elks_int then returns to the caller of run_cpu. * * The return value is the value of AX when the int $80 occured. * On return ES is set to the DS of the client program. * * The instruction times are for the 286 * * If we were using a 486 then using mov's would be faster on the 286 they * are the same speed but push/pop is smaller. */ #asm .data bx_temp: ! Tempoary storage for BX. .word 0 .text ! The is where we store the current_ds in the _TEXT_ segment cs_current_ds: ! for the elks_int routine .word 0 #endasm unsigned int run_cpu() { #asm mov ax,ds ; 2 seg cs ! Store ds for return mov [cs_current_ds],ax ; 5 cli ! We`re messing! ; 3 test [_intr_pending],#$FFFF ! Last chance ... jz skp sti xor ax,ax ret skp: push bp ; 3 push si ; 3 push di ; 3 mov [_current_stack],sp ; 5 mov ax,#1 ; 2 mov [_in_process],ax ; 5 mov sp,[_proc] ; 5 pop ax ! pppop ; 5 pop [bx_temp] ; 5 pop cx ; 5 pop dx ; 5 pop di ; 5 pop si ; 5 pop bp ; 5 pop es ; 5 mov bx,sp ! Switch to client stack ; 2 mov ss,[bx+8] ! SS ; 5 mov sp,[bx+10] ! SP ; 5 push [bx+6] ! flags ; 5 push [bx+4] ! CS ; 5 push [bx+2] ! PC ; 5 push [bx+0] ! DS ; 5 mov bx,[bx_temp] ; 5 pop ds ; 5 iret ; 17 #endasm } unsigned int elks_int() { #asm .text cli ; 3 push ds ; 3 push cs ; 3 pop ds ; 5 mov ds,[cs_current_ds] ; 5 mov [bx_temp],bx ; 3 mov bx,[_proc] ; 5 add bx,#16 ; 2 pop [bx+0] ! DS ; 5 pop [bx+2] ! PC ; 5 pop [bx+4] ! CS ; 5 pop [bx+6] ! flags ; 5 mov [bx+8],ss ! SS ; 3 mov [bx+10],sp ! SP ; 3 mov sp,bx ! Ready for pppppush ; 2 mov bx,ds ; 2 mov ss,bx ; 2 push es ! wheeee ; 3 push bp ; 3 push si ; 3 push di ; 3 push dx ; 3 push cx ; 3 push [bx_temp] ; 5 push ax ! This is the return value, handy ; 3 mov sp,[_current_stack] ; 5 mov bx,#1 ; 2 mov [_in_process],bx ; 5 sti ! Finished F**** around with the stack ; 2 mov bx,[_proc] ; 5 mov es,[bx+16] ! Set ES to the client`s DS ; 5 pop di ; 5 pop si ; 5 pop bp ; 5 #endasm } dev86-0.16.21/doselks/doselks.c000066400000000000000000000132561231050321700160720ustar00rootroot00000000000000 #include "doselks.h" #define DEBUGGER void build_stack(/* char ** argv, char ** envp */); long elks_int_orig; union REGS regs; int process_running; int exit_code = 255; main(argc, argv, envp) int argc; char ** argv; char ** envp; { int rv; current_ds = __get_ds(); if( argc <= 1 ) { printf("Usage: %s <8086_exe> [args]\n", argv[0]); exit(exit_code); } proc = calloc(sizeof(struct process), 1); if( proc == 0 ) printf("Unable to allocate memory for executable\n"); else if( (rv = loadexe(argv[1])) >= 0 ) { proc->pid = 1; proc->ppid = 1; proc->pgrp = 1; proc->umask = 022; proc->next = proc; build_stack(argv+1, envp); elks_int_orig = __getvect(ELKSINT); __setvect(ELKSINT, (long)elks_int); #ifndef MAKEME run_executable(); #else dump_core(); #endif __setvect(ELKSINT, elks_int_orig); } else { if( rv == -ENOMEM ) printf("Unable to allocate memory for executable\n"); else printf("Cannot execute %s\n", argv[1]); } return(exit_code); } int loadexe(fname) char * fname; { char bbuf[1024]; long size; unsigned int tsize, dsize; struct elks_exec_hdr mh; int i; int fd = -1; int err = ENOEXEC; proc->text_seg = 0; proc->data_seg = 0; if( ( fd = open(fname, O_RDONLY|O_BINARY) ) < 0 ) goto no_exec; /* Load the elks binary image and set it up in a suitable * segment. Load CS and DS/SS according to image type. */ if( read(fd, &mh,sizeof(mh))!=sizeof(mh) || mh.hlen!=EXEC_HEADER_SIZE || (mh.type!=ELKS_COMBID&&mh.type!=ELKS_SPLITID) ) goto no_exec; if(mh.type==ELKS_COMBID) { tsize = 0; dsize = ((mh.tseg+mh.chmem + 0xF)>>4); } else { tsize = ((mh.tseg+0xF) >> 4); dsize = ((mh.chmem+0xF) >> 4); } if(tsize) { if( (proc->text_seg = seg_allocate(tsize)) == 0) goto no_mem; proc->cs = proc->text_seg->seg; } if( (proc->data_seg = seg_allocate(dsize)) == 0 ) goto no_mem; proc->ds = proc->data_seg->seg; if(proc->text_seg == 0) proc->cs = proc->ds; #ifdef DEBUGGER fprintf(stderr,"Executable - %s. tseg=0x%04lx dseg=0x%04lx bss=0x%04lx chmem=0x%04lx\n", mh.type==ELKS_COMBID?"(impure)":"Sep I/D", mh.tseg,mh.dseg,mh.bseg,mh.chmem); #endif if(proc->text_seg) { for(size=0; sizemh.tseg-size ) i=mh.tseg-size; if(read(fd,bbuf,i)!=i) goto no_exec; __movedata(current_ds, (unsigned)bbuf, proc->cs, (int)size, i); size += i; } } else mh.dseg += mh.tseg; for(size=0; sizemh.dseg-size ) i=mh.dseg-size; if(read(fd,bbuf,i)!=i) goto no_exec; __movedata(current_ds, (unsigned)bbuf, proc->ds, (int)size, i); size += i; } close(fd); /* Zap the bss */ memset(bbuf, '\0', 1024); mh.dseg += mh.bseg; for(; sizemh.dseg-size ) i=mh.dseg-size; __movedata(current_ds, (unsigned)bbuf, proc->ds, (int)size, i); size += i; } /* * Load the VM86 registers */ proc->ss=proc->ds; proc->es=0; /* This will be preserved */ proc->sp=mh.chmem; /* Args stacked later */ proc->pc=0; /* Run from 0 */ /* * Loaded */ return 0; no_mem:; err = ENOMEM; no_exec:; seg_free(proc->text_seg); seg_free(proc->data_seg); if( fd > 0 ) close(fd); return -err; } void build_stack(argv, envp) char ** argv; char ** envp; { char buffer[1024]; char **p; int argv_len=0, argv_count=0; int envp_len=0, envp_count=0; int stack_bytes; unsigned short * pip; char * pcp; /* How much space for argv */ if(argv) for(p=argv; *p; p++) { argv_count++; argv_len += strlen(*p)+1; } /* How much space for envp */ if(envp) for(p=envp; *p; p++) { envp_count++; envp_len += strlen(*p)+1; } /* tot it all up */ stack_bytes = 2 /* argc */ + argv_count * 2 + 2 /* argv */ + argv_len + envp_count * 2 + 2 /* envp */ + envp_len; if( stack_bytes > sizeof(buffer)-2 ) { printf("Environment too large\n"); exit(exit_code); } /* Allocate it */ proc->sp -= stack_bytes; #ifdef DEBUGGER printf("Argv = (%d,%d), Envp=(%d,%d), stack=%d\n", argv_count, argv_len, envp_count, envp_len, stack_bytes); #endif /* Now build the data */ pip=(unsigned short *) buffer; pcp=buffer+sizeof(unsigned short *)*(1+argv_count+1+envp_count+1); *pip++ = argv_count; for(p=argv; *p; p++) { *pip++ = (pcp-buffer)+proc->sp; strcpy(pcp, *p); pcp += strlen(*p)+1; } *pip++ = 0; for(p=envp; *p; p++) { *pip++ = (pcp-buffer)+proc->sp; strcpy(pcp, *p); pcp += strlen(*p)+1; } *pip++ = 0; __movedata(current_ds, (unsigned)buffer, proc->ds, proc->sp, stack_bytes); } /***************************************************************************/ dump_core() { char bbuf[1024]; int i, fd; unsigned destseg; printf("Not dumping core\n"); /* if( ( fd = open("core", O_WRONLY|O_BINARY|O_CREAT|O_TRUNC) ) < 0 ) { return -1; } destseg = proc->memory; for(i=0; i<(proc->memsize+63)/64; i++) { __movedata( destseg+i*64, 0, current_ds, (unsigned)bbuf, 1024); if( write(fd, bbuf, 1024) < 0 ) printf("FAIL 7\n"); } close(fd); */ } /***************************************************************************/ seg_allocate(size) { struct segment *nptr = calloc(sizeof(struct segment),1); if( nptr == 0 ) return 0; nptr->ref_count = 1; nptr->size = size; nptr->seg = __segalloc(size); if( nptr->seg == 0 ) { free(nptr); return 0; } return nptr; } seg_free(ptr) struct segment * ptr; { if(ptr == 0) return; if( --ptr->ref_count > 0 ) return; __segfree(ptr->seg); free(ptr); } dev86-0.16.21/doselks/doselks.h000066400000000000000000000043511231050321700160730ustar00rootroot00000000000000 #include /* Sneaky, use the _linuxmt_ header files _not_ dos */ #undef __SYSINC__ #define __SYSINC__(__h_file) #include #include #include #include #include #include #include #include #include #include #include /* Function return vals */ extern unsigned int elks_int(); extern unsigned int run_cpu(); /* Elks binary formats */ #define EXEC_HEADER_SIZE 32 struct elks_exec_hdr { unsigned long type; #define ELKS_COMBID 0x04100301L #define ELKS_SPLITID 0x04200301L unsigned long hlen; unsigned long tseg; unsigned long dseg; unsigned long bseg; unsigned long unused; unsigned long chmem; unsigned long unused2; }; /* Elks cpu structure. */ struct fd_ref { int ftype; union { int i; FILE * f; } fd; } ; struct segment { unsigned int seg; unsigned int size; int ref_count; }; struct process { unsigned int ax; /* NOTE The order of this is _closely_ related to */ unsigned int bx; /* the coroutine assembler */ unsigned int cx; unsigned int dx; unsigned int di; unsigned int si; unsigned int bp; unsigned int es; unsigned int ds; /* start +16 +0 */ unsigned int pc; /* start +16 +2 */ unsigned int cs; /* start +16 +4 */ unsigned int flgs; /* start +16 +6 */ unsigned int ss; /* start +16 +8 */ unsigned int sp; /* start +16 +10 */ /* From here down only accessed from C */ int pending_op; struct process * next; struct segment * text_seg; struct segment * data_seg; int pid; int ppid; int pgrp; int umask; int uid; int gid; int euid; int egid; int suid; int sgid; long ignmask, trpmask; int sigtrap; struct fd_ref fds[20]; struct rusage ruse; }; extern struct process * proc; extern unsigned int current_ds, current_stack; extern int in_process; extern int process_running; extern int intr_pending; /* Elks syscall interface */ #define ELKSINT 0x80 typedef int (*Scallp)( /* int, int, int */ ); extern Scallp syscalltab[]; /******************************************************************************/ #ifndef O_BINARY #define O_BINARY 0 #endif dev86-0.16.21/doselks/syscalls.c000066400000000000000000000242141231050321700162570ustar00rootroot00000000000000 #include "doselks.h" #include "syscalls.h" /***************************************************************************/ /* Need to use stdio for CR<->NL translation */ #define MAX_FD 20 FILE * tty_file[MAX_FD] = {stdin, stdout, stderr}; int nextpid = 2; int proc_one = 1; /***************************************************************************/ #define sys_exit elks_exit elks_exit(wait_stat) int wait_stat; { struct process * cur; int x; if(wait_stat & 0x80) dump_core(); /* save wait_stat */ proc->ax = wait_stat; if(proc->pid == 1) proc_one = 0; process_running--; seg_free(proc->text_seg); seg_free(proc->data_seg); for(cur=proc->next; cur!=proc; cur=cur->next) if(cur->ppid == proc->pid) cur->ppid = 1; return 0; } #define sys_fork elks_fork elks_fork(bx, cx, dx) int bx, cx, dx; { unsigned int size, i; struct process * newproc; if(nextpid<0) return -EINVAL; /* TODO: max 32k forks */ newproc = calloc(sizeof(struct process), 1); if( newproc == 0 ) return -ENOMEM; proc->pending_op = 0; *newproc = *proc; newproc->ppid = newproc->pid; newproc->data_seg = seg_allocate(proc->data_seg->size); if( newproc->data_seg == 0 ) { free(newproc); return -ENOMEM; } newproc->text_seg->ref_count++; newproc->cs = newproc->text_seg->seg; newproc->ds = newproc->data_seg->seg; newproc->ss = newproc->ds; newproc->pid = nextpid++; /* Duplicate memory */ for(i=0; idata_seg->size; i+=size ) { size = 0xFFF; if(size > newproc->data_seg->size-i) size = newproc->data_seg->size-i; __movedata(proc->ds, i*16, newproc->ds, i*16, size*16); } proc->ax = newproc->pid; newproc->ax = 0; proc->next = newproc; process_running++; /* proc = newproc; */ return newproc->pid; } struct process * get_zombie(ppid, pid) int ppid, pid; { struct process * prev, * cur, *running=0; /* Process group, not defined */ if( pid < -1 ) return 0; if( pid == 0 ) pid = -1; for(prev=proc, cur=proc->next; cur!=proc; prev=cur, cur=cur->next) { if(cur->ppid == ppid && (pid == -1 || cur->pid == pid)) { if(cur->pending_op != 1) { running = cur; continue; } prev->next = cur->next; cur->next = 0; return cur; } } return running; } #define sys_wait4 elks_wait4 elks_wait4(bx, cx, dx, di, si) int bx, cx, dx, di, si; { struct process * cur; int cpid; cur = get_zombie(proc->pid, bx); if( cur == 0 ) return -ECHILD; if( cur->pending_op != 1) { if( dx & WNOHANG ) return 0; else return -EINTR; } cpid = cur->pid; if( cx ) __doke_es(cx, cur->ax); if( di ) __movedata(current_ds, (unsigned)&(cur->ruse), proc->ds, di, sizeof(struct rusage)); free(cur); return cpid; } #define sys_exec elks_exec int elks_exec(bx, cx, dx) int bx, cx, dx; { struct process oldproc; char fname[128]; int ax; oldproc = *proc; __strnget_es(fname, bx, sizeof(fname)-1); fname[sizeof(fname)-1] = '\0'; if( (ax=loadexe(fname)) != 0 ) { *proc = oldproc; return ax; } __movedata(oldproc.ds, cx, proc->ds, proc->sp-dx, dx); /* Fudge pointers. */ proc->sp -= dx; /* Args */ ax = proc->sp + 2; __set_es(proc->ds); while(__deek_es(ax) != 0 ) __doke_es(ax, __deek_es(ax)-dx), ax+=2; /* env */ ax+=2; while(__deek_es(ax) != 0 ) __doke_es(ax, __deek_es(ax)-dx), ax+=2; seg_free(oldproc.text_seg); seg_free(oldproc.data_seg); return 0; } #define sys_read elks_read int elks_read(bx, cx, dx) int bx, cx, dx; { register int ch, rv=0; if( bx<0 || bx>MAX_FD || tty_file[bx] == 0 ) return -EBADF; do { ch = fgetc(tty_file[bx]); if( ch == EOF ) break; __poke_es(cx++, ch); rv++; } while(--dx > 0 && stdio_pending(tty_file[bx])); return rv; } #define sys_write elks_write int elks_write(bx, cx, dx) unsigned int bx, cx, dx; { char ch[2]; register unsigned int i; if( bx<0 || bx>MAX_FD || tty_file[bx] == 0 ) return -EBADF; for(i=dx; i>0; i--) { if( fputc(__peek_es(cx++), tty_file[bx]) == EOF ) return -1; } fflush(tty_file[bx]); return dx; } #define sys_open elks_open int elks_open(bx, cx, dx) { char fname[128]; int i; char *mode = ""; __strnget_es(fname, bx, sizeof(fname)-1); fname[sizeof(fname)-1] = '\0'; for(i=0; i= MAX_FD ) return -EMFILE; /* Translate the mode; more or less */ switch(cx&O_ACCMODE) { case O_RDONLY: mode="r"; break; case O_WRONLY: if( cx&O_APPEND ) mode="a"; else if( cx&O_TRUNC ) mode="w"; else mode="r+"; break; case O_RDWR: if( cx&O_APPEND ) mode="a+"; else if( cx&O_TRUNC ) mode="w+"; else mode="r+"; break; } if( ( tty_file[i] = fopen(fname, mode) ) == 0 ) { if( errno == 0 ) return -ENOENT; return -errno; } return i; } #define sys_close elks_close int elks_close(bx, cx, dx) { if( bx<0 || bx>MAX_FD || tty_file[bx] == 0 ) return -EBADF; fclose(tty_file[bx]); tty_file[bx] = 0; return 0; } #define sys_lseek elks_lseek int elks_lseek(bx, cx, dx) { long l; if( bx<0 || bx>MAX_FD || tty_file[bx] == 0 ) return -EBADF; __movedata(proc->ds, cx, current_ds, &l, 4); if( fseek(tty_file[bx], l, dx) < 0 ) return -ESPIPE; l = ftell(tty_file[bx]); __movedata(current_ds, &l, proc->ds, cx, 4); return 0; } #define sys_brk elks_brk int elks_brk(bx, cx, dx) { /* For the moment we don't care; libc does enough */ return 0; } #define sys_getpid elks_getpid int elks_getpid(bx, cx, dx) { __doke_es(bx, proc->ppid); return proc->pid; } #define sys_getuid elks_getuid int elks_getuid(bx, cx, dx) { __doke_es(bx, proc->euid); return proc->uid; } #define sys_getgid elks_getgid int elks_getgid(bx, cx, dx) { __doke_es(bx, proc->egid); return proc->gid; } #define sys_setuid elks_setuid int elks_setuid(bx, cx, dx) { if( proc->euid == 0 || proc->uid == bx || proc->euid == bx || proc->suid == bx) { if( proc->euid == 0 ) proc->suid = proc->uid = bx; proc->euid = bx; } else return -EPERM; } #define sys_setgid elks_setgid int elks_setgid(bx, cx, dx) { if( proc->euid == 0 || proc->gid == bx || proc->egid == bx || proc->sgid == bx) { if( proc->euid == 0 ) proc->sgid = proc->gid = bx; proc->egid = bx; } else return -EPERM; } #define sys_umask elks_umask int elks_umask(bx, cx, dx) { cx= proc->umask; proc->umask = (bx&0777); return cx; } void sig_trap(signo) int signo; { proc->sp -= 2; __doke_es(proc->sp, signo); proc->sp -= 2; __doke_es(proc->sp, proc->pc); proc->pc = proc->sigtrap; } #define sys_signal elks_signal int elks_signal(bx,cx,dx) { int rv; if( bx < 0 || bx >= NSIG ) return -EINVAL; if( bx == SIGSTOP || bx == SIGKILL ) return 0; proc->trpmask &= ~(1L<ignmask &= ~(1L<ignmask |= (1L<trpmask |= (1L<sigtrap = cx; } return 0; } #define sys_lstat elks_stat #define sys_stat elks_stat int elks_stat(bx,cx,dx) { struct stat ms; char fnamebuf[65]; char dtabuf[128]; /* I think this only needs 32 bytes ... but ... */ int v; long ttime, tdate; __strnget_es(fnamebuf, bx, sizeof(fnamebuf)-1); fnamebuf[64] = '\0'; v = __dos_stat(fnamebuf, dtabuf); if( v < 0 ) return -ENOENT; ms.st_dev= *dtabuf; ms.st_ino= 0; ms.st_mode= ((dtabuf[0x15]&0x1)?0555:0777); /* + File or directory */ if (dtabuf[0x15]&0x10) ms.st_mode |= S_IFDIR; else ms.st_mode |= S_IFREG; ms.st_nlink= 1; ms.st_uid= 0; ms.st_gid= 0; ms.st_rdev= 0; ms.st_size= *(long*)(dtabuf+0x1A); ttime = *((unsigned short*)(dtabuf+0x16)); ttime = ( ttime &0x1F) * 2 + ((ttime>>5) &0x2F) * 60 + ((ttime>>11) &0x1F) * 3600L; /* FIXME: This needs a julian day calculator .. */ tdate = *((unsigned short*)(dtabuf+0x18)); tdate = ((tdate) &0x1F) -32 + ((tdate>>5) &0x0F) * 31 + ((tdate>>9) &0x7F) * (31*12); ms.st_mtime= tdate*86400L + ttime; ms.st_atime= ms.st_mtime; ms.st_ctime= ms.st_mtime; /* copy &ms -> es:cx */ __movedata(current_ds, &ms, proc->ds, cx, sizeof(struct stat)); return 0; } /***************************************************************************/ #define sys_enosys elks_enosys int elks_enosys(bx, cx, dx) int bx, cx, dx; { printf("Unimplemented syscall(%d,0x%04x,0x%04x,0x%04x)\n", proc->ax,proc->bx,proc->cx,proc->dx); return -ENOSYS; } #include "defn_tab.v" Scallp syscalltab[] = { #include "call_tab.v" elks_enosys }; FILE * error; run_executable() { register unsigned int r_ax; register Scallp ptr; process_running=1; error = fopen("errlog", "w"); do { if( proc->pending_op == 0 ) { fprintf(error, "Run %d AX=%-4d proc =%04x IP=%04x...", proc->pid, proc->ax, proc, proc->pc); fflush(error); proc->pending_op = run_cpu(); } if( r_ax = proc->pending_op ) { if( r_ax >= sizeof(syscalltab)/sizeof(Scallp) ) r_ax = 0; fprintf(error, "%d: Call_%d(%04x, %04x, %04x) -> ", proc->pid, r_ax, proc->bx, proc->cx, proc->dx); fflush(error); if( r_ax == 1 ) (void) elks_exit(proc->bx << 8); else { __set_es(proc->ds); if( (proc->ax = (*syscalltab[r_ax])(proc->bx, proc->cx, proc->dx, proc->di, proc->si)) != (unsigned) -EINTR ) { proc->pending_op = 0; /* fprintf(error, "%d\n", proc->ax); fflush(error); continue; */ } } fprintf(error, "%d\n", proc->ax); fflush(error); } intr_pending = 0; /* FIXME: deal with */ do { proc = proc->next; } while(proc->pending_op==1 && process_running); } while(process_running); } dev86-0.16.21/doselks/syscalls.h000066400000000000000000000050611231050321700162630ustar00rootroot00000000000000extern int sys_exit __P((int, int, int)); extern int sys_vfork __P((int, int, int)); extern int sys_read __P((int, int, int)); extern int sys_write __P((int, int, int)); extern int sys_open __P((int, int, int)); extern int sys_close __P((int, int, int)); extern int sys_wait __P((int, int, int)); extern int sys_creat __P((int, int, int)); extern int sys_link __P((int, int, int)); extern int sys_unlink __P((int, int, int)); extern int sys_waitpid __P((int, int, int)); extern int sys_chdir __P((int, int, int)); extern int sys_time __P((int, int, int)); extern int sys_mknod __P((int, int, int)); extern int sys_chmod __P((int, int, int)); extern int sys_chown __P((int, int, int)); extern int sys_brk __P((int, int, int)); extern int sys_stat __P((int, int, int)); extern int sys_lseek __P((int, int, int)); extern int sys_getpid __P((int, int, int)); extern int sys_mount __P((int, int, int)); extern int sys_umount __P((int, int, int)); extern int sys_setuid __P((int, int, int)); extern int sys_getuid __P((int, int, int)); extern int sys_stime __P((int, int, int)); extern int sys_ptrace __P((int, int, int)); extern int sys_alarm __P((int, int, int)); extern int sys_fstat __P((int, int, int)); extern int sys_pause __P((int, int, int)); extern int sys_utime __P((int, int, int)); extern int sys_stty __P((int, int, int)); extern int sys_gtty __P((int, int, int)); extern int sys_access __P((int, int, int)); extern int sys_nice __P((int, int, int)); extern int sys_ftime __P((int, int, int)); extern int sys_sync __P((int, int, int)); extern int sys_kill __P((int, int, int)); extern int sys_rename __P((int, int, int)); extern int sys_mkdir __P((int, int, int)); extern int sys_rmdir __P((int, int, int)); extern int sys_pipe __P((int, int, int)); extern int sys_times __P((int, int, int)); extern int sys_prof __P((int, int, int)); extern int sys_setgid __P((int, int, int)); extern int sys_getgid __P((int, int, int)); extern int sys_signal __P((int, int, int)); extern int sys_acct __P((int, int, int)); extern int sys_plock __P((int, int, int)); extern int sys_ioctl __P((int, int, int)); extern int sys_fcntl __P((int, int, int)); extern int sys_exec __P((int, int, int)); extern int sys_umask __P((int, int, int)); extern int sys_chroot __P((int, int, int)); extern int sys_sigaction __P((int, int, int)); extern int sys_sigsuspend __P((int, int, int)); extern int sys_sigpending __P((int, int, int)); extern int sys_sigprocmask __P((int, int, int)); extern int sys_sigreturn __P((int, int, int)); extern int sys_reboot __P((int, int, int)); dev86-0.16.21/elksemu/000077500000000000000000000000001231050321700142545ustar00rootroot00000000000000dev86-0.16.21/elksemu/Kernel_patch000066400000000000000000000015101231050321700165730ustar00rootroot00000000000000This kernel patch allows you to run Linux-8086 executables transparently on a Linux-i386 (1.2.13) system. It requires V0.0.2 or better of elksemu in the file "/lib/elksemu". If you are using kernel 1.3.* or later try the module: binfmt_elks.o If you are using 2.0.36, 2.1.43 or 2.2.0 and later use binfmt_misc. --- orig-13/fs/exec.c Sun Sep 24 13:22:37 1995 +++ linux/fs/exec.c Sun Feb 11 20:11:47 1996 @@ -615,6 +615,12 @@ set_fs(old_fs); if (retval < 0) goto exec_error2; +#ifndef NO_ELKSEMU + /* What a horrible hack! :-) */ + if ((bprm.buf[0] == 1) && (bprm.buf[1] == 3) && + (bprm.buf[2] == 0x20 || bprm.buf[2] == 0x10) && (bprm.buf[3] == 4)) + memcpy(bprm.buf, "#!/lib/elksemu\n", 16); +#endif if ((bprm.buf[0] == '#') && (bprm.buf[1] == '!') && (!sh_bang)) { /* * This section does the #! interpretation. dev86-0.16.21/elksemu/Makefile000066400000000000000000000031701231050321700157150ustar00rootroot00000000000000# # Makefile for elksemu. # # Use BCC to make a tiny static a.out version. ifeq ($(CC),bcc) CFLAGS=-Ml -ansi -s $(DEFS) endif ifeq ($(CC),ncc) CFLAGS=-Ml -ansi -s $(DEFS) endif # Default ifeq ($(CFLAGS),) CFLAGS=-O endif # Turn on elkemu's strace like facility. # DEFS=-DDEBUG # For gcc making a.out with a basically ELF compiler # CFLAGS=-O2 -fno-strength-reduce -b i486-linuxaout -N -s -static OBJ=elks.o elks_sys.o elks_signal.o minix.o elksemu: $(OBJ) $(CC) $(CFLAGS) -o $@ $^ elks_sys.o: call_tab.v efile.h $(OBJ): elks.h call_tab.v: dummy -cp -p ../libc/syscall/call_tab.v . 2>/dev/null -cp -p ../libc/syscall/defn_tab.v . 2>/dev/null efile.h: ../libc/error/liberror.txt sh mkefile ../libc/error/liberror.txt dummy: # The kernel patch or module _requires_ this location but binfmt-misc is easy # to redirect. install: elksemu install -d $(DIST)/lib install -s -o root -g root -m 4555 elksemu $(DIST)/lib/elksemu clean realclean: rm -f $(OBJ) binfmt_elks.o elksemu call_tab.v defn_tab.v efile.h module: binfmt_elks.o # HOW to compile the module... # BUT remember you don't need it for a recent 2.1.X; use binfmt_misc. # This matches my compile (2.0.x); yours may be different. MODCFLAGS=-D__KERNEL__ -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer \ -fno-strength-reduce -pipe -m486 -DCPU=486 -DMODULE -DMODVERSIONS \ -include /usr/include/linux/modversions.h binfmt_elks.o: binfmt_elks.c gcc -c $(MODCFLAGS) binfmt_elks.c # This is another option #MODCFLAGS=-O -fomit-frame-pointer -DCPU=386 -D__KERNEL__ -DMODULE # Or this ... #MODCFLAGS=-O -fomit-frame-pointer -D__KERNEL__ -DMODULE -DCONFIG_MODVERSIONS dev86-0.16.21/elksemu/README000066400000000000000000000016701231050321700151400ustar00rootroot00000000000000 Elksemu is an emulator for the environment that elks will provide on a real ELKS machine. The emulator only runs on linux-i386 or similar. If you're using a 2.0.36, 2.1.43, 2.2.0 or later kernel then the binfmt_misc driver is in the stock kernel and all you need to do is add the following line into the relevent /etc/rc* file. echo ':i86-elks:M::\x01\x03\x20\x00:\xff\xff\xff\x83:/usr/bin/elksemu:' \ > /proc/sys/fs/binfmt_misc/register Note, however, if binfmt_misc is compiled as a module it will not auto load so you will have to do this manually. If your kernel version is 1.2.13 then apply the patch in the Kernel_patch file. If you're using one of the other 2.0.X series then the binfmt_elks.c module should be able to compile and install. BUT do note you need the modules and probably modversions options and you _may_ have to alter the compile command to match those seen when you compile modules that come with the kernel. Rob. dev86-0.16.21/elksemu/Security000066400000000000000000000014751231050321700160150ustar00rootroot00000000000000Is is possible to install /usr/bin/elksemu as a suid-root executable. This gives two additional facilities when running elks executables. 1) It is now possible to run programs that are execute only, without read permission, as the file is opened while we have superuser access. 2) If the ELKS executable has suid or sgid bits set these will be honoured. The user now needs execute access to run an executable, this is checked. If the executable does not have either suid/sgid bits set then all extra permissions will be dropped within the first few lines of the main() function. Because of this you need only check this tiny piece of code if you intend never to use suid. If you have any problem with elksemu being suid-root the program will run as before, with no complaints, if you remove the suid permission. Rob. dev86-0.16.21/elksemu/binfmt_elks.c000066400000000000000000000052631231050321700167230ustar00rootroot00000000000000/* * linux/fs/binfmt_elks.c * * Copyright (C) 1996 Martin von Löwis * original #!-checking implemented by tytso. * ELKS hack added by Chad Page... * Cleaned up some more by Robert de Bath */ #include #ifndef LINUX_VERSION_CODE #include #endif #include #include #include #include static int do_load_elksaout(struct linux_binprm *bprm,struct pt_regs *regs) { char *cp, *interp, *i_name, *i_arg; int retval; /* What a horrible hack! :-) */ if ((bprm->buf[0] != 1) || (bprm->buf[1] != 3) || (bprm->buf[2] != 0x20 && bprm->buf[2] != 0x10) || (bprm->buf[3] != 4) || bprm->sh_bang) return -ENOEXEC; bprm->sh_bang++; iput(bprm->inode); #if LINUX_VERSION_CODE >= 0x010300 bprm->dont_iput=1; #endif interp = "/lib/elksemu"; i_name = interp; i_arg = 0; for (cp=i_name; *cp && (*cp != ' ') && (*cp != '\t'); cp++) { if (*cp == '/') i_name = cp+1; } /* * OK, we've parsed out the interpreter name and * (optional) argument. * Splice in (1) the interpreter's name for argv[0] * (2) (optional) argument to interpreter * (3) filename of shell script (replace argv[0]) * * This is done in reverse order, because of how the * user environment and arguments are stored. */ remove_arg_zero(bprm); bprm->p = copy_strings(1, &bprm->filename, bprm->page, bprm->p, 2); bprm->argc++; if (i_arg) { bprm->p = copy_strings(1, &i_arg, bprm->page, bprm->p, 2); bprm->argc++; } bprm->p = copy_strings(1, &i_name, bprm->page, bprm->p, 2); bprm->argc++; if (!bprm->p) return -E2BIG; /* * OK, now restart the process with the interpreter's inode. * Note that we use open_namei() as the name is now in kernel * space, and we don't need to copy it. */ retval = open_namei(interp, 0, 0, &bprm->inode, NULL); if (retval) return retval; #if LINUX_VERSION_CODE >= 0x010300 bprm->dont_iput=0; #endif retval=prepare_binprm(bprm); if(retval<0) return retval; return search_binary_handler(bprm,regs); } static int load_elksaout(struct linux_binprm *bprm,struct pt_regs *regs) { int retval; MOD_INC_USE_COUNT; retval = do_load_elksaout(bprm,regs); MOD_DEC_USE_COUNT; return retval; } struct linux_binfmt elksaout_format = { #ifndef MODULE NULL, 0, load_elksaout, NULL, NULL #else NULL, &mod_use_count_, load_elksaout, NULL, NULL #endif }; int init_elksaout_binfmt(void) { return register_binfmt(&elksaout_format); } #ifdef MODULE #if LINUX_VERSION_CODE < 0x010300 char kernel_version[] = UTS_RELEASE; #endif int init_module(void) { return init_elksaout_binfmt(); } void cleanup_module( void) { unregister_binfmt(&elksaout_format); } #endif dev86-0.16.21/elksemu/elks.c000066400000000000000000000155451231050321700153700ustar00rootroot00000000000000/* * ELKSEMU An emulator for Linux8086 binaries. * * VM86 is used to process all the 8086 mode code. * We trap up to 386 mode for system call emulation and naughties. */ #include #include #include #include #include #include #include #include #include #include #include #include #include "elks.h" #ifdef __BCC__ #define OLD_LIBC_VERSION #endif volatile struct vm86_struct elks_cpu; unsigned char *elks_base; /* Paragraph aligned */ #ifdef DEBUG #define dbprintf(x) db_printf x #else #define dbprintf(x) #endif static void elks_init() { elks_cpu.screen_bitmap=0; elks_cpu.cpu_type = CPU_286; /* * All INT xx calls are trapped. */ memset((void *)&elks_cpu.int_revectored,0xFF, sizeof(elks_cpu.int_revectored)); } static void elks_take_interrupt(int arg) { #if 1 if(arg==0x20) { minix_syscall(); return; } #endif if(arg!=0x80) { dbprintf(("Took an int %d\n", arg)); fflush(stderr); kill(getpid(), SIGILL); return; } dbprintf(("syscall AX=%x BX=%x CX=%x DX=%x\n", (unsigned short)elks_cpu.regs.eax, (unsigned short)elks_cpu.regs.ebx, (unsigned short)elks_cpu.regs.ecx, (unsigned short)elks_cpu.regs.edx)); elks_cpu.regs.eax = elks_syscall(); dbprintf(("elks syscall returned %d\n", elks_cpu.regs.eax)); /* Finally return to vm86 state */ } static int load_elks(int fd) { /* Load the elks binary image and set it up in a suitable VM86 segment. Load CS and DS/SS according to image type. chmem is ignored we always use 64K segments */ struct elks_exec_hdr mh; unsigned char *dsp; if(read(fd, &mh,sizeof(mh))!=sizeof(mh)) return -ENOEXEC; if(mh.hlen!=EXEC_HEADER_SIZE) return -ENOEXEC; if(mh.type!=ELKS_COMBID&&mh.type!=ELKS_SPLITID) return -ENOEXEC; #ifdef DEBUG fprintf(stderr,"Linux-86 binary - %lX. tseg=%ld dseg=%ld bss=%ld\n", mh.type,mh.tseg,mh.dseg,mh.bseg); #endif if(read(fd,elks_base,mh.tseg)!=mh.tseg) return -ENOEXEC; if(mh.type==ELKS_COMBID) dsp=elks_base+mh.tseg; else dsp=elks_base+65536; if(read(fd,dsp,mh.dseg)!=mh.dseg) return -ENOEXEC; memset(dsp+mh.dseg,0, mh.bseg); /* * Load the VM86 registers */ if(mh.type==ELKS_COMBID) dsp=elks_base; elks_cpu.regs.ds=PARAGRAPH(dsp); elks_cpu.regs.es=PARAGRAPH(dsp); elks_cpu.regs.ss=PARAGRAPH(dsp); elks_cpu.regs.esp=65536; /* Args stacked later */ elks_cpu.regs.cs=PARAGRAPH(elks_base); elks_cpu.regs.eip=0; /* Run from 0 */ /* * Loaded, check for sanity. */ if( dsp != ELKS_PTR(unsigned char, 0) ) { printf("Error VM86 problem %lx!=%lx (Is DS > 16 bits ?)\n", (long)dsp, (long)ELKS_PTR(char, 0)); exit(0); } return 0; } #ifndef OLD_LIBC_VERSION /* * recent versions of libc have changed the proto for vm86() * for now I'll just override ... */ #define OLD_SYS_vm86 113 #define NEW_SYS_vm86 166 static inline int vm86_mine(struct vm86_struct* v86) { int __res; __asm__ __volatile__("int $0x80\n" :"=a" (__res):"a" ((int)OLD_SYS_vm86), "b" ((int)v86)); return __res; } #endif void run_elks() { /* * Execute 8086 code for a while. */ #ifndef OLD_LIBC_VERSION int err=vm86_mine((struct vm86_struct*)&elks_cpu); #else int err=vm86((struct vm86_struct*)&elks_cpu); #endif switch(VM86_TYPE(err)) { /* * Signals are just re-starts of emulation (yes the * handler might alter elks_cpu) */ case VM86_SIGNAL: break; case VM86_UNKNOWN: fprintf(stderr, "VM86_UNKNOWN returned\n"); exit(1); case VM86_INTx: elks_take_interrupt(VM86_ARG(err)); break; case VM86_STI: fprintf(stderr, "VM86_STI returned\n"); break; /* Shouldnt be seen */ default: fprintf(stderr, "Unknown return value from vm86\n"); exit(1); } } void build_stack(char ** argv, char ** envp) { char **p; int argv_len=0, argv_count=0; int envp_len=0, envp_count=0; int stack_bytes; unsigned short * pip; unsigned short pcp; /* How much space for argv */ for(p=argv; *p; p++) { argv_count++; argv_len += strlen(*p)+1; } /* How much space for envp */ for(p=envp; *p; p++) { envp_count++; envp_len += strlen(*p)+1; } /* tot it all up */ stack_bytes = 2 /* argc */ + argv_count * 2 + 2 /* argv */ + argv_len + envp_count * 2 + 2 /* envp */ + envp_len; /* Allocate it */ elks_cpu.regs.esp -= stack_bytes; /* Sanity check printf("Argv = (%d,%d), Envp=(%d,%d), stack=%d\n", argv_count, argv_len, envp_count, envp_len, stack_bytes); */ /* Now copy in the strings */ pip=ELKS_PTR(unsigned short, elks_cpu.regs.esp); pcp=elks_cpu.regs.esp+2*(1+argv_count+1+envp_count+1); *pip++ = argv_count; for(p=argv; *p; p++) { *pip++ = pcp; strcpy(ELKS_PTR(char, pcp), *p); pcp += strlen(*p)+1; } *pip++ = 0; for(p=envp; *p; p++) { *pip++ = pcp; strcpy(ELKS_PTR(char, pcp), *p); pcp += strlen(*p)+1; } *pip++ = 0; } int main(int argc, char *argv[], char *envp[]) { int fd; struct stat st; int ruid, euid, rgid, egid; if(argc<=1) { fprintf(stderr,"elksemu cmd args.....\n"); exit(1); } /* This uses the _real_ user ID If the file is exec only that's */ /* ok cause the suid root will override. */ /* BTW, be careful here, security problems are possible because of * races if you change this. */ if( access(argv[1], X_OK) < 0 || (fd=open(argv[1], O_RDONLY)) < 0 || fstat(fd, &st) < 0 ) { perror(argv[1]); exit(1); } /* Check the suid bits ... */ ruid = getuid(); rgid = getgid(); euid = ruid; egid = rgid; if( st.st_mode & S_ISUID ) euid = st.st_uid; if( st.st_mode & S_ISGID ) egid = st.st_gid; /* Set the _real_ permissions, or revoke superuser priviliages */ setregid(rgid, egid); setreuid(ruid, euid); dbprintf(("ELKSEMU\n")); elks_init(); /* The Linux vm will deal with not allocating the unused pages */ #if __AOUT__ #if __GNUC__ /* GNU malloc will align to 4k with large chunks */ elks_base = malloc(0x20000); #else /* But others won't */ elks_base = malloc(0x20000+4096); elks_base = (void*) (((int)elks_base+4095) & -4096); #endif #else /* For ELF first 128M is unmapped, it needs to be mapped manually */ elks_base = mmap((void*)0x10000, 0x20000, PROT_EXEC|PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE|MAP_FIXED, 0, 0); #endif if( (long)elks_base < 0 || (long)elks_base >= 0xE0000 ) { fprintf(stderr, "Elks memory is at an illegal address\n"); exit(255); } if(load_elks(fd) < 0) { fprintf(stderr,"Not a elks binary.\n"); exit(1); } close(fd); build_stack(argv+1, envp); while(1) run_elks(); } #ifdef DEBUG void db_printf(const char * fmt, ...) { static FILE * db_fd = 0; va_list ptr; int rv; if( db_fd == 0 ) { db_fd = fopen("/tmp/ELKS_log", "a"); if( db_fd == 0 ) db_fd = stderr; setbuf(db_fd, 0); } fprintf(db_fd, "%d: ", getpid()); va_start(ptr, fmt); rv = vfprintf(db_fd,fmt,ptr); va_end(ptr); } #endif dev86-0.16.21/elksemu/elks.h000066400000000000000000000036121231050321700153650ustar00rootroot00000000000000/* * Definitions for emulating ELKS */ #define ELKS_CS_OFFSET 0 #define ELKS_DS_OFFSET 0 /* For split I/D */ #define HZ 100 #define ELKS_SIG_IGN (-1) #define ELKS_SIG_DFL 0 #define WRITE_USPACE 0 #define READ_USPACE 1 #if !__ELF__ #define __AOUT__ 1 #endif /* * Minix view of stat(). We have to squash a bit here and give * wrong values with inode >65535 etc */ struct elks_stat { unsigned short est_dev; unsigned short est_inode; unsigned short est_mode; unsigned short est_nlink; unsigned short est_uid; unsigned short est_gid; unsigned short est_rdev; int est_size; int est_atime; int est_mtime; int est_ctime; }; /* * Minix ioctl list */ #define ELKS_TIOCGETP (('t'<<8)|8) #define ELKS_TIOCSETP (('t'<<8)|9) #define ELKS_TIOCGETC (('t'<<8)|18) #define ELKS_TIOCSETC (('t'<<8)|17) #define ELKS_TIOCFLUSH (('t'<<8)|16) /* * fcntl list */ #define ELKS_F_DUPFD 0 #define ELKS_F_GETFD 1 #define ELKS_F_SETFD 2 #define ELKS_F_GETFL 3 #define ELKS_F_SETFL 4 #define ELKS_F_GETLK 5 #define ELKS_F_SETLK 6 #define ELKS_F_SETLKW 7 /* * Elks binary formats */ #define EXEC_HEADER_SIZE 32 struct elks_exec_hdr { unsigned long type; #define ELKS_COMBID 0x04100301L #define ELKS_SPLITID 0x04200301L unsigned long hlen; unsigned long tseg; unsigned long dseg; unsigned long bseg; unsigned long unused; unsigned long chmem; unsigned long unused2; }; #define PARAGRAPH(x) (((unsigned long)(x))>>4) #define ELKS_DSEG(x) ((unsigned char *)(((x)&0xFFFF)+(elks_cpu.regs.ds<<4))) #define ELKS_PTR(_t,x) ((_t *) ((elks_cpu.regs.ds<<4)+((x)&0xFFFF)) ) #define ELKS_PEEK(_t,x) (*((_t *) ((elks_cpu.regs.ds<<4)+((x)&0xFFFF)) )) #define ELKS_POKE(_t,x,_v) \ (*((_t *) ((elks_cpu.regs.ds<<4)+((x)&0xFFFF)) ) = (_v)) extern unsigned char * elks_base; extern volatile struct vm86_struct elks_cpu; void db_printf(const char *, ...); int elks_syscall(void); void minix_syscall(void); dev86-0.16.21/elksemu/elks_signal.c000066400000000000000000000016411231050321700167150ustar00rootroot00000000000000 #include #include #include #include #include #include #include #include #include #include "elks.h" static int elks_sigtrap= -1; void sig_trap(int signo) { elks_cpu.regs.esp -= 2; ELKS_POKE(unsigned short, elks_cpu.regs.esp, signo); elks_cpu.regs.esp -= 2; ELKS_POKE(unsigned short, elks_cpu.regs.esp, elks_cpu.regs.eip); elks_cpu.regs.eip = elks_sigtrap; } int elks_signal(int bx,int cx,int dx,int di,int si) { void (*oldsig)(int) = 0; if( bx < 0 || bx >= NSIG ) { errno = EINVAL; return -1; } if( cx == 0 ) oldsig = signal(bx, SIG_DFL); else if( cx == 1 ) oldsig = signal(bx, SIG_IGN); else { elks_sigtrap = cx; oldsig = signal(bx, sig_trap); } if( oldsig == SIG_ERR) return -1; if( oldsig == SIG_DFL) return 0; if( oldsig == SIG_IGN) return 1; return 2; } dev86-0.16.21/elksemu/elks_sys.c000066400000000000000000000432751231050321700162670ustar00rootroot00000000000000/* * System calls are mostly pretty easy as the emulator is tightly bound to * the elks task. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "elks.h" #include "efile.h" #ifdef DEBUG #define dbprintf(x) db_printf x #else #define dbprintf(x) #endif #define sys_signal elks_signal extern int elks_signal(int bx,int cx,int dx,int di,int si); /* Forward refs */ static int elks_termios(int bx,int cx,int dx,int di,int si); static int elks_enosys(int bx,int cx,int dx,int di,int si); #define DIRCOUNT 20 DIR * dirtab[DIRCOUNT]; int diropen = 0; static int elks_opendir(char * dname); static int elks_readdir(int bx,int cx,int dx,int di,int si); static int elks_closedir(int bx); /* * Compress a host stat into a elks one. Lose upper bits with wild * abandon. For SYS5.3 this isn't a problem, but machines with 32 * bit inodes (BSD, SYS5 with veritas, newest SCO) you lose the top * bits which can confuse a few programs which use inode numbers * (eg gnu tar). */ static void squash_stat(struct stat *s, int bx) { #if 1 /* Can't use elks_stat, shot in the foot by alignment */ ELKS_POKE(short, bx+0, s->st_dev); ELKS_POKE(short, bx+2, s->st_ino ^ (s->st_ino>>16)); ELKS_POKE(short, bx+4, s->st_mode); ELKS_POKE(short, bx+6, s->st_nlink); ELKS_POKE(short, bx+8, s->st_uid); ELKS_POKE(short, bx+10, s->st_gid); ELKS_POKE(short, bx+12, s->st_rdev); ELKS_POKE(long, bx+14, s->st_size); ELKS_POKE(long, bx+18, s->st_atime); ELKS_POKE(long, bx+22, s->st_mtime); ELKS_POKE(long, bx+26, s->st_ctime); #else struct elks_stat * ms = ELKS_PTR(struct elks_stat, bx); ms->est_dev=s->st_dev; ms->est_inode=(unsigned short)s->st_ino; /* Bits lost */ ms->est_mode=s->st_mode; ms->est_nlink=s->st_nlink; ms->est_uid=s->st_uid; ms->est_gid=s->st_gid; ms->est_rdev=s->st_rdev; ms->est_size=s->st_size; ms->est_atime=s->st_atime; ms->est_mtime=s->st_mtime; ms->est_ctime=s->st_ctime; #endif } /* * Implementation of ELKS syscalls. */ #define sys_exit elks_exit static int elks_exit(int bx,int cx,int dx,int di,int si) { dbprintf(("exit(%d)\n",bx)); exit(bx); } #define sys_vfork elks_fork #define sys_fork elks_fork static int elks_fork(int bx,int cx,int dx,int di,int si) { dbprintf(("fork()\n")); /* This is fun 8) - fork the emulator (its easier that way) */ return fork(); } #define sys_read elks_read static int elks_read(int bx,int cx,int dx,int di,int si) { dbprintf(("read(%d, %d, %d)\n", bx,cx,dx)); if( bx >= 10000 && bx < 10000+DIRCOUNT) return elks_readdir(bx, cx, dx, di, si); if( dx < 0 || dx > 1024 ) dx = 1024; return read(bx, ELKS_PTR(void, cx), dx); } #define sys_write elks_write static int elks_write(int bx,int cx,int dx,int di,int si) { #ifdef TESTING if( dx > 1024 || dx < 0 ) { dx = 1024; dbprintf(("write(%d, %d, >%d)\n",bx,cx,dx)); } else #endif { dbprintf(("write(%d, %d, %d)\n",bx,cx,dx)); } return write(bx,ELKS_PTR(void, cx),dx); } #define sys_open elks_open static int elks_open(int bx,int cx,int dx,int di,int si) { struct stat s; /* Assumes _all_ flags are the same */ char *dp=ELKS_PTR(char, bx); dbprintf(("open(%s, %d, %d)\n", dp,cx,dx)); /* Nasty hack so /lib/liberror.txt doesn't exist on the host. */ if (strcmp(dp, "/lib/liberror.txt") == 0 ) { int fd = open("/tmp/liberror.txt", O_CREAT|O_EXCL|O_RDWR, 0666); if (fd < 0) return fd; unlink("/tmp/liberror.txt"); write(fd, efile, sizeof(efile)); lseek(fd, 0L, 0); return fd; } if( cx == O_RDONLY ) { if(stat(dp,&s)==-1) return -1; if( S_ISDIR(s.st_mode) ) return elks_opendir(dp); } return open(dp,cx,dx); } #define sys_close elks_close static int elks_close(int bx,int cx,int dx,int di,int si) { dbprintf(("close(%d)\n",bx)); if( bx >= 10000 && bx < 10000+DIRCOUNT) return elks_closedir(bx); return close(bx); } #define sys_wait4 elks_wait4 static int elks_wait4(int bx,int cx,int dx,int di,int si) { int status; unsigned short *tp=ELKS_PTR(unsigned short, cx); int r; struct rusage use; dbprintf(("wait4(%d, %d, %d, %d)\n", bx, cx, dx, di)); r=wait4((int)(short)bx, &status, dx, &use ); *tp=status; if( di ) memcpy(ELKS_PTR(void, di), &use, sizeof(use)); return r; } #define sys_link elks_link static int elks_link(int bx,int cx,int dx,int di,int si) { dbprintf(("link(%s,%s)\n", ELKS_PTR(char, bx), ELKS_PTR(char, cx))); return link(ELKS_PTR(char, bx),ELKS_PTR(char, cx)); } #define sys_unlink elks_unlink static int elks_unlink(int bx,int cx,int dx,int di,int si) { dbprintf(("unlink(%s)\n",ELKS_PTR(char, bx))); return unlink(ELKS_PTR(char, bx)); } #define sys_chdir elks_chdir static int elks_chdir(int bx,int cx,int dx,int di,int si) { dbprintf(("chdir(%s)\n",ELKS_PTR(char, bx))); return chdir(ELKS_PTR(char, bx)); } #define sys_fchdir elks_fchdir static int elks_fchdir(int bx,int cx,int dx,int di,int si) { dbprintf(("fchdir(%s)\n",bx)); return fchdir(bx); } #define sys_mknod elks_mknod static int elks_mknod(int bx,int cx,int dx,int di,int si) { dbprintf(("mknod(%s,%d,%d)\n", ELKS_PTR(char, bx),cx,dx)); return mknod(ELKS_PTR(char, bx),cx,dx); } #define sys_chmod elks_chmod static int elks_chmod(int bx,int cx,int dx,int di,int si) { dbprintf(("chmod(%s,%d)\n", ELKS_PTR(char, bx),cx)); return chmod(ELKS_PTR(char, bx), cx); } #define sys_chown elks_chown static int elks_chown(int bx,int cx,int dx,int di,int si) { dbprintf(("chown(%s,%d,%d)\n", ELKS_PTR(char, bx),cx,dx)); return chown(ELKS_PTR(char, bx),cx,dx); } #define sys_brk elks_brk static int elks_brk(int bx,int cx,int dx,int di,int si) { dbprintf(("brk(%d)\n",bx)); if(bx>=elks_cpu.regs.esp) { errno= 1; /* Really return -1 */ return -1; } return 0; /* Can't return bx, 0xBAD1 is an error */ } #define sys_stat elks_stat static int elks_stat(int bx,int cx,int dx,int di,int si) { struct stat s; dbprintf(("stat(%s,%d)\n", ELKS_PTR(char, bx), cx)); if(stat(ELKS_PTR(char, bx),&s)==-1) return -1; squash_stat(&s,cx); return 0; } #define sys_lstat elks_lstat static int elks_lstat(int bx,int cx,int dx,int di,int si) { struct stat s; dbprintf(("lstat(%s,%d)\n", ELKS_PTR(char, bx), cx)); if(lstat(ELKS_PTR(char, bx),&s)==-1) return -1; squash_stat(&s,cx); return 0; } #define sys_lseek elks_lseek static int elks_lseek(int bx,int cx,int dx,int di,int si) { long l=ELKS_PEEK(long, cx); dbprintf(("lseek(%d,%ld,%d)\n",bx,l,dx)); l = lseek(bx,l,dx); if( l < 0 ) return -1; ELKS_POKE(long, cx, l); return 0; } #define sys_getpid elks_getpid static int elks_getpid(int bx,int cx,int dx,int di,int si) { dbprintf(("getpid/getppid()\n")); ELKS_POKE(unsigned short, bx, getppid()); return getpid(); } #define sys_setuid elks_setuid static int elks_setuid(int bx,int cx,int dx,int di,int si) { dbprintf(("setuid(%d)\n",bx)); return setuid(bx); } #define sys_getuid elks_getuid static int elks_getuid(int bx,int cx,int dx,int di,int si) { dbprintf(("get[e]uid()\n")); ELKS_POKE(unsigned short, bx, geteuid()); return getuid(); } #define sys_alarm elks_alarm static int elks_alarm(int bx,int cx,int dx,int di,int si) { dbprintf(("alarm(%d)\n",bx&0xFFFF)); return alarm(bx&0xFFFF); } #define sys_fstat elks_fstat static int elks_fstat(int bx,int cx,int dx,int di,int si) { struct stat s; int err; dbprintf(("fstat(%d,%d)\n",bx,cx)); err=fstat(bx,&s); squash_stat(&s,cx); return err; } #define sys_pause elks_pause static int elks_pause(int bx,int cx,int dx,int di,int si) { dbprintf(("pause()\n")); return pause(); } #define sys_utime elks_utime static int elks_utime(int bx,int cx,int dx,int di,int si) { unsigned long *up=ELKS_PTR(long, cx); struct utimbuf u; u.actime=*up++; u.modtime=*up; return utime(ELKS_PTR(char, bx), &u); } #define sys_access elks_access static int elks_access(int bx,int cx,int dx,int di,int si) { dbprintf(("access(%s,%d)\n",ELKS_PTR(char, bx),cx)); return access(ELKS_PTR(char, bx),cx); } #define sys_sync elks_sync static int elks_sync(int bx,int cx,int dx,int di,int si) { dbprintf(("sync()\n")); sync(); return 0; } #define sys_kill elks_kill static int elks_kill(int bx,int cx,int dx,int di,int si) { dbprintf(("kill(%d,%d)\n",bx,cx)); return kill(bx,cx); } #define sys_pipe elks_pipe static int elks_pipe(int bx,int cx,int dx,int di,int si) { unsigned short *dp=ELKS_PTR(unsigned short, bx); int p[2]; int err=pipe(p); if(err==-1) return err; *dp++=p[0]; *dp=p[1]; return 0; } #define sys_times elks_times static int elks_times(int bx,int cx,int dx,int di,int si) { struct tms t; long clock_ticks=times(&t); long *tp=ELKS_PTR(long, bx); long *clkt=ELKS_PTR(long, cx); *tp++=t.tms_utime; *tp++=t.tms_stime; *tp++=t.tms_cutime; *tp=t.tms_cstime; *clkt = clock_ticks; return 0; /* Should be clock_ticks */ } #define sys_setgid elks_setgid static int elks_setgid(int bx,int cx,int dx,int di,int si) { return setgid(bx); } #define sys_getgid elks_getgid static int elks_getgid(int bx,int cx,int dx,int di,int si) { ELKS_POKE(unsigned short, bx, getegid()); return getgid(); } /* * Exec is fun. The Minix user library builds a complete elks stack image. * Great except that we need to unpack it all again and do a real exec. If * its another elks image then our kernel side binary loader will load * elksemu again and we'll take the Unix args and turn them back into a * elks stack image. * * For now we run elksemu ourselves and do token attempts at binary checking. * * Of course if the kernel misc module is confiured we could just run the exe. */ #define sys_execve elks_execve static int elks_execve(int bx,int cx,int dx,int di,int si) { int fd; int arg_ct,env_ct; int ct; char **argp, **envp; unsigned short *bp; unsigned char *base; unsigned short *tmp; struct elks_exec_hdr mh; int is_elks = 1; dbprintf(("exec(%s,%d,%d)\n",ELKS_PTR(char, bx), cx, dx)); base=ELKS_PTR(unsigned char, cx); bp=ELKS_PTR(unsigned short, cx+2); tmp=bp; fd=open(ELKS_PTR(char, bx),O_RDONLY); if(fd==-1) { errno = ENOENT; return -1; } if(read(fd, &mh, sizeof(mh))!=sizeof(mh)) { close(fd); errno = ENOEXEC; return -1; } close(fd); if(mh.hlen!=EXEC_HEADER_SIZE || (mh.type!=ELKS_COMBID && mh.type!=ELKS_SPLITID)) is_elks = 0; arg_ct = env_ct = 0; while(*tmp++) arg_ct++; while(*tmp++) env_ct++; arg_ct+=2; /* elksemu-path progname arg0...argn */ argp=malloc(sizeof(char *)*(arg_ct+1)); envp=malloc(sizeof(char *)*(env_ct+1)); if(!argp||!envp) { errno = ENOMEM; return -1; } ct=0; if( is_elks ) { argp[0]="/usr/bin/elksemu"; /* argp[1]=ELKS_PTR(char, bx); */ ct=1; } while(*bp) argp[ct++]=ELKS_PTR(char, cx+ *bp++); argp[ct]=0; bp++; ct=0; while(*bp) envp[ct++]=ELKS_PTR(char, cx+ *bp++); envp[ct]=0; if( is_elks ) { argp[1]=ELKS_PTR(char, bx); execve(argp[0],argp,envp); } else execve(ELKS_PTR(char, bx),argp,envp); if( errno == ENOEXEC || errno == EACCES ) return -1; perror("elksemu"); exit(1); } #define sys_umask elks_umask static int elks_umask(int bx,int cx,int dx,int di,int si) { return umask(bx); } #define sys_chroot elks_chroot static int elks_chroot(int bx,int cx,int dx,int di,int si) { dbprintf(("chroot(%s)\n", ELKS_PTR(char, bx))); return chroot(ELKS_PTR(char, bx)); } #define sys_fcntl elks_fcntl static int elks_fcntl(int bx,int cx,int dx,int di,int si) { dbprintf(("fcntl(%d,%d,%d)\n", bx,cx,dx)); switch(cx) { case ELKS_F_GETFD: return fcntl(bx,F_GETFD,0); case ELKS_F_GETFL: return fcntl(bx,F_GETFL,0); case ELKS_F_DUPFD: return fcntl(bx,F_DUPFD,dx); case ELKS_F_SETFD: return fcntl(bx,F_SETFD,dx); case ELKS_F_SETFL: return fcntl(bx,F_SETFL,dx); /* * Fixme: Unpack and process elks file locks */ case ELKS_F_GETLK: case ELKS_F_SETLK: case ELKS_F_SETLKW: errno = EINVAL; return -1; } errno = EINVAL; return -1; } #define sys_dup elks_dup static int elks_dup(int bx,int cx,int dx,int di,int si) { return dup(bx); } #define sys_dup2 elks_dup2 static int elks_dup2(int bx,int cx,int dx,int di,int si) { return dup2(bx, cx); } #define sys_rename elks_rename static int elks_rename(int bx,int cx,int dx,int di,int si) { dbprintf(("rename(%s,%s)\n", ELKS_PTR(char, bx), ELKS_PTR(char, cx))); return rename(ELKS_PTR(char, bx), ELKS_PTR(char, cx)); } #define sys_mkdir elks_mkdir static int elks_mkdir(int bx,int cx,int dx,int di,int si) { dbprintf(("mkdir(%s,%d)\n", ELKS_PTR(char, bx),cx)); return mkdir(ELKS_PTR(char, bx),cx); } #define sys_rmdir elks_rmdir static int elks_rmdir(int bx,int cx,int dx,int di,int si) { dbprintf(("rmdir(%s)\n", ELKS_PTR(char, bx))); return rmdir(ELKS_PTR(char, bx)); } #define sys_gettimeofday elks_gettimeofday static int elks_gettimeofday(int bx,int cx,int dx,int di,int si) { struct timeval tv; struct timezone tz; int ax; dbprintf(("gettimeofday(%d,%d)\n",bx,cx)); ax = gettimeofday(&tv, &tz); if( ax == 0 && bx ) { ELKS_POKE(long, bx, tv.tv_sec); ELKS_POKE(long, bx+4, tv.tv_usec); } if( ax == 0 && cx ) { ELKS_POKE(short, cx, tz.tz_minuteswest); ELKS_POKE(short, cx+2, tz.tz_dsttime); } return ax?-1:0; } #define sys_settimeofday elks_settimeofday static int elks_settimeofday(int bx,int cx,int dx,int di,int si) { struct timeval tv, *pv = 0; struct timezone tz, *pz = 0; int ax; dbprintf(("settimeofday(%d,%d)\n",bx,cx)); if( bx ) { pv = &tv; tv.tv_sec = ELKS_PEEK(long, bx); tv.tv_usec = ELKS_PEEK(long, bx+4); } if( cx ) { pz = &tz; tz.tz_minuteswest = ELKS_PEEK(short, cx); tz.tz_dsttime = ELKS_PEEK(short, cx+2); } ax = settimeofday(pv, pz); return ax?-1:0; } #define sys_nice elks_nice static int elks_nice(int bx,int cx,int dx,int di,int si) { dbprintf(("nice(%d)\n",bx)); return nice(bx); } #define sys_symlink elks_symlink static int elks_symlink(int bx,int cx,int dx,int di,int si) { dbprintf(("symlink(%s,%s)\n", ELKS_PTR(char, bx), ELKS_PTR(char, cx))); return symlink(ELKS_PTR(char, bx), ELKS_PTR(char, cx)); } #define sys_readlink elks_readlink static int elks_readlink(int bx,int cx,int dx,int di,int si) { dbprintf(("readlink(%s,%s,%d)\n", ELKS_PTR(char, bx), ELKS_PTR(char, cx), dx)); return readlink(ELKS_PTR(char, bx), ELKS_PTR(char, cx), dx); } #define sys_ioctl elks_ioctl static int elks_ioctl(int bx,int cx,int dx,int di,int si) { dbprintf(("ioctl(%d,0x%04x,0x%04x)\n", bx,cx,dx)); switch((cx>>8)&0xFF) { case 'T': return elks_termios(bx,cx,dx,di,si); default: return elks_enosys(bx,cx,dx,di,si); } } #define sys_reboot elks_reboot static int elks_reboot(int bx,int cx,int dx,int di,int si) { errno = EINVAL; if( bx != 0xfee1 || cx != 0xdead ) return -1; switch(dx) { /* graceful shutdown, C-A-D off, kill -? 1 */ case 0: return reboot(0xfee1dead, 672274793, 0); /* Enable C-A-D */ case 0xCAD: return reboot(0xfee1dead, 672274793, 0x89abcdef); /* Time to die! */ case 0xD1E: return reboot(0xfee1dead, 672274793, 0x1234567); } return -1; } /****************************************************************************/ static int elks_opendir(char * dname) { DIR * d; int rv; for(rv=0; rv= DIRCOUNT ) { errno=ENOMEM; return -1; } d = opendir(dname); if( d == 0 ) return -1; dirtab[rv] = d; return 10000+rv; } #define sys_readdir elks_readdir static int elks_readdir(int bx,int cx,int dx,int di,int si) { struct dirent * ent; /* Only read _ONE_ _WHOLE_ dirent at a time */ if( dx != 266 && dx != 1 ) { errno=EINVAL; return -1; } errno = 0; ent = readdir(dirtab[bx-10000]); if( ent == 0 ) { if( errno ) { return -1; } else return 0; } memcpy(ELKS_PTR(char, cx+10), ent->d_name, ent->d_reclen+1); ELKS_POKE(long, cx, ent->d_ino); ELKS_POKE(short, cx+8, ent->d_reclen); return dx; } static int elks_closedir(int bx) { bx-=10000; if( dirtab[bx] ) closedir(dirtab[bx]); dirtab[bx] = 0; return 0; } /****************************************************************************/ static int elks_termios(int bx,int cx,int dx,int di,int si) { int rv = 0; switch(cx&0xFF) { case 0x01: rv = ioctl(bx, TCGETS, ELKS_PTR(void, dx)); break; case 0x02: rv = ioctl(bx, TCSETS, ELKS_PTR(void, dx)); break; case 0x03: rv = ioctl(bx, TCSETSW, ELKS_PTR(void, dx)); break; case 0x04: rv = ioctl(bx, TCSETSF, ELKS_PTR(void, dx)); break; case 0x09: rv = ioctl(bx, TCSBRK, dx); break; case 0x0A: rv = ioctl(bx, TCXONC, dx); break; case 0x0B: rv = ioctl(bx, TCFLSH, dx); break; case 0x11: rv = ioctl(bx, TIOCOUTQ, ELKS_PTR(void, dx)); break; case 0x1B: rv = ioctl(bx, TIOCINQ, ELKS_PTR(void, dx)); break; default: rv = -1; errno = EINVAL; break; } return rv; } /****************************************************************************/ /* */ /****************************************************************************/ #define sys_enosys elks_enosys static int elks_enosys(int bx,int cx,int dx,int di,int si) { fprintf(stderr, "Function number %d called (%d,%d,%d)\n", (int)(0xFFFF&elks_cpu.regs.eax), bx, cx, dx); errno = ENOSYS; return -1; } #include "defn_tab.v" /* * */ typedef int (*funcp)(int, int, int, int, int); static funcp jump_tbl[] = { #include "call_tab.v" elks_enosys }; int elks_syscall(void) { int r, n; int bx=elks_cpu.regs.ebx&0xFFFF; int cx=elks_cpu.regs.ecx&0xFFFF; int dx=elks_cpu.regs.edx&0xFFFF; int di=elks_cpu.regs.edi&0xFFFF; int si=elks_cpu.regs.esi&0xFFFF; errno=0; n = (elks_cpu.regs.eax&0xFFFF); if( n>= 0 && n< sizeof(jump_tbl)/sizeof(funcp) ) r = (*(jump_tbl[n]))(bx, cx, dx, di, si); else return -ENOSYS; if(r>=0) return r; else return -errno; } dev86-0.16.21/elksemu/minix.c000066400000000000000000000035621231050321700155520ustar00rootroot00000000000000#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "elks.h" #ifdef DEBUG #define dbprintf(x) db_printf x #else #define dbprintf(x) #endif static char * minix_names[] = { "0", "EXIT", "FORK", "READ", "WRITE", "OPEN", "CLOSE", "WAIT", "CREAT", "LINK", "UNLINK", "WAITPID", "CHDIR", "TIME", "MKNOD", "CHMOD", "CHOWN", "BRK", "STAT", "LSEEK", "GETPID", "MOUNT", "UMOUNT", "SETUID", "GETUID", "STIME", "PTRACE", "ALARM", "FSTAT", "PAUSE", "UTIME", "31", "32", "ACCESS", "34", "35", "SYNC", "KILL", "RENAME", "MKDIR", "RMDIR", "DUP", "PIPE", "TIMES", "44", "45", "SETGID", "GETGID", "SIGNAL", "49", "50", "51", "52", "53", "IOCTL", "FCNTL", "56", "57", "58", "EXEC", "UMASK", "CHROOT", "SETSID", "GETPGRP", "KSIG", "UNPAUSE", "66", "REVIVE", "TASK_REPLY", "69", "70", "SIGACTION", "SIGSUSPEND", "SIGPENDING", "SIGPROCMASK", "SIGRETURN", "REBOOT", "77" }; void minix_syscall() { static char *nm[4] = {"?", "send", "receive", "sendrec"}; char tsks[10], syss[10]; int sr = (unsigned short) elks_cpu.regs.ecx; int tsk = (unsigned short) elks_cpu.regs.eax; int sys = ELKS_PEEK(short, (unsigned short) elks_cpu.regs.ebx + 2); if (sr < 0 || sr > 3) sr = 0; switch(tsk) { case 0: strcpy(tsks, "MM"); break; case 1: strcpy(tsks, "FS"); break; default: sprintf(tsks, "task(%d)", tsk); } if( sys > 0 && sys < 77 ) strcpy(syss, minix_names[sys]); else sprintf(syss, "%d", sys); fprintf(stderr, "Minix syscall %s(%s,&{%d,%s,...})\n", nm[sr], tsks, getpid(), syss); exit(99); } dev86-0.16.21/elksemu/mkefile000066400000000000000000000002061231050321700156110ustar00rootroot00000000000000#!/bin/sh - awk ' BEGIN { printf "char efile[] =\n" } { printf " \"%s\\n\"\n", $0 } END{ printf ";\n"; } ' < "$1" > efile.h dev86-0.16.21/ifdef.c000066400000000000000000000235501231050321700140350ustar00rootroot00000000000000/* (C) 1992,1996,1998-9 R de Bath */ #include #include #include #ifdef __STDC__ /* == Not braindead compiler (hopefully!) */ #include #define P(x) x #else #define P(x) () #define void char #endif /* * Linked list of variables, the only source for these is the command line * and the (optional) manifest constants. */ struct varrec { struct varrec * next; int state; char name[1]; } *varlist = 0; int cuttype = 0; /* 0 = use blank lines */ /* 1 = use #lines */ /* 2 = use '# 'oldtext */ /* 3 = delete unused lines */ int striphash = 0; int stripcomment = 0; char linebuf[2048]; char * filename; int lineno; int prline; FILE * fd; int iflevel = 0; int keeptext = 1; int unknown_stat = 0; char * commentstr = "#"; char names[16][32]; char state[16]; int main P((int argc, char ** argv)); void Usage P((char * prog)); void save_name P((char * varname, int state)); void do_file P((char * fname)); void set_line P((int lineno)); int do_hashcom P((void)); int do_ifdef P((char * p, int which)); void check_name P((char * nm)); void fatal P((char * msg)); void manifest_constant P((void)); int main(argc, argv) int argc; char ** argv; { int ar; char * ptr; if( argc <= 1 ) Usage(argv[0]); for(ar=1; arname, varname) != 0; prev=curr, curr=curr->next) ; if( curr == 0 ) { curr = (struct varrec*) malloc(sizeof(struct varrec)+strlen(varname)); if( curr == 0 ) fatal("Out of memory error"); if( prev ) prev->next = curr; else varlist = curr; curr->next = 0; strcpy(curr->name, varname); } curr->state = state; } void do_file(fname) char * fname; { filename = fname; prline = lineno = 0; fd = fopen(fname, "r"); if( fd == 0 ) fatal("Cannot open file"); if( cuttype == 1 ) printf("#line 1 \"%s\"\n", filename); /* NB: limited line length */ while( fgets(linebuf, sizeof(linebuf), fd) != 0 ) { int f = 1; char * p = linebuf; lineno++; while(isspace(*p)) p++; if( *p == '#' ) f = do_hashcom(); if(f) { if( keeptext ) { if( cuttype == 1 ) set_line(lineno); printf("%s", linebuf); } else { if( cuttype == 0 ) printf("\n"); if( cuttype == 2 ) printf("%s %s", commentstr, linebuf); } } } fclose(fd); if( iflevel != 0 ) fatal("Not enough endif's"); } void set_line(lineno) int lineno; { if( prline+2 == lineno ) printf("\n"); else if( prline+1 != lineno ) printf("#line %d \"%s\"\n", lineno, filename); prline = lineno; } int do_hashcom() { char * p = linebuf; int flg = -1; while(isspace(*p)) p++; if( *p == '#' ) p++; while(isspace(*p)) p++; if(strncmp(p, "ifdef", 5) == 0) { do_ifdef(p+5, 'D'); } else if(strncmp(p, "ifndef", 6) == 0) { do_ifdef(p+6, 'U'); } else if(strncmp(p, "if", 2) == 0 && isspace(p[2]) ) { state[iflevel++] = keeptext; keeptext |= 2; } else if(strncmp(p, "else", 4) == 0) { if( iflevel == 0 ) fatal("#else at top level"); if( iflevel && state[iflevel-1]) keeptext ^= 1; } else if(strncmp(p, "endif", 5) == 0) { flg = (keeptext&2); if( iflevel == 0 ) fatal("Too many endif's"); iflevel--; keeptext = state[iflevel]; } else if( !striphash ) return 1; if( flg < 0 ) flg = (keeptext&2); if( flg ) return 1; if( cuttype == 0 ) printf("\n"); if( cuttype == 2 ) printf("%s %s", commentstr, linebuf); return 0; } int do_ifdef(p, which) char * p; int which; { char * nm; char * s; struct varrec * curr; while( *p == ' ' || *p == '\t') p++; nm = p; for(curr=varlist; curr ; curr = curr->next) { s = curr->name; p = nm; while( *p == *s ) { p++; s++; } if( *s == '\0' && *p <= ' ' ) /* FIXME alphanum */ break; } state[iflevel] = keeptext; iflevel++; p=nm; s=names[iflevel]; while(*p > ' ') *s++ = *p++; *s = '\0'; if( curr == 0 ) { if( unknown_stat == 0 ) { if( keeptext ) keeptext |= 2; return 0; } if( keeptext ) keeptext = (unknown_stat == which); return 1; } if( keeptext ) keeptext = (curr->state == which); return 1; } #if 0 do_if(p) char * p; { /* * Look for: * defined Label * one sort of || && * 0 * 1 * * Skip characters: WS, (, ) * * Give up on unknown characters and labels without a defined or assumed * state. BUT note that if there is another label that forces the state * of the result irrespective of an unknown label the state should be set. * */ static char wbuf[256]; int combiner = 0; int true_defs = 0; int false_defs = 0; int unkn_defs = 0; int state = 0; char * d; for(;;) { d=wbuf; do { while( isspace(*p) || (d==wbuf && (*p == '(' || *p == ')' ))) p++; if( d!=wbuf && (*p == '(' || *p == ')' )) break; while( !(isspace(*p) || *p == '(' || *p == ')' )) if( d ' ' ) fputc(*nm++, stderr); fputc('\'', stderr); fputc('\n', stderr); } void fatal(msg) char * msg; { fprintf(stderr, "Fatal error:%s\n", msg); exit(1); } /* This places manifest constants defined by the C compiler into ifdef * * Unfortunatly I can find no way of discovering the variables automatically */ void manifest_constant() { /* General */ #ifdef __STDC__ save_name("__STDC__", 'D'); #endif #ifdef __GNUC__ save_name("__GNUC__", 'D'); #endif #ifdef GNUMAKE save_name("GNUMAKE", 'D'); #endif if( sizeof(int) < 4 ) save_name("__SMALL_INTS__", 'D'); if( sizeof(char *) <= 2 ) save_name("__SMALL_MEMORY__", 'D'); if( sizeof(long) == 4 ) save_name("__LONG_32_BIT__", 'D'); if( sizeof(long) == 8 ) save_name("__LONG_64_BIT__", 'D'); /* MSDOS */ #ifdef MSDOS save_name("MSDOS", 'D'); #endif #ifdef __MSDOS__ save_name("__MSDOS__", 'D'); #endif /* Linux/unix */ #ifdef __linux__ save_name("__linux__", 'D'); #ifdef __i386__ save_name("__elksemu_works__", 'D'); #endif #endif #ifdef __unix__ save_name("__unix__", 'D'); #endif #ifdef __GNUC__ save_name("__GNUC__", 'D'); #endif #ifdef __ELF__ save_name("__ELF__", 'D'); #endif #ifdef __i386__ save_name("__i386__", 'D'); #endif #ifdef __i486__ save_name("__i486__", 'D'); #endif #ifdef i386 save_name("i386", 'D'); #endif #ifdef linux save_name("linux", 'D'); #endif #ifdef unix save_name("unix", 'D'); #endif /* BCC */ #ifdef __BCC__ save_name("__BCC__", 'D'); #endif #ifdef __AS386_16__ save_name("__AS386_16__", 'D'); #endif #ifdef __AS386_32__ save_name("__AS386_32__", 'D'); #endif /* AIX, RS6000 */ #ifdef _IBMR2 save_name("_IBMR2", 'D'); #endif #ifdef _AIX save_name("_AIX", 'D'); #endif #ifdef _AIX32 save_name("_AIX32", 'D'); #endif /* Ugh! Minix is actually _very_ nasty */ #ifdef __minix save_name("__minix", 'D'); #endif /* This isn't much nicer */ #ifdef __CYGWIN__ save_name("__CYGWIN__", 'D'); #endif #ifdef __APPLE__ save_name("__APPLE__", 'D'); #endif } dev86-0.16.21/ld/000077500000000000000000000000001231050321700132065ustar00rootroot00000000000000dev86-0.16.21/ld/6809/000077500000000000000000000000001231050321700136145ustar00rootroot00000000000000dev86-0.16.21/ld/6809/config.h000066400000000000000000000016151231050321700152350ustar00rootroot00000000000000/* config.h - configuration for linker */ /* Copyright (C) 1994 Bruce Evans */ /* one of these target processors must be defined */ #undef I8086 /* Intel 8086 */ #undef I80386 /* Intel 80386 */ #define MC6809 /* Motorola 6809 */ /* one of these target operating systems must be defined */ #define EDOS /* generate EDOS executable */ #undef MINIX /* generate Minix executable */ /* these may need to be defined to suit the source processor */ #define HOST_8BIT /* enable some 8-bit optimizations */ /* #define S_ALIGNMENT 4 */ /* source memory alignment, power of 2 */ /* don't use for 8 bit processors */ /* don't use even for 80386 - overhead for */ /* alignment cancels improved access */ /* these must be defined to suit the source libraries */ #define CREAT_PERMS 0666 /* permissions for creat() */ #define EXEC_PERMS 0111 /* extra permissions to set for executable */ dev86-0.16.21/ld/Makefile000066400000000000000000000022231231050321700146450ustar00rootroot00000000000000 LIBDIR =/usr/bin CFLAGS =-O LDFLAGS = # Will need some of these if you want native executables on non-Linux/i386 # -DDETECTAOUT # Turn on detection. # -DV7_A_OUT # a.out.h is like V7 # -DBSD_A_OUT # a.out.h is like BSD # -DSTANDARD_GNU_A_OUT # a.out.h is like GNU normal. # # -DREL_OUTPUT -DBUGCOMPAT # -r Produces weird *.o files. # DEFS =-DREL_OUTPUT # An alternative file for a non-standard a.out.h (eg i386 linux on an Alpha) # # NATIVE=-DA_OUT_INCL='"a_out_local.h"' OBJS= dumps.o io.o ld.o readobj.o table.o typeconv.o linksyms.o mkar.o \ writex86.o writebin.o writeemu.o all: ld86 objchop catimage objdump86 ld86: $(OBJS) $(CC) $(LDFLAGS) $(OBJS) -o $@ install: ld86 install -d $(LIBDIR) install -m 755 ld86 $(LIBDIR) clean realclean clobber: rm -f *.o ld86 ld86r objchop catimage objdump86 $(OBJS): align.h ar.h bindef.h byteord.h config.h const.h globvar.h obj.h \ syshead.h type.h x86_aout.h ar.h: test -f ar.h || \ { rm -f ar.h ; ln -s ../libc/include/ar.h . ; } || \ ln ../libc/include/ar.h . writebin.o: writebin.c $(CC) $(CFLAGS) $(DEFS) $(NATIVE) -c $< writerel.o: writebin.c .c.o: $(CC) $(CFLAGS) $(DEFS) -c $< -o $@ dev86-0.16.21/ld/align.h000066400000000000000000000006321231050321700144520ustar00rootroot00000000000000/* align.h - memory alignment requirements for linker */ /* Copyright (C) 1994 Bruce Evans */ #ifndef S_ALIGNMENT # define align(x) #else #if defined(__STDC__) && defined(_POSIX_SOURCE) # define align(x) ((x)=(void *) \ (((ssize_t)(x) + (S_ALIGNMENT-1)) & ~(S_ALIGNMENT-1))) #else # define align(x) ((x)=(void *) \ ((char *)(x) + ((S_ALIGNMENT-(char)(x)) & (S_ALIGNMENT-1)))) #endif #endif dev86-0.16.21/ld/bindef.h000066400000000000000000000031601231050321700146060ustar00rootroot00000000000000 /* Only do native on Linux/i386 by default -- it's safer. */ #ifndef DETECTAOUT #if defined(__i386__) && defined(__linux__) #define DETECTAOUT #else # ifdef A_OUT_INCL # define DETECTAOUT # endif #endif #endif #ifdef DETECTAOUT /* Ok, I'm just gonna make it simple ... override this if you like. */ #ifndef A_OUT_INCL #define A_OUT_INCL #endif #include A_OUT_INCL /* Try and guess type ... */ #ifndef V7_A_OUT #ifndef BSD_A_OUT #ifndef STANDARD_GNU_A_OUT # ifndef C_EXT # define BSD_A_OUT # endif /* Not sure about this one ... it works here ... */ # if defined(BSD_A_OUT) && defined(N_MAGIC) # define STANDARD_GNU_A_OUT # endif #endif #endif #endif /* General specs as to how it works ... */ # ifdef BSD_A_OUT # ifdef STANDARD_GNU_A_OUT # define RELOC_INFO_SIZE 8 /* unportable bitfields - bcc doesn't pack */ # else # define RELOC_INFO_SIZE (sizeof (struct relocation_info)) # endif # ifdef N_EXT # define C_EXT N_EXT # endif # define C_STAT 0 # define n_was_name n_un.n_name # define n_was_numaux n_other # define n_was_other n_numaux # define n_was_sclass n_type # define n_was_strx n_un.n_strx # define n_was_type n_desc # else /* not BSD_A_OUT */ # define RELOC_INFO_SIZE (sizeof (struct reloc)) # define n_was_name n_name # define n_was_numaux n_numaux # define n_was_other n_other # define n_was_sclass n_sclass # define n_was_strx n_value # define n_was_type n_type # endif /* BSD_A_OUT */ /* And finally make sure it worked */ #if defined(A_MINHDR) || defined(BSD_A_OUT) #if defined(C_EXT) && defined(C_STAT) && !defined(SCNHSZ) #define AOUT_DETECTED 1 #endif #endif #endif /* NO_AOUT */ dev86-0.16.21/ld/byteord.h000066400000000000000000000010271231050321700150270ustar00rootroot00000000000000/* byteord.h - byte order dependencies for C compiler, assembler, linker */ /* Copyright (C) 1994 Bruce Evans */ /* These are for the targets of everything and for linker source too. */ #ifdef I8086 # define INT_BIG_ENDIAN 0 # define LONG_BIG_ENDIAN 0 /* except longs are back to front for Xenix */ #endif #ifdef I80386 # define INT_BIG_ENDIAN 0 # define LONG_BIG_ENDIAN 0 #endif #ifdef MC6809 # define INT_BIG_ENDIAN 1 /* byte order in words is high-low */ # define LONG_BIG_ENDIAN 1 /* byte order in longs is high-low */ #endif dev86-0.16.21/ld/catimage.c000066400000000000000000000137071231050321700151340ustar00rootroot00000000000000/* * This program concatenates memory images the executables specified * on it's command line. * * The 'boot' image must have a symbol table any symbols that match * the below patterns have their values patched. * * int __seg0_text; - Always zero * int __seg0_data; - Segment offset of data of boot executable * * int __seg1_text; - Segment offset of text of first executable * int __seg1_data; - Segment offset of data of first executable * int __seg2_text; - Segment offset of text of second executable * int __seg2_data; - Segment offset of data of second executable * * int __seg9_text; - Segment offset of text of executable nine * int __seg9_data; - Segment offset of data of executable nine * * Any segment that's not an exact multiple of 16 bytes long is rounded up. * */ #include #ifdef __STDC__ #include #include #endif #include "x86_aout.h" #ifndef __OUT_OK #error "Compile error: struct exec invalid (long not 32 bit ?)" #endif unsigned long text_offt[10]; /* Locations to patch (0=don't) */ unsigned long data_offt[10]; char * input_file = ""; FILE * ofd; FILE * ifd = 0; struct exec header; main(argc, argv) int argc; char ** argv; { long image_offset, text_off; int image_id; if( argc < 3 || argc > 11 ) fatal("Usage: catimage mem.bin boot.out [a1.out] ... [a9.out]"); open_obj(argv[2]); ofd = fopen(argv[1], "w"); if( ofd == 0 ) fatal("Cannot open output file"); read_symtable(); image_offset = 0; for(image_id=0; image_id < argc-2; image_id++) { open_obj(argv[image_id+2]); printf("File %-14s seg=0x%04lx text=0x%04lx data=0x%04lx\n", input_file, (image_offset>>4), (header.a_text>>4), (header.a_total>>4)); text_off = image_offset; if( header.a_flags & A_SEP ) { copy_segment(image_offset, A_TEXTPOS(header), header.a_text); image_offset += header.a_text; image_offset = ((image_offset+15L)&-16L); copy_segment(image_offset, A_DATAPOS(header), header.a_data); } else { copy_segment(image_offset, A_TEXTPOS(header), header.a_text+header.a_data); } patch_bin(text_offt[image_id], (unsigned)(text_off>>4)); patch_bin(data_offt[image_id], (unsigned)(image_offset>>4)); image_offset += header.a_total; image_offset = ((image_offset+15L)&-16L); } if( fseek(ofd, image_offset-1, 0) < 0 ) fatal("Cannot seek to end of output"); fputc('\0', ofd); fclose(ofd); printf("Output file size %ldKb\n", ((image_offset+0x3FF)>>10)); if( ifd ) fclose(ifd); exit(0); } open_obj(fname) char * fname; { input_file = fname; if( ifd ) fclose(ifd); ifd = fopen(fname, "r"); if( ifd == 0 ) fatal("Cannot open input file"); if( fread(&header, A_MINHDR, 1, ifd) != 1 ) fatal("Incomplete executable header"); if( BADMAG(header) ) fatal("Input file has bad magic number"); } copy_segment(out_offset, in_offset, length) long out_offset, in_offset, length; { char buffer[1024]; int ssize; long bsize = length; if( fseek(ifd, in_offset, 0) < 0 ) fatal("Cannot seek to start of input segment"); if( fseek(ofd, out_offset, 0) < 0 ) fatal("Cannot seek to start of output segment"); while(bsize>0) { if( bsize > sizeof(buffer) ) ssize = sizeof(buffer); else ssize = bsize; if( (ssize=fread(buffer, 1, ssize, ifd)) <= 0 ) fatal("Error reading segment from executable"); if( fwrite(buffer, 1, ssize, ofd) != ssize ) fatal("Error writing output file"); bsize -= ssize; } } patch_bin(file_off, value) long file_off; int value; { char wbuf[4]; if( file_off > 0 ) { printf("Patch at offset 0x%05lx = %04x\n", file_off, value); wbuf[0] = value; wbuf[0] = (value>>8); if( fseek(ofd, file_off, 0) < 0 ) fatal("Cannot seek to patch binary"); if( fwrite(wbuf, 1, 2, ofd) != 2 ) fatal("Error patching output file"); } } read_symtable() { struct nlist item; int nitems; long base_off = 0; if( header.a_syms == 0 ) fatal("Input file has been stripped!"); if( fseek(ifd, A_SYMPOS(header), 0) < 0 ) fatal("Cannot seek to start of symbols"); nitems = header.a_syms; /* Foreach symbol */ while( fread(&item, sizeof(struct nlist), 1, ifd) == 1 ) { if( nitems-- <= 0 ) break; /* Match the name */ if( memcmp(item.n_name, "__seg", 5) != 0 || item.n_name[6] != '_' ) continue; /* Externals only */ if( (item.n_sclass & N_CLASS) != C_EXT ) continue; /* Data seg only */ if( (item.n_sclass & N_SECT) != N_DATA && (item.n_sclass & N_SECT) != N_BSS && (item.n_sclass & N_SECT) != N_TEXT ) continue; if( item.n_name[5] < '0' || item.n_name[5] > '9' ) continue; if( (header.a_flags & A_SEP) && (item.n_sclass & N_SECT) != N_TEXT ) base_off = header.a_text; else base_off = 0; switch( item.n_name[7] ) { case 'd': data_offt[item.n_name[5]-'0'] = base_off+item.n_value; break; case 't': text_offt[item.n_name[5]-'0'] = base_off+item.n_value; break; } #ifdef DEBUG printf("%-8.8s ", item.n_name); printf("%08lx ", item.n_value); switch(item.n_sclass & N_CLASS) { case C_NULL: printf("C_NULL "); break; case C_EXT: printf("C_EXT "); break; case C_STAT: printf("C_STAT "); break; default: printf("%-6d ", (item.n_sclass & N_CLASS)); break; } switch(item.n_sclass & N_SECT) { case N_UNDF: printf("N_UNDF "); break; case N_ABS : printf("N_ABS "); break; case N_TEXT: printf("N_TEXT "); break; case N_DATA: printf("N_DATA "); break; case N_BSS : printf("N_BSS "); break; case N_COMM: printf("N_COMM "); break; } printf("\n"); #endif } } fatal(str) char * str; { fprintf(stderr, "catimage:%s: %s\n", input_file, str); exit(2); } dev86-0.16.21/ld/config.h000066400000000000000000000020101231050321700146150ustar00rootroot00000000000000/* config.h - configuration for linker */ /* Copyright (C) 1994 Bruce Evans */ /* one of these target processors must be defined */ #undef I8086 /* Intel 8086 */ #define I80386 /* Intel 80386 */ #undef MC6809 /* Motorola 6809 */ /* one of these target operating systems must be defined */ #undef EDOS /* generate EDOS executable */ #define MINIX /* generate Minix executable */ /* these may need to be defined to suit the source processor */ #undef HOST_8BIT /* enable some 8-bit optimizations */ #ifndef __AS386_16__ #define S_ALIGNMENT 4 /* source memory alignment, power of 2 */ /* don't use for 8 bit processors */ /* don't use even for 80386 - overhead for */ /* alignment cancels improved access */ #endif /* Any machine can use long offsets but i386 needs them */ #ifdef I80386 #define LONG_OFFSETS #endif /* these must be defined to suit the source libraries */ #define CREAT_PERMS 0666 /* permissions for creat() */ #define EXEC_PERMS 0111 /* extra permissions to set for executable */ dev86-0.16.21/ld/const.h000066400000000000000000000003571231050321700145120ustar00rootroot00000000000000/* const.h - constants for linker */ /* Copyright (C) 1994 Bruce Evans */ #define FALSE 0 #define NUL_PTR ((void*)0) #define TRUE 1 #define EXTERN extern #define FORWARD static #define PRIVATE static #define PUBLIC #include "config.h" dev86-0.16.21/ld/dumps.c000066400000000000000000000041121231050321700145000ustar00rootroot00000000000000/* dumps.c - print data about symbols and modules for linker */ /* Copyright (C) 1994 Bruce Evans */ #include "syshead.h" #include "const.h" #include "obj.h" #include "type.h" #include "globvar.h" /* print list of modules and whether they are loaded */ PUBLIC void dumpmods() { struct modstruct *modptr; char *s, *d; int i; for (modptr = modfirst; modptr != NUL_PTR; modptr = modptr->modnext) { for(s=d=modptr->filename; *s ; s++) if( *s == '/' ) d=s+1; if( memcmp(d, "libc", 4) == 0 && !modptr->loadflag ) continue; putstr(modptr->modname); i = strlen(modptr->modname); while(i<16) putbyte(' '),i++; putbyte( modptr->loadflag ? '+':'-' ); putstr(d); if( modptr->archentry ) { putbyte('('); putstr(modptr->archentry); putbyte(')'); } putbyte('\n'); } } /* print data about symbols (in loaded modules only) */ PUBLIC void dumpsyms() { flags_t flags; struct modstruct *modptr; struct symstruct **symparray; struct symstruct *symptr; char uflag; for (modptr = modfirst; modptr != NUL_PTR; modptr = modptr->modnext) if (modptr->loadflag) { for (symparray = modptr->symparray; (symptr = *symparray) != NUL_PTR; ++symparray) if (symptr->modptr == modptr) { uflag = FALSE; if (((flags = symptr->flags) & (C_MASK | I_MASK)) == I_MASK) uflag = TRUE; putbstr(20, uflag ? "" : modptr->modname); putstr(" "); putbstr(20, symptr->name); putstr(" "); putbyte(hexdigit[flags & SEGM_MASK]); putstr(" "); if (uflag) putstr(" "); else #ifdef LONG_OFFSETS put08lx(symptr->value); #else put08x(symptr->value); #endif if( flags & (E_MASK|C_MASK) ) putstr(flags & A_MASK ? " A" : " R"); else putstr(flags & A_MASK ? " a" : " r"); if (uflag) putstr(" U"); if (flags & C_MASK) putstr(" C"); if (flags & N_MASK) putstr(" N"); putbyte('\n'); } } putstr("Total memory used: "); #ifdef LONG_OFFSETS put08lx(memory_used()); #else put08x(memory_used()); #endif putbyte('\n'); } dev86-0.16.21/ld/globvar.h000066400000000000000000000016271231050321700150210ustar00rootroot00000000000000/* globvar.h - global variables for linker */ /* Copyright (C) 1994 Bruce Evans */ #ifndef EXTERN #define EXTERN #endif EXTERN unsigned errcount; /* count of errors */ EXTERN struct entrylist *entryfirst; /* first on list of entry symbols */ EXTERN struct modstruct *modfirst; /* data for 1st module */ EXTERN struct redlist *redfirst; /* first on list of redefined symbols */ /* K&R _explicitly_ says extern followed by public is OK */ extern char hexdigit[]; /* constant */ extern int headerless; /* Don't output header on exe */ #ifndef VERY_SMALL_MEMORY extern int v7; /* Generate an UNIX v7 a.out header */ #endif #ifndef MSDOS extern int cpm86; /* Generate CP/M-86 CMD header */ #endif extern bin_off_t text_base_value; /* Base address of text seg */ extern bin_off_t data_base_value; /* Base or alignment of data seg */ extern bin_off_t heap_top_value; /* Minimum 'total' value in x86 header */ dev86-0.16.21/ld/io.c000066400000000000000000000300531231050321700137620ustar00rootroot00000000000000/* io.c - input/output and error modules for linker */ /* Copyright (C) 1994 Bruce Evans */ #include "syshead.h" #include "const.h" #include "type.h" #include "globvar.h" #include "version.h" #define DRELBUFSIZE 3072 #define ERR (-1) #define ERRBUFSIZE 1024 #define INBUFSIZE 1024 #define OUTBUFSIZE 2048 #define TRELBUFSIZE 1024 #ifdef REL_OUTPUT PRIVATE char *drelbuf; /* extra output buffer for data relocations */ PRIVATE char *drelbufptr; /* data relocation output buffer ptr */ PRIVATE char *drelbuftop; /* data relocation output buffer top */ #endif PRIVATE char *errbuf; /* error buffer (actually uses STDOUT) */ PRIVATE char *errbufptr; /* error buffer ptr */ PRIVATE char *errbuftop; /* error buffer top */ PRIVATE int errfil = STDOUT_FILENO; PRIVATE char *inbuf; /* input buffer */ PRIVATE char *inbufend; /* input buffer top */ PRIVATE char *inbufptr; /* end of input in input buffer */ PRIVATE int infd; /* input file descriptor */ PRIVATE char *inputname; /* name of current input file */ PRIVATE char *outbuf; /* output buffer */ PRIVATE char *outbufptr; /* output buffer ptr */ PRIVATE char *outbuftop; /* output buffer top */ PRIVATE int outfd; /* output file descriptor */ PRIVATE mode_t outputperms; /* permissions of output file */ PRIVATE char *outputname; /* name of output file */ PRIVATE char *refname; /* name of program for error reference */ #ifdef REL_OUTPUT PRIVATE char *trelbuf; /* extra output buffer for text relocations */ PRIVATE char *trelbufptr; /* text relocation output buffer ptr */ PRIVATE char *trelbuftop; /* text relocation output buffer top */ PRIVATE int trelfd; /* text relocation output file descriptor */ #endif PRIVATE unsigned warncount; /* count of warnings */ #ifdef MSDOS #define off_t long /* NOT a typedef */ #endif FORWARD void errexit P((char *message)); FORWARD void flushout P((void)); #ifdef REL_OUTPUT FORWARD void flushtrel P((void)); #endif FORWARD void outhexdigs P((bin_off_t num)); FORWARD void outputerror P((char *message)); FORWARD void put04x P((unsigned num)); FORWARD void putstrn P((char *message)); FORWARD void refer P((void)); FORWARD void stderr_out P((void)); PUBLIC void ioinit(progname) char *progname; { infd = ERR; if (*progname) refname = progname; /* name must be static (is argv[0]) */ else refname = "link"; for(progname=refname; *progname; progname++) if(*progname=='/') refname=progname+1; #ifdef REL_OUTPUT drelbuf = malloc(DRELBUFSIZE); drelbuftop = drelbuf + DRELBUFSIZE; #endif errbuf = malloc(ERRBUFSIZE); errbufptr = errbuf; errbuftop = errbuf + ERRBUFSIZE; inbuf = malloc(INBUFSIZE); outbuf = malloc(OUTBUFSIZE);/* outbuf invalid if this fails but then */ /* will not be used - tableinit() aborts */ outbuftop = outbuf + OUTBUFSIZE; #ifdef REL_OUTPUT trelbuf = malloc(TRELBUFSIZE); trelbuftop = trelbuf + TRELBUFSIZE; #endif } PUBLIC void closein() { if (infd != ERR && close(infd) < 0) inputerror("cannot close"); infd = ERR; } PUBLIC void closeout() { #ifdef REL_OUTPUT unsigned nbytes; #endif flushout(); #ifdef REL_OUTPUT flushtrel(); nbytes = drelbufptr - drelbuf; if (write(trelfd, drelbuf, nbytes) != nbytes) outputerror("cannot write"); #endif if (close(outfd) == ERR) outputerror("cannot close"); #ifdef REL_OUTPUT if (close(trelfd) == ERR) outputerror("cannot close"); #endif } PUBLIC void errtrace(name, level) char *name; int level; { while (level-- > 0) putbyte(' '); putstrn(name); } PUBLIC void executable() { if (errcount) unlink(outputname); #ifndef MSDOS else chmod(outputname, outputperms); #endif } PUBLIC void flusherr() { if( errbufptr != errbuf ) write(errfil, errbuf, (unsigned) (errbufptr - errbuf)); errbufptr = errbuf; } PRIVATE void stderr_out() { if( errfil != STDERR_FILENO ) { flusherr(); errfil = STDERR_FILENO; } } PRIVATE void flushout() { unsigned nbytes; nbytes = outbufptr - outbuf; if (write(outfd, outbuf, nbytes) != nbytes) outputerror("cannot write"); outbufptr = outbuf; } #ifdef REL_OUTPUT PRIVATE void flushtrel() { unsigned nbytes; nbytes = trelbufptr - trelbuf; if (write(trelfd, trelbuf, nbytes) != nbytes) outputerror("cannot write"); trelbufptr = trelbuf; } #endif PUBLIC void openin(filename) char *filename; { #if 0 /* XXX - this probably won't work with constructed lib names? */ if (infd == ERR || strcmp(inputname, filename) != 0) #endif { closein(); inputname = filename; /* this relies on filename being static */ #ifdef O_BINARY if ((infd = open(filename, O_BINARY|O_RDONLY)) < 0) #else if ((infd = open(filename, O_RDONLY)) < 0) #endif inputerror("cannot open"); inbufptr = inbufend = inbuf; } } PUBLIC void openout(filename) char *filename; { mode_t oldmask; outputname = filename; #ifdef O_BINARY if ((outfd = open(filename, O_BINARY|O_WRONLY|O_CREAT|O_TRUNC, CREAT_PERMS)) == ERR) #else if ((outfd = creat(filename, CREAT_PERMS)) == ERR) #endif outputerror("cannot open"); #ifndef MSDOS /* Can't do this on MSDOS; it upsets share.exe */ oldmask = umask(0); umask(oldmask); outputperms = ((CREAT_PERMS | EXEC_PERMS) & ~oldmask); chmod(filename, outputperms & ~EXEC_PERMS); #endif #ifdef REL_OUTPUT drelbufptr = drelbuf; #endif outbufptr = outbuf; #ifdef REL_OUTPUT #ifdef O_BINARY if ((trelfd = open(filename, O_BINARY|O_WRONLY, CREAT_PERMS)) == ERR) #else if ((trelfd = open(filename, O_WRONLY, CREAT_PERMS)) == ERR) #endif outputerror("cannot reopen"); trelbufptr = trelbuf; #endif } PRIVATE void outhexdigs(num) register bin_off_t num; { if (num >= 0x10) { outhexdigs(num / 0x10); num %= 0x10; } putbyte(hexdigit[num]); } PRIVATE void put04x(num) register unsigned num; { putbyte(hexdigit[num / 0x1000]); putbyte(hexdigit[(num / 0x100) & 0x0F]); putbyte(hexdigit[(num / 0x10) & 0x0F]); putbyte(hexdigit[num & 0x0F]); } #ifdef LONG_OFFSETS PUBLIC void put08lx(num) register bin_off_t num; { put04x(num / 0x10000); put04x(num % 0x10000); } #else /* not LONG_OFFSETS */ PUBLIC void put08x(num) register bin_off_t num; { putstr("0000"); put04x(num); } #endif /* not LONG_OFFSETS */ PUBLIC void putbstr(width, str) unsigned width; char *str; { unsigned length; for (length = strlen(str); length < width; ++length) putbyte(' '); putstr(str); } PUBLIC void putbyte(ch) int ch; { register char *ebuf; ebuf = errbufptr; if (ebuf >= errbuftop) { flusherr(); ebuf = errbufptr; } *ebuf++ = ch; errbufptr = ebuf; } PUBLIC void putstr(message) char *message; { while (*message != 0) putbyte(*message++); } PRIVATE void putstrn(message) char *message; { putstr(message); putbyte('\n'); flusherr(); errfil = STDOUT_FILENO; } PUBLIC int readchar() { int ch; register char *ibuf; int nread; ibuf = inbufptr; if (ibuf >= inbufend) { ibuf = inbufptr = inbuf; nread = read(infd, ibuf, INBUFSIZE); if (nread <= 0) { inbufend = ibuf; return ERR; } inbufend = ibuf + nread; } ch = (unsigned char) *ibuf++; inbufptr = ibuf; return ch; } PUBLIC void readin(buf, count) char *buf; unsigned count; { int ch; while (count--) { if ((ch = readchar()) < 0) prematureeof(); *buf++ = ch; } } PUBLIC bool_pt readineofok(buf, count) char *buf; unsigned count; { int ch; while (count--) { if ((ch = readchar()) < 0) return TRUE; *buf++ = ch; } return FALSE; } PUBLIC void seekin(offset) unsigned long offset; { inbufptr = inbufend = inbuf; if (lseek(infd, (off_t) offset, SEEK_SET) != offset) prematureeof(); } PUBLIC void seekout(offset) unsigned long offset; { flushout(); if (lseek(outfd, (off_t) offset, SEEK_SET) != offset) outputerror("cannot seek in"); } #ifdef REL_OUTPUT PUBLIC void seektrel(offset) unsigned long offset; { flushtrel(); if (lseek(trelfd, (off_t) offset, SEEK_SET) != offset) outputerror("cannot seek in"); } #endif PUBLIC void writechar(ch) int ch; { register char *obuf; obuf = outbufptr; if (obuf >= outbuftop) { flushout(); obuf = outbufptr; } *obuf++ = ch; outbufptr = obuf; } #ifdef REL_OUTPUT PUBLIC void writedrel(buf, count) register char *buf; unsigned count; { register char *rbuf; rbuf = drelbufptr; while (count--) { if (rbuf >= drelbuftop) inputerror("data relocation buffer full while processing"); *rbuf++ = *buf++; } drelbufptr = rbuf; } #endif PUBLIC void writeout(buf, count) register char *buf; unsigned count; { register char *obuf; obuf = outbufptr; while (count--) { if (obuf >= outbuftop) { outbufptr = obuf; flushout(); obuf = outbufptr; } *obuf++ = *buf++; } outbufptr = obuf; } #ifdef REL_OUTPUT PUBLIC void writetrel(buf, count) register char *buf; unsigned count; { register char *rbuf; rbuf = trelbufptr; while (count--) { if (rbuf >= trelbuftop) { trelbufptr = rbuf; flushtrel(); rbuf = trelbufptr; } *rbuf++ = *buf++; } trelbufptr = rbuf; } #endif /* error module */ PRIVATE void errexit(message) char *message; { putstrn(message); exit(2); } PUBLIC void fatalerror(message) char *message; { refer(); errexit(message); } PUBLIC void inputerror(message) char *message; { refer(); putstr(message); putstr(" input file "); errexit(inputname); } PUBLIC void input1error(message) char *message; { refer(); putstr(inputname); errexit(message); } PRIVATE void outputerror(message) char *message; { refer(); putstr(message); putstr(" output file "); errexit(outputname); } PUBLIC void outofmemory() { inputerror("out of memory while processing"); } PUBLIC void prematureeof() { inputerror("premature end of"); } PUBLIC void redefined(name, message, archentry, deffilename, defarchentry) char *name; char *message; char *archentry; char *deffilename; char *defarchentry; { ++warncount; refer(); putstr("warning: "); putstr(name); putstr(" redefined"); putstr(message); putstr(" in file "); putstr(inputname); if (archentry != NUL_PTR) { putbyte('('); putstr(archentry); putbyte(')'); } putstr("; using definition in "); putstr(deffilename); if (defarchentry != NUL_PTR) { putbyte('('); putstr(defarchentry); putbyte(')'); } putstrn(""); } PUBLIC void interseg(fname, aname, name) char *fname, *aname, *name; { ++errcount; refer(); putstr("error in "); putstr(fname); if( aname ) { putstr("("); putstr(aname); putstr(")"); } putstr(" intersegment jump to "); if( name ) putstr(name); else putstr("same file"); putstrn(""); } PRIVATE void refer() { stderr_out(); putstr(refname); putstr(": "); } PUBLIC void reserved(name) char *name; { ++errcount; stderr_out(); putstr("incorrect use of reserved symbol: "); putstrn(name); } PUBLIC void size_error(seg, count, size) int seg; bin_off_t count; bin_off_t size; { refer(); putstr("seg "); outhexdigs((bin_off_t) seg); putstr(" has wrong size "); outhexdigs(count); putstr(", supposed to be "); outhexdigs(size); errexit(""); } PUBLIC void undefined(name) char *name; { ++errcount; stderr_out(); putstr("undefined symbol: "); putstrn(name); } PUBLIC void usage() { stderr_out(); putstr("usage: "); putstr(refname); #ifdef REL_OUTPUT errexit("\ [-03NMdimrstz[-]] [-llib_extension] [-o outfile] [-Ccrtfile]\n\ [-Llibdir] [-Olibfile] [-Ttextaddr] [-Ddataaddr] [-Hheapsize] infile..."); #else errexit("\ [-03NMdimstz[-]] [-llib_extension] [-o outfile] [-Ccrtfile]\n\ [-Llibdir] [-Olibfile] [-Ttextaddr] [-Ddataaddr] [-Hheapsize] infile..."); #endif } PUBLIC void version_msg() { stderr_out(); #ifdef VERSION putstr("ld86 version: "); errexit(VERSION); #else errexit("ld86 version unknown"); #endif } PUBLIC void use_error(message) char *message; { refer(); putstrn(message); usage(); } dev86-0.16.21/ld/ld.c000066400000000000000000000150441231050321700137550ustar00rootroot00000000000000/* ld.c - linker for Introl format (6809 C) object files 6809/8086/80386 */ /* Copyright (C) 1994 Bruce Evans */ #include "syshead.h" #include "const.h" #include "byteord.h" #include "type.h" #include "globvar.h" #define MAX_LIBS (NR_STDLIBS + 5) #ifdef MC6809 #define NR_STDLIBS 1 #else #define NR_STDLIBS 0 #endif PUBLIC bin_off_t text_base_value = 0; /* XXX */ PUBLIC bin_off_t data_base_value = 0; /* XXX */ PUBLIC bin_off_t heap_top_value = 0; /* XXX */ PUBLIC int headerless = 0; #ifndef VERY_SMALL_MEMORY PUBLIC int v7 = 0; #endif #ifndef MSDOS PUBLIC int cpm86 = 0; #endif PUBLIC char hexdigit[] = "0123456789abcdef"; PRIVATE bool_t flag[128]; PRIVATE char *libs[MAX_LIBS] = { #ifdef MC6809 "/usr/local/lib/m09/", #endif 0 }; PRIVATE int lastlib = NR_STDLIBS; FORWARD char *buildname P((char *pre, char *mid, char *suf)); FORWARD char *expandlib P((char *fn)); PRIVATE char *buildname(pre, mid, suf) char *pre; char *mid; char *suf; { char *name; name = ourmalloc(strlen(pre) + strlen(mid) + strlen(suf) + 1); strcpy(name, pre); strcat(name, mid); strcat(name, suf); return name; } PRIVATE char *expandlib(fn) char *fn; { char *path, *s; int i; for (i = lastlib - 1; i >= 0; --i) { path = ourmalloc(strlen(libs[i]) + strlen(fn) + 2); strcpy(path, libs[i]); s = path + strlen(path); if (s!=path && s[-1] != '/') strcat(path, "/"); strcat(path, fn); if (access(path, R_OK) == 0) return path; ourfree(path); } return NUL_PTR; } PUBLIC int main(argc, argv) int argc; char **argv; { register char *arg; int argn; static char crtprefix[] = "crt"; static char crtsuffix[] = ".o"; char *infilename; static char libprefix[] = "lib"; static char libsuffix[] = ".a"; char *outfilename; char *tfn; int icount=0; ioinit(argv[0]); objinit(); syminit(); typeconv_init(INT_BIG_ENDIAN, LONG_BIG_ENDIAN); #ifndef MC6809 flag['3'] = sizeof(char *) >= 4; #endif outfilename = NUL_PTR; for (argn = 1; argn < argc; ++argn) { arg = argv[argn]; if (*arg != '-') { readsyms(arg, flag['t']); icount++; } else switch (arg[1]) { case 'v': version_msg(); case 'r': /* relocatable output */ case 't': /* trace modules linked */ if (icount > 0) usage(); #ifdef REL_OUTPUT case 'B': /* Broken -r for dosemu. */ #endif case '0': /* use 16-bit libraries */ case '3': /* use 32-bit libraries */ case 'M': /* print symbols linked */ case 'i': /* separate I & D output */ case 'm': /* print modules linked */ case 's': /* strip symbols */ case 'z': /* unmapped zero page */ case 'N': /* Native format a.out */ case 'd': /* Make a headerless outfile */ #ifndef MSDOS case 'c': /* Write header in CP/M-86 format */ #endif case 'y': /* Use a newer symbol table */ #ifndef VERY_SMALL_MEMORY case '7': /* Produce a UNIX v7 a.out header */ #endif if (arg[2] == 0) flag[(int) arg[1]] = TRUE; else if (arg[2] == '-' && arg[3] == 0) flag[(int) arg[1]] = FALSE; else usage(); if (arg[1] == '0') /* flag 0 is negative logic flag 3 */ flag['3'] = !flag['0']; break; case 'C': /* startfile name */ tfn = buildname(crtprefix, arg + 2, crtsuffix); if ((infilename = expandlib(tfn)) == NUL_PTR) infilename = tfn; /*fatalerror(tfn); * XXX - need to describe failure */ readsyms(infilename, flag['t']); icount++; break; case 'L': /* library path */ if (lastlib < MAX_LIBS) libs[lastlib++] = arg + 2; else fatalerror("too many library paths"); break; case 'O': /* library file name */ if ((infilename = expandlib(arg + 2)) == NUL_PTR) infilename = arg+2; /* fatalerror(arg); * XXX */ readsyms(infilename, flag['t']); break; case 'T': /* text base address */ if (arg[2] == 0 && ++argn >= argc) usage(); errno = 0; if (arg[2] == 0 ) text_base_value = strtoul(argv[argn], (char **)0, 16); else text_base_value = strtoul(arg+2, (char **)0, 16); if (errno != 0) use_error("invalid text address"); break; case 'D': /* data base address */ if (arg[2] == 0 && ++argn >= argc) usage(); errno = 0; if (arg[2] == 0 ) data_base_value = strtoul(argv[argn], (char **)0, 16); else data_base_value = strtoul(arg+2, (char **)0, 16); if (errno != 0) use_error("invalid data address"); break; case 'H': /* heap top address */ if (arg[2] == 0 && ++argn >= argc) usage(); errno = 0; if (arg[2] == 0 ) heap_top_value = strtoul(argv[argn], (char **)0, 16); else heap_top_value = strtoul(arg+2, (char **)0, 16); if (errno != 0) use_error("invalid heap top"); break; case 'l': /* library name */ tfn = buildname(libprefix, arg + 2, libsuffix); if ((infilename = expandlib(tfn)) == NUL_PTR) infilename = tfn; /* fatalerror(tfn); * XXX */ readsyms(infilename, flag['t']); icount+=2; break; case 'o': /* output file name */ if (arg[2] != 0 || ++argn >= argc || outfilename != NUL_PTR) usage(); outfilename = argv[argn]; break; default: usage(); } } if(icount==0) usage(); #ifdef BUGCOMPAT if( icount==1 && ( flag['r'] && !flag['N'] ) ) { flag['r'] = 0; flag['B'] = 1; } #endif #ifdef REL_OUTPUT #ifndef MSDOS if( flag['r'] && !flag['N'] ) { /* Do a relocatable link -- actually fake it with 'ar.c' */ ld86r(argc, argv); } #endif #endif #ifdef MSDOS /* MSDOS Native is special, we make a COM file */ if( flag['N'] ) { flag['N'] = 0; flag['d'] = 1; text_base_value = 0x100; } #endif /* Headerless executables can't use symbols. */ headerless = flag['d']; if( headerless ) flag['s'] = 1; #ifndef VERY_SMALL_MEMORY /* UNIX seventh edition executables */ v7 = flag['7']; #endif #ifndef MSDOS /* CP/M-86 executables can't use symbols. */ cpm86 = flag['c']; if ( cpm86 ) flag['s'] = 1; #endif linksyms(flag['r'] | flag['B']); if (outfilename == NUL_PTR) outfilename = "a.out"; #ifndef MSDOS if( flag['N'] ) writebin(outfilename, flag['i'], flag['3'], flag['s'], flag['z'] & flag['3']); else #endif if( flag['B'] ) write_dosemu(outfilename, flag['i'], flag['3'], flag['s'], flag['z'] & flag['3']); else write_elks(outfilename, flag['i'], flag['3'], flag['s'], flag['z'], flag['y']); if (flag['m']) dumpmods(); if (flag['M']) dumpsyms(); flusherr(); return errcount ? 1 : 0; } dev86-0.16.21/ld/ld86r.c000066400000000000000000000045271231050321700143210ustar00rootroot00000000000000#include #include #include #include #ifdef __STDC__ #include #include #else #include #endif #define ARMAG "!\n" #define SARMAG 8 #define ARFMAG "`\n" struct ar_hdr { char ar_name[16], ar_date[12], ar_uid[6], ar_gid[6], ar_mode[8], ar_size[10], ar_fmag[2]; } arbuf; void fatal(char * str) { fprintf(stderr, "%s\n", str); exit(2); } void main(int argc, char ** argv) { char buf[128]; FILE * fd, * ifd; struct stat st; int ar, libarg=0, need_o = 0, got_o = 0; for(ar=1; ar 1 || need_o > got_o ) fatal("Err, what's the output gonna be called?"); if( (fd =fopen(argv[libarg], "wb")) == 0 ) fatal("Cannot open archive"); if( fwrite(ARMAG, 1, SARMAG, fd) != SARMAG) fatal("Cannot write magic"); for(ar=1; armodnext != NUL_PTR) fatalerror("relocatable output only works for one input file"); for (modptr = modfirst; modptr != NUL_PTR; modptr = modptr->modnext) modptr->loadflag = TRUE; return; } #endif if ((symptr = findsym("_start")) != NUL_PTR || (symptr = findsym("_main")) != NUL_PTR) entrysym(symptr); do { if ((elptr = entryfirst) == NUL_PTR) fatalerror("no start symbol"); for (modptr = modfirst; modptr != NUL_PTR; modptr = modptr->modnext) modptr->loadflag = FALSE; for (; elptr != NUL_PTR; elptr = elptr->elnext) linkrefs(elptr->elsymptr->modptr); if ((symptr = findsym("start")) != NUL_PTR) linkrefs(symptr->modptr); needlink = FALSE; { struct redlist *prlptr = 0; struct redlist *rlptr; for (rlptr = redfirst; rlptr != NUL_PTR; rlptr = (prlptr = rlptr)->rlnext) if (rlptr->rlmodptr->loadflag && rlptr->rlmodptr->class > rlptr->rlsymptr->modptr->class) { rlptr->rlsymptr->modptr = rlptr->rlmodptr; rlptr->rlsymptr->value = rlptr->rlvalue; if (rlptr == redfirst) redfirst = rlptr->rlnext; else prlptr->rlnext = rlptr->rlnext; needlink = TRUE; } } } while (needlink); } PRIVATE void linkrefs(modptr) struct modstruct *modptr; { register struct symstruct **symparray; register struct symstruct *symptr; modptr->loadflag = TRUE; for (symparray = modptr->symparray; (symptr = *symparray) != NUL_PTR; ++symparray) if (symptr->modptr->loadflag == FALSE) linkrefs(symptr->modptr); } dev86-0.16.21/ld/mkar.c000066400000000000000000000044131231050321700143060ustar00rootroot00000000000000 #include #include #include #include #ifdef __STDC__ #include #include #else #include #endif #include "type.h" #include "ar.h" static struct ar_hdr arbuf; #ifdef __STDC__ void ld86r(int argc, char ** argv) #else ld86r(argc, argv) int argc; char ** argv; #endif { char buf[128]; FILE * fd, * ifd; struct stat st; int ar, libarg=0, need_o = 0, got_o = 0; for(ar=1; ar 1 || need_o > got_o ) fatalerror("-o option required for -r"); if( (fd =fopen(argv[libarg], "wb")) == 0 ) fatalerror("Cannot open archive"); if( fwrite(ARMAG, 1, SARMAG, fd) != SARMAG) fatalerror("Cannot write magic"); for(ar=1; ar #ifdef __STDC__ #include #include #endif #include "x86_aout.h" #ifndef __OUT_OK main() { fprintf(stderr, "Compile error: struct exec invalid\n"); exit(1); } #else FILE * ifd; struct exec header; main(argc, argv) int argc; char ** argv; { FILE * ofd; if( argc != 5 ) fatal("Usage: objchop a.out text.bin data.bin sizes.asm"); ifd = fopen(argv[1], "r"); if( ifd == 0 ) fatal("Cannot open input file"); if( fread(&header, A_MINHDR, 1, ifd) != 1 ) fatal("Incomplete executable header"); if( BADMAG(header) ) fatal("Input file has bad magic number"); if( fseek(ifd, A_TEXTPOS(header), 0) < 0 ) fatal("Cannot seek to start of text"); write_file(argv[2], header.a_text); if( fseek(ifd, A_DATAPOS(header), 0) < 0 ) fatal("Cannot seek to start of data"); write_file(argv[3], header.a_data); ofd = fopen(argv[4], "w"); if( ofd == 0 ) fatal("Cannot open output file"); fprintf(ofd, "TEXT_SIZE=%ld\nDATA_SIZE=%ld\nBSS_SIZE=%ld\nALLOC_SIZE=%ld\n", header.a_text, header.a_data, header.a_bss, header.a_total); fclose(ofd); exit(0); } write_file(fname, bsize) char * fname; long bsize; { char buffer[1024]; int ssize; FILE * ofd; ofd = fopen(fname, "w"); if( ofd == 0 ) fatal("Cannot open output file"); while(bsize>0) { if( bsize > sizeof(buffer) ) ssize = sizeof(buffer); else ssize = bsize; if( (ssize=fread(buffer, 1, ssize, ifd)) <= 0 ) fatal("Error reading segment from executable"); if( fwrite(buffer, 1, ssize, ofd) != ssize ) fatal("Error writing output file"); bsize -= ssize; } fclose(ofd); } fatal(str) char * str; { fprintf(stderr, "objchop: %s\n", str); exit(2); } #endif dev86-0.16.21/ld/objdump86.c000066400000000000000000000514701231050321700151770ustar00rootroot00000000000000/* * This is a combination of three tools for decoding information from * Dev86/ELKS object files and executables. * * This executable can be given the names: * * objdump86: Dumps detailed information about a binary file. * size86: Summary sizes of the data in a binary file. * nm86: The symbol table of the binary file. * * None of these programs have any options. * This may be a minor problem with nm86. * * Copyright (c) 1999 by Greg Haerr * Added archive file reading capabilties */ #include #ifdef __STDC__ #include #else #include #endif #include #include "const.h" #include "ar.h" #include "obj.h" FILE * ifd; char * ifname; #ifdef __STDC__ #define _(x) x #else #define _(x) () #endif long get_long _((void)); long get_sized _((int sz)); unsigned int get_word _((void)); int get_byte _((void)); int main _((int argc, char**argv)); void do_file _((char * fname)); long read_arheader _((char *archentry)); void do_module _((char * fname, char *archive)); int error _((char * str)); int read_objheader _((void)); int read_sectheader _((void)); int read_syms _((void)); void disp_sectheader _((void)); int disp_syms _((void)); void read_databytes _((void)); void hex_output _((int ch)); void fetch_aout_hdr _((void)); void dump_aout _((void)); void size_aout _((void)); void nm_aout _((void)); #ifndef VERY_SMALL_MEMORY void fetch_v7_hdr _((void)); void dump_v7 _((void)); void size_v7 _((void)); #endif int obj_ver; int sections; long segsizes[16]; long textoff; long textlen; long str_off; long str_len; long filepos; int num_syms; long code_bytes; char ** symnames; char * strtab; struct { unsigned int nameoff, symtype; long offset; } *symtab; int display_mode = 0; int multiple_files = 0; int byte_order = 0; int opt_o; long size_text, size_data, size_bss; long tot_size_text=0, tot_size_data=0, tot_size_bss=0; int main(argc, argv) int argc; char ** argv; { int ar; char * p; ifd = stdin; /* In Libc6 stdin is weird */ p = strrchr(argv[0], '/'); if(p) p++; else p=argv[0]; if( p[0] == 's' ) display_mode = 1; if( p[0] == 'n' ) display_mode = 2; multiple_files = 0; for(ar=1; ar1); if( display_mode == 1 ) printf("text\tdata\tbss\tdec\thex\tfilename\n"); for(ar=1; ar 0) { filepos += sizeof(struct ar_hdr); magic = get_word(); if(magic == 0x86A3) { /* OMAGIC*/ fseek(ifd, filepos, 0); do_module(archentry, fname); } else if(magic == 0x3C21 ) /* "!<" */ filelength = SARMAG; filepos += ld_roundup(filelength, 2, long); fseek(ifd, filepos, 0); } } else { fseek(ifd, 0L, 0); do_module(fname, NULL); } fclose(ifd); } /* read archive header and return length */ long read_arheader(archentry) char *archentry; { char * endptr; struct ar_hdr arheader; if(fread((char *)&arheader, sizeof(arheader), 1, ifd) != 1) return 0; strncpy(archentry, arheader.ar_name, sizeof(arheader.ar_name)); archentry[sizeof(arheader.ar_name)] = 0; endptr = archentry + sizeof(arheader.ar_name); do { *endptr-- = 0; } while(endptr > archentry && (*endptr == ' ' || *endptr == '/')); return strtoul(arheader.ar_size, (char **)NULL, 0); } void do_module(fname, archive) char * fname; char * archive; { int modno, i; size_text = size_data = size_bss = 0; byte_order = 0; if( !display_mode ) { if(archive) printf("ARCHIVEFILE '%s'\n", archive); printf("OBJECTFILE '%s'\n", fname); } switch( read_objheader() ) { case 0: /* as86 object file */ for(modno=1; modno<=sections; modno++) { if( modno != 1 && !display_mode ) printf("OBJECTSECTION %d\n", modno); if( read_sectheader() < 0 ) break; /* segments 0, 4-E are text, 1-3 are data*/ for(i=0; i<16; i++) { if(i < 1 || i > 4) size_text += segsizes[i]; else size_data += segsizes[i]; } if( read_syms() < 0 ) break; strtab = malloc((unsigned int)str_len+1); if( strtab == 0 ) { error("Out of memory"); break; } str_off = ftell(ifd); fread(strtab, 1, (unsigned int)str_len, ifd); disp_sectheader(); disp_syms(); if( display_mode == 0 ) printf("text\tdata\tbss\tdec\thex\tfilename\n"); if( display_mode != 2 ) { printf("%ld\t%ld\t%ld\t%ld\t%lx\t", size_text, size_data, size_bss, size_text+ size_data+ size_bss, size_text+ size_data+ size_bss); if(archive) printf("%s(%s)\n", archive, fname); else printf("%s\n", fname); tot_size_text += size_text; tot_size_data += size_data; tot_size_bss += size_bss; } if( sections == 1 && display_mode != 0 ) break; read_databytes(); } break; case 1: /* ELKS executable */ fseek(ifd, 0L, 0); fetch_aout_hdr(); switch(display_mode) { case 0: dump_aout(); break; case 1: size_aout(); break; case 2: nm_aout(); break; } break; #ifndef VERY_SMALL_MEMORY case 2: /* V7 executable */ fseek(ifd, 0L, 0); fetch_v7_hdr(); switch(display_mode) { case 0: dump_v7(); break; case 1: size_v7(); break; case 2: error("Symbol table not supported for v7"); exit(1); break; } break; #endif } if( strtab ) free(strtab); if( symnames ) free(symnames); strtab = 0; symnames = 0; } int error(str) char * str; { switch( display_mode ) { case 1: fprintf(stderr, "size: %s: %s\n", ifname, str); break; case 2: fprintf(stderr, "nm: %s: %s\n", ifname, str); break; default: printf("Error: %s\n", str); break; } return -1; } int read_objheader() { unsigned char buf[5]; if( fread(buf, 1, 5, ifd) != 5 ) return error("Cannot read object header"); if( buf[0] != 0xA3 || buf[1] != 0x86 ) { if( buf[0] == 1 && buf[1] == 3 ) { sections = 1; return 1; } #ifndef VERY_SMALL_MEMORY if( buf[1] == 1 ) /* 04xx octal */ { sections = 1; return 2; } #endif return error("Bad magic number"); } if( (unsigned char)(buf[0] + buf[1] + buf[2] + buf[3]) != buf[4] ) return error("Bad header checksum"); sections= buf[2]+256*buf[3]; return 0; } int read_sectheader() { long ssenc; int i; textoff = get_long(); /* Offset of bytecode in file */ textlen = get_long(); /* Length of text+data (no bss) in memory */ str_len = get_word(); /* Length of string table in file */ obj_ver = get_word(); /* 0.0 */ (void)get_long(); /* Ignore fives */ ssenc = get_long(); /* Sixteen segment size sizes */ for(i=0; i<16; i++) { int ss; ss = (i^3); ss = ((ssenc>>(2*(15-ss)))&3); segsizes[i] = get_sized(ss); } num_syms = get_word(); /* Number of symbol codes */ return 0; } void disp_sectheader() { int i; if( display_mode ) return; printf("MODULE '%s'\n", strtab); printf("BYTEPOS %08lx\n", textoff); printf("BINLEN %08lx\n", textlen); printf("STRINGS %04lx +%04lx\n", str_off, str_len); printf("VERSION %d.%d\n", obj_ver/256, obj_ver%256); for(i=0; i<16; i++) if( segsizes[i] ) printf("SEG%x %08lx\n", i, segsizes[i]); printf("\n"); printf("SYMS %u\n", num_syms); } int read_syms() { int i; if( num_syms < 0 ) return error("Bad symbol table"); symnames = malloc(num_syms*sizeof(char*)+1); if( symnames == 0 ) return error("Out of memory"); symtab = calloc(num_syms, sizeof(*symtab)); if( symtab == 0 ) return error("Out of memory"); for(i=0; i>14)&3); if( symtype == 0x43 || symtype == 0x2003 ) size_bss += symtab[i].offset; } return 0; } int disp_syms() { int i; if(display_mode == 2 && multiple_files && !opt_o) printf("\n%s:\n", ifname); for(i=0; i str_len || nameoff < 0) symnames[i] = strtab + str_len; else symnames[i] = strtab+nameoff; if( !display_mode ) { printf("SYM %-4d %08lx ", i, offset); printf("%s", (symtype&0x2000)?"C":"."); printf("%s", (symtype&0x0100)?"N":"."); printf("%s", (symtype&0x0080)?"E":"."); printf("%s", (symtype&0x0040)?"I":"."); printf("%c", "T12D456789abcdeUAhijklmnopqrstuv"[symtype&0x1F]); if( symtype &0x1E20 ) printf(" %04x", symtype); printf(" %s\n", symnames[i]); } if( display_mode == 2 ) { if (opt_o) printf("%s: ", ifname); if( symtype == 0x004f || symtype == 0x0040 ) printf(" "); else printf("%08lx ", offset); switch(symtype) { case 0x004F: putchar('U'); break; case 0x0000: putchar('t'); break; case 0x0003: putchar('d'); break; case 0x2003: putchar('b'); break; case 0x0043: putchar('C'); break; case 0x0083: putchar('D'); break; case 0x0080: putchar('T'); break; case 0x0040: putchar('T'); break; case 0x0180: putchar('N'); break; case 0x0010: putchar('a'); break; case 0x0090: putchar('A'); break; default: if((symtype & ~0xF) == 0x40 ) putchar('u'); else if((symtype & ~0xF) == 0x80 ) printf("%c", "T12D456789abcdeU"[symtype&0xF]); else putchar('?'); break; } printf(" %s\n", symnames[i]); } } if( !display_mode ) printf("\n"); return 0; } void read_databytes() { static char * relstr[] = {"ERR", "DB", "DW", "DD"}; long l, cpos; int ch, i; int curseg = 0; int relsize = 0; cpos = ftell(ifd); fseek(ifd, filepos+textoff, 0); printf("\nBYTECODE\n"); for(;;) { if( (ch=get_byte()) == -1 ) break; if( ch == 0 ) break; switch( ch & 0xC0 ) { case 0x00: switch(ch & 0xF0) { case 0x00: /* Relocator size */ printf("RELSZ %d\n", relsize= (ch&0xF)); if(relsize>3) relsize=3; break; case 0x10: /* Skip bytes */ printf("SKP %ld\n", get_sized(ch&0xF)); break; case 0x20: /* Segment */ printf("SEG %x\n", curseg= (ch&0xF)); break; default: printf("CODE %02x - unknown\n", ch); goto break_break ; } break; case 0x40: /* Raw bytes */ { int abscnt = (ch&0x3F); if( abscnt == 0 ) abscnt = 64; for( i=0; i7), buf, 2); if( ch > ' ' && ch <= '~' ) linebuf[50+pos] = ch; else linebuf[50+pos] = '.'; pos = ((pos+1) & 0xF); if( pos == 0 ) { printf(": %.66s\n", linebuf); memset(linebuf, ' ', sizeof(linebuf)); } } } /************************************************************************/ /* ELKS a.out versions */ long header[12]; int h_len, h_flgs, h_cpu; void fetch_aout_hdr() { int i; header[0] = get_long(); header[1] = get_long(); byte_order = ((header[0]>>24) & 3); h_len = (header[1] & 0xFF); h_flgs = ((header[0]>>16) & 0xFF); h_cpu = ((header[0]>>24) & 0xFF); for(i=2; i<8; i++) { if( i*4 <= h_len ) header[i] = get_long(); else header[i] = 0; } } void dump_aout() { static char * cpu[] = { "unknown", "8086", "m68k", "ns16k", "i386", "sparc" }; static char * byteord[] = { "LITTLE_ENDIAN", "(2143)","(3412)","BIG_ENDIAN" }; int i; long l; if( h_cpu > 0x17 ) h_cpu &= 3; printf("HLEN %d\n", h_len); printf("CPU %s %s\n", cpu[h_cpu>>2], byteord[h_cpu&3]); printf("FLAGS:"); if( h_flgs & 0x01 ) printf(" A_UZP"); if( h_flgs & 0x02 ) printf(" A_PAL"); if( h_flgs & 0x04 ) printf(" A_NSYM"); if( h_flgs & 0x08 ) printf(" FLG-08"); if( h_flgs & 0x10 ) printf(" A_EXEC"); if( h_flgs & 0x20 ) printf(" A_SEP"); if( h_flgs & 0x40 ) printf(" A_PURE"); if( h_flgs & 0x80 ) printf(" A_TOVLY"); printf("\n"); if( header[5] ) printf("a_entry = 0x%08lx\n", header[5]); printf("a_total = 0x%08lx\n", header[6]); if( header[7] ) printf("a_syms = 0x%08lx\n", header[7]); if( h_len >= 36 ) printf("a_trsize = 0x%08lx\n", header[8]); if( h_len >= 40 ) printf("a_drsize = 0x%08lx\n", header[9]); if( h_len >= 44 ) printf("a_tbase = 0x%08lx\n", header[10]); if( h_len >= 48 ) printf("a_dbase = 0x%08lx\n", header[11]); printf("\n"); size_aout(); printf("\n"); if( header[7] ) { printf("SYMBOLS\n"); nm_aout(); } else printf("NO SYMBOLS\n"); printf("\n"); printf("TEXTSEG\n"); fseek(ifd, (long)h_len, 0); for(l=0; l 16) { if( fread(n_name, 1, 8, ifd) != 8 ) break; n_name[8] = 0; n_value = get_long(); if( (n_sclass = getc(ifd)) == EOF ) break; if( (n_numaux = getc(ifd)) == EOF ) break; n_type = get_word(); if( pending_nl && n_sclass == 0 ) { printf("%s", n_name); continue; } if( pending_nl ) putchar('\n'); if (opt_o) printf("%s: ", ifname); if( n_sclass == 0x10 ) printf(" "); else printf("%08lx ", n_value); switch(n_sclass) { case 0x01: printf("a "); break; case 0x12: printf("T "); break; case 0x13: printf("D "); break; case 0x14: printf("C "); break; case 0x1a: printf("t "); break; case 0x1b: printf("d "); break; case 0x1c: printf("b "); break; case 0x10: printf("U "); break; default: if( display_mode ) { printf("? "); break; } printf("n_sclass="); switch(n_sclass>>3) { case 0: printf("C_NULL,"); break; case 2: printf("C_EXT,"); break; case 3: printf("C_STAT,"); break; default: printf("%04o,", n_sclass&0xF8); } switch(n_sclass&7) { case 0: printf("N_UNDF "); break; case 1: printf("N_ABS "); break; case 2: printf("N_TEXT "); break; case 3: printf("N_DATA "); break; case 4: printf("N_BSS "); break; case 5: printf("N_COMM "); break; default: printf("%o ", n_sclass&7); break; } break; } if( display_mode == 0 ) { if( n_numaux ) printf("n_numaux=%02x ", n_numaux); if( n_type ) printf("n_type=%04x ", n_type); } printf("%s", n_name); pending_nl=1; } if( pending_nl ) putchar('\n'); } #ifndef VERY_SMALL_MEMORY /************************************************************************/ /* V7 a.out versions */ void fetch_v7_hdr() { int i; h_len = 8; for(i=0; i for cross-link */ #include "const.h" #include "byteord.h" #include "obj.h" #include "type.h" #include "globvar.h" /* Linking takes 2 passes. The 1st pass reads through all files specified in the command line, and all libraries. All public symbols are extracted and stored in a chained hash table. For each module, its file and header data recorded, and the resulting structures are chained together (interleaved with the symbols). The symbol descriptors are separated from the symbol names, so we must record all the descriptors of a module before putting the symbols in the symbol table (poor design). The descriptors are stored in the symbol table, then moved to the top of the table to make room for the symols. The symbols referred to in a given module are linked together by a chain beginning in the module descriptor. */ PRIVATE unsigned convertsize[NSEG / 4] = {0, 1, 2, 4}; PRIVATE struct entrylist *entrylast; /* last on list of entry symbols */ PRIVATE struct redlist *redlast; /* last on list of redefined symbols */ PRIVATE struct modstruct *modlast; /* data for last module */ FORWARD long readarheader P((char **parchentry)); FORWARD unsigned readfileheader P((void)); FORWARD void readmodule P((char *filename, char *archentry)); FORWARD void reedmodheader P((void)); FORWARD bool_pt redsym P((struct symstruct *symptr, bin_off_t value)); FORWARD unsigned checksum P((char *string, unsigned length)); FORWARD unsigned segbits P((unsigned seg, char *sizedesc)); /* initialise object file handler */ PUBLIC void objinit() { modfirst = modlast = NUL_PTR; entryfirst = entrylast = NUL_PTR; redfirst = redlast = NUL_PTR; } /* read all symbol definitions in an object file */ PUBLIC void readsyms(filename, trace) char *filename; bool_pt trace; { char *archentry; long filelength; char filemagic[SARMAG]; unsigned long filepos; unsigned modcount; if (trace) errtrace(filename, 0); openin(filename); /* input is not open, so position is start */ switch ((unsigned) readsize(2)) { case OMAGIC: seekin((unsigned long) 0); for (modcount = readfileheader(); modcount-- != 0;) readmodule(filename, (char *) NUL_PTR); break; default: seekin((unsigned long) 0); readin(filemagic, sizeof filemagic); if (strncmp(filemagic, ARMAG, sizeof filemagic) != 0) input1error(" has bad magic number"); filepos = SARMAG; while ((filelength = readarheader(&archentry)) > 0) { unsigned int magic; if (trace) errtrace(archentry, 2); filepos += sizeof(struct ar_hdr); magic = (unsigned) readsize(2); if(magic == OMAGIC) { seekin(filepos); for (modcount = readfileheader(); modcount-- != 0;) { readmodule(stralloc(filename), archentry); modlast->textoffset += filepos; } } else if( magic == 0x3C21 ) /* "!<" */ filelength = SARMAG; seekin(filepos += ld_roundup(filelength, 2, long)); } break; } closein(); } /* read archive header and return length */ PRIVATE long readarheader(parchentry) char **parchentry; { struct ar_hdr arheader; char *endptr; char *nameptr; if (readineofok((char *) &arheader, sizeof arheader)) return 0; strncpy (*parchentry = nameptr = ourmalloc(sizeof arheader.ar_name + 1), arheader.ar_name, sizeof arheader.ar_name); endptr = nameptr + sizeof arheader.ar_name; do *endptr-- = 0; while (endptr > nameptr && (*endptr == ' ' || *endptr == '/')); return strtoul(arheader.ar_size, (char **) NUL_PTR, 0); } /* read and check file header of the object file just opened */ PRIVATE unsigned readfileheader() { struct { char magic[2]; char count[2]; /* really an int */ } fileheader; char filechecksum; /* part of fileheader but would unalign */ readin((char *) &fileheader, sizeof fileheader); readin(&filechecksum, sizeof filechecksum); if (filechecksum != checksum((char *) &fileheader, sizeof fileheader)) input1error(" is not an object file (checksum failed)"); return c2u2(fileheader.count); } /* read the next module */ PRIVATE void readmodule(filename, archentry) char *filename; char *archentry; { struct symdstruct /* to save parts of symbol before name known */ { bin_off_t dvalue; flags_t dflags; }; struct symdstruct *endsymdptr; flags_t flags; unsigned nsymbol; struct symdstruct *symdptr; char *symname; struct symstruct **symparray; struct symstruct *symptr; reedmodheader(); modlast->filename = filename; modlast->archentry = archentry; nsymbol = readsize(2); symdptr = (struct symdstruct *) ourmalloc(nsymbol * sizeof(struct symdstruct)); for (endsymdptr = symdptr + nsymbol; symdptr < endsymdptr; ++symdptr) { readsize(2); /* discard string offset, assume strings seq */ symdptr->dflags = flags = readsize(2); symdptr->dvalue = readconvsize((flags & SZ_MASK) >> SZ_SHIFT); /* NB unsigned flags to give logical shift */ /* bug in Xenix 2.5 cc causes (int) of the */ /* argument to turn flags into an int */ } symdptr = (struct symdstruct *) moveup(nsymbol * sizeof(struct symdstruct)); modlast->symparray = symparray = (struct symstruct **) ourmalloc((nsymbol + 1) * sizeof(struct symstruct *)); symname = readstring(); /* module name */ modlast->modname = stralloc(symname); /* likely OK overlapped copy */ for (endsymdptr = symdptr + nsymbol; symdptr < endsymdptr; *symparray++ = symptr, release((char *) ++symdptr)) { symname = readstring(); if ((flags = symdptr->dflags) & (E_MASK | I_MASK) && (symptr = findsym(symname)) != NUL_PTR) { /* weaken segment-checking by letting the maximum segment (SEGM_MASK) mean any segment */ if ((symptr->flags & SEGM_MASK) == SEGM_MASK) symptr->flags &= ~(flags_t) SEGM_MASK | (flags & SEGM_MASK); else if ((flags & SEGM_MASK) == SEGM_MASK) flags &= ~(flags_t) SEGM_MASK | (symptr->flags & SEGM_MASK); if ((flags ^ symptr->flags) & (A_MASK | SEGM_MASK)) { redefined(symname, " with different segment or relocatability", archentry, symptr->modptr->filename, symptr->modptr->archentry); continue; } if (symptr->flags & E_MASK) { if (flags & E_MASK && redsym(symptr, symdptr->dvalue)) redefined(symname, "", archentry, symptr->modptr->filename, symptr->modptr->archentry); continue; } if (flags & I_MASK && symdptr->dvalue <= symptr->value) continue; } else symptr = addsym(symname); symptr->modptr = modlast; symptr->value = symdptr->dvalue; symptr->flags = flags; if (flags & N_MASK) entrysym(symptr); } *symparray = NUL_PTR; } /* put symbol on entry symbol list if it is not already */ PUBLIC void entrysym(symptr) struct symstruct *symptr; { register struct entrylist *elptr; for (elptr = entryfirst; elptr != NUL_PTR; elptr = elptr->elnext) if (symptr == elptr->elsymptr) return; elptr = (struct entrylist *) ourmalloc(sizeof(struct entrylist)); elptr->elnext = NUL_PTR; elptr->elsymptr = symptr; if (entryfirst == NUL_PTR) entryfirst = elptr; else entrylast->elnext = elptr; entrylast = elptr; } /* read the header of the next module */ PRIVATE void reedmodheader() { struct { char htextoffset[4]; /* offset to module text in file */ char htextsize[4]; /* size of text (may be 0 for last mod) */ char stringssize[2]; /* size of string area */ char hclass; /* module class */ char revision; /* module revision */ } modheader; unsigned seg; unsigned count; char *cptr; struct modstruct *modptr; readin((char *) &modheader, sizeof modheader); modptr = (struct modstruct *) ourmalloc(sizeof(struct modstruct)); modptr->modnext = NUL_PTR; modptr->textoffset = c4u4(modheader.htextoffset); modptr->class = modheader.hclass; readin(modptr->segmaxsize, sizeof modptr->segmaxsize); readin(modptr->segsizedesc, sizeof modptr->segsizedesc); cptr = modptr->segsize; for (seg = 0; seg < NSEG; ++seg) { if ((count = segsizecount(seg, modptr)) != 0) { if (cptr == modptr->segsize) ourmalloc(count - 1); /* 1st byte reserved in struct */ else ourmalloc(count); readin(cptr, count); cptr += count; } } if (modfirst == NUL_PTR) modfirst = modptr; else modlast->modnext = modptr; modlast = modptr; } PRIVATE bool_pt redsym(symptr, value) register struct symstruct *symptr; bin_off_t value; { register struct redlist *rlptr; char class; if (symptr->modptr->class != (class = modlast->class)) for (rlptr = redfirst;; rlptr = rlptr->rlnext) { if (rlptr == NUL_PTR) { rlptr = (struct redlist *) ourmalloc(sizeof(struct redlist)); rlptr->rlnext = NUL_PTR; rlptr->rlsymptr = symptr; if (symptr->modptr->class < class) /* prefer lower class - put other on redlist */ { rlptr->rlmodptr = modlast; rlptr->rlvalue = value; } else { rlptr->rlmodptr = symptr->modptr; symptr->modptr = modlast; rlptr->rlvalue = symptr->value; symptr->value = value; } if (redfirst == NUL_PTR) redfirst = rlptr; else redlast->rlnext = rlptr; redlast = rlptr; return FALSE; } if (symptr == rlptr->rlsymptr && class == rlptr->rlmodptr->class) break; } return TRUE; } PRIVATE unsigned checksum(string, length) char *string; unsigned length; { unsigned char sum; /* this is a 1-byte checksum */ for (sum = 0; length-- != 0;) sum += *string++ & 0xFF; return sum; } PUBLIC bin_off_t readconvsize(countindex) unsigned countindex; { return readsize(convertsize[countindex]); } PUBLIC bin_off_t readsize(count) unsigned count; { char buf[MAX_OFFSET_SIZE]; if (count == 0) return 0; readin(buf, count); return cntooffset(buf, count); } PRIVATE unsigned segbits(seg, sizedesc) unsigned seg; char *sizedesc; { return 3 & ((unsigned) sizedesc[((NSEG - 1) - seg) / 4] >> (2 * (seg % 4))); /* unsigned to give logical shift */ } PUBLIC unsigned segsizecount(seg, modptr) unsigned seg; struct modstruct *modptr; { return convertsize[segbits(seg, modptr->segsizedesc)]; } dev86-0.16.21/ld/rel_aout.h000066400000000000000000000252131231050321700151740ustar00rootroot00000000000000#ifndef _BSD_A_OUT_H #define _BSD_A_OUT_H struct exec { /* a.out header */ unsigned char a_magic[2]; /* magic number */ unsigned char a_flags; /* flags, see below */ unsigned char a_cpu; /* cpu id */ unsigned char a_hdrlen; /* length of header */ unsigned char a_unused; /* reserved for future use */ unsigned short a_version; /* version stamp (not used at present) */ long a_text; /* size of text segement in bytes */ long a_data; /* size of data segment in bytes */ long a_bss; /* size of bss segment in bytes */ long a_entry; /* entry point */ long a_total; /* total memory allocated */ long a_syms; /* size of symbol table */ /* SHORT FORM ENDS HERE */ long a_trsize; /* text relocation size */ long a_drsize; /* data relocation size */ long a_tbase; /* text relocation base */ long a_dbase; /* data relocation base */ }; #define A_MAGIC0 ((unsigned char) 0x01) #define A_MAGIC1 ((unsigned char) 0x03) #define BADMAG(X) ((X).a_magic[0] != A_MAGIC0 || (X).a_magic[1] != A_MAGIC1) /* CPU Id of TARGET machine (byte order coded in low order two bits) */ #define A_NONE 0x00 /* unknown */ #define A_I8086 0x04 /* intel i8086/8088 */ #define A_M68K 0x0B /* motorola m68000 */ #define A_NS16K 0x0C /* national semiconductor 16032 */ #define A_I80386 0x10 /* intel i80386 */ #define A_SPARC 0x17 /* Sun SPARC */ #define A_BLR(cputype) ((cputype&0x01)!=0) /* TRUE if bytes left-to-right */ #define A_WLR(cputype) ((cputype&0x02)!=0) /* TRUE if words left-to-right */ /* Flags. */ #define A_UZP 0x01 /* unmapped zero page (pages) */ #define A_EXEC 0x10 /* executable */ #define A_SEP 0x20 /* separate I/D */ #define A_PURE 0x40 /* pure text */ /* not used */ #define A_TOVLY 0x80 /* text overlay */ /* not used */ /* Tell a.out.gnu.h not to define `struct exec'. */ #define __STRUCT_EXEC_OVERRIDE__ /* Hide M_386 from enum declaration in a.out.h. */ #define M_386 HIDE_M_386 #ifndef __A_OUT_GNU_H__ #define __A_OUT_GNU_H__ #if defined(sequent) && defined(i386) #define a_magic a_info #include #undef a_magic #define __STRUCT_EXEC_OVERRIDE__ #define N_NLIST_DECLARED #define N_RELOCATION_INFO_DECLARED #endif #define __GNU_EXEC_MACROS__ #ifndef __STRUCT_EXEC_OVERRIDE__ struct exec { unsigned long a_info; /* Use macros N_MAGIC, etc for access */ unsigned long a_text; /* length of text, in bytes */ unsigned long a_data; /* length of data, in bytes */ unsigned long a_bss; /* length of uninitialized data area for file, in bytes */ unsigned long a_syms; /* length of symbol table data in file, in bytes */ unsigned long a_entry; /* start address */ unsigned long a_trsize; /* length of relocation info for text, in bytes */ unsigned long a_drsize; /* length of relocation info for data, in bytes */ }; #endif /* __STRUCT_EXEC_OVERRIDE__ */ /* these go in the N_MACHTYPE field */ enum machine_type { #if defined (M_OLDSUN2) M__OLDSUN2 = M_OLDSUN2, #else M_OLDSUN2 = 0, #endif #if defined (M_68010) M__68010 = M_68010, #else M_68010 = 1, #endif #if defined (M_68020) M__68020 = M_68020, #else M_68020 = 2, #endif #if defined (M_SPARC) M__SPARC = M_SPARC, #else M_SPARC = 3, #endif /* skip a bunch so we don't run into any of sun's numbers */ M_386 = 100, }; #if !defined (N_MAGIC) #define N_MAGIC(exec) ((exec).a_info & 0xffff) #endif #define N_MACHTYPE(exec) ((enum machine_type)(((exec).a_info >> 16) & 0xff)) #define N_FLAGS(exec) (((exec).a_info >> 24) & 0xff) #define N_SET_INFO(exec, magic, type, flags) \ ((exec).a_info = ((magic) & 0xffff) \ | (((int)(type) & 0xff) << 16) \ | (((flags) & 0xff) << 24)) #define N_SET_MAGIC(exec, magic) \ ((exec).a_info = (((exec).a_info & 0xffff0000) | ((magic) & 0xffff))) #define N_SET_MACHTYPE(exec, machtype) \ ((exec).a_info = \ ((exec).a_info&0xff00ffff) | ((((int)(machtype))&0xff) << 16)) #define N_SET_FLAGS(exec, flags) \ ((exec).a_info = \ ((exec).a_info&0x00ffffff) | (((flags) & 0xff) << 24)) #ifndef OMAGIC /* Code indicating object file or impure executable. */ #define OMAGIC 0407 /* Code indicating pure executable. */ #define NMAGIC 0410 /* Code indicating demand-paged executable. */ #define ZMAGIC 0413 #endif /* not OMAGIC */ #if !defined (N_BADMAG) #define N_BADMAG(x) \ (N_MAGIC(x) != OMAGIC && N_MAGIC(x) != NMAGIC \ && N_MAGIC(x) != ZMAGIC) #endif #define _N_BADMAG(x) \ (N_MAGIC(x) != OMAGIC && N_MAGIC(x) != NMAGIC \ && N_MAGIC(x) != ZMAGIC) #define _N_HDROFF(x) (SEGMENT_SIZE - sizeof (struct exec)) #if !defined (N_TXTOFF) #define N_TXTOFF(x) \ (N_MAGIC(x) == ZMAGIC ? _N_HDROFF((x)) + sizeof (struct exec) : sizeof (struct exec)) #endif #if !defined (N_DATOFF) #define N_DATOFF(x) (N_TXTOFF(x) + (x).a_text) #endif #if !defined (N_TRELOFF) #define N_TRELOFF(x) (N_DATOFF(x) + (x).a_data) #endif #if !defined (N_DRELOFF) #define N_DRELOFF(x) (N_TRELOFF(x) + (x).a_trsize) #endif #if !defined (N_SYMOFF) #define N_SYMOFF(x) (N_DRELOFF(x) + (x).a_drsize) #endif #if !defined (N_STROFF) #define N_STROFF(x) (N_SYMOFF(x) + (x).a_syms) #endif /* Address of text segment in memory after it is loaded. */ #if !defined (N_TXTADDR) #define N_TXTADDR(x) 0 #endif /* Address of data segment in memory after it is loaded. Note that it is up to you to define SEGMENT_SIZE on machines not listed here. */ #if defined(vax) || defined(hp300) || defined(pyr) #define SEGMENT_SIZE PAGE_SIZE #endif #ifdef hp300 #define PAGE_SIZE 4096 #endif #ifdef sony #define SEGMENT_SIZE 0x2000 #endif /* Sony. */ #ifdef is68k #define SEGMENT_SIZE 0x20000 #endif #if defined(m68k) && defined(PORTAR) #define PAGE_SIZE 0x400 #define SEGMENT_SIZE PAGE_SIZE #endif #define _N_SEGMENT_ROUND(x) (((x) + SEGMENT_SIZE - 1) & ~(SEGMENT_SIZE - 1)) #define _N_TXTENDADDR(x) (N_TXTADDR(x)+(x).a_text) #ifndef N_DATADDR #define N_DATADDR(x) \ (N_MAGIC(x)==OMAGIC? (_N_TXTENDADDR(x)) \ : (_N_SEGMENT_ROUND (_N_TXTENDADDR(x)))) #endif /* Address of bss segment in memory after it is loaded. */ #if !defined (N_BSSADDR) #define N_BSSADDR(x) (N_DATADDR(x) + (x).a_data) #endif #if !defined (N_NLIST_DECLARED) struct nlist { union { char *n_name; struct nlist *n_next; long n_strx; } n_un; unsigned char n_type; char n_other; short n_desc; unsigned long n_value; }; #endif /* no N_NLIST_DECLARED. */ #if !defined (N_UNDF) #define N_UNDF 0 #endif #if !defined (N_ABS) #define N_ABS 2 #endif #if !defined (N_TEXT) #define N_TEXT 4 #endif #if !defined (N_DATA) #define N_DATA 6 #endif #if !defined (N_BSS) #define N_BSS 8 #endif #if !defined (N_COMM) #define N_COMM 18 #endif #if !defined (N_FN) #define N_FN 15 #endif #if !defined (N_EXT) #define N_EXT 1 #endif #if !defined (N_TYPE) #define N_TYPE 036 #endif #if !defined (N_STAB) #define N_STAB 0340 #endif /* The following type indicates the definition of a symbol as being an indirect reference to another symbol. The other symbol appears as an undefined reference, immediately following this symbol. Indirection is asymmetrical. The other symbol's value will be used to satisfy requests for the indirect symbol, but not vice versa. If the other symbol does not have a definition, libraries will be searched to find a definition. */ #define N_INDR 0xa /* The following symbols refer to set elements. All the N_SET[ATDB] symbols with the same name form one set. Space is allocated for the set in the text section, and each set element's value is stored into one word of the space. The first word of the space is the length of the set (number of elements). The address of the set is made into an N_SETV symbol whose name is the same as the name of the set. This symbol acts like a N_DATA global symbol in that it can satisfy undefined external references. */ /* These appear as input to LD, in a .o file. */ #define N_SETA 0x14 /* Absolute set element symbol */ #define N_SETT 0x16 /* Text set element symbol */ #define N_SETD 0x18 /* Data set element symbol */ #define N_SETB 0x1A /* Bss set element symbol */ /* This is output from LD. */ #define N_SETV 0x1C /* Pointer to set vector in data area. */ #if !defined (N_RELOCATION_INFO_DECLARED) /* This structure describes a single relocation to be performed. The text-relocation section of the file is a vector of these structures, all of which apply to the text section. Likewise, the data-relocation section applies to the data section. */ struct relocation_info { /* Address (within segment) to be relocated. */ unsigned long r_address; #if 0 /* The meaning of r_symbolnum depends on r_extern. */ unsigned int r_symbolnum:24; /* Nonzero means value is a pc-relative offset and it should be relocated for changes in its own address as well as for changes in the symbol or section specified. */ unsigned int r_pcrel:1; /* Length (as exponent of 2) of the field to be relocated. Thus, a value of 2 indicates 1<<2 bytes. */ unsigned int r_length:2; /* 1 => relocate with value of symbol. r_symbolnum is the index of the symbol in file's the symbol table. 0 => relocate with the address of a segment. r_symbolnum is N_TEXT, N_DATA, N_BSS or N_ABS (the N_EXT bit may be set also, but signifies nothing). */ unsigned int r_extern:1; /* Four bits that aren't used, but when writing an object file it is desirable to clear them. */ unsigned int r_pad:4; #else unsigned long foo; #endif }; #endif /* no N_RELOCATION_INFO_DECLARED. */ #endif /* __A_OUT_GNU_H__ */ #undef M_386 #define M_386 A_I80386 #undef N_MAGIC #define N_MAGIC3(magic0, magic1, type) \ ((magic0) | ((magic1) << 8) | ((type) << 16)) #define N_MAGIC(exec) \ N_MAGIC3((exec).a_magic[0], (exec).a_magic[1], (exec).a_flags) #undef N_MACHTYPE #define N_MACHTYPE(exec) ((enum machine_type)((exec).a_cpu)) #undef N_FLAGS #define N_FLAGS(exec) 0 #undef N_SET_INFO #define N_SET_INFO(exec, magic, type, flags) \ ((exec).a_magic[0] = (magic) & 0xff, \ (exec).a_magic[1] = ((magic) >> 8) & 0xff, \ (exec).a_flags = ((magic) >> 16) & 0xff, \ (exec).a_cpu = (type) & 0xff) #undef N_SET_MAGIC #define N_SET_MAGIC(exec, magic) \ ((exec).a_magic[0] = (magic) & 0xff, \ (exec).a_magic[1] = ((magic) >> 8) & 0xff, \ (exec).a_flags = ((magic) >> 16) & 0xff) #undef N_SET_MACHTYPE #define N_SET_MACHTYPE(exec, machtype) \ ((exec).a_cpu = (machtype) & 0xff, \ (exec).a_hdrlen = sizeof (exec)) #undef N_SET_FLAGS #define N_SET_FLAGS(exec, flags) /* nothing */ #undef OMAGIC #define OMAGIC N_MAGIC3(A_MAGIC0, A_MAGIC1, 0) #undef NMAGIC #define NMAGIC N_MAGIC3(A_MAGIC0, A_MAGIC1, A_EXEC) #undef ZMAGIC #define ZMAGIC N_MAGIC3(A_MAGIC0, A_MAGIC1, A_EXEC) #undef _N_HDROFF #define _N_HDROFF(x) 0 #undef PAGE_SIZE #define PAGE_SIZE 16 #define SEGMENT_SIZE PAGE_SIZE #define getpagesize() PAGE_SIZE #endif /* _BSD_A_OUT_H */ dev86-0.16.21/ld/syshead.h000066400000000000000000000034571231050321700150300ustar00rootroot00000000000000 #ifndef POSIX_HEADERS_MISSING #include #include #include #include #endif #ifndef STDC_HEADERS_MISSING #include #include #include #endif #ifdef MSDOS #undef POSIX_HEADERS_MISSING #include #include #include #include #undef min #define R_OK 0 #define mode_t unsigned short #define SEEK_SET 0 #define STDOUT_FILENO 1 #define STDERR_FILENO 2 #define VERSION "MSDOS Compile" #endif /******************************************************************************/ /* EEEEyuk!! */ #ifdef __STDC__ #define P(x) x #else #define P(x) () #endif #ifdef STDC_HEADERS_MISSING extern int errno; char *strcat P((char *dest, const char *src)); unsigned long strtoul P((const char *s, char **endptr, int base)); void exit P((int status)); void *malloc P((unsigned size)); int strncmp P((const char *s1, const char *s2, unsigned n)); char *strncpy P((char *dest, const char *src, unsigned n)); char * strcpy P((char* dest, char* src)); void *memset P((void *s, int c, unsigned n)); #endif #ifdef POSIX_HEADERS_MISSING #define R_OK 0 int access P((const char *path, int amode)); #define SEEK_SET 0 #define STDOUT_FILENO 1 #define STDERR_FILENO 2 #define mode_t unsigned short #define off_t long int chmod P((const char *path, int mode)); int close P((int fd)); int creat P((const char *path, int mode)); int fstat P((int fd, struct stat *statbuf)); off_t lseek P((int fd, off_t offset, int whence)); int open P((const char *path, int oflag, ...)); int read P((int fd, void *buf, unsigned nbytes)); mode_t umask P((int oldmask)); int write P((int fd, const void *buf, unsigned nbytes)); #endif #ifndef O_RDONLY #define O_RDONLY 0 #endif #ifndef O_WRONLY #define O_WRONLY 1 #endif #ifndef O_RDWR #define O_RDWR 2 #endif dev86-0.16.21/ld/table.c000066400000000000000000000106571231050321700144520ustar00rootroot00000000000000/* table.c - table-handler module for linker */ /* Copyright (C) 1994 Bruce Evans */ #include "syshead.h" #include "const.h" #include "align.h" #include "obj.h" #include "type.h" #include "globvar.h" #define GOLDEN 157 /* GOLDEN/HASHTABSIZE approx golden ratio */ #define HASHTABSIZE 256 PRIVATE struct symstruct *hashtab[HASHTABSIZE]; /* hash table */ PRIVATE char *tableptr; /* next free spot in catchall table */ PRIVATE char *tableend; /* ptr to spot after last in table */ PUBLIC int maxused = 0; /* Stats */ PRIVATE int mainavail, usedtop; /* Stats */ FORWARD struct symstruct **gethashptr P((char *name)); FORWARD void check_used P((void)); /* initialise symbol table */ PUBLIC void syminit() { unsigned i; for (i = sizeof(int) <= 2 ? 0xE000 : (unsigned) 0x38000; i != 0; i -= 512) if ((tableptr = malloc(i)) != NUL_PTR) break; if (tableptr == NUL_PTR) outofmemory(); tableend = tableptr + i; for (i = 0; i < HASHTABSIZE; i++) hashtab[i] = NUL_PTR; mainavail = tableend - tableptr; usedtop = 0; } /* add named symbol to end of table - initialise only name and next fields */ /* caller must not duplicate names of externals for findsym() to work */ PUBLIC struct symstruct *addsym(name) char *name; { struct symstruct **hashptr; struct symstruct *oldsymptr = 0; struct symstruct *symptr; hashptr = gethashptr(name); symptr = *hashptr; while (symptr != NUL_PTR) { oldsymptr = symptr; symptr = symptr->next; } align(tableptr); symptr = (struct symstruct *) tableptr; if ((tableptr = symptr->name + (strlen(name) + 1)) > tableend) outofmemory(); symptr->modptr = NUL_PTR; symptr->next = NUL_PTR; if (name != symptr->name) strcpy(symptr->name, name); /* should't happen */ if (*hashptr == NUL_PTR) *hashptr = symptr; else oldsymptr->next = symptr; return symptr; } /* lookup named symbol */ PUBLIC struct symstruct *findsym(name) char *name; { struct symstruct *symptr; symptr = *gethashptr(name); while (symptr != NUL_PTR && (!(symptr->flags & (E_MASK | I_MASK)) || strcmp(symptr->name, name) != 0)) symptr = symptr->next; return symptr; } /* convert name to a hash table ptr */ PRIVATE struct symstruct **gethashptr(name) register char *name; { register unsigned hashval; hashval = 0; while (*name) hashval = hashval * 2 + *name++; return hashtab + ((hashval * GOLDEN) & (HASHTABSIZE - 1)); /* #asm GOLDEN EQU 157 HASHTABSIZE EQU 256 CLRB can build value here since HASHTABSIZE <= 256 LDA ,X BEQ HASHVAL.EXIT HASHVAL.LOOP ADDB ,X+ LSLB LDA ,X BNE HASHVAL.LOOP RORB LDA #GOLDEN MUL HASHVAL.EXIT HASHVAL.EXIT LDX #_hashtab ABX discard A - same as taking mod HASHTABSIZE ABX #endasm */ } /* move symbol descriptor entries to top of table (no error checking) */ PUBLIC char *moveup(nbytes) unsigned nbytes; { register char *source; register char *target; usedtop += nbytes; mainavail -= nbytes; source = tableptr; target = tableend; while (nbytes--) *--target = *--source; tableptr = source; return tableend = target; } /* our version of malloc */ PUBLIC char *ourmalloc(nbytes) unsigned nbytes; { char *allocptr; align(tableptr); allocptr = tableptr; if ((tableptr += nbytes) > tableend) outofmemory(); return allocptr; } /* our version of free (release from bottom of table) */ PUBLIC void ourfree(cptr) char *cptr; { check_used(); tableptr = cptr; check_used(); } /* read string from file into table at offset suitable for next symbol */ PUBLIC char *readstring() { int c; char *s; char *start; align(tableptr); start = s = ((struct symstruct *) tableptr)->name; while (TRUE) { /* Stats: need a checkused against 's', maybe. */ if (s >= tableend) outofmemory(); if ((c = readchar()) < 0) prematureeof(); if ((*s++ = c) == 0) return start; } /* NOTREACHED */ } /* release from top of table */ PUBLIC void release(cptr) char *cptr; { check_used(); mainavail += cptr - tableend; usedtop -= cptr - tableend; tableend = cptr; } PRIVATE void check_used() { int used; used = usedtop + mainavail - (tableend - tableptr); if (used > maxused) maxused = used; } PUBLIC int memory_used() { check_used(); return maxused; } /* allocate space for string */ PUBLIC char *stralloc(s) char *s; { return strcpy(ourmalloc((unsigned) strlen(s) + 1), s); } dev86-0.16.21/ld/type.h000066400000000000000000000125551231050321700143500ustar00rootroot00000000000000/* type.h - types for linker */ /* Copyright (C) 1994 Bruce Evans */ typedef int bool_pt; typedef unsigned char bool_t; typedef unsigned short u2_t; typedef unsigned u2_pt; typedef unsigned long u4_t; typedef unsigned long u4_pt; #ifdef HOST_8BIT typedef char fastin_t; #else typedef int fastin_t; #endif typedef int fastin_pt; typedef unsigned flags_t; /* unsigned makes shifts logical */ #ifdef LONG_OFFSETS typedef unsigned long bin_off_t; #else typedef unsigned bin_off_t; #endif #ifdef OBJ_H /* obj.h is included */ struct entrylist /* list of entry symbols */ { struct entrylist *elnext; /* next on list */ struct symstruct *elsymptr; /* entry on list */ }; struct modstruct /* module table entry format */ { char *filename; /* file containing this module */ char *archentry; /* name of component file for archives */ char *modname; /* name of module */ unsigned long textoffset; /* offset to module text in file */ char class; /* class of module */ char loadflag; /* set if module to be loaded */ char segmaxsize[NSEG / 4]; /* |SF|SE|..|S0|, 2 bits for seg max size */ /* 00 = 1, 01 = 2, 10 = 3, 11 = 4 */ char segsizedesc[NSEG / 4]; /* |SF|SE|..|S0|, 2 bits for #bytes for size */ /* 00 = 0, 01 = 1, 10 = 2, 11 = 4 */ struct symstruct **symparray; /* ^array of ptrs to referenced syms */ struct modstruct *modnext; /* next module in order of initial reading */ char segsize[1]; /* up to 64 size bytes begin here */ }; /* careful with sizeof( struct modstruct )!! */ struct redlist /* list of redefined (exported) symbols */ { struct redlist *rlnext; /* next on list */ struct symstruct *rlsymptr; /* to symbol with same name, flags */ struct modstruct *rlmodptr; /* module for this redefinition */ bin_off_t rlvalue; /* value for this redefinition */ }; struct symstruct /* symbol table entry format */ { struct modstruct *modptr; /* module where symbol is defined */ bin_off_t value; /* value of symbol */ flags_t flags; /* see below (unsigned makes shifts logical) */ struct symstruct *next; /* next symbol with same hash value */ char name[1]; /* name is any string beginning here */ }; /* don't use sizeof( struct symstruct )!! */ #endif /* obj.h is included */ /* prototypes */ #ifndef P #ifdef __STDC__ #define P(x) x #else #define P(x) () #endif #endif /* dump.c */ void dumpmods P((void)); void dumpsyms P((void)); /* io.c */ void ioinit P((char *progname)); void closein P((void)); void closeout P((void)); void errtrace P((char *name, int level)); void executable P((void)); void flusherr P((void)); void openin P((char *filename)); void openout P((char *filename)); void putstr P((char *message)); void put08x P((bin_off_t num)); void put08lx P((bin_off_t num)); void putbstr P((unsigned width, char *str)); void putbyte P((int ch)); int readchar P((void)); void readin P((char *buf, unsigned count)); bool_pt readineofok P((char *buf, unsigned count)); void seekin P((unsigned long offset)); void seekout P((unsigned long offset)); void seektrel P((unsigned long offset)); void writechar P((int c)); void writedrel P((char *buf, unsigned count)); void writeout P((char *buf, unsigned count)); void writetrel P((char *buf, unsigned count)); void fatalerror P((char *message)); void inputerror P((char *message)); void input1error P((char *message)); void outofmemory P((void)); void prematureeof P((void)); void redefined P((char *name, char *message, char *archentry, char *deffilename, char *defarchentry)); void interseg P((char *fname, char *aname, char *name)); void reserved P((char *name)); void size_error P((int seg, bin_off_t count, bin_off_t size)); void undefined P((char *name)); void usage P((void)); void version_msg P((void)); void use_error P((char *message)); /* ld.c */ int main P((int argc, char **argv)); /* readobj.c */ void objinit P((void)); void readsyms P((char *filename, bool_pt trace)); #ifdef OBJ_H void entrysym P((struct symstruct *symptr)); unsigned segsizecount P((unsigned seg, struct modstruct *modptr)); #endif bin_off_t readconvsize P((unsigned countindex)); bin_off_t readsize P((unsigned count)); /* table.c */ void syminit P((void)); struct symstruct *addsym P((char *name)); struct symstruct *findsym P((char *name)); char *moveup P((unsigned nbytes)); char *ourmalloc P((unsigned nbytes)); void ourfree P((char *cptr)); char *readstring P((void)); void release P((char *cptr)); int memory_used P((void)); char *stralloc P((char *s)); /* typeconvert.c */ u2_pt c2u2 P((char *buf)); u4_t c4u4 P((char *buf)); u2_pt cnu2 P((char *buf, unsigned count)); u4_t cnu4 P((char *buf, unsigned count)); void u2c2 P((char *buf, u2_pt offset)); void u4c4 P((char *buf, u4_t offset)); void u2cn P((char *buf, u2_pt offset, unsigned count)); void u4cn P((char *buf, u4_t offset, unsigned count)); bool_pt typeconv_init P((bool_pt big_endian, bool_pt long_big_endian)); /* writebin.c */ void writebin P((char *outfilename, bool_pt argsepid, bool_pt argbits32, bool_pt argstripflag, bool_pt arguzp)); void write_dosemu P((char *outfilename, bool_pt argsepid, bool_pt argbits32, bool_pt argstripflag, bool_pt arguzp)); /* write_elks.c */ void write_elks P((char *outfilename, bool_pt argsepid, bool_pt argbits32, bool_pt argstripflag, bool_pt arguzp, bool_pt nsym)); /* linksym.c */ void linksyms P((bool_pt argreloc_output)); /* mkar.c */ void ld86r P((int argc, char ** argv)); dev86-0.16.21/ld/typeconv.c000066400000000000000000000065541231050321700152330ustar00rootroot00000000000000 /* * Type conversion routines, these have been rewritten for portability. * * The only requirement is now that the u2_t and u4_t must be big enough. */ #include "syshead.h" #include "const.h" #include "type.h" #include "globvar.h" void xxerr P((char *)); void xxerr(x) char * x; { write(2, x, strlen(x)); } static int no_swap = 1; static int long_off[4] = {0,1,2,3}; static int int_off[2] = {0,1}; PUBLIC bool_pt typeconv_init(big_endian, long_big_endian) bool_pt big_endian; bool_pt long_big_endian; { int i; no_swap = (!big_endian && !long_big_endian); for(i=0; i<4; i++) long_off[i] = i; for(i=0; i<2; i++) int_off[i] = i; if( long_big_endian ) { i = long_off[0]; long_off[0] = long_off[2]; long_off[2] = i; i = long_off[1]; long_off[1] = long_off[3]; long_off[3] = i; } if( big_endian ) { i = long_off[2]; long_off[2] = long_off[3]; long_off[3] = i; i = long_off[0]; long_off[0] = long_off[1]; long_off[1] = i; i = int_off[0]; int_off[0] = int_off[1]; int_off[1] = i; } return 1; } PUBLIC void u2c2(buf, offset) char *buf; u2_pt offset; { #ifdef __AS386_16__ if( no_swap ) { *((unsigned short*)buf) = offset; /* UNALIGNED ACCESS! */ return; } #endif buf[int_off[0]] = offset; buf[int_off[1]] = (offset>>8); } PUBLIC void u4c4(buf, offset) char *buf; u4_t offset; { int i; #ifdef __AS386_16__ if( no_swap ) { *((unsigned long*)buf) = offset; /* UNALIGNED ACCESS! */ return; } #endif for(i=0; i<4; i++) { buf[long_off[i]] = offset; offset >>= 8; } } PUBLIC void u4cn(buf, offset, count) char *buf; u4_t offset; unsigned count; { switch(count) { case 1: buf[0] = (char) offset; return; case 2: u2c2(buf, (u2_pt) offset); return; case 4: u4c4(buf, (u4_t) offset); return; default: xxerr("WARNING: typeconv.c(u4cn) illegal count\n"); return; } } PUBLIC void u2cn(buf, offset, count) char *buf; u2_pt offset; unsigned count; { switch(count) { case 1: buf[0] = (char) offset; return; case 2: u2c2(buf, (u2_pt) offset); return; case 4: u4c4(buf, (u4_t) offset); return; default: xxerr("WARNING: typeconv.c(u2cn) illegal count\n"); return; } } PUBLIC u2_pt c2u2(buf) char *buf; { u2_pt res; #ifdef __AS386_16__ if( no_swap ) return *((u2_pt *)buf); /* UNALIGNED ACCESS! */ #endif res = ((unsigned char *)buf) [int_off[0]] + ((((unsigned char *)buf) [int_off[1]]) << 8); return res; } PUBLIC u4_t c4u4(buf) char *buf; { u4_t res; int i; #ifdef __AS386_16__ if( no_swap ) return *((u4_t *)buf); /* UNALIGNED ACCESS! */ #endif res = 0; for(i=3; i>=0; i--) { res = (res<<8) + ((unsigned char *)buf) [long_off[i]]; } return res; } PUBLIC u4_t cnu4(buf, count) char *buf; unsigned count; { switch (count) { case 0: return 0; case 1: return buf[0] & 0xFF; case 2: return c2u2(buf); case 4: return c4u4(buf); default: xxerr("WARNING: typeconv.c(cnu4) illegal count\n"); return 0; } } PUBLIC u2_pt cnu2(buf, count) char *buf; unsigned count; { switch (count) { case 0: return 0; case 1: return buf[0] & 0xFF; case 2: return c2u2(buf); case 4: return (u2_pt) c4u4(buf); default: xxerr("WARNING: typeconv.c(cnu2) illegal count\n"); return 0; } } dev86-0.16.21/ld/v7_aout.h000066400000000000000000000011661231050321700147470ustar00rootroot00000000000000/* Header format of 16-bit * Seventh edition UNIX executables */ #ifndef _V7_A_OUT_H #define _V7_A_OUT_H #define V7_MAGIC4 0405 /* v7 overlay */ #define V7_OMAGIC 0407 /* I&D in one segment (impure) */ #define V7_NMAGIC 0410 /* read-only text */ #define V7_MAGIC3 0411 /* v7 separate I&D (pure) */ #define V7_ZMAGIC 0413 /* v8 demand load */ #define V7_HEADERLEN 16 struct v7_exec { short magic; unsigned short textsize; unsigned short datasize; unsigned short bsssize; unsigned short symtabsize; unsigned short entry; unsigned short pad; unsigned short noreloc; }; #endif /* _V7_A_OUT_H */ dev86-0.16.21/ld/writebin.c000066400000000000000000000644101231050321700152020ustar00rootroot00000000000000 /* writebin.c - write binary file for linker */ /* Copyright (C) 1994 Bruce Evans */ #include "syshead.h" #include "bindef.h" #include "const.h" #include "obj.h" #include "type.h" #include "globvar.h" #ifdef AOUT_DETECTED #define btextoffset (text_base_value) #define bdataoffset (data_base_value) #define page_size() 4096 #ifdef __ELF__ #ifndef ELF_SYMS #define ELF_SYMS 1 #endif #endif #ifdef EDOS # define FILEHEADERLENGTH 0 #endif #ifdef MINIX # ifdef BSD_A_OUT # ifdef STANDARD_GNU_A_OUT # define HEADERLEN (sizeof(struct exec)) # else # define HEADERLEN (48) # endif # else # ifdef REL_OUTPUT # define HEADERLEN (reloc_output?sizeof(struct exec):A_MINHDR) /* part of header not counted in offsets */ # else # define HEADERLEN (A_MINHDR) # endif # endif # ifndef FILEHEADERLENGTH # define FILEHEADERLENGTH (headerless?0:HEADERLEN) # endif #endif #define DPSEG 2 #define CM_MASK 0xC0 #define MODIFY_MASK 0x3F #define S_MASK 0x04 #define OF_MASK 0x03 #define CM_SPECIAL 0 #define CM_ABSOLUTE 0x40 #define CM_OFFSET_RELOC 0x80 #define CM_SYMBOL_RELOC 0xC0 #define CM_EOT 0 #define CM_BYTE_SIZE 1 #define CM_WORD_SIZE 2 #define CM_LONG_SIZE 3 #define CM_1_SKIP 17 #define CM_2_SKIP 18 #define CM_4_SKIP 19 #define CM_0_SEG 32 #define ABS_TEXT_MAX 64 #define offsetof(struc, mem) ((int) &((struc *) 0)->mem) #define memsizeof(struc, mem) sizeof(((struc *) 0)->mem) PRIVATE bool_t bits32; /* nonzero for 32-bit executable */ PRIVATE bin_off_t combase[NSEG];/* bases of common parts of segments */ PRIVATE bin_off_t comsz[NSEG]; /* sizes of common parts of segments */ PRIVATE fastin_t curseg; /* current segment, 0 to $F */ PRIVATE bin_off_t edataoffset; /* end of data */ PRIVATE bin_off_t endoffset; /* end of bss */ PRIVATE bin_off_t etextoffset; /* end of text */ PRIVATE bin_off_t etextpadoff; /* end of padded text */ #ifdef REL_OUTPUT PRIVATE unsigned ndreloc; /* number of data relocations */ #endif PRIVATE unsigned nsym; /* number of symbols written */ #ifdef REL_OUTPUT PRIVATE unsigned ntreloc; /* number of text relocations */ extern bool_t reloc_output; /* nonzero to leave reloc info in output */ #endif PRIVATE unsigned relocsize; /* current relocation size 1, 2 or 4 */ PRIVATE bin_off_t segadj[NSEG]; /* adjusts (file offset - seg offset) */ /* depends on zero init */ PRIVATE bin_off_t segbase[NSEG];/* bases of data parts of segments */ PRIVATE char segboundary[9] = "__seg0DH"; /* name of seg boundary __seg0DL to __segfCH */ PRIVATE bin_off_t segpos[NSEG]; /* segment positions for current module */ PRIVATE bin_off_t segsz[NSEG]; /* sizes of data parts of segments */ /* depends on zero init */ PRIVATE bool_t sepid; /* nonzero for separate I & D */ PRIVATE bool_t stripflag; /* nonzero to strip symbols */ PRIVATE bin_off_t spos; /* position in current seg */ PRIVATE bool_t uzp; /* nonzero for unmapped zero page */ #ifdef EDOS FORWARD unsigned binheaderlength P((char *commandname)); FORWARD char *idconvert P((struct entrylist *elptr, char *commandname)); #endif FORWARD void linkmod P((struct modstruct *modptr)); FORWARD void padmod P((struct modstruct *modptr)); FORWARD void setsym P((char *name, bin_off_t value)); FORWARD void symres P((char *name)); FORWARD void setseg P((fastin_pt newseg)); FORWARD void skip P((unsigned countsize)); #ifdef EDOS FORWARD void writeheader P((char *commandname)); #else FORWARD void writeheader P((void)); #endif FORWARD void writenulls P((bin_off_t count)); /* write binary file */ #ifndef FUNCNAME #define FUNCNAME writebin #endif PUBLIC void FUNCNAME(outfilename, argsepid, argbits32, argstripflag, arguzp) char *outfilename; bool_pt argsepid; bool_pt argbits32; bool_pt argstripflag; bool_pt arguzp; { char buf4[4]; #ifdef EDOS char *commandname; #endif char *cptr; struct nlist extsym; flags_t flags; struct modstruct *modptr; fastin_t seg; unsigned sizecount; bin_off_t tempoffset; sepid = argsepid; bits32 = argbits32; stripflag = argstripflag; #ifdef REL_OUTPUT uzp = arguzp && !reloc_output; #else uzp = arguzp; #endif if (uzp) { if (btextoffset == 0) #ifdef QMAGIC btextoffset = page_size()+HEADERLEN; #else btextoffset = page_size(); #endif if (bdataoffset == 0 && sepid) bdataoffset = page_size(); } #ifdef EDOS commandname = stralloc(outfilename); if ((cptr = strchr(commandname, ':')) != NUL_PTR) commandname = cptr + 1; if ((cptr = strrchr(commandname, '.')) != NUL_PTR) *cptr = 0; #endif /* reserve special symbols use curseg to pass parameter to symres() */ for (curseg = 0; curseg < NSEG; ++curseg) { segboundary[5] = hexdigit[curseg]; /* to __segX?H */ segboundary[6] = 'D'; symres(segboundary); /* __segXDH */ segboundary[7] = 'L'; symres(segboundary); /* __segXDL */ segboundary[6] = 'C'; symres(segboundary); /* __segXCL */ segboundary[7] = 'H'; symres(segboundary); /* __segXCH */ #ifndef DATASEGS if( curseg > 3 ) { segboundary[6] = 'S'; segboundary[7] = 'O'; symres(segboundary); /* __segXSO */ } #endif } #ifdef EDOS curseg = 0; /* data seg, s.b. variable */ #else curseg = 3; #endif symres("__edata"); symres("__end"); curseg = 0; /* text seg, s.b. variable */ symres("__etext"); symres("__segoff"); /* calculate segment and common sizes (sum over loaded modules) */ /* use zero init of segsz[] */ /* also relocate symbols relative to starts of their segments */ for (modptr = modfirst; modptr != NUL_PTR; modptr = modptr->modnext) if (modptr->loadflag) { register struct symstruct **symparray; register struct symstruct *symptr; for (symparray = modptr->symparray; (symptr = *symparray) != NUL_PTR; ++symparray) if (symptr->modptr == modptr && !(symptr->flags & A_MASK)) { if (!(symptr->flags & (I_MASK | SA_MASK))) { /* relocate by offset of module in segment later */ /* relocate by offset of segment in memory special */ /* symbols get relocated improperly */ symptr->value += segsz[symptr->flags & SEGM_MASK]; } else if (symptr->value == 0) { #ifdef REL_OUTPUT if (!reloc_output) #endif undefined(symptr->name); } else { #ifdef REL_OUTPUT #if 0 if (!reloc_output) #else if (!reloc_output || !(symptr->flags & I_MASK)) #endif #endif { tempoffset = ld_roundup(symptr->value, 4, bin_off_t); /* temp kludge quad alignment for 386 */ symptr->value = comsz[seg = symptr->flags & SEGM_MASK]; comsz[seg] += tempoffset; } if (!(symptr->flags & SA_MASK)) symptr->flags |= C_MASK; } } for (seg = 0, cptr = modptr->segsize; seg < NSEG; ++seg) { segsz[seg] += cntooffset(cptr, sizecount = segsizecount((unsigned) seg, modptr)); #ifndef EDOS /* adjust sizes to even to get quad boundaries */ /* this should be specifiable dynamically */ segsz[seg] = ld_roundup(segsz[seg], 4, bin_off_t); comsz[seg] = ld_roundup(comsz[seg], 4, bin_off_t); #endif cptr += sizecount; } } /* calculate seg positions now their sizes are known */ /* temp use fixed order 0D 0C 1D 1C 2D 2C ... */ /* #ifdef DATASEGS * Assume seg 0 is text and rest are data #else * Assume seg 1..3 are data, Seg 0 is real text, seg 4+ are far text #endif */ #ifdef EDOS if (btextoffset == 0) btextoffset = binheaderlength(commandname); #endif segpos[0] = segbase[0] = spos = btextoffset; combase[0] = segbase[0] + segsz[0]; segadj[1] = segadj[0] = -btextoffset; etextpadoff = etextoffset = combase[0] + comsz[0]; if (sepid) { etextpadoff = ld_roundup(etextoffset, 0x10, bin_off_t); segadj[1] += etextpadoff - bdataoffset; } #ifdef QMAGIC else if (uzp && bdataoffset == 0) { bdataoffset = ld_roundup(etextoffset, page_size(), bin_off_t); etextpadoff = ld_roundup(etextoffset, page_size(), bin_off_t); segadj[1] += etextpadoff - bdataoffset; } #endif else if (bdataoffset == 0) bdataoffset = etextpadoff; segpos[1] = segbase[1] = edataoffset = bdataoffset; combase[1] = segbase[1] + segsz[1]; #ifndef DATASEGS for (seg = 4; seg < NSEG; ++seg) { segpos[seg] = segbase[seg] = 0; combase[seg] = segbase[seg] + segsz[seg]; segadj[seg] = etextpadoff; etextpadoff += ld_roundup(segsz[seg] + comsz[seg], 0x10, bin_off_t); segadj[1] += ld_roundup(segsz[seg] + comsz[seg], 0x10, bin_off_t); } for (seg = 2; seg < 4; ++seg) #else for (seg = 2; seg < NSEG; ++seg) #endif { segpos[seg] = segbase[seg] = combase[seg - 1] + comsz[seg - 1]; #ifdef MC6809 if (seg == DPSEG) { /* temporarily have fixed DP seg */ /* adjust if nec so it only spans 1 page */ tempoffset = segsz[seg] + comsz[seg]; if (tempoffset > 0x100) fatalerror("direct page segment too large"); if ((((segbase[seg] + tempoffset) ^ segbase[seg]) & ~(bin_off_t) 0xFF) != 0) segpos[seg] = segbase[seg] = (segbase[seg] + 0xFF) & ~(bin_off_t) 0xFF; } #endif #ifdef QMAGIC if(seg==3 && uzp && !stripflag) /* XXX Stripped last seek needed */ { bin_off_t val; val = ld_roundup(segbase[seg]+segsz[seg], page_size(), bin_off_t); segsz[seg] = val - segbase[seg]; } #endif combase[seg] = segbase[seg] + segsz[seg]; segadj[seg] = segadj[seg - 1]; } /* relocate symbols by offsets of segments in memory */ for (modptr = modfirst; modptr != NUL_PTR; modptr = modptr->modnext) if (modptr->loadflag) { register struct symstruct **symparray; register struct symstruct *symptr; for (symparray = modptr->symparray; (symptr = *symparray) != NUL_PTR; ++symparray) if (symptr->modptr == modptr && !(symptr->flags & A_MASK)) { if (symptr->flags & (C_MASK | SA_MASK)) { #ifdef REL_OUTPUT #if 0 if (!reloc_output) #else if (!reloc_output || !(symptr->flags & I_MASK)) #endif #endif symptr->value += combase[symptr->flags & SEGM_MASK]; } else #ifdef REL_OUTPUT if (!reloc_output || !(symptr->flags & I_MASK)) #endif symptr->value += segbase[symptr->flags & SEGM_MASK]; } } /* adjust special symbols */ for (seg = 0; seg < NSEG; ++seg) { #ifdef DATASEGS if (segsz[seg] != 0) /* only count data of nonzero length */ #else if (segsz[seg] != 0 && seg < 4) #endif edataoffset = segbase[seg] + segsz[seg]; segboundary[5] = hexdigit[seg]; /* to __segX?H */ segboundary[6] = 'D'; setsym(segboundary, (tempoffset = segbase[seg]) + segsz[seg]); /* __segXDH */ segboundary[7] = 'L'; setsym(segboundary, tempoffset); /* __segXDL */ segboundary[6] = 'C'; setsym(segboundary, tempoffset = combase[seg]); /* __segXCL */ segboundary[7] = 'H'; setsym(segboundary, tempoffset + comsz[seg]); /* __segXCH */ #ifndef DATASEGS if( seg > 3 ) { segboundary[6] = 'S'; segboundary[7] = 'O'; setsym(segboundary, (bin_off_t)(segadj[seg]-segadj[0])/0x10); /* __segXSO */ } #endif } setsym("__etext", etextoffset); setsym("__edata", edataoffset); #ifdef DATASEGS setsym("__end", endoffset = combase[NSEG - 1] + comsz[NSEG - 1]); #else setsym("__end", endoffset = combase[3] + comsz[3]); #endif setsym("__segoff", (bin_off_t)(segadj[1]-segadj[0])/0x10); if( !bits32 ) { if( etextoffset > 65536L ) fatalerror("text segment too large for 16bit"); if( endoffset > 65536L ) fatalerror("data segment too large for 16bit"); } openout(outfilename); #ifdef REL_OUTPUT if (reloc_output) seektrel(FILEHEADERLENGTH + (unsigned long) (etextpadoff - btextoffset) + (unsigned long) (edataoffset - bdataoffset)); #endif #ifdef EDOS writeheader(commandname); #else writeheader(); #endif for (modptr = modfirst; modptr != NUL_PTR; modptr = modptr->modnext) if (modptr->loadflag) { linkmod(modptr); padmod(modptr); } /* dump symbol table */ #ifdef MINIX if (!stripflag) { #ifdef BSD_A_OUT unsigned stringoff; #endif seekout(FILEHEADERLENGTH + (unsigned long) (etextpadoff - btextoffset) + (unsigned long) (edataoffset - bdataoffset) #ifdef REL_OUTPUT + ((unsigned long) ndreloc + ntreloc) * RELOC_INFO_SIZE #endif ); extsym.n_was_numaux = extsym.n_was_type = 0; #ifdef BSD_A_OUT stringoff = 4; #endif for (modptr = modfirst; modptr != NUL_PTR; modptr = modptr->modnext) if (modptr->loadflag) { register struct symstruct **symparray; register struct symstruct *symptr; for (symparray = modptr->symparray; (symptr = *symparray) != NUL_PTR; ++symparray) if (symptr->modptr == modptr) { #ifdef BSD_A_OUT offtocn((char *) &extsym.n_was_strx, (bin_off_t) stringoff, 4); #else #if ELF_SYMS if( symptr->name[0] == '_' && symptr->name[1] ) strncpy((char *) extsym.n_was_name, symptr->name+1, sizeof extsym.n_was_name); else { memcpy((char *) extsym.n_was_name, "__", 2); strncpy((char *) extsym.n_was_name+2, symptr->name, sizeof(extsym.n_was_name)-2); } #else strncpy((char *) extsym.n_was_name, symptr->name, sizeof extsym.n_was_name); #endif #endif u4cn((char *) &extsym.n_value, (u4_t) symptr->value, sizeof extsym.n_value); if ((flags = symptr->flags) & A_MASK) extsym.n_was_sclass = N_ABS; else if (flags & (E_MASK | I_MASK)) extsym.n_was_sclass = C_EXT; else extsym.n_was_sclass = C_STAT; if (!(flags & I_MASK) || ( #ifdef REL_OUTPUT !reloc_output && #endif (flags & C_MASK))) switch (flags & (A_MASK | SEGM_MASK)) { #ifdef DATASEGS case 0: #else default: #endif extsym.n_was_sclass |= N_TEXT; case A_MASK: break; #ifdef DATASEGS default: #else case 1: case 2: case 3: case A_MASK|1: case A_MASK|2: case A_MASK|3: #endif if (flags & (C_MASK | SA_MASK)) extsym.n_was_sclass |= N_BSS; else extsym.n_was_sclass |= N_DATA; break; } writeout((char *) &extsym, sizeof extsym); ++nsym; #ifdef BSD_A_OUT #if ELF_SYMS stringoff += strlen(symptr->name); if( symptr->name[0] != '_' || symptr->name[1] == '\0' ) stringoff += 3; #else stringoff += strlen(symptr->name) + 1; #endif #endif } } #ifdef BSD_A_OUT offtocn((char *) &extsym.n_was_strx, (bin_off_t) stringoff, 4); writeout((char *) &extsym.n_was_strx, 4); for (modptr = modfirst; modptr != NUL_PTR; modptr = modptr->modnext) if (modptr->loadflag) { register struct symstruct **symparray; register struct symstruct *symptr; for (symparray = modptr->symparray; (symptr = *symparray) != NUL_PTR; ++symparray) if (symptr->modptr == modptr) #if ELF_SYMS { if( symptr->name[0] == '_' && symptr->name[1] ) writeout(symptr->name + 1, strlen(symptr->name)); else { writeout("__", 2); writeout(symptr->name, strlen(symptr->name) + 1); } } #else writeout(symptr->name, strlen(symptr->name) + 1); #endif } #endif seekout((unsigned long) offsetof(struct exec, a_syms)); u4cn(buf4, (u4_t) nsym * sizeof extsym, memsizeof(struct exec, a_syms)); writeout(buf4, memsizeof(struct exec, a_syms)); #ifdef REL_OUTPUT if( FILEHEADERLENGTH >= offsetof(struct exec, a_trsize)+8) { seekout((unsigned long) offsetof(struct exec, a_trsize)); u4cn(buf4, (u4_t) ntreloc * RELOC_INFO_SIZE, memsizeof(struct exec, a_trsize)); writeout(buf4, memsizeof(struct exec, a_trsize)); seekout((unsigned long) offsetof(struct exec, a_drsize)); u4cn(buf4, (u4_t) ndreloc * RELOC_INFO_SIZE, memsizeof(struct exec, a_drsize)); writeout(buf4, memsizeof(struct exec, a_drsize)); } #endif } #endif /* MINIX */ closeout(); #ifdef REL_OUTPUT if (!reloc_output) #endif executable(); } #ifdef EDOS PRIVATE unsigned binheaderlength(commandname) char *commandname; { unsigned count; char *name; struct entrylist *elptr; struct symstruct *startptr; count = 2 + 2 + 1; /* len len nul */ startptr = findsym("start"); for (elptr = entryfirst; elptr != NUL_PTR; elptr = elptr->elnext) { name = idconvert(elptr, commandname); count += strlen(name) + 1 + 2 + 1; /* nul off flg */ ourfree(name); if (startptr != NUL_PTR) count += 6; /* LBSR $xxxx and LBRA $xxxx */ } return count; } /* convert name of symbol (entry) list element to a Basic identifier */ /* new name is built in storage obtained from stralloc() */ /* the special name _main is converted to the command name first */ /* copy upper case and numerals, convert lower case to upper, ignore rest */ PRIVATE char *idconvert(elptr, commandname) struct entrylist *elptr; char *commandname; { char *name; char *newname; if (strcmp(name = elptr->elsymptr->name, "_main") == 0) name = commandname; newname = stralloc(name); { register char *t; register char *s; t = newname; s = name; do { if (*s >= '0' && *s <= '9' || *s >= 'A' && *s <= 'Z') *t++ = *s; if (*s >= 'a' && *s <= 'z') *t++ = *s + ('A' - 'a'); } while (*s++); *t = 0; } if (*newname < 'A') /* numeral or null */ fatalerror("bad entry name"); return newname; } #endif /* EDOS */ PRIVATE void linkmod(modptr) struct modstruct *modptr; { char buf[ABS_TEXT_MAX]; int command; unsigned char modify; bin_off_t offset; int symbolnum; struct symstruct **symparray; struct symstruct *symptr; setseg(0); relocsize = 2; symparray = modptr->symparray; openin(modptr->filename); /* does nothing if already open */ seekin(modptr->textoffset); while (TRUE) { if ((command = readchar()) < 0) prematureeof(); modify = command & MODIFY_MASK; switch (command & CM_MASK) { case CM_SPECIAL: switch (modify) { case CM_EOT: segpos[curseg] = spos; return; case CM_BYTE_SIZE: relocsize = 1; break; case CM_WORD_SIZE: relocsize = 2; break; case CM_LONG_SIZE: #ifdef LONG_OFFSETS relocsize = 4; break; #else fatalerror("relocation by long offsets not implemented"); #endif case CM_1_SKIP: skip(1); break; case CM_2_SKIP: skip(2); break; case CM_4_SKIP: skip(4); break; default: if ((modify -= CM_0_SEG) >= NSEG) inputerror("bad data in"); setseg(modify); break; } break; case CM_ABSOLUTE: if (modify == 0) modify = ABS_TEXT_MAX; readin(buf, (unsigned) modify); writeout(buf, (unsigned) modify); spos += (int) modify; break; case CM_OFFSET_RELOC: offset = readsize(relocsize); if (modify & R_MASK) { #ifndef DATASEGS int m = (modify & SEGM_MASK); if( curseg != m && m != SEGM_MASK ) interseg(modptr->filename, modptr->archentry, (char*)0); #endif offset -= (spos + relocsize); } offtocn(buf, segbase[modify & SEGM_MASK] + offset, relocsize); writeout(buf, relocsize); #ifdef REL_OUTPUT if (reloc_output) { u4_t bitfield; if (curseg == 0) { ++ntreloc; offtocn(buf, spos, 4); writetrel(buf, 4); } else { ++ndreloc; offtocn(buf, spos - segbase[1], 4); writedrel(buf, 4); } if ((modify & SEGM_MASK) == 0) bitfield = N_TEXT; else bitfield = N_DATA; if (modify & R_MASK) bitfield |= 1L << 24; if (relocsize == 2) bitfield |= 1L << 25; else if (relocsize == 4) bitfield |= 1L << 26; u4cn(buf, bitfield, 4); if (curseg == 0) writetrel(buf, 4); else writedrel(buf, 4); } #endif /* REL_OUTPUT */ spos += relocsize; break; case CM_SYMBOL_RELOC: symptr = symparray[symbolnum = readconvsize((unsigned) (modify & S_MASK ? 2 : 1))]; offset = readconvsize((unsigned) modify & OF_MASK); if (modify & R_MASK) { #ifndef DATASEGS int m = (symptr->flags & SEGM_MASK); if( curseg != m && m != SEGM_MASK ) interseg(modptr->filename, modptr->archentry, symptr->name); #endif offset -= (spos + relocsize); } #ifdef REL_OUTPUT if (!reloc_output || !(symptr->flags & I_MASK)) #endif offset += symptr->value; offtocn(buf, offset, relocsize); writeout(buf, relocsize); #ifdef REL_OUTPUT if (reloc_output) { u4_t bitfield; if (curseg == 0) { ++ntreloc; offtocn(buf, spos, 4); writetrel(buf, 4); } else { ++ndreloc; offtocn(buf, spos - segbase[1], 4); writedrel(buf, 4); } if (symptr->flags & I_MASK) bitfield = (1L << 27) | symbolnum; else if ((symptr->flags & SEGM_MASK) == 0) bitfield = N_TEXT; else if (symptr->flags & (C_MASK | SA_MASK)) bitfield = N_BSS; else bitfield = N_DATA; if (modify & R_MASK) bitfield |= 1L << 24; if (relocsize == 2) bitfield |= 1L << 25; else if (relocsize == 4) bitfield |= 1L << 26; u4cn(buf, bitfield, 4); if (curseg == 0) writetrel(buf, 4); else writedrel(buf, 4); } #endif /* REL_OUTPUT */ spos += relocsize; } } } PRIVATE void padmod(modptr) struct modstruct *modptr; { bin_off_t count; fastin_t seg; bin_off_t size; unsigned sizecount; char *sizeptr; for (seg = 0, sizeptr = modptr->segsize; seg < NSEG; ++seg) { size = cntooffset(sizeptr, sizecount = segsizecount((unsigned) seg, modptr)); sizeptr += sizecount; if ((count = segpos[seg] - segbase[seg]) != size) size_error(seg, count, size); /* pad to quad boundary */ /* not padding in-between common areas which sometimes get into file */ if ((size = ld_roundup(segpos[seg], 4, bin_off_t) - segpos[seg]) != 0) { setseg(seg); writenulls(size); segpos[seg] = spos; } segbase[seg] = segpos[seg]; } } PRIVATE void setsym(name, value) char *name; bin_off_t value; { struct symstruct *symptr; #ifdef REL_OUTPUT if (!reloc_output) #endif if ((symptr = findsym(name)) != NUL_PTR) symptr->value = value; } PRIVATE void symres(name) register char *name; { register struct symstruct *symptr; if ((symptr = findsym(name)) != NUL_PTR) { if ((symptr->flags & SEGM_MASK) == SEGM_MASK) symptr->flags &= ~SEGM_MASK | curseg; if (symptr->flags != (I_MASK | curseg) || symptr->value != 0) reserved(name); #ifdef REL_OUTPUT if (!reloc_output) #endif symptr->flags = E_MASK | curseg; /* show defined, not common */ } } /* set new segment */ PRIVATE void setseg(newseg) fastin_pt newseg; { if (newseg != curseg) { segpos[curseg] = spos; spos = segpos[curseg = newseg]; seekout(FILEHEADERLENGTH + (unsigned long) spos + (unsigned long) segadj[curseg]); } } PRIVATE void skip(countsize) unsigned countsize; { writenulls((bin_off_t) readsize(countsize)); } #ifdef EDOS PRIVATE void writeheader(commandname) char *commandname; { char buf[MAX_OFFSET_SIZE]; bin_off_t offset; unsigned headlength; char *name; struct entrylist *elptr; struct symstruct *startptr; headlength = binheaderlength(commandname); for (elptr = entryfirst; elptr != NUL_PTR; elptr = elptr->elnext) headlength -= 6; offset = headlength; startptr = findsym("start"); offtocn(buf, edataoffset, 2); writeout(buf, 2); writechar(0xFF); /* dummy data length 0xFFFF takes everything */ writechar(0xFF); for (elptr = entryfirst; elptr != NUL_PTR; elptr = elptr->elnext) { name = idconvert(elptr, commandname); writeout(name, (unsigned) strlen(name) + 1); ourfree(name); offtocn(buf, startptr == NUL_PTR ? elptr->elsymptr->value : offset, 2); writeout(buf, 2); writechar(0x82); /* 8 = set flags from here, 2 = cmd line */ offset += 6; /* LBSR $xxxx and LBRA $xxxx */ } writechar(0); if (startptr != NUL_PTR) { offset = headlength + 3; /* over 1st LBSR */ for (elptr = entryfirst; elptr != NUL_PTR; elptr = elptr->elnext) { writechar(0x17); /* LBSR */ offtocn(buf, startptr->value - offset, 2); writeout(buf, 2); writechar(0x16); /* LBRA */ offtocn(buf, elptr->elsymptr->value - offset - 3, 2); writeout(buf, 2); offset += 6; } } } #endif /* EDOS */ #ifdef MINIX PRIVATE void writeheader() { struct exec header; memset(&header, 0, sizeof header); #ifdef STANDARD_GNU_A_OUT #ifdef N_SET_MAGIC #ifdef QMAGIC if(uzp) N_SET_MAGIC(header, QMAGIC); else #endif N_SET_MAGIC(header, OMAGIC); #else *(unsigned short *) &header.a_magic = OMAGIC; /* XXX - works for 386BSD */ #endif #else header.a_magic[0] = A_MAGIC0; header.a_magic[1] = A_MAGIC1; #endif #ifdef REL_OUTPUT if (!reloc_output) #endif { #ifdef STANDARD_GNU_A_OUT #ifdef N_SET_FLAGS N_SET_FLAGS(header, 0); #else /* XXX - works for 386BSD */ #endif #else header.a_flags = sepid ? A_SEP : A_EXEC; if (uzp) header.a_flags |= A_UZP; #endif } #ifdef BSD_A_OUT #ifdef STANDARD_GNU_A_OUT #ifdef N_SET_FLAGS N_SET_MACHTYPE(header, M_386); #else /* XXX - works for 386BSD which doesn't define its own machtype :-( */ #endif #else header.a_cpu = (bits32 || reloc_output) ? A_I80386 : A_I8086; #endif #else header.a_cpu = bits32 ? A_I80386 : A_I8086; #endif #ifndef STANDARD_GNU_A_OUT header.a_hdrlen = FILEHEADERLENGTH; #endif #ifdef QMAGIC if (uzp) offtocn((char *) &header.a_text, etextpadoff - btextoffset+HEADERLEN, sizeof header.a_text); else #endif offtocn((char *) &header.a_text, etextpadoff - btextoffset, sizeof header.a_text); offtocn((char *) &header.a_data, edataoffset - bdataoffset, sizeof header.a_data); offtocn((char *) &header.a_bss, endoffset - edataoffset, sizeof header.a_bss); #ifdef REL_OUTPUT if (!reloc_output) #endif { offtocn((char *) &header.a_entry, btextoffset, sizeof header.a_entry); #ifndef STANDARD_GNU_A_OUT offtocn((char *) &header.a_total, (bin_off_t) (endoffset < 0x00010000L ? 0x00010000L : endoffset + 0x0008000L), sizeof header.a_total); #endif } if( FILEHEADERLENGTH ) writeout((char *) &header, FILEHEADERLENGTH); } #endif /* MINIX */ PRIVATE void writenulls(count) bin_off_t count; { long lcount = count; if( lcount < 0 ) fatalerror("org command requires reverse seek"); spos += count; while (count-- > 0) writechar(0); } #else #ifndef FUNCNAME #define FUNCNAME writebin #endif PUBLIC void FUNCNAME(outfilename, argsepid, argbits32, argstripflag, arguzp) char *outfilename; bool_pt argsepid; bool_pt argbits32; bool_pt argstripflag; bool_pt arguzp; { char * s = "WARNING: Native a.out generation not included, sorry\n"; write(2, s, strlen(s)); write_elks(outfilename, argsepid, argbits32, argstripflag, arguzp, 0); } #endif dev86-0.16.21/ld/writeemu.c000066400000000000000000000010121231050321700152050ustar00rootroot00000000000000/* * This uses a special version of writebin for bug compatibility with * the old bin86 package. * * This _should_ be replaced by a function that writes out a as86 object * but then it would completely **** up dosemu compiles. * * NOTE: A some time I intend to replace this with a routine that generates * an as86 object file. */ #undef A_OUT_INCL #define A_OUT_INCL "rel_aout.h" #define BSD_A_OUT 1 #define FILEHEADERLENGTH 32 #define ELF_SYMS 0 #define FUNCNAME write_dosemu #include "writebin.c" dev86-0.16.21/ld/writex86.c000066400000000000000000000471001231050321700150540ustar00rootroot00000000000000/* writex86.c - write binary file for linker */ /* Copyright (C) 1994 Bruce Evans */ #include "syshead.h" #include "x86_aout.h" #ifndef VERY_SMALL_MEMORY #include "v7_aout.h" #endif #ifndef MSDOS #include "x86_cpm86.h" #endif #include "const.h" #include "obj.h" #include "type.h" #include "globvar.h" #define btextoffset (text_base_value) #define bdataoffset (data_base_value) #define page_size() ((bin_off_t)4096) #ifndef ELF_SYMS #define ELF_SYMS 0 #endif #ifdef MSDOS # define FILEHEADERLENGTH (headerless?0:A_MINHDR) #else # ifdef VERY_SMALL_MEMORY # define FILEHEADERLENGTH (headerless?0:(cpm86?CPM86_HEADERLEN:A_MINHDR)) # else # define FILEHEADERLENGTH (headerless?0:(cpm86?CPM86_HEADERLEN:(v7?V7_HEADERLEN:A_MINHDR))) # endif #endif /* part of header not counted in offsets */ #define DPSEG 2 #define CM_MASK 0xC0 #define MODIFY_MASK 0x3F #define S_MASK 0x04 #define OF_MASK 0x03 #define CM_SPECIAL 0 #define CM_ABSOLUTE 0x40 #define CM_OFFSET_RELOC 0x80 #define CM_SYMBOL_RELOC 0xC0 #define CM_EOT 0 #define CM_BYTE_SIZE 1 #define CM_WORD_SIZE 2 #define CM_LONG_SIZE 3 #define CM_1_SKIP 17 #define CM_2_SKIP 18 #define CM_4_SKIP 19 #define CM_0_SEG 32 #define ABS_TEXT_MAX 64 #define offsetof(struc, mem) ((int) &((struc *) 0)->mem) #define memsizeof(struc, mem) sizeof(((struc *) 0)->mem) PRIVATE bool_t bits32; /* nonzero for 32-bit executable */ PRIVATE bin_off_t combase[NSEG];/* bases of common parts of segments */ PRIVATE bin_off_t comsz[NSEG]; /* sizes of common parts of segments */ PRIVATE fastin_t curseg; /* current segment, 0 to $F */ PRIVATE bin_off_t edataoffset; /* end of data */ PRIVATE bin_off_t endoffset; /* end of bss */ PRIVATE bin_off_t etextoffset; /* end of text */ PRIVATE bin_off_t etextpadoff; /* end of padded text */ PRIVATE unsigned nsym; /* number of symbols written */ PRIVATE unsigned relocsize; /* current relocation size 1, 2 or 4 */ PRIVATE bin_off_t segadj[NSEG]; /* adjusts (file offset - seg offset) */ /* depends on zero init */ PRIVATE bin_off_t segbase[NSEG];/* bases of data parts of segments */ PRIVATE char segboundary[9] = "__seg0DH"; /* name of seg boundary __seg0DL to __segfCH */ PRIVATE bin_off_t segpos[NSEG]; /* segment positions for current module */ PRIVATE bin_off_t segsz[NSEG]; /* sizes of data parts of segments */ /* depends on zero init */ PRIVATE bool_t sepid; /* nonzero for separate I & D */ PRIVATE bool_t stripflag; /* nonzero to strip symbols */ PRIVATE bin_off_t spos; /* position in current seg */ PRIVATE bool_t uzp; /* nonzero for unmapped zero page */ PRIVATE bool_t xsym; /* extended symbol table */ FORWARD void linkmod P((struct modstruct *modptr)); FORWARD void padmod P((struct modstruct *modptr)); FORWARD void setsym P((char *name, bin_off_t value)); FORWARD void symres P((char *name)); FORWARD void setseg P((fastin_pt newseg)); FORWARD void skip P((unsigned countsize)); FORWARD void writeheader P((void)); #ifndef VERY_SMALL_MEMORY FORWARD void v7header P((void)); #endif #ifndef MSDOS FORWARD void cpm86header P((void)); #endif FORWARD void writenulls P((bin_off_t count)); EXTERN bool_t reloc_output; /* write binary file */ PUBLIC void write_elks(outfilename, argsepid, argbits32, argstripflag, arguzp, argxsym) char *outfilename; bool_pt argsepid; bool_pt argbits32; bool_pt argstripflag; bool_pt arguzp; bool_pt argxsym; { char buf4[4]; char *cptr; struct nlist extsym; flags_t flags; struct modstruct *modptr; fastin_t seg; unsigned sizecount; bin_off_t tempoffset; if( reloc_output ) #ifndef MSDOS fatalerror("Output binformat not configured relocatable, use -N"); #else fatalerror("Cannot use -r under MSDOS, sorry"); #endif sepid = argsepid; bits32 = argbits32; stripflag = argstripflag; uzp = arguzp; xsym = argxsym; if (uzp) { if (btextoffset == 0) btextoffset = page_size(); if (bdataoffset == 0 && sepid) bdataoffset = page_size(); } /* reserve special symbols use curseg to pass parameter to symres() */ for (curseg = 0; curseg < NSEG; ++curseg) { segboundary[5] = hexdigit[curseg]; /* to __segX?H */ segboundary[6] = 'D'; symres(segboundary); /* __segXDH */ segboundary[7] = 'L'; symres(segboundary); /* __segXDL */ segboundary[6] = 'C'; symres(segboundary); /* __segXCL */ segboundary[7] = 'H'; symres(segboundary); /* __segXCH */ #ifndef DATASEGS if( curseg > 3 ) { segboundary[6] = 'S'; segboundary[7] = 'O'; symres(segboundary); /* __segXSO */ } #endif } curseg = 3; symres("__edata"); symres("__end"); symres("__heap_top"); curseg = 0; /* text seg, s.b. variable */ symres("__etext"); symres("__segoff"); /* calculate segment and common sizes (sum over loaded modules) */ /* use zero init of segsz[] */ /* also relocate symbols relative to starts of their segments */ for (modptr = modfirst; modptr != NUL_PTR; modptr = modptr->modnext) if (modptr->loadflag) { register struct symstruct **symparray; register struct symstruct *symptr; for (symparray = modptr->symparray; (symptr = *symparray) != NUL_PTR; ++symparray) if (symptr->modptr == modptr && !(symptr->flags & A_MASK)) { if (!(symptr->flags & (I_MASK | SA_MASK))) { /* relocate by offset of module in segment later */ /* relocate by offset of segment in memory special */ /* symbols get relocated improperly */ symptr->value += segsz[symptr->flags & SEGM_MASK]; } else if (symptr->value == 0) { undefined(symptr->name); } else { tempoffset = ld_roundup(symptr->value, 4, bin_off_t); /* temp kludge quad alignment for 386 */ symptr->value = comsz[seg = symptr->flags & SEGM_MASK]; comsz[seg] += tempoffset; if (!(symptr->flags & SA_MASK)) symptr->flags |= C_MASK; } } for (seg = 0, cptr = modptr->segsize; seg < NSEG; ++seg) { segsz[seg] += cntooffset(cptr, sizecount = segsizecount((unsigned) seg, modptr)); /* adjust sizes to even to get quad boundaries */ /* this should be specifiable dynamically */ segsz[seg] = ld_roundup(segsz[seg], 4, bin_off_t); comsz[seg] = ld_roundup(comsz[seg], 4, bin_off_t); cptr += sizecount; } } /* calculate seg positions now their sizes are known */ /* #ifdef DATASEGS * Assume seg 0 is text and rest are data #else * Assume seg 1..3 are data, Seg 0 is real text, seg 4+ are far text #endif */ segpos[0] = segbase[0] = spos = btextoffset; combase[0] = segbase[0] + segsz[0]; segadj[1] = segadj[0] = -btextoffset; etextpadoff = etextoffset = combase[0] + comsz[0]; if (sepid) { etextpadoff = ld_roundup(etextoffset, 0x10, bin_off_t); segadj[1] += etextpadoff - bdataoffset; } else if (bdataoffset == 0) bdataoffset = etextpadoff; segpos[1] = segbase[1] = edataoffset = bdataoffset; combase[1] = segbase[1] + segsz[1]; #ifndef DATASEGS for (seg = 4; seg < NSEG; ++seg) { segpos[seg] = segbase[seg] = 0; combase[seg] = segbase[seg] + segsz[seg]; segadj[seg] = etextpadoff; etextpadoff += ld_roundup(segsz[seg] + comsz[seg], 0x10, bin_off_t); segadj[1] += ld_roundup(segsz[seg] + comsz[seg], 0x10, bin_off_t); } for (seg = 2; seg < 4; ++seg) #else for (seg = 2; seg < NSEG; ++seg) #endif { segpos[seg] = segbase[seg] = combase[seg - 1] + comsz[seg - 1]; #ifdef MC6809 if (seg == DPSEG) { /* temporarily have fixed DP seg */ /* adjust if nec so it only spans 1 page */ tempoffset = segsz[seg] + comsz[seg]; if (tempoffset > 0x100) fatalerror("direct page segment too large"); if ((((segbase[seg] + tempoffset) ^ segbase[seg]) & ~(bin_off_t) 0xFF) != 0) segpos[seg] = segbase[seg] = (segbase[seg] + 0xFF) & ~(bin_off_t) 0xFF; } #endif combase[seg] = segbase[seg] + segsz[seg]; segadj[seg] = segadj[seg - 1]; } /* relocate symbols by offsets of segments in memory */ for (modptr = modfirst; modptr != NUL_PTR; modptr = modptr->modnext) if (modptr->loadflag) { register struct symstruct **symparray; register struct symstruct *symptr; for (symparray = modptr->symparray; (symptr = *symparray) != NUL_PTR; ++symparray) if (symptr->modptr == modptr && !(symptr->flags & A_MASK)) { if (symptr->flags & (C_MASK | SA_MASK)) symptr->value += combase[symptr->flags & SEGM_MASK]; else symptr->value += segbase[symptr->flags & SEGM_MASK]; } } /* adjust special symbols */ for (seg = 0; seg < NSEG; ++seg) { #ifdef DATASEGS if (segsz[seg] != 0) /* only count data of nonzero length */ #else if (segsz[seg] != 0 && seg < 4) #endif edataoffset = segbase[seg] + segsz[seg]; segboundary[5] = hexdigit[seg]; /* to __segX?H */ segboundary[6] = 'D'; setsym(segboundary, (tempoffset = segbase[seg]) + segsz[seg]); /* __segXDH */ segboundary[7] = 'L'; setsym(segboundary, tempoffset); /* __segXDL */ segboundary[6] = 'C'; setsym(segboundary, tempoffset = combase[seg]); /* __segXCL */ segboundary[7] = 'H'; setsym(segboundary, tempoffset + comsz[seg]); /* __segXCH */ #ifndef DATASEGS if( seg > 3 ) { segboundary[6] = 'S'; segboundary[7] = 'O'; setsym(segboundary, (bin_off_t)(segadj[seg]-segadj[0])/0x10); /* __segXSO */ } #endif } setsym("__etext", etextoffset); setsym("__edata", edataoffset); #ifdef DATASEGS setsym("__end", endoffset = combase[NSEG - 1] + comsz[NSEG - 1]); #else setsym("__end", endoffset = combase[3] + comsz[3]); #endif setsym("__segoff", (bin_off_t)(segadj[1]-segadj[0])/0x10); if( !bits32 ) { if( etextoffset > 65536L ) fatalerror("text segment too large for 16bit"); if( endoffset > 65536L ) fatalerror("data segment too large for 16bit"); } if( heap_top_value < 0x100 || endoffset > heap_top_value-0x100) heap_top_value = endoffset + 0x8000; if( heap_top_value > 0x10000 && !bits32 ) heap_top_value = 0x10000; setsym("__heap_top", (bin_off_t)heap_top_value); openout(outfilename); #ifndef MSDOS if (cpm86) cpm86header(); else #endif #ifndef VERY_SMALL_MEMORY if (v7) v7header(); else #endif writeheader(); for (modptr = modfirst; modptr != NUL_PTR; modptr = modptr->modnext) if (modptr->loadflag) { linkmod(modptr); padmod(modptr); } /* dump symbol table */ if (!stripflag) { seekout(FILEHEADERLENGTH + (unsigned long) (etextpadoff - btextoffset) + (unsigned long) (edataoffset - bdataoffset) ); extsym.n_numaux = extsym.n_type = 0; for (modptr = modfirst; modptr != NUL_PTR; modptr = modptr->modnext) if (modptr->loadflag) { register struct symstruct **symparray; register struct symstruct *symptr; for (symparray = modptr->symparray; (symptr = *symparray) != NUL_PTR; ++symparray) if (symptr->modptr == modptr) { #if ELF_SYMS if (symptr->name[0] == '_' && symptr->name[1] ) strncpy((char *) extsym.n_name, symptr->name+1, sizeof extsym.n_name); else { memcpy((char *) extsym.n_name, "$", 1); strncpy((char *) extsym.n_name+1, symptr->name, sizeof(extsym.n_name)-1); } #else strncpy((char *) extsym.n_name, symptr->name, sizeof extsym.n_name); #endif u4cn((char *) &extsym.n_value, (u4_t) symptr->value, sizeof extsym.n_value); if ((flags = symptr->flags) & A_MASK) extsym.n_sclass = N_ABS; else if (flags & (E_MASK | I_MASK)) extsym.n_sclass = C_EXT; else extsym.n_sclass = C_STAT; if (!(flags & I_MASK) || flags & C_MASK) switch (flags & (A_MASK | SEGM_MASK)) { #ifdef DATASEGS case 0: #else default: #endif extsym.n_sclass |= N_TEXT; case A_MASK: break; #ifdef DATASEGS default: #else case 1: case 2: case 3: case A_MASK|1: case A_MASK|2: case A_MASK|3: #endif if (flags & (C_MASK | SA_MASK)) extsym.n_sclass |= N_BSS; else extsym.n_sclass |= N_DATA; break; } writeout((char *) &extsym, sizeof extsym); ++nsym; #if !ELF_SYMS if( xsym ) { int i; extsym.n_sclass = 0; memset((void*)&extsym.n_value,0, sizeof(extsym.n_value)); for(i=sizeof extsym.n_name; iname); i+=sizeof extsym.n_name) { strncpy((char *) extsym.n_name, symptr->name+i, sizeof extsym.n_name); writeout((char *) &extsym, sizeof extsym); ++nsym; } } #endif } } seekout((unsigned long) offsetof(struct exec, a_syms)); u4cn(buf4, (u4_t) nsym * sizeof extsym, memsizeof(struct exec, a_syms)); writeout(buf4, memsizeof(struct exec, a_syms)); } closeout(); executable(); } PRIVATE void linkmod(modptr) struct modstruct *modptr; { char buf[ABS_TEXT_MAX]; int command; unsigned char modify; bin_off_t offset; int symbolnum; struct symstruct **symparray; struct symstruct *symptr; setseg(0); relocsize = 2; symparray = modptr->symparray; openin(modptr->filename); /* does nothing if already open */ seekin(modptr->textoffset); while (TRUE) { if ((command = readchar()) < 0) prematureeof(); modify = command & MODIFY_MASK; switch (command & CM_MASK) { case CM_SPECIAL: switch (modify) { case CM_EOT: segpos[curseg] = spos; return; case CM_BYTE_SIZE: relocsize = 1; break; case CM_WORD_SIZE: relocsize = 2; break; case CM_LONG_SIZE: #ifdef LONG_OFFSETS relocsize = 4; break; #else fatalerror("relocation by long offsets not implemented"); #endif case CM_1_SKIP: skip(1); break; case CM_2_SKIP: skip(2); break; case CM_4_SKIP: skip(4); break; default: if ((modify -= CM_0_SEG) >= NSEG) inputerror("bad data in"); setseg(modify); break; } break; case CM_ABSOLUTE: if (modify == 0) modify = ABS_TEXT_MAX; readin(buf, (unsigned) modify); writeout(buf, (unsigned) modify); spos += (int) modify; break; case CM_OFFSET_RELOC: offset = readsize(relocsize); if (modify & R_MASK) { #ifndef DATASEGS int m = (modify & SEGM_MASK); if( curseg != m && m != SEGM_MASK ) interseg(modptr->filename, modptr->archentry, (char*)0); #endif offset -= (spos + relocsize); } offtocn(buf, segbase[modify & SEGM_MASK] + offset, relocsize); writeout(buf, relocsize); spos += relocsize; break; case CM_SYMBOL_RELOC: symptr = symparray[symbolnum = readconvsize((unsigned) (modify & S_MASK ? 2 : 1))]; offset = readconvsize((unsigned) modify & OF_MASK); if (modify & R_MASK) { #ifndef DATASEGS int m = (symptr->flags & SEGM_MASK); if( curseg != m && m != SEGM_MASK ) interseg(modptr->filename, modptr->archentry, symptr->name); #endif offset -= (spos + relocsize); } offset += symptr->value; offtocn(buf, offset, relocsize); writeout(buf, relocsize); spos += relocsize; } } } PRIVATE void padmod(modptr) struct modstruct *modptr; { bin_off_t count; fastin_t seg; bin_off_t size; unsigned sizecount; char *sizeptr; for (seg = 0, sizeptr = modptr->segsize; seg < NSEG; ++seg) { size = cntooffset(sizeptr, sizecount = segsizecount((unsigned) seg, modptr)); sizeptr += sizecount; if ((count = segpos[seg] - segbase[seg]) != size) size_error(seg, count, size); /* pad to quad boundary */ /* not padding in-between common areas which sometimes get into file */ if ((size = ld_roundup(segpos[seg], 4, bin_off_t) - segpos[seg]) != 0) { setseg(seg); writenulls(size); segpos[seg] = spos; } segbase[seg] = segpos[seg]; } } PRIVATE void setsym(name, value) char *name; bin_off_t value; { struct symstruct *symptr; if ((symptr = findsym(name)) != NUL_PTR) symptr->value = value; } PRIVATE void symres(name) register char *name; { register struct symstruct *symptr; if ((symptr = findsym(name)) != NUL_PTR) { if ((symptr->flags & SEGM_MASK) == SEGM_MASK) symptr->flags &= ~SEGM_MASK | curseg; if (symptr->flags != (I_MASK | curseg) || symptr->value != 0) reserved(name); symptr->flags = E_MASK | curseg; /* show defined, not common */ } } /* set new segment */ PRIVATE void setseg(newseg) fastin_pt newseg; { if (newseg != curseg) { segpos[curseg] = spos; spos = segpos[curseg = newseg]; seekout(FILEHEADERLENGTH + (unsigned long) spos + (unsigned long) segadj[curseg]); } } PRIVATE void skip(countsize) unsigned countsize; { writenulls((bin_off_t) readsize(countsize)); } #ifndef MSDOS PRIVATE void cpm86header() { struct cpm86_exec header; memset(&header, 0, sizeof header); if (sepid) { header.ce_group[0].cg_type = CG_CODE; u2c2(header.ce_group[0].cg_len, (15 + etextpadoff) / 16); u2c2(header.ce_group[0].cg_min, (15 + etextpadoff) / 16); header.ce_group[1].cg_type = CG_DATA; u2c2(header.ce_group[1].cg_len, (15 + edataoffset) / 16); u2c2(header.ce_group[1].cg_min, (15 + endoffset ) / 16); u2c2(header.ce_group[1].cg_max, 0x1000); } else { header.ce_group[0].cg_type = CG_CODE; u2c2(header.ce_group[0].cg_len, (15 + edataoffset) / 16); u2c2(header.ce_group[0].cg_min, (15 + endoffset ) / 16); } if( FILEHEADERLENGTH ) writeout((char *) &header, FILEHEADERLENGTH); } #endif PRIVATE void writeheader() { struct exec header; memset(&header, 0, sizeof header); header.a_magic[0] = A_MAGIC0; header.a_magic[1] = A_MAGIC1; header.a_flags = sepid ? A_SEP : A_EXEC; if (uzp) header.a_flags |= A_UZP; header.a_cpu = bits32 ? A_I80386 : A_I8086; header.a_hdrlen = FILEHEADERLENGTH; offtocn((char *) &header.a_text, etextpadoff - btextoffset, sizeof header.a_text); offtocn((char *) &header.a_data, edataoffset - bdataoffset, sizeof header.a_data); offtocn((char *) &header.a_bss, endoffset - edataoffset, sizeof header.a_bss); if (uzp) offtocn((char *) &header.a_entry, page_size(), sizeof header.a_entry); offtocn((char *) &header.a_total, (bin_off_t) heap_top_value, sizeof header.a_total); if( FILEHEADERLENGTH ) writeout((char *) &header, FILEHEADERLENGTH); } #ifndef VERY_SMALL_MEMORY PRIVATE void v7header() { struct v7_exec header; if( sizeof header != FILEHEADERLENGTH ) fatalerror("Executable miscompiled, computed wrong header size"); memset(&header, 0, sizeof header); if( bits32 ) fatalerror("V7 a.out format is for 16-bit only"); offtocn((char *) &header.magic, sepid ? V7_MAGIC3 : V7_OMAGIC, sizeof header.magic); offtocn((char *) &header.textsize, etextpadoff - btextoffset, sizeof header.textsize); offtocn((char *) &header.datasize, edataoffset - bdataoffset, sizeof header.datasize); offtocn((char *) &header.bsssize, endoffset - edataoffset, sizeof header.bsssize); if( !stripflag ) fatalerror("Symbol table not implemented for V7 yet"); if( uzp ) fatalerror("No QMAGIC for V7"); offtocn((char *) &header.entry, entryfirst->elsymptr->value, sizeof header.entry); if( FILEHEADERLENGTH ) writeout((char *) &header, FILEHEADERLENGTH); } #endif PRIVATE void writenulls(count) bin_off_t count; { long lcount = count; spos += count; #if 0 /* This will only work if we record the highest spos found an seek there * at the end of the generation */ seekout(FILEHEADERLENGTH + (unsigned long) spos + (unsigned long) segadj[curseg]); return; #endif if( lcount < 0 ) fatalerror("org command requires reverse seek"); while (count-- > 0) writechar(0); } dev86-0.16.21/ld/x86_aout.h000066400000000000000000000105231231050321700150350ustar00rootroot00000000000000/* Copyright (C) 1990-1996 * This file is part of the ld86 command for Linux-86 * It is distributed under the GNU Library General Public License. * * - This may actually be BSD or Minix code, can someone clarify please. -RDB */ #ifndef __AOUT_H #define __AOUT_H /* If the host isn't an x86 all bets are off, use chars. */ #if defined(i386) || defined(__BCC__) || defined(MSDOS) typedef long Long; #define __OUT_OK 1 #else /* Beware: this will probably allow some BE hosts to generate broken files. */ #ifdef INT32_MAX #include typedef int32_t Long; #define __OUT_OK 1 #else typedef char Long[4]; #endif #endif struct exec { /* a.out header */ unsigned char a_magic[2]; /* magic number */ unsigned char a_flags; /* flags, see below */ unsigned char a_cpu; /* cpu id */ unsigned char a_hdrlen; /* length of header */ unsigned char a_unused; /* reserved for future use */ unsigned char a_version[2]; /* version stamp (not used at present) */ Long a_text; /* size of text segement in bytes */ Long a_data; /* size of data segment in bytes */ Long a_bss; /* size of bss segment in bytes */ Long a_entry; /* entry point */ Long a_total; /* total memory allocated */ Long a_syms; /* size of symbol table */ /* SHORT FORM ENDS HERE */ Long a_trsize; /* text relocation size */ Long a_drsize; /* data relocation size */ Long a_tbase; /* text relocation base */ Long a_dbase; /* data relocation base */ }; #define A_MAGIC0 (unsigned char) 0x01 #define A_MAGIC1 (unsigned char) 0x03 #define BADMAG(X) ((X).a_magic[0] != A_MAGIC0 ||(X).a_magic[1] != A_MAGIC1) /* CPU Id of TARGET machine (byte order coded in low order two bits) */ #define A_NONE 0x00 /* unknown */ #define A_I8086 0x04 /* intel i8086/8088 */ #define A_M68K 0x0B /* motorola m68000 */ #define A_NS16K 0x0C /* national semiconductor 16032 */ #define A_I80386 0x10 /* intel i80386 */ #define A_SPARC 0x17 /* Sun SPARC */ #define A_BLR(cputype) ((cputype&0x01)!=0) /* TRUE if bytes left-to-right */ #define A_WLR(cputype) ((cputype&0x02)!=0) /* TRUE if words left-to-right */ /* Flags. */ #define A_UZP 0x01 /* unmapped zero page (pages) */ #define A_PAL 0x02 /* page aligned executable */ #define A_NSYM 0x04 /* new style symbol table */ #define A_EXEC 0x10 /* executable */ #define A_SEP 0x20 /* separate I/D */ #define A_PURE 0x40 /* pure text */ #define A_TOVLY 0x80 /* text overlay */ /* Offsets of various things. */ #define A_MINHDR 32 #define A_TEXTPOS(X) ((long)(X).a_hdrlen) #define A_HASRELS(X) ((X).a_hdrlen > (unsigned char) A_MINHDR) #define A_HASEXT(X) ((X).a_hdrlen > (unsigned char) (A_MINHDR + 8)) #define A_HASLNS(X) ((X).a_hdrlen > (unsigned char) (A_MINHDR + 16)) #define A_HASTOFF(X) ((X).a_hdrlen > (unsigned char) (A_MINHDR + 24)) #ifdef __OUT_OK #define A_DATAPOS(X) (A_TEXTPOS(X) + (X).a_text) #define A_TRELPOS(X) (A_DATAPOS(X) + (X).a_data) #define A_DRELPOS(X) (A_TRELPOS(X) + (X).a_trsize) #define A_SYMPOS(X) (A_TRELPOS(X) + (A_HASRELS(X) ? \ ((X).a_trsize + (X).a_drsize) : 0)) #endif struct reloc { long r_vaddr; /* virtual address of reference */ unsigned short r_symndx; /* internal segnum or extern symbol num */ unsigned short r_type; /* relocation type */ }; /* r_tyep values: */ #define R_ABBS 0 #define R_RELLBYTE 2 #define R_PCRBYTE 3 #define R_RELWORD 4 #define R_PCRWORD 5 #define R_RELLONG 6 #define R_PCRLONG 7 #define R_REL3BYTE 8 #define R_KBRANCHE 9 /* r_symndx for internal segments */ #define S_ABS ((unsigned short)-1) #define S_TEXT ((unsigned short)-2) #define S_DATA ((unsigned short)-3) #define S_BSS ((unsigned short)-4) struct nlist { /* symbol table entry */ char n_name[8]; /* symbol name */ Long n_value; /* value */ unsigned char n_sclass; /* storage class */ unsigned char n_numaux; /* number of auxiliary entries (not used) */ unsigned short n_type; /* language base and derived type (not used) */ }; /* Low bits of storage class (section). */ #define N_SECT 07 /* section mask */ #define N_UNDF 00 /* undefined */ #define N_ABS 01 /* absolute */ #define N_TEXT 02 /* text */ #define N_DATA 03 /* data */ #define N_BSS 04 /* bss */ #define N_COMM 05 /* (common) */ /* High bits of storage class. */ #define N_CLASS 0370 /* storage class mask */ #define C_NULL 0 #define C_EXT 0020 /* external symbol */ #define C_STAT 0030 /* static */ #endif /* _AOUT_H */ dev86-0.16.21/ld/x86_cpm86.h000066400000000000000000000021561231050321700150250ustar00rootroot00000000000000/* Copyright (C) 2002 * This file is part of the ld86 command for Linux-86 * It is distributed under the GNU Library General Public License. * * CP/M-86 CMD file header */ #ifndef __CPM86_H #define __CPM86_H typedef char Short16[2]; struct cpm86_group { unsigned char cg_type; /* 1=Code 2=Data */ Short16 cg_len; /* Group length, paragraphs */ Short16 cg_base; /* Group address, normally 0 for relocatable */ Short16 cg_min; /* Minimum size, normally = group length */ Short16 cg_max; /* Maximum size, normally 0x1000 (64k) */ }; struct cpm86_exec { /* CP/M-86 header */ struct cpm86_group ce_group[8]; unsigned char ce_spare[51]; Short16 ce_rsxs; /* Record with RSX list */ Short16 ce_fixups; /* Record with fixups */ unsigned char ce_flags; /* Concurrent CP/M flags */ }; /* Group types */ #define CG_EMPTY 0 #define CG_CODE 1 #define CG_DATA 2 #define CG_EXTRA 3 #define CG_STACK 4 #define CG_AUX1 5 #define CG_AUX2 6 #define CG_AUX3 7 #define CG_AUX4 8 #define CG_PURE 9 /* Code that is known to be pure */ #define CPM86_HEADERLEN 0x80 #endif /* _CPM86_H */ dev86-0.16.21/libbsd/000077500000000000000000000000001231050321700140465ustar00rootroot00000000000000dev86-0.16.21/libbsd/Make.defs000066400000000000000000000031341231050321700155670ustar00rootroot00000000000000# Copyright (C) 1995,1996 Robert de Bath # This file is part of the Linux-8086 C library and is distributed # under the GNU Library General Public License. # Set PLATFORM to i386-Linux to build for Linux/386 and to i86-ELKS to # build for ELKS. This doesn't quite work yet, though, because of some of # the platform and/or compiler-specific code flying around here. # Eventually, compiler-specificity won't be an issue, and we can put # platform-specific code in i86/ and i386/. -Nat # Define enviroment var for others. ifeq ($(PLATFORM),) PLATFORM=i86-ELKS #PLATFORM=i86-DOS #PLATFORM=i386-Linux endif VERMAJOR=0 VERMINOR=0 VERPATCH=4 VER=$(VERMAJOR).$(VERMINOR).$(VERPATCH) LIBDEFS=-D__LIBBSD__ LIBBSD=libbsd.a ifneq ($(PLATFORM),i386-Linux) # Normal standard 8086 code ifeq ($(PLATFORM),i86-ELKS) ARCH=-0 # 8086 elks code With "Caller saves" and "First arg in AX" # ARCH=-0 -C-c -C-f endif # MSDOS COM file (msdos libs don't support "First arg in AX") ifeq ($(PLATFORM),i86-DOS) ARCH=-0 -d -D__MSDOS__ LIBC=libdos.a endif # BCC 386. ifeq ($(PLATFORM),i386-BCC) ARCH=-3 endif CC=bcc $(ARCH) CCFLAGS=-O -I -I$(TOP)/libc/include LKFLAGS=-L -L$(TOP)/ -s else # ifeq ($(PLATFORM),i386-Linux) CC=gcc $(ARCH) # ARCH=-b i486-linuxaout LKFLAGS=-static -N CCFLAGS=-O6 -fomit-frame-pointer -I- -I$(TOP)/include -I. -fno-builtin WALL= -ansi -pedantic -Wwrite-strings -Wpointer-arith -Wcast-qual \ -Wcast-align -Wtraditional -Wstrict-prototypes -Wmissing-prototypes \ -Wnested-externs -Winline -Wshadow endif # ifeq ($(PLATFORM),i386-Linux) CFLAGS=$(CCFLAGS) $(LIBDEFS) LDFLAGS=$(LKFLAGS) dev86-0.16.21/libbsd/Makefile000066400000000000000000000017011231050321700155050ustar00rootroot00000000000000# libbsd A collection of library modules similar or equal to their # BSD UNIX equivalents, to make the job of porting BSD pro- # grams to LINUX easier. # # Author: Rick Sladkey, # Ported to linux-86 (by removing select.c): Dick Porter # # This file is part of the Linux-8086 C library and is distributed # under the GNU Library General Public License. TOP=$(TOPDIR) include Make.defs LIBBSD=libbsd.a TARGETS=$(LIBBSD) SRCS= daemon.c logwtmp.c logout.c pty.c login_tty.c \ sgtty.c cfsetspeed.c revoke.c setpassent.c \ checkrhosts.c OBJS=$(SRCS:.c=.o) TXT=COPYING Changes Contributors MAGIC \ Make.defs Makefile New_subdir Pre_main README TODO KERNEL all: $(TARGETS) install: all install -d $(BCCHOME) install -d $(LIBDIR)/i86 install -m 644 $(LIBBSD) $(LIBDIR)/i86 tests: dummy make -C tests $(LIBBSD): $(OBJS) $(AR) rc $(LIBBSD) $(OBJS) realclean: clean clean: dummy rm -f *.o rm -f $(LIBBSD) dummy: dev86-0.16.21/libbsd/README000066400000000000000000000114361231050321700147330ustar00rootroot00000000000000 LINUX NET DISTRIBUTION Version 0.03 Fred N. van Kempen Ross Biro Rick Sladkey The NET distribution for LINUX is a complete set of executables, setup files, documentation and all the sources needed to rebuild the package. It is intended as the `official' NET package for the LINUX operating system, mostly to get rid of the current situation of total chaos in NETland... The first distribution has been done by Ross Biro, who wrote the TCP/IP stuff in the LINUX kernel to start with. As usual, the Berkeley BSD UNIX software was taken as a base for this distri- bution. Several `foreign' programs are included as well. To make porting easy, a library has been built which contains the modules from BSD UNIX that were missing in the LINUX library. They are declared in the header files that go with it. These files must be copied to the /usr/net/include/bsd directory and a symbolic link must be created from /usr/include/bsd. This is a compliation of some net sources, mostly from bsd-net2. I have made an effort to get the programs to compile with few or no changes except for a new Makefile. This resulted in a bsd include directory and a bsd library. Take a look at them to see what types of things are required to get BSD sources to compile correctly without changes. Some of the tricks are pretty ugly. Please don't laugh... Everything should compile straight with the libc-4.2 libraries. Just type "make" in this directory. You may have to do some surgery on libbsd/libbsd.a to get things to compile with libc-4.1. Notes ===== bsd: The directory "bsd" contains include files that, for the most part, just overload include files of the same name from /usr/include. It provides some BSD things like "union wait" and others. libbsd: The libbsd.a archive is a small library of some functions that are not in our libc as well as some emulation support functions referenced in the bsd header files. Notably, it includes a half-decent transparent sgtty emulation package. inetd: Works. Only pathname changes. ftp: Works. No changes. ftpd: I find that ls with ftpd doesn't work very often. It reports "Transport endpoint already connected" 9 times out of 10. I think this is a bug in the kernel which will be fixed in a subsequent release. There was a memory allocation bug in the original source, look for "#ifdef linux". Also, the shadow password stuff is not compiled in as I haven't had a chance to mess with that. telnet: Works but see the man page for info about the .telnetrc file and other new options. This is a really nice telnet with rlogin emulation and lots of other stuff not present in older telnets. The original Linux port of telnet/telnetd was done by Pete Chown. telnetd: Several people have reported that the 0.1 telnetd sometimes disconnected before getting to the login prompt. The 0.2 version omits the vhangup stuff which might have been causing the problem. Also fixed is the problem with /etc/wtmp not being updated correctly on logout. It was trying to use /var/adm/wtmp. finger: Works. One minor change for POSIX timezone handling. fingerd: Works, no changes. ping: Works, no changes. Must be suid to root. named: Works. A few changes for pathnames and net device configuration stuff. nslookup: Works, but it's fussier than older nslookups about named being setup correctly. Note the -I option is needed for flex -- that was a tough one to find. No changes. named-xfer: Not tested. rcp: Works. Must be suid to root. rsh: Works. Must be suid to root. rshd: Works. rlogin: Works OK but needs more testing. This one depends pretty heavily on the sgtty emulation in libbsd which is not complete yet. There is an odd timing bug with select and termio settings. Look for "sleep(1)" to see what I mean. Must be suid to root. rlogind: Works with the URGENT stuff commented out. There was a nasty bug with shared libraries because environ was redefined. talk: Works. This is the new byte-order independent talk, not the old talk that, e.g., native SunOS uses. The old one wouldn't work with them anyway. Not the fault of Linux. Includes a one line patch for a bug in our curses and another for a bug in the original source dealing with select. ntalkd: Works. No changes. tftp: Works. No changes. tftpd: Works. No changes. Sample Entries for inetd.conf ============================= telnet stream tcp nowait root /usr/etc/inet/telnetd telnetd ntalk dgram udp wait root /usr/etc/inet/ntalkd ntalkd ftp stream tcp nowait root /usr/etc/inet/ftpd ftpd -l finger stream tcp nowait root /usr/etc/inet/fingerd finger shell stream tcp nowait root /usr/etc/inet/rshd rshd login stream tcp nowait root /usr/etc/inet/rlogind rlogind tftp dgram udp wait root /usr/etc/inet/tftpd tftpd Rick Sladkey jrs@world.std.com dev86-0.16.21/libbsd/README.HLU000066400000000000000000000011031231050321700153500ustar00rootroot00000000000000HJ, This is the source of the current "libbsd.a" as I have it next to the libc 4.3.2. You can safely ignore the blahblah in the other README- throw it away after you added this stuff to the rest of libc... I think the best way to add this to the standard set of C libraries is to keep it in the form of a single non-sharable library (/usr/lib/libbsd.a) that only gets linked if the user asks for it by typing "-lbsd". I don't know if this is pos- sible, but I don't think it should be added to the "shared" image, because it might cause other problems in that case... Fred. dev86-0.16.21/libbsd/cfsetspeed.c000066400000000000000000000012441231050321700163400ustar00rootroot00000000000000/* cfsetspeed.c - emulate BSD cfsetspeed with cfset[io]speed - rick sladkey */ #include struct { int flag, val; } xref[] = { B0, 0, B50, 50, B75, 75, B110, 110, B134, 134, B150, 150, B200, 200, B300, 300, B600, 600, B1200, 1200, B1800, 1800, B2400, 2400, B4800, 4800, B9600, 9600, B19200, 19200, B38400, 38400, #ifdef B57600 B57600, 57600, #endif #ifdef B115200 B115200,115200, #endif 0, -1, }; int cfsetspeed(p,speed) struct termios *p; int speed; { int i; for (i = 0; xref[i].val != -1; i++) { if (xref[i].val == speed) { speed = xref[i].flag; cfsetispeed(p, speed); cfsetospeed(p, speed); return 0; } } return -1; } dev86-0.16.21/libbsd/checkrhosts.c000066400000000000000000000001021231050321700165230ustar00rootroot00000000000000 /* This is not functional. Oh well. */ int _check_rhosts_file; dev86-0.16.21/libbsd/daemon.c000066400000000000000000000046471231050321700154700ustar00rootroot00000000000000/*- * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)daemon.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include #include #include int daemon(nochdir, noclose) int nochdir, noclose; { int fd; switch (fork()) { case -1: return (-1); case 0: break; default: _exit(0); } if (setsid() == -1) return (-1); if (!nochdir) (void)chdir("/"); if (!noclose && (fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) { (void)dup2(fd, STDIN_FILENO); (void)dup2(fd, STDOUT_FILENO); (void)dup2(fd, STDERR_FILENO); if (fd > 2) (void)close (fd); } return (0); } dev86-0.16.21/libbsd/login_tty.c000066400000000000000000000043361231050321700162300ustar00rootroot00000000000000/*- * Copyright (c) 1990 The Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)login_tty.c 1.2 (Berkeley) 6/21/90"; #endif /* LIBC_SCCS and not lint */ #include #include #include #include login_tty(fd) int fd; { (void) setsid(); if (ioctl(fd, TIOCSCTTY, (char *)1) == -1) return (-1); (void) dup2(fd, 0); (void) dup2(fd, 1); (void) dup2(fd, 2); if (fd > 2) (void) close(fd); return (0); } dev86-0.16.21/libbsd/logout.c000066400000000000000000000051051231050321700155240ustar00rootroot00000000000000/* * Copyright (c) 1988 The Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)logout.c 5.5 (Berkeley) 6/1/90"; #endif /* LIBC_SCCS and not lint */ #include #include #include #include #include #include typedef struct utmp UTMP; logout(line) register char *line; { register int fd; UTMP ut; int rval; off_t lseek(); time_t time(); if ((fd = open(_PATH_UTMP, O_RDWR)) < 0) return(0); rval = 0; while (read(fd, (char *)&ut, sizeof(UTMP)) == sizeof(UTMP)) { if (!ut.ut_user[0] || strncmp(ut.ut_line, line, UT_LINESIZE)) continue; ut.ut_type = DEAD_PROCESS; (void)time(&ut.ut_time); (void)lseek(fd, -(long)sizeof(UTMP), L_INCR); (void)write(fd, (char *)&ut, sizeof(UTMP)); rval = 1; } (void)close(fd); return(rval); } dev86-0.16.21/libbsd/logwtmp.c000066400000000000000000000053331231050321700157070ustar00rootroot00000000000000/* * Copyright (c) 1988 The Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)logwtmp.c 5.5 (Berkeley) 6/1/90"; #endif /* LIBC_SCCS and not lint */ #include #include #include #include #include #include logwtmp(line, name, host) char *line, *name, *host; { struct utmp ut; struct stat buf; int fd; time_t time(); char *strncpy(); if ((fd = open(_PATH_WTMP, O_WRONLY|O_APPEND, 0)) < 0) return; if (fstat(fd, &buf) == 0) { ut.ut_pid = getpid(); ut.ut_type = (name[0] != '\0')? USER_PROCESS : DEAD_PROCESS; (void) strncpy(ut.ut_id, "", 2); (void) strncpy(ut.ut_line, line, sizeof(ut.ut_line)); (void) strncpy(ut.ut_user, name, sizeof(ut.ut_user)); (void) strncpy(ut.ut_host, host, sizeof(ut.ut_host)); (void) time(&ut.ut_time); if (write(fd, (char *)&ut, sizeof(struct utmp)) != sizeof(struct utmp)) (void) ftruncate(fd, buf.st_size); } (void) close(fd); } dev86-0.16.21/libbsd/pty.c000066400000000000000000000072231231050321700150320ustar00rootroot00000000000000/*- * Copyright (c) 1990 The Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)pty.c 5.6 (Berkeley) 5/10/91"; #endif /* LIBC_SCCS and not lint */ #include #include #include #include #include #include #include #include #include #include openpty(amaster, aslave, name, termp, winp) int *amaster, *aslave; char *name; struct termios *termp; struct winsize *winp; { static char line[] = "/dev/ptyXX"; register const char *cp1, *cp2; register int master, slave, ttygid; struct group *gr; if ((gr = getgrnam("tty")) != NULL) ttygid = gr->gr_gid; else ttygid = -1; for (cp1 = "pqrs"; *cp1; cp1++) { line[8] = *cp1; for (cp2 = "0123456789abcdef"; *cp2; cp2++) { line[9] = *cp2; if ((master = open(line, O_RDWR, 0)) == -1) { if (errno == ENOENT) return (-1); /* out of ptys */ } else { line[5] = 't'; (void) chown(line, getuid(), ttygid); (void) chmod(line, S_IRUSR|S_IWUSR|S_IWGRP); (void) revoke(line); if ((slave = open(line, O_RDWR, 0)) != -1) { *amaster = master; *aslave = slave; if (name) strcpy(name, line); if (termp) (void) tcsetattr(slave, TCSAFLUSH, termp); if (winp) (void) ioctl(slave, TIOCSWINSZ, (char *)winp); return (0); } (void) close(master); line[5] = 'p'; } } } errno = ENOENT; /* out of ptys */ return (-1); } forkpty(amaster, name, termp, winp) int *amaster; char *name; struct termios *termp; struct winsize *winp; { int master, slave, pid; if (openpty(&master, &slave, name, termp, winp) == -1) return (-1); switch (pid = fork()) { case -1: return (-1); case 0: /* * child */ (void) close(master); login_tty(slave); return (0); } /* * parent */ *amaster = master; (void) close(slave); return (pid); } dev86-0.16.21/libbsd/revoke.c000066400000000000000000000001601231050321700155020ustar00rootroot00000000000000/* revoke.c - can't quite emulate BSD revoke? - rick sladkey */ int revoke(line) char *line; { return 0; } dev86-0.16.21/libbsd/setpassent.c000066400000000000000000000001361231050321700164030ustar00rootroot00000000000000/* setpassent.c - vacuous setpassent for BSD - rick sladkey */ void setpassent(i) int i; { } dev86-0.16.21/libbsd/sgtty.c000066400000000000000000000135021231050321700153650ustar00rootroot00000000000000/* sgtty.c - emulate BSD sgtty stuff with termios - ross biro, rick sladkey */ #define _SGTTY_SOURCE #include #include #include #include #include #include struct mask { unsigned short mask; unsigned short res; }; struct sf { struct mask iflag; struct mask oflag; struct mask cflag; struct mask lflag; }; static struct sf trans[] = { /* order is important here. */ /* iflag oflag cflag lflag */ /* this needs to be fixed. */ {{0,0}, {OPOST,0}, {0,0}, {ISIG,0}}, /* O_RAW */ {{0,0}, {0,0}, {0,0}, {XCASE,XCASE}}, /* O_LCASE */ {{ICRNL,ICRNL}, {ONLCR, ONLCR}, {0,0}, {0,0}}, /* O_CRMOD */ {{0,0}, {0,0}, {0,0}, {ECHO,ECHO}}, /* O_ECHO */ {{0,0}, {0,0}, {PARENB|PARODD,PARENB|PARODD}, {0,0}},/* O_ODDP */ {{0,0}, {0,0}, {PARENB|PARODD,PARENB}, {0,0}}, /* O_EVENP */ {{0,0}, {0,0}, {0,0}, {ICANON,0}}, /* O_CBREAK */ }; #define _BSD_VDISABLE 255 static int bchar (c) unsigned char c; { return c == _POSIX_VDISABLE ? _BSD_VDISABLE : c; } static int pchar (c) unsigned char c; { return c == _BSD_VDISABLE ? _POSIX_VDISABLE : c; } int gtty (fd,sg) int fd; struct sgttyb *sg; { struct termios t; int err; int i; err = ioctl (fd, TCGETS, &t); if (err < 0) return (err); sg->sg_ispeed = cfgetispeed (&t); sg->sg_ospeed = cfgetospeed (&t); sg->sg_erase = bchar (t.c_cc[VERASE]); sg->sg_kill = bchar (t.c_cc[VKILL]); sg->sg_flags = 0; for (i = 0; i < sizeof (trans) / sizeof (struct sf); i++) { if ((t.c_iflag & trans[i].iflag.mask) == trans[i].iflag.res && (t.c_oflag & trans[i].oflag.mask) == trans[i].oflag.res && (t.c_cflag & trans[i].cflag.mask) == trans[i].cflag.res && (t.c_lflag & trans[i].lflag.mask) == trans[i].lflag.res) { sg->sg_flags |= 1 << i; } } return (0); } static int tiocset (fd,sg,method) int fd; struct sgttyb *sg; int method; { struct termios t; int err; int i; err = ioctl (fd, TCGETS, &t); if (err < 0) return (err); cfsetispeed (&t, sg->sg_ispeed); cfsetospeed (&t, sg->sg_ospeed); t.c_cc[VERASE] = pchar (sg->sg_erase); t.c_cc[VKILL] = pchar (sg->sg_kill); for (i = sizeof (trans) / sizeof (struct sf) - 1; i >= 0; i--) { t.c_iflag &= ~trans[i].iflag.mask; t.c_oflag &= ~trans[i].oflag.mask; t.c_cflag &= ~trans[i].cflag.mask; t.c_lflag &= ~trans[i].lflag.mask; if (sg->sg_flags & (1 << i)) { t.c_iflag |= trans[i].iflag.res; t.c_oflag |= trans[i].oflag.res; t.c_cflag |= trans[i].cflag.res; t.c_lflag |= trans[i].lflag.res; } else { t.c_iflag |= (~trans[i].iflag.res) & trans[i].iflag.mask; t.c_oflag |= (~trans[i].oflag.res) & trans[i].oflag.mask; t.c_cflag |= (~trans[i].cflag.res) & trans[i].cflag.mask; t.c_lflag |= (~trans[i].lflag.res) & trans[i].lflag.mask; } } return (ioctl (fd, method, &t)); } int stty (fd,sg) int fd; struct sgttyb *sg; { return tiocset (fd, sg, TCSETSF); } static int tiocsetn (fd,sg) int fd; struct sgttyb *sg; { return tiocset (fd, sg, TCSETS); } static int tiocgetc (fd,tc) int fd; struct tchars *tc; { struct termios t; int err; err = ioctl (fd, TCGETS, &t); if (err < 0) return (err); tc->t_intrc = bchar (t.c_cc[VINTR]); tc->t_quitc = bchar (t.c_cc[VQUIT]); tc->t_eofc = bchar (t.c_cc[VEOF]); tc->t_startc = bchar (t.c_cc[VSTART]); tc->t_stopc = bchar (t.c_cc[VSTOP]); tc->t_brkc = bchar (t.c_cc[VEOL]); return (0); } static int tiocsetc (fd,tc) int fd; struct tchars *tc; { struct termios t; int err; err = ioctl (fd, TCGETS, &t); if (err < 0) return (err); t.c_cc[VINTR] = pchar (tc->t_intrc); t.c_cc[VQUIT] = pchar (tc->t_quitc); t.c_cc[VEOF] = pchar (tc->t_eofc); t.c_cc[VEOL] = pchar (tc->t_brkc); t.c_cc[VSTART] = pchar (tc->t_startc); t.c_cc[VSTOP] = pchar (tc->t_stopc); return (ioctl (fd, TCSETS, &t)); } static int tiocgltc (fd,tc) int fd; struct ltchars *tc; { struct termios t; int err; err = ioctl (fd, TCGETS, &t); if (err < 0) return (err); tc->t_werasc = bchar (t.c_cc[VWERASE]); tc->t_suspc = bchar (t.c_cc[VSUSP]); tc->t_dsuspc = bchar (t.c_cc[VSUSP]); tc->t_rprntc = bchar (t.c_cc[VREPRINT]); tc->t_flushc = bchar (t.c_cc[VDISCARD]); tc->t_lnextc = bchar (t.c_cc[VLNEXT]); return (0); } static int tiocsltc (fd,tc) int fd; struct ltchars *tc; { struct termios t; int err; err = ioctl (fd, TCGETS, &t); if (err < 0) return (err); t.c_cc[VWERASE] = pchar (tc->t_werasc); t.c_cc[VSUSP] = pchar (tc->t_suspc); if(t.c_cc[VSUSP] == _POSIX_VDISABLE) t.c_cc[VSUSP] = pchar (tc->t_dsuspc); t.c_cc[VREPRINT] = pchar (tc->t_rprntc); t.c_cc[VDISCARD] = pchar (tc->t_flushc); t.c_cc[VLNEXT] = pchar (tc->t_lnextc); return (ioctl (fd, TCSETS, &t)); } static int tioclget (fd,lflagsp) int fd; int *lflagsp; { struct termios t; int lflags = 0; *lflagsp = lflags; return 0; } static int tioclset (fd,lflagsp) int fd; int *lflagsp; { return 0; } static int tiocflush (fd,arg) int fd; int *arg; { return 0; } int bsd_ioctl (fd,option,arg) int fd; int option; void *arg; { switch (option) { case TIOCGETP: return gtty(fd, (struct sgttyb *) arg); case TIOCSETP: return stty(fd, (struct sgttyb *) arg); case TIOCGETC: return tiocgetc(fd, (struct tchars *) arg); case TIOCSETC: return tiocsetc(fd, (struct tchars *) arg); case TIOCGLTC: return tiocgltc(fd, (struct ltchars *) arg); case TIOCSLTC: return tiocsltc(fd, (struct ltchars *) arg); case TIOCLGET: return tioclget(fd, (int *) arg); case TIOCLSET: return tioclset(fd, (int *) arg); case TIOCFLUSH: return tiocflush(fd, (int *) arg); case TIOCSETN: return tiocsetn(fd, (struct sgttyb *) arg); default: return ioctl(fd, option, arg); } } dev86-0.16.21/libbsd/snprintf.c000066400000000000000000000004351231050321700160570ustar00rootroot00000000000000/* snprintf.c - emulate BSD snprintf with sprintf - rick sladkey */ #include #include int snprintf(char *s, int len, char *format, ...) { va_list args; int result; va_start(args, format); result = vsprintf(s, format, args); va_end(args); return result; } dev86-0.16.21/libc/000077500000000000000000000000001231050321700135205ustar00rootroot00000000000000dev86-0.16.21/libc/COPYING000066400000000000000000000612611231050321700145610ustar00rootroot00000000000000 GNU LIBRARY GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1991 Free Software Foundation, Inc. 675 Mass Ave, Cambridge, MA 02139, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the library GPL. It is numbered 2 because it goes with version 2 of the ordinary GPL.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Library General Public License, applies to some specially designated Free Software Foundation software, and to any other libraries whose authors decide to use it. You can use it for your libraries, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library, or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link a program with the library, you must provide complete object files to the recipients so that they can relink them with the library, after making changes to the library and recompiling it. And you must show them these terms so they know their rights. Our method of protecting your rights has two steps: (1) copyright the library, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the library. Also, for each distributor's protection, we want to make certain that everyone understands that there is no warranty for this free library. If the library is modified by someone else and passed on, we want its recipients to know that what they have is not the original version, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that companies distributing free software will individually obtain patent licenses, thus in effect transforming the program into proprietary software. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License, which was designed for utility programs. This license, the GNU Library General Public License, applies to certain designated libraries. This license is quite different from the ordinary one; be sure to read it in full, and don't assume that anything in it is the same as in the ordinary license. The reason we have a separate public license for some libraries is that they blur the distinction we usually make between modifying or adding to a program and simply using it. Linking a program with a library, without changing the library, is in some sense simply using the library, and is analogous to running a utility program or application program. However, in a textual and legal sense, the linked executable is a combined work, a derivative of the original library, and the ordinary General Public License treats it as such. Because of this blurred distinction, using the ordinary General Public License for libraries did not effectively promote software sharing, because most developers did not use the libraries. We concluded that weaker conditions might promote sharing better. However, unrestricted linking of non-free programs would deprive the users of those programs of all benefit from the free status of the libraries themselves. This Library General Public License is intended to permit developers of non-free programs to use free libraries, while preserving your freedom as a user of such programs to change the free libraries that are incorporated in them. (We have not seen how to achieve this as regards changes in header files, but we have achieved it as regards changes in the actual functions of the Library.) The hope is that this will lead to faster development of free libraries. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, while the latter only works together with the library. Note that it is possible for a library to be covered by the ordinary General Public License rather than by this special one. GNU LIBRARY GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Library General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also compile or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. c) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. d) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Library General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS Appendix: How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! dev86-0.16.21/libc/Config.dflt000066400000000000000000000002421231050321700155760ustar00rootroot00000000000000bcc:+: bios:+: conio:+: error:+: getent:+: gtermcap:+: i386fp:+: i386sys:+: malloc:+: misc:+: msdos:+: regexp:+: stdio:+: string:+: syscall:+: termios:+: time:+: dev86-0.16.21/libc/Config_sh000066400000000000000000000066401231050321700153500ustar00rootroot00000000000000#!/bin/sh - # Copyright (C) 1996 Robert de Bath # This file is part of the Linux-8086 C library and is distributed # under the GNU Library General Public License. main() { rm -f .config.tmp ALLON=yes if [ "$ALLON" = yes -a -f .config.lst ] then grep '^[^:]*:+:' .config.lst > .config.tmp [ -s .config.tmp ] && ALLON=no fi if [ "$ALLON" = yes -a -f Config.dflt ] then grep '^[^:]*:+:' Config.dflt > .config.tmp [ -s .config.tmp ] && { ALLON=no grep -q '^kinclude:' .config.tmp >/dev/null 2>&1 || { [ -d "$ELKSSRC/include" ] || echo 'kinclude:+:' >> .config.tmp } } fi egrep -v '^#|^$' /dev/null */[Cc]onfig | \ sed -e 's./.:.' -e 's/[ ]*:[ ]*/:/g' >> .config.tmp 2>/dev/null ls */Makefile | sed 's-/Makefile-:+:+-' >> .config.tmp sort .config.tmp > .config.lst unset_dups if [ ! -s .config.lst ] then echo 'No configuration options' exit 0 fi CHANGED=0 RUNNING=1 [ "$DIST" != "" -o ! -t 1 -o ! -t 0 ] && { RUNNING=0 echo 'Using default configuration' } while [ $RUNNING = 1 ] do display echo echon 'Select config option to flip [or quit] >' read n v="" case "$n" in [qQ]* ) RUNNING=0 ;; [0-9] ) v=$n ;; [0-9][0-9] ) v=$n ;; * ) echo '\007' ;; esac if [ "$v" != "" ] then set_option $v fi done if [ "$CHANGED" = 1 -a \( -f libc.a -o -f crt0.o \) ] then echo ' You should now run a "make clean" to clean out the libc.a ' exit 1 fi exit 0 } display() { clear awk -F: < .config.lst '{ if( $3 == "+" ) next; if( $2 == "+" ) { flags[$1] = 1; next; } printf("%2d) ", ++count); if( $1 in flags ) printf("(ON) "); else printf("(OFF) "); if( $2 == "Config" ) printf(" "); else printf("* "); printf("%s\n", $4); }' } unset_dups() { awk -F: < .config.lst '{ if( $2 == "+" && $3 == "+") { if( noco[$1] != 1 ) noco[$1] = 2; next; } if( $2 == "+" ) { flags[$1] = 1; next; } if( "'$ALLON'" == "yes" && $2 == "Config" ) flags[$1] = 1; if( $1 in flags ) { if( $3 in gottype ) ; else { printf("%s:+:\n", $1); gottype[$3] = 1; } } noco[$1] = 1; printf("%s\n", $0); } END { for(i in noco) if( noco[i] == 2 ) printf("%s:+:+\n", i); }' | sort > .config.tmp ALLON=no mv -f .config.tmp .config.lst } set_option() { rm -f .config.tmp1 awk -F: < .config.lst '{ if( $2 == "+" && $3 == "+" ) { print $0; next; } if( $2 == "+" ) { flags[$1] = 1; next; } if( ++cnt == '$1' ) { if( $1 in flags ) ; else printf("%s:+:\n", $1) > ".config.tmp1"; printf("%s\n", $0) > ".config.tmp1"; } else { if( $1 in flags ) printf("%s:+:\n", $1); printf("%s\n", $0); } }' > .config.tmp2 if [ -f .config.tmp1 ] then CHANGED=1 else echo 'Cannot change that option!' sleep 2 fi cat .config.tmp[12] > .config.lst rm .config.tmp[12] unset_dups } echon() { [ "$ECHON" = "" ] && { if echo -n | grep -e -n >/dev/null then ECHON="echo "; ECHOT='\c' else ECHON="echo -n"; ECHOT='' fi } $ECHON "$@""$ECHOT" } main dev86-0.16.21/libc/KERNEL000066400000000000000000000024211231050321700144220ustar00rootroot00000000000000 KERNEL SYSTEM CALL INTERFACE: The kernel system calls are all done through interrupt 0x80 All parameters are passed in the 'AX,BX,CX,DX,DI,SI' registers. The AX register contains the system call number. The BX,CX,DX,DI,SI registers contain the first 5 arguments from the stack. (NB If the syscall is know to have less than 5 args the rest are not loaded) On return from the syscall AX has the return value. If AX is -ve then errno= -AX and return val = -1; The system calls are named in syscall/syscall.dat. There is a script syscall/mksyscall which generates the assembler for the system calls, near the top there is a line: COMPACT=1 If this is changed to COMPACT=0 the code generated will be slightly faster and larger. -RDB KERNEL SIGNAL INTERFACE: It is assumed the kernel will never pass a signal to the userspace routine unless it's _explicitly_ asked for! The Kernel need only save space for _one_ function pointer (to system_signal) and must deal with SIG_DFL and SIG_IGN in kernel space. When a signal is required the kernel must set all the registers as if returning from a interrupt normally then push the number of the signal to be generated, push the current pc value, then set the pc to the address of the 'system_signal' function. This is in syscall/signal.c -RDB dev86-0.16.21/libc/Make.defs000066400000000000000000000033071231050321700152430ustar00rootroot00000000000000############################################################################ # Normal standard 8086 code ifeq ($(PLATFORM),i86-ELKS) OBJ=crt0.o LIBC=$(TOP)/libc.a ARCH=-Mn LIB_CPU=i86 LIB_OS=ELKS endif ############################################################################## # 8086 elks code With "Caller saves" and "First arg in AX" ifeq ($(PLATFORM),i86-FAST) OBJ=crt0.o LIBC=$(TOP)/libc_f.a ARCH=-Mf LIB_CPU=i86 LIB_OS=ELKS endif ############################################################################## # Standalone executable ifeq ($(PLATFORM),i86-BIOS) OBJ=crt0.o LIBC=$(TOP)/libc_s.a ARCH=-Ms LIB_CPU=i86 LIB_OS=BIOS endif ############################################################################## # MSDOS COM file (msdos libs don't support "First arg in AX") ifeq ($(PLATFORM),i86-DOS) OBJ=crt0.o LIBC=$(TOP)/libdos.a ARCH=-Md LIB_CPU=i86 LIB_OS=DOS endif ############################################################################## # BCC 386. ifeq ($(PLATFORM),i386-BCC) OBJ=crt3.o LIBC=$(TOP)/libc3.a ARCH=-Ml LIB_CPU=i386 LIB_OS=ELKS endif ############################################################################## # GCC 386. ifeq ($(PLATFORM),i386-GCC) OBJ=crtg.o LIBC=$(TOP)/libcg.a ARCH= LIB_CPU=g386 LIB_OS=ELKS CC=gcc CCFLAGS=-O -g -nostdinc -I$(TOP)/include endif ############################################################################## # Anonymous ifeq ($(PLATFORM),ANON) OBJ=crt0.o LIBC=$(TOP)/libc.a ARCH= LIB_CPU=Bigbad LIB_OS=Nice CC=cc CCFLAGS=-I$(TOP)/include endif ############################################################################## # Unknown ifeq ($(LIB_CPU),) OBJ=crtX.o LIBC=$(TOP)/libc_X.a ARCH= LIB_CPU=Unknown LIB_OS=Unknown endif .PRECIOUS: $(LIBC) dev86-0.16.21/libc/Makefile000066400000000000000000000051251231050321700151630ustar00rootroot00000000000000# Copyright (C) 1996,1997 Robert de Bath # This file is part of the Linux-8086 C library and is distributed # under the GNU Library General Public License. ifeq ($(TOPDIR),) # This should work, but .. TOP=.. else TOP=$(TOPDIR)/libc endif LIBBCC=$(TOP)/libbcc.a CC=bcc CCFLAGS=-I -I$(TOP)/include DEFS=-D__LIBC__ include Make.defs ifeq ($(VERSION),) include VERSION endif CFLAGS=$(ARCH) $(CCFLAGS) $(DEFS) USERID=$(shell id -gn) GROUPID=$(shell id -un) ############################################################################ MAKEPASS= \ LIBC='$(LIBC)' CC='$(CC)' ARCH='$(ARCH)' CCFLAGS='$(CCFLAGS)' \ DEFS='$(DEFS)' LIB_CPU='$(LIB_CPU)' LIB_OS='$(LIB_OS)' \ all: $(OBJ) $(LIBC) $(LIBBCC) @: $(LIBC): transfer .config.dir @for i in `cat .config.dir` ; do \ $(MAKE) $(MAKEPASS) -C $$i all || exit 1 ; \ done $(LIBBCC): .config.dir $(MAKE) $(MAKEPASS) LIBC=$(LIBBCC) -C bcc all crt3.o: crt0.c Makefile $(CC) -c $(CFLAGS) -D__LIBC_VER__='"$(VERSION)"' -o $@ crt0.c crt0.o: crt0.c Makefile $(CC) -c $(CFLAGS) -D__LIBC_VER__='"$(VERSION)"' -o $@ crt0.c crtg.o: crt0.c Makefile $(CC) -c $(CFLAGS) -D__LIBC_VER__='"$(VERSION)"' -o $@ crt0.c crtX.o: @echo "You need to define the 'PLATFORM=...' variable," @echo "Preferably by doing make from `dirname \`pwd\``" @exit 1 ############################################################################ transfer: .config.dir @for i in `cat .config.dir`; do \ grep -s '^transfer' $$i/Makefile && $(MAKE) -s -C $$i $@ ; \ done ; echo -n @[ -d include/linuxmt/. ] || \ ln -s $(ELKSSRC)/include/linuxmt include @[ -d include/arch/. ] || \ ln -s $(ELKSSRC)/include/arch include ############################################################################ realclean: clean noconfig clean: rm -f *.o *.a @for i in */Makefile ; do \ $(MAKE) -C `dirname $$i` $@ || exit 1 ; \ done ############################################################################ install_incl: transfer install -d $(DISTINCL)/include rm -f $(DISTINCL)/include/linuxmt $(DISTINCL)/include/arch ||: cp -LpR include/* $(DISTINCL)/include -chown -R $(USERID):$(GROUPID) $(DISTINCL)/include -chmod -R ugo-x,u=rwX,og=rX $(DISTINCL)/include ############################################################################ config: sh Config_sh .config.dir: .config.lst @grep '^[^:]*:+:' < .config.lst | sed 's/:.*//' > .config.tmp @mv -f .config.tmp .config.dir .config.lst: Config_sh sh Config_sh noconfig: rm -f .config.dir .config.lst .config.tmp ############################################################################ dev86-0.16.21/libc/New_subdir000077500000000000000000000030521231050321700155470ustar00rootroot00000000000000#!/bin/sh - # Copyright (C) 1995,1996 Robert de Bath # This file is part of the Linux-8086 C library and is distributed # under the GNU Library General Public License. cat < $1/Makefile # Copyright (C) $YEAR $NAME <$EMAIL> # This file is part of the Linux-8086 C library and is distributed # under the GNU Library General Public License. OBJ=$1.o CFLAGS=$(ARCH) $(CCFLAGS) $(DEFS) all: $(LIBC)($(OBJ)) @: clean: rm -f *.o libc.a ! cat < $1/README Copyright (C) $YEAR $NAME <$EMAIL> This file is part of the Linux-8086 C library and is distributed under the GNU Library General Public License. There's currently nothing special about $1. -$FNAME ! cat < $1/$1.c /* Copyright (C) $YEAR $NAME <$EMAIL> * This file is part of the Linux-8086 C library and is distributed * under the GNU Library General Public License. */ $1() { /* FIXME :-) */ } ! echo "Ok, the directory $1 has now been created ..." exit 0 dev86-0.16.21/libc/Pre_main000066400000000000000000000042011231050321700151720ustar00rootroot00000000000000 There is support for calling functions before main and from inside the exit() function. The exit processing uses the standard 'atexit' and 'on_exit' functions see the normal man pages. Execution of code before main is Linux-8086 (actually BCC) specific; the method works like this: /**********************/ long global_var_that_needs_init; #ifdef __AS386_16__ #asm loc 1 ! Make sure the pointer is in the correct segment auto_func: ! Label for bcc -M to work. .word _init_vars ! Pointer to the autorun function .word no_op ! Space filler cause segs are padded to 4 bytes. .text ! So the function after is also in the correct seg. #endasm #endif #ifdef __AS386_32__ #asm loc 1 ! Make sure the pointer is in the correct segment auto_func: ! Label for bcc -M to work. .long _init_vars ! Pointer to the autorun function .text ! So the function after is also in the correct seg. #endasm #endif static void init_vars() { time(&global_var_that_needs_init); } /**********************/ The most important part is that the asm code _MUST_ be compiled into the same object file as the variable that is being initialised. If this is not so the init_vars function will not be linked in and will not be executed. Also do note that the init functions are called in essentially random order (It's actually the order that they appear in the executable) so you must be careful not to call any routines that have their own autostart from inside your autostart. Nevertheless you should try to ensure that your routines will fail gracefully if they are called before the initilisation routine. If you do not know if a routine has an autostart create a test program calling the routine and compile with: bcc -0 [other_stuff] -M test.c | sort +2 | more Look down the list for lines like this: crt0 ZP_safety 1 00000000 R crt0 auto_start 1 00000008 R objname auto_func 1 00000008 R <<**** crt0 data_start 2 00000010 R crt0 _environ 3 00000010 R The line marked is an autostart function call. Robert. dev86-0.16.21/libc/README000066400000000000000000000047131231050321700144050ustar00rootroot00000000000000SYSTEM CALLS The system call table (syscalls/syscall.dat) is constantly changing, using skewed versions is _very_ likely to give you segfaults and strange behaviour. For this lib you should use the same version of elksemu. The system call table will only be frozen when the linux-86 kernel is running and reasonably stable. The 386 version is using a distinct list that matches the Linux-i386 syscall list. THE COMPILER You should use the versions of bcc, unproto, as86, ld86 and elksemu that are in this version of the combined development environment. Some other versions will work but often they'll just appear to work or not work at all. The original bcc-cc1 won't pickup the right header files, the original ld86 won't generate COM files or 386-Linux files and looks in the wrong place for crt0.o and libc.a. The original as is just plain broken! Main Subdirectories. bcc Lots of BCC helper functions bios Minimal 'system' calls for standalone executables. error The C error functions. getent Routines for /etc/group, /etc/passwd and /etc/utmp gtermcap GNU termcap i386fp BCC's floating point routines for 386 code. include Some include files, some new others Glib or Glib hacked. kinclude Kernel include files, here for now. malloc Malloc routines misc Various larger functions msdos This is the syscall directory for msdos. regexp Standard regular expression parser stdio Robert's standard I/O string The functions for string.h syscall All the system call functions, and some tied lib ones. termios Termimal mode control. time Unix time related functions. Directory structure: The top Makefile will try to call any "Makefile" it finds in a subdirectory, so to add a new chunk to "libc.a" just drop in the directory a Makefile that understands "make clean" and "make libc.a" (Which must also update ../libc.a) There's now a tiny script (New_subdir) that'll do this. Make config will look in all subdirectories for a file 'Config' any it finds will be displayed and can be used to switch a directory on or off. The exit(rv) function is already defined. It will call the contents of the function pointer (*__cleanup)() before it calls _exit(); This pointer should be used through the 'atexit' or 'on_exit' lib functions. (See standard man pages) If you need to call something before main see the file 'Pre_main'. -Robert -=*=- -=*=- -=*=- -=*=- -=*=- -=*=- -=*=- -=*=- -=*=- -=*=- -=*=- -=*=- -=*=- dev86-0.16.21/libc/bcc/000077500000000000000000000000001231050321700142475ustar00rootroot00000000000000dev86-0.16.21/libc/bcc/Config000066400000000000000000000000511231050321700153730ustar00rootroot00000000000000 bcclib: Library of bcc helper functions dev86-0.16.21/libc/bcc/Makefile000066400000000000000000000040771231050321700157170ustar00rootroot00000000000000# Copyright (C) 1995,1996 Robert de Bath # This file is part of the Linux-8086 C library and is distributed # under the GNU Library General Public License. # Support for integer arithmetic ifeq ($(LIB_CPU),i86) IOBJ=__idiv.o __idivu.o __imod.o __imodu.o __imul.o __isl.o __isr.o __isru.o ISRC=bcc_int.c endif # Support for integer arithmetic when compiling for the i386 ifeq ($(LIB_CPU),i386) ISRC=bcc_i386.c IOBJ=__idiv.o __idivu.o __imod.o __imodu.o __imul.o __isl.o __isr.o __isru.o \ __divsi3.o endif # Support for long arithmetic on little-endian (normal) longs LSRC=bcc_long.c LOBJ=__laddl.o __landl.o __lcmpl.o __lcoml.o __ldecl.o __ldivl.o __ldivul.o \ __leorl.o __lincl.o __lmodl.o __lmodul.o __lmull.o __lnegl.o __lorl.o \ __lsll.o __lsrl.o __lsrul.o __lsubl.o __ltstl.o # Memory allocation primitives AOBJ=errno.o __brk_addr.o sbrk.o brk.o ASRC=heap.c # Support for long arithmetic on big-endian (words-swapped) longs RSRC=bcc_bsw.c ROBJ=__laddb.o __landb.o __lcmpb.o __lcomb.o __ldecb.o __ldivb.o __ldivub.o \ __leorb.o __lincb.o __lmodb.o __lmodub.o __lmulb.o __lnegb.o __lorb.o \ __lslb.o __lsrb.o __lsrub.o __lsubb.o __ltstb.o # Miscellaneous I/O and far access junk PSRC=bcc_io.c POBJ=__inport.o __inportb.o __outport.o __outportb.o __peekb.o __peekw.o \ __pokeb.o __pokew.o ifeq ($(LIB_CPU),i86) OBJ=__ldivmod.o $(IOBJ) $(LOBJ) $(AOBJ) endif ifeq ($(LIB_CPU),i386) OBJ=$(IOBJ) $(AOBJ) endif OLDOBJ=$(ROBJ) $(POBJ) CFLAGS=$(ARCH) $(CCFLAGS) $(DEFS) ifneq ($(OBJ),) all: $(LIBC) @$(RM) $(OBJ) $(LIBC): $(LIBC)($(OBJ)) $(LIBC)($(IOBJ)): $(ISRC) $(CC) $(CFLAGS) -DL_$* $< -c -o $*.o $(AR) $(ARFLAGS) $@ $*.o $(LIBC)($(LOBJ)): $(LSRC) $(CC) $(CFLAGS) -DL_$* $< -c -o $*.o $(AR) $(ARFLAGS) $@ $*.o $(LIBC)($(AOBJ)): $(ASRC) $(CC) $(CFLAGS) -DL_$* $< -c -o $*.o $(AR) $(ARFLAGS) $@ $*.o $(LIBC)($(ROBJ)): $(RSRC) $(CC) $(CFLAGS) -DL_$* $< -c -o $*.o $(AR) $(ARFLAGS) $@ $*.o $(LIBC)($(POBJ)): $(PSRC) $(CC) $(CFLAGS) -DL_$* $< -c -o $*.o $(AR) $(ARFLAGS) $@ $*.o else all: @: endif clean: rm -f *.o libc.a dev86-0.16.21/libc/bcc/__ldivmod.c000066400000000000000000000073341231050321700163560ustar00rootroot00000000000000/************************************************************************/ /* This file contains the BCC compiler helper functions */ /* (C) Copyright Bruce Evans */ /* Function ldivmod */ #ifdef __AS386_16__ #asm .text .even ! ldivmod.s - 32 over 32 to 32 bit division and remainder for 8086 ! ldivmod( dividend bx:ax, divisor di:cx ) [ signed quot di:cx, rem bx:ax ] ! ludivmod( dividend bx:ax, divisor di:cx ) [ unsigned quot di:cx, rem bx:ax ] ! dx is not preserved ! NB negatives are handled correctly, unlike by the processor ! divison by zero does not trap ! let dividend = a, divisor = b, quotient = q, remainder = r ! a = b * q + r mod 2**32 ! where: ! if b = 0, q = 0 and r = a ! otherwise, q and r are uniquely determined by the requirements: ! r has the same sign as b and absolute value smaller than that of b, i.e. ! if b > 0, then 0 <= r < b ! if b < 0, then 0 >= r > b ! (the absoulute value and its comparison depend on signed/unsigned) ! the rule for the sign of r means that the quotient is truncated towards ! negative infinity in the usual case of a positive divisor ! if the divisor is negative, the division is done by negating a and b, ! doing the division, then negating q and r .globl ldivmod ldivmod: mov dx,di ! sign byte of b in dh mov dl,bh ! sign byte of a in dl test di,di jns set_asign neg di neg cx sbb di,*0 set_asign: test bx,bx jns got_signs ! leave r = a positive neg bx neg ax sbb bx,*0 j got_signs .globl ludivmod .even ludivmod: xor dx,dx ! both sign bytes 0 got_signs: push bp push si mov bp,sp push di ! remember b push cx b0 = -4 b16 = -2 test di,di jne divlarge test cx,cx je divzero cmp bx,cx jae divlarge ! would overflow xchg dx,bx ! a in dx:ax, signs in bx div cx xchg cx,ax ! q in di:cx, junk in ax xchg ax,bx ! signs in ax, junk in bx xchg ax,dx ! r in ax, signs back in dx mov bx,di ! r in bx:ax j zdivu1 divzero: ! return q = 0 and r = a test dl,dl jns return j negr ! a initially minus, restore it divlarge: push dx ! remember sign bytes mov si,di ! w in si:dx, initially b from di:cx mov dx,cx xor cx,cx ! q in di:cx, initially 0 mov di,cx ! r in bx:ax, initially a ! use di:cx rather than dx:cx in order to ! have dx free for a byte pair later cmp si,bx jb loop1 ja zdivu ! finished if b > r cmp dx,ax ja zdivu ! rotate w (= b) to greatest dyadic multiple of b <= r loop1: shl dx,*1 ! w = 2*w rcl si,*1 jc loop1_exit ! w was > r counting overflow (unsigned) cmp si,bx ! while w <= r (unsigned) jb loop1 ja loop1_exit cmp dx,ax jbe loop1 ! else exit with carry clear for rcr loop1_exit: rcr si,*1 rcr dx,*1 loop2: shl cx,*1 ! q = 2*q rcl di,*1 cmp si,bx ! if w <= r jb loop2_over ja loop2_test cmp dx,ax ja loop2_test loop2_over: add cx,*1 ! q++ adc di,*0 sub ax,dx ! r = r-w sbb bx,si loop2_test: shr si,*1 ! w = w/2 rcr dx,*1 cmp si,b16[bp] ! while w >= b ja loop2 jb zdivu cmp dx,b0[bp] jae loop2 zdivu: pop dx ! sign bytes zdivu1: test dh,dh js zbminus test dl,dl jns return ! else a initially minus, b plus mov dx,ax ! -a = b * q + r ==> a = b * (-q) + (-r) or dx,bx je negq ! use if r = 0 sub ax,b0[bp] ! use a = b * (-1 - q) + (b - r) sbb bx,b16[bp] not cx ! q = -1 - q (same as complement) not di negr: neg bx neg ax sbb bx,*0 return: mov sp,bp pop si pop bp ret .even zbminus: test dl,dl ! (-a) = (-b) * q + r ==> a = b * q + (-r) js negr ! use if initial a was minus mov dx,ax ! a = (-b) * q + r ==> a = b * (-q) + r or dx,bx je negq ! use if r = 0 sub ax,b0[bp] ! use a = b * (-1 - q) + (b + r) (b is now -b) sbb bx,b16[bp] not cx not di mov sp,bp pop si pop bp ret .even negq: neg di neg cx sbb di,*0 mov sp,bp pop si pop bp ret #endasm #endif dev86-0.16.21/libc/bcc/alloca.c000066400000000000000000000025601231050321700156510ustar00rootroot00000000000000/* Copyright (C) 1995,1996 Robert de Bath * This file is part of the Linux-8086 C library and is distributed * under the GNU Library General Public License. */ /* Alloca is a nice interesting function */ /* Needs change to BCC to work, as BCC doesn't use 'mov sp,bp:pop bp' */ /* The only other way to do it is to use malloc and the emacs alloca */ #if 0 THIS IS BROKEN!!! #asm export _alloca .text _alloca: pop cx ! The program counter pop ax ! The argument (>1 arg == snafu) inc ax and al,$FE ! Round up to even test ax,ax jz too_big ! Well _I_ think it means 64k ! :-) (ANSI too IIUC) mov bx,sp sub bx,ax ! Calc new SP jb too_big ! SP wrapped, snafu! mov ax,[brk_addr] add ax,#64 ! Check if brk has allocated the memory first but cmp bx,ax ! leave a little bit of space before we collide! jb too_big xchg bx,sp ! Put it in place, may need the old SP for other args mov ax,sp ! The bottom of the area allocated ! This is needed if si/di popped before mov sp,bp !push [bx+4] ! This copies the saved register vars and possibly a temp !push [bx+2] ! value, beware snafu if called within complex expression! !push [bx] ! push ax ! Anything really, it will be deallocated by the caller jmp cx ! Return too_big: xor ax,ax ! Sorry not enough stack push ax ! More junk jmp cx ! Return #endasm #endif dev86-0.16.21/libc/bcc/bcc_bsw.c000066400000000000000000000150101231050321700160120ustar00rootroot00000000000000/************************************************************************/ /* This file contains the BCC compiler helper functions */ /* (C) Copyright Bruce Evans */ /* Support for long arithmetic on big-endian (words-swapped) longs * __laddb.o __landb.o __lcmpb.o __lcomb.o __ldecb.o __ldivb.o __ldivub.o * __leorb.o __lincb.o __lmodb.o __lmodub.o __lmulb.o __lnegb.o __lorb.o * __lslb.o __lsrb.o __lsrub.o __lsubb.o __ltstb.o */ #ifdef __AS386_16__ #asm .text ! This is common to all. .even #endasm /************************************************************************/ /* Function laddb */ #ifdef L___laddb #asm ! laddb.s .globl laddb .globl laddub laddb: laddub: add bx,2(di) adc ax,(di) ret #endasm #endif /************************************************************************/ /* Function landb */ #ifdef L___landb #asm ! landb.s .globl landb .globl landub landb: landub: and ax,(di) and bx,2(di) ret #endasm #endif /************************************************************************/ /* Function lcmpb */ #ifdef L___lcmpb #asm ! lcmpb.s ! lcmpb, lcmpub don`t preserve ax .globl lcmpb .globl lcmpub lcmpb: lcmpub: sub ax,(di) ! don`t need to preserve ax je LCMP_NOT_SURE ret .even LCMP_NOT_SURE: cmp bx,2(di) jb LCMP_B_AND_LT ! b (below) becomes lt (less than) as well jge LCMP_EXIT ! ge and already ae ! else make gt as well as a (above) inc ax ! clear ov and mi, set ne for greater than LCMP_EXIT: ret .even LCMP_B_AND_LT: dec ax ! clear ov, set mi and ne for less than ret #endasm #endif /************************************************************************/ /* Function lcomb */ #ifdef L___lcomb #asm ! lcomb.s .globl lcomb .globl lcomub lcomb: lcomub: not ax not bx ret #endasm #endif /************************************************************************/ /* Function ldecb */ #ifdef L___ldecb #asm ! ldecb.s .globl ldecb .globl ldecub ldecb: ldecub: cmp 2(bx),*0 je LDEC_BOTH dec 2(bx) ret .even LDEC_BOTH: dec 2(bx) dec (bx) ret #endasm #endif /************************************************************************/ /* Function ldivb */ #ifdef L___ldivb #asm ! ldivb.s ! ax:bx / (di):2(di), quotient ax:bx, remainder cx:di, dx not preserved .globl ldivb .extern ldivmod ldivb: xchg ax,bx mov cx,2(di) mov di,(di) call ldivmod ! bx:ax / di:cx, quot di:cx, rem bx:ax xchg ax,di xchg bx,cx ret #endasm #endif /************************************************************************/ /* Function ldivub */ #ifdef L___ldivub #asm ! ldivub.s ! unsigned ax:bx / (di):2(di), quotient ax:bx,remainder cx:di, dx not preserved .globl ldivub .extern ludivmod ldivub: xchg ax,bx mov cx,2(di) mov di,(di) call ludivmod ! unsigned bx:ax / di:cx, quot di:cx, rem bx:ax xchg ax,di xchg bx,cx ret #endasm #endif /************************************************************************/ /* Function leorb */ #ifdef L___leorb #asm ! leorb.s .globl leorb .globl leorub leorb: leorub: xor ax,(di) xor bx,2(di) ret #endasm #endif /************************************************************************/ /* Function lincb */ #ifdef L___lincb #asm ! lincb.s .globl lincb .globl lincub lincb: lincub: inc 2(bx) je LINC_HIGH_WORD ret .even LINC_HIGH_WORD: inc (bx) ret #endasm #endif /************************************************************************/ /* Function lmodb */ #ifdef L___lmodb #asm ! lmodb.s ! ax:bx % (di):2(di), remainder ax:bx, quotient cx:di, dx not preserved .globl lmodb .extern ldivmod lmodb: xchg ax,bx mov cx,2(di) mov di,(di) call ldivmod ! bx:ax / di:cx, quot di:cx, rem bx:ax xchg ax,bx xchg cx,di ret #endasm #endif /************************************************************************/ /* Function lmodub */ #ifdef L___lmodub #asm ! lmodub.s ! unsigned ax:bx / (di):2(di), remainder ax:bx,quotient cx:di, dx not preserved .globl lmodub .extern ludivmod lmodub: xchg ax,bx mov cx,2(di) mov di,(di) call ludivmod ! unsigned bx:ax / di:cx, quot di:cx, rem bx:ax xchg ax,bx xchg cx,di ret #endasm #endif /************************************************************************/ /* Function lmulb */ #ifdef L___lmulb #asm ! lmulb.s ! lmulb, lmulub don`t preserve cx, dx .globl lmulb .globl lmulub lmulb: lmulub: mul 2(di) xchg ax,bx mov cx,ax mul (di) add bx,ax mov ax,2(di) mul cx add bx,dx xchg ax,bx ret #endasm #endif /************************************************************************/ /* Function lnegb */ #ifdef L___lnegb #asm ! lnegb.s .globl lnegb .globl lnegub lnegb: lnegub: neg ax neg bx sbb ax,*0 ret #endasm #endif /************************************************************************/ /* Function lorb */ #ifdef L___lorb #asm ! lorb.s .globl lorb .globl lorub lorb: lorub: or ax,(di) or bx,2(di) ret #endasm #endif /************************************************************************/ /* Function lslb */ #ifdef L___lslb #asm ! lslb.s ! lslb, lslub don`t preserve cx .globl lslb .globl lslub lslb: lslub: mov cx,di jcxz LSL_EXIT cmp cx,*32 jae LSL_ZERO LSL_LOOP: shl bx,*1 rcl ax,*1 loop LSL_LOOP LSL_EXIT: ret .even LSL_ZERO: xor ax,ax mov bx,ax ret #endasm #endif /************************************************************************/ /* Function lsrb */ #ifdef L___lsrb #asm ! lsrb.s ! lsrb doesn`t preserve cx .globl lsrb lsrb: mov cx,di jcxz LSR_EXIT cmp cx,*32 jae LSR_SIGNBIT LSR_LOOP: sar ax,*1 rcr bx,*1 loop LSR_LOOP LSR_EXIT: ret .even LSR_SIGNBIT: mov cx,*32 ! equivalent to +infinity in this context j LSR_LOOP #endasm #endif /************************************************************************/ /* Function lsrub */ #ifdef L___lsrub #asm ! lsrub.s ! lsrub doesn`t preserve cx .globl lsrub lsrub: mov cx,di jcxz LSRU_EXIT cmp cx,*32 jae LSRU_ZERO LSRU_LOOP: shr ax,*1 rcr bx,*1 loop LSRU_LOOP LSRU_EXIT: ret .even LSRU_ZERO: xor ax,ax mov bx,ax ret #endasm #endif /************************************************************************/ /* Function lsubb */ #ifdef L___lsubb #asm ! lsubb.s .globl lsubb .globl lsubub lsubb: lsubub: sub bx,2(di) sbb ax,(di) ret #endasm #endif /************************************************************************/ /* Function ltstb */ #ifdef L___ltstb #asm ! ltstb.s ! ltstb, ltstub don`t preserve ax .globl ltstb .globl ltstub ltstb: ltstub: test ax,ax je LTST_NOT_SURE ret .even LTST_NOT_SURE: test bx,bx js LTST_FIX_SIGN ret .even LTST_FIX_SIGN: inc ax ! clear ov and mi, set ne for greater than ret #endasm #endif #endif dev86-0.16.21/libc/bcc/bcc_i386.c000066400000000000000000000035111231050321700157130ustar00rootroot00000000000000/************************************************************************/ /* This file contains the BCC compiler helper functions */ /* (C) Copyright Bruce Evans */ /* Support for 386 integer arithmetic * __divsi3.o __idiv.o __idivu.o __imod.o __imodu.o __imul.o * __isl.o __isr.o __isru.o */ #ifdef __AS386_32__ #asm .text ! This is common to all. .align 4 #endasm #ifdef L___divsi3 #asm ! divsi3.s .globl ___divsi3 ___divsi3: push edx mov eax,[esp+4+4] cdq idiv [esp+4+4+4] pop edx ret .globl ___udivsi3 .text .align 4 ___udivsi3: push edx mov eax,[esp+4+4] sub edx,edx div [esp+4+4+4] pop edx ret #endasm #endif #ifdef L___idiv #asm ! idiv.s ! idiv_ doesn`t preserve edx (returns remainder in it) .globl idiv_ idiv_: cdq idiv ebx ret #endasm #endif #ifdef L___idivu #asm ! idivu.s ! idiv_u doesn`t preserve edx (returns remainder in it) .globl idiv_u idiv_u: xor edx,edx div ebx ret #endasm #endif #ifdef L___imod #asm ! imod.s ! imod doesn`t preserve edx (returns quotient in it) .globl imod imod: cdq idiv ebx mov eax,edx ! instruction queue full so xchg slower ret #endasm #endif #ifdef L___imodu #asm ! imodu.s ! imodu doesn`t preserve edx (returns quotient in it) .globl imodu imodu: xor edx,edx div ebx mov eax,edx ! instruction queue full so xchg slower ret #endasm #endif #ifdef L___imul #asm ! imul.s ! imul_, imul_u don`t preserve edx .globl imul_ .globl imul_u imul_: imul_u: imul ebx ret #endasm #endif #ifdef L___isl #asm ! isl.s ! isl, islu don`t preserve cl .globl isl .globl islu isl: islu: mov cl,bl shl eax,cl ret #endasm #endif #ifdef L___isr #asm ! isr.s ! isr doesn`t preserve cl .globl isr isr: mov cl,bl sar eax,cl ret #endasm #endif #ifdef L___isru #asm ! isru.s ! isru doesn`t preserve cl .globl isru isru: mov cl,bl shr eax,cl ret #endasm #endif #endif dev86-0.16.21/libc/bcc/bcc_int.c000066400000000000000000000043711231050321700160210ustar00rootroot00000000000000/************************************************************************/ /* This file contains the BCC compiler helper functions */ /* (C) Copyright Bruce Evans */ /* Support for integer arithmetic * __idiv.o __idivu.o __imod.o __imodu.o __imul.o __isl.o __isr.o __isru.o */ #ifdef __AS386_16__ #asm .text ! This is common to all. .even #endasm /************************************************************************/ /* Function idiv */ #ifdef L___idiv #asm ! idiv.s ! idiv_ doesn`t preserve dx (returns remainder in it) .globl idiv_ idiv_: cwd idiv bx ret #endasm #endif /************************************************************************/ /* Function idivu */ #ifdef L___idivu #asm ! idivu.s ! idiv_u doesn`t preserve dx (returns remainder in it) .globl idiv_u idiv_u: xor dx,dx div bx ret #endasm #endif /************************************************************************/ /* Function imod */ #ifdef L___imod #asm ! imod.s ! imod doesn`t preserve dx (returns quotient in it) .globl imod imod: cwd idiv bx mov ax,dx ret #endasm #endif /************************************************************************/ /* Function imodu */ #ifdef L___imodu #asm ! imodu.s ! imodu doesn`t preserve dx (returns quotient in it) .globl imodu imodu: xor dx,dx div bx mov ax,dx ! instruction queue full so xchg slower ret #endasm #endif /************************************************************************/ /* Function imul */ #ifdef L___imul #asm ! imul.s ! imul_, imul_u don`t preserve dx .globl imul_ .globl imul_u imul_: imul_u: imul bx ret #endasm #endif /************************************************************************/ /* Function isl */ #ifdef L___isl #asm ! isl.s ! isl, islu don`t preserve cl .globl isl .globl islu isl: islu: mov cl,bl shl ax,cl ret #endasm #endif /************************************************************************/ /* Function isr */ #ifdef L___isr #asm ! isr.s ! isr doesn`t preserve cl .globl isr isr: mov cl,bl sar ax,cl ret #endasm #endif /************************************************************************/ /* Function isru */ #ifdef L___isru #asm ! isru.s ! isru doesn`t preserve cl .globl isru isru: mov cl,bl shr ax,cl ret #endasm #endif #endif dev86-0.16.21/libc/bcc/bcc_io.c000066400000000000000000000061341231050321700156350ustar00rootroot00000000000000/************************************************************************/ /* This file contains the BCC compiler helper functions */ /* (C) Prentice Hall (Minix) http://www.cs.vu.nl/~ast/minix.html */ /* Miscellaneous obsolete junk * __inport.o __inportb.o __outport.o __outportb.o __peekb.o __peekw.o * __pokeb.o __pokew.o */ #ifdef __AS368_16__ #if !__FIRST_ARG_IN_AX__ #asm .text ! This is common to all. .even #endasm /************************************************************************/ /* Function inport */ #ifdef L___inport #asm ! int inport( int port ); ! reads a word from the i/o port port and returns it .globl _inport _inport: pop bx pop dx dec sp dec sp inw jmp bx #endasm #endif /************************************************************************/ /* Function inportb */ #ifdef L___inportb #asm ! int inportb( int port ); ! reads a byte from the i/o port port and returns it .globl _inportb _inportb: pop bx pop dx dec sp dec sp in sub ah,ah jmp bx #endasm #endif /************************************************************************/ /* Function outport */ #ifdef L___outport #asm ! void outport( int port, int value ); ! writes the word value to the i/o port port .globl _outport _outport: pop bx pop dx pop ax sub sp,*4 outw jmp bx #endasm #endif /************************************************************************/ /* Function outportb */ #ifdef L___outportb #asm ! void oportb( int port, char value ); ! writes the byte value to the i/o port port ! this would be outportb except for feeble linkers .globl _oportb _oportb: pop bx pop dx pop ax sub sp,*4 out jmp bx #endasm #endif /************************************************************************/ /* Function peekb */ #ifdef L___peekb #asm ! int peekb( unsigned segment, char *offset ); ! returns the (unsigned) byte at the far pointer segment:offset .define _peekb _peekb: mov cx,ds pop dx pop ds pop bx sub sp,*4 movb al,(bx) subb ah,ah mov ds,cx jmp dx #endasm #endif /************************************************************************/ /* Function peekw */ #ifdef L___peekw #asm ! int peekw( unsigned segment, int *offset ); ! returns the word at the far pointer segment:offset .define _peekw _peekw: mov cx,ds pop dx pop ds pop bx sub sp,*4 mov ax,(bx) mov ds,cx jmp dx #endasm #endif /************************************************************************/ /* Function pokeb */ #ifdef L___pokeb #asm ! void pokeb( unsigned segment, char *offset, char value ); ! writes the byte value at the far pointer segment:offset .define _pokeb _pokeb: mov cx,ds pop dx pop ds pop bx pop ax sub sp,*6 movb (bx),al mov ds,cx jmp dx #endasm #endif /************************************************************************/ /* Function pokew */ #ifdef L___pokew #asm ! void pokew( unsigned segment, int *offset, int value ); ! writes the word value at the far pointer segment:offset .define _pokew _pokew: mov cx,ds pop dx pop ds pop bx pop ax sub sp,*6 mov (bx),ax mov ds,cx jmp dx #endasm #endif #endif /* !__FIRST_ARG_IN_AX__ */ #endif dev86-0.16.21/libc/bcc/bcc_long.c000066400000000000000000000140141231050321700161610ustar00rootroot00000000000000/************************************************************************/ /* This file contains the BCC compiler helper functions */ /* (C) Copyright Bruce Evans */ /* Support for long arithmetic on little-endian (normal) longs * __laddl.o __landl.o __lcmpl.o __lcoml.o __ldecl.o __ldivl.o __ldivul.o * __leorl.o __lincl.o __lmodl.o __lmodul.o __lmull.o __lnegl.o __lorl.o * __lsll.o __lsrl.o __lsrul.o __lsubl.o __ltstl.o */ #ifdef __AS386_16__ #asm .text ! This is common to all. .even #endasm /************************************************************************/ /* Function laddl */ #ifdef L___laddl #asm ! laddl.s .globl laddl .globl laddul laddl: laddul: add ax,[di] adc bx,2[di] ret #endasm #endif /************************************************************************/ /* Function landl */ #ifdef L___landl #asm ! landl.s .globl landl .globl landul landl: landul: and ax,[di] and bx,2[di] ret #endasm #endif /************************************************************************/ /* Function lcmpl */ #ifdef L___lcmpl #asm ! lcmpl.s ! lcmpl, lcmpul don`t preserve bx .globl lcmpl .globl lcmpul lcmpl: lcmpul: sub bx,2[di] je LCMP_NOT_SURE ret .even LCMP_NOT_SURE: cmp ax,[di] jb LCMP_B_AND_LT jge LCMP_EXIT inc bx LCMP_EXIT: ret .even LCMP_B_AND_LT: dec bx ret #endasm #endif /************************************************************************/ /* Function lcoml */ #ifdef L___lcoml #asm ! lcoml.s .globl lcoml .globl lcomul lcoml: lcomul: not ax not bx ret #endasm #endif /************************************************************************/ /* Function ldecl */ #ifdef L___ldecl #asm ! ldecl.s .globl ldecl .globl ldecul ldecl: ldecul: cmp word ptr [bx],*0 je LDEC_BOTH dec word ptr [bx] ret .even LDEC_BOTH: dec word ptr [bx] dec word ptr 2[bx] ret #endasm #endif /************************************************************************/ /* Function ldivl */ #ifdef L___ldivl #asm ! ldivl.s ! bx:ax / 2(di):(di), quotient bx:ax, remainder di:cx, dx not preserved .globl ldivl .extern ldivmod ldivl: mov cx,[di] mov di,2[di] call ldivmod xchg ax,cx xchg bx,di ret #endasm #endif /************************************************************************/ /* Function ldivul */ #ifdef L___ldivul #asm ! ldivul.s ! unsigned bx:ax / 2(di):(di), quotient bx:ax,remainder di:cx, dx not preserved .globl ldivul .extern ludivmod ldivul: mov cx,[di] mov di,2[di] call ludivmod xchg ax,cx xchg bx,di ret #endasm #endif /************************************************************************/ /* Function leorl */ #ifdef L___leorl #asm ! leorl.s .globl leorl .globl leorul leorl: leorul: xor ax,[di] xor bx,2[di] ret #endasm #endif /************************************************************************/ /* Function lincl */ #ifdef L___lincl #asm ! lincl.s .globl lincl .globl lincul lincl: lincul: inc word ptr [bx] je LINC_HIGH_WORD ret .even LINC_HIGH_WORD: inc word ptr 2[bx] ret #endasm #endif /************************************************************************/ /* Function lmodl */ #ifdef L___lmodl #asm ! lmodl.s ! bx:ax % 2(di):(di), remainder bx:ax, quotient di:cx, dx not preserved .globl lmodl .extern ldivmod lmodl: mov cx,[di] mov di,2[di] call ldivmod ret #endasm #endif /************************************************************************/ /* Function lmodul */ #ifdef L___lmodul #asm ! lmodul.s ! unsigned bx:ax / 2(di):(di), remainder bx:ax,quotient di:cx, dx not preserved .globl lmodul .extern ludivmod lmodul: mov cx,[di] mov di,2[di] call ludivmod ret #endasm #endif /************************************************************************/ /* Function lmull */ #ifdef L___lmull #asm ! lmull.s ! lmull, lmulul don`t preserve cx, dx .globl lmull .globl lmulul lmull: lmulul: mov cx,ax mul word ptr 2[di] xchg ax,bx mul word ptr [di] add bx,ax mov ax,ptr [di] mul cx add bx,dx ret #endasm #endif /************************************************************************/ /* Function lnegl */ #ifdef L___lnegl #asm ! lnegl.s .globl lnegl .globl lnegul lnegl: lnegul: neg bx neg ax sbb bx,*0 ret #endasm #endif /************************************************************************/ /* Function lorl */ #ifdef L___lorl #asm ! lorl.s .globl lorl .globl lorul lorl: lorul: or ax,[di] or bx,2[di] ret #endasm #endif /************************************************************************/ /* Function lsll */ #ifdef L___lsll #asm ! lsll.s ! lsll, lslul don`t preserve cx .globl lsll .globl lslul lsll: lslul: mov cx,di jcxz LSL_EXIT cmp cx,*32 jae LSL_ZERO LSL_LOOP: shl ax,*1 rcl bx,*1 loop LSL_LOOP LSL_EXIT: ret .even LSL_ZERO: xor ax,ax mov bx,ax ret #endasm #endif /************************************************************************/ /* Function lsrl */ #ifdef L___lsrl #asm ! lsrl.s ! lsrl doesn`t preserve cx .globl lsrl lsrl: mov cx,di jcxz LSR_EXIT cmp cx,*32 jae LSR_SIGNBIT LSR_LOOP: sar bx,*1 rcr ax,*1 loop LSR_LOOP LSR_EXIT: ret .even LSR_SIGNBIT: mov cx,*32 j LSR_LOOP #endasm #endif /************************************************************************/ /* Function lsrul */ #ifdef L___lsrul #asm ! lsrul.s ! lsrul doesn`t preserve cx .globl lsrul lsrul: mov cx,di jcxz LSRU_EXIT cmp cx,*32 jae LSRU_ZERO LSRU_LOOP: shr bx,*1 rcr ax,*1 loop LSRU_LOOP LSRU_EXIT: ret .even LSRU_ZERO: xor ax,ax mov bx,ax ret #endasm #endif /************************************************************************/ /* Function lsubl */ #ifdef L___lsubl #asm ! lsubl.s .globl lsubl .globl lsubul lsubl: lsubul: sub ax,[di] sbb bx,2[di] ret #endasm #endif /************************************************************************/ /* Function ltstl */ #ifdef L___ltstl #asm ! ltstl.s ! ltstl, ltstul don`t preserve bx .globl ltstl .globl ltstul ltstl: ltstul: test bx,bx je LTST_NOT_SURE ret .even LTST_NOT_SURE: test ax,ax js LTST_FIX_SIGN ret .even LTST_FIX_SIGN: inc bx ret #endasm #endif #endif dev86-0.16.21/libc/bcc/heap.c000066400000000000000000000065421231050321700153370ustar00rootroot00000000000000/* Copyright (C) 1995,1996 Robert de Bath * This file is part of the Linux-8086 C library and is distributed * under the GNU Library General Public License. */ #include /****************************************************************************/ #ifdef L_errno int errno = 0; /* libc error value */ #endif /****************************************************************************/ #ifdef __AS386_16__ #ifdef L___brk_addr #asm .data export brk_addr brk_addr: .word __end ! This holds the current return for sbrk(0) .text #endasm #endif /****************************************************************************/ #ifdef L_sbrk int sbrk(brk_off) int brk_off; { #asm mov bx,sp #if !__FIRST_ARG_IN_AX__ mov ax,[bx+2] ! Fetch the requested value #endif test ax,ax jnz has_change mov ax,[brk_addr] ! Simple one, read current - can`t fail. jmp eof has_change: js go_down add ax,[brk_addr] ! Goin up! jc Enomem sub bx,#511 ! Safety space 512 bytes cmp bx,ax ! Too close ? jb Enomem sbrk_ok: #if !defined(__MSDOS__) && !defined(__STANDALONE__) push ax ! MSDOS `kernel` doesn`t care call ___brk ! Tell the kernel test ax,ax pop ax ! ASSUME ___brk doesn`t alter stack! jnz Enomem ! Ugh! kernel didn`t like the idea! #endif xchg [brk_addr],ax ! Save away new val jmp eof ! Return it go_down: add ax,[brk_addr] jnc Enomem cmp ax,#__end jae sbrk_ok Enomem: mov ax,#12 ! This should be ENOMEM not a magic. mov [_errno],ax mov ax,#-1 eof: #endasm } #endif /****************************************************************************/ #ifdef L_brk int brk(new_brk) char * new_brk; { #asm mov bx,sp #if !__FIRST_ARG_IN_AX__ mov ax,[bx+2] ! Fetch the requested value #endif sub bx,#512 ! Safety space 512 bytes cmp bx,ax ! Too close ? jb Enomem cmp ax,#__end jae brk_ok Enomem: mov ax,#12 ! This should be ENOMEM not a magic. mov [_errno],ax mov ax,#-1 ret brk_ok: #if !defined(__MSDOS__) && !defined(__STANDALONE__) push ax call ___brk ! Tell the kernel test ax,ax pop bx ! ASSUME ___brk doesn`t alter stack! jnz Enomem ! Ugh! kernel didn`t like the idea! mov [brk_addr],bx ! Save away new val #else mov [brk_addr],ax ! MSDOS `kernel` doesn`t care mov ax,#0 #endif #endasm } #endif #endif /****************************************************************************/ #ifdef __AS386_32__ extern char * __brk_addr; extern char * __brk(); #ifdef L___brk_addr char * __brk_addr = 0; /* This holds the current return for sbrk(0) */ char * __brk(val) { #asm #if __FIRST_ARG_IN_AX__ mov ebx,eax #else mov ebx,[esp+4] #endif mov eax,#45 int $80 #endasm } __brk_addr_init() { if( __brk_addr == 0 && (__brk_addr = __brk(0)) == 0 ) { errno = ENOMEM; return -1; } return 0; } #endif #ifdef L_sbrk char * sbrk(brk_off) int brk_off; { char * new_brk; if( __brk_addr_init() ) return (char*)-1; if( brk_off == 0 ) return __brk_addr; new_brk = __brk_addr + brk_off; __brk_addr = __brk(new_brk); if( __brk_addr != new_brk ) { errno = ENOMEM; return (char*)-1; } return __brk_addr - brk_off; } #endif #ifdef L_brk int brk(new_brk) char * new_brk; { if( __brk_addr_init() ) return -1; __brk_addr = __brk(new_brk); if( __brk_addr == new_brk ) return 0; errno = ENOMEM; return -1; } #endif #endif dev86-0.16.21/libc/bcc/ldiv.c000066400000000000000000000007531231050321700153560ustar00rootroot00000000000000/************************************************************************/ /* This file contains the BCC compiler helper functions */ /* (C) Copyright Bruce Evans */ #ifdef __AS386_16__ #asm .text export _ldiv _ldiv: push bp mov bp,sp push di push si mov ax,[bp+6] mov bx,[bp+8] mov cx,[bp+10] mov di,[bp+12] call ldivmod mov si,[bp+4] mov [si],cx mov [si+2],di mov [si+4],ax mov [si+6],bx mov ax,si pop si pop di pop bp ret .data .bss #endasm #endif dev86-0.16.21/libc/bios/000077500000000000000000000000001231050321700144545ustar00rootroot00000000000000dev86-0.16.21/libc/bios/Config000066400000000000000000000000461231050321700156040ustar00rootroot00000000000000bios: Minimal syscalls for BIOS level dev86-0.16.21/libc/bios/Makefile000066400000000000000000000022071231050321700161150ustar00rootroot00000000000000# Copyright (C) 1996 Robert de Bath # This file is part of the Linux-8086 C library and is distributed # under the GNU Library General Public License. ifeq ($(LIB_OS),BIOS) ASRC=bios.c AOBJ=bios_start.o bios_isatty.o bios_abort.o bios_nofiles.o \ bios_read.o bios_write.o bios_lseek.o bios_close.o BSRC=bios_vid.c BOBJ=bios_putch.o bios_getch.o bios_getche.o bios_cputs.o bios_kbhit.o \ bios_rdline.o CSRC=bios_min.c COBJ=bios_putc.o bios_getc.o bios_khit.o DSRC=bios_disk.c DOBJ=bios_disk_rd.o bios_disk_wr.o bios_disk_rs.o bios_get_dpt.o OBJ=$(AOBJ) $(BOBJ) $(COBJ) $(DOBJ) \ time.o fileops.o fs_dos.o rawio.o vt52.o ansi.o CFLAGS=$(ARCH) $(CCFLAGS) $(DEFS) all: $(LIBC)($(OBJ)) @$(RM) $(OBJ) $(LIBC)($(AOBJ)): $(ASRC) $(CC) $(CFLAGS) -DL_$* $< -c -o $*.o $(AR) $(ARFLAGS) $@ $*.o $(LIBC)($(BOBJ)): $(BSRC) $(CC) $(CFLAGS) -DL_$* $< -c -o $*.o $(AR) $(ARFLAGS) $@ $*.o $(LIBC)($(COBJ)): $(CSRC) $(CC) $(CFLAGS) -DL_$* $< -c -o $*.o $(AR) $(ARFLAGS) $@ $*.o $(LIBC)($(DOBJ)): $(DSRC) $(CC) $(CFLAGS) -DL_$* $< -c -o $*.o $(AR) $(ARFLAGS) $@ $*.o else all: @: endif clean: rm -f *.o libc.a dev86-0.16.21/libc/bios/README000066400000000000000000000006261231050321700153400ustar00rootroot00000000000000Copyright (C) 1996 Robert de Bath This file is part of the Linux-8086 C library and is distributed under the GNU Library General Public License. This is a very simple set of functions for standalone executables. There is a choice as to which console type you want to use, I think the VT52 clone is best. To activate it you have to call 'vt52_putc' at least once. -Robert dev86-0.16.21/libc/bios/ansi.c000066400000000000000000000114551231050321700155600ustar00rootroot00000000000000/* Copyright (C) 1996 Robert de Bath * This file is part of the Linux-8086 C library and is distributed * under the GNU Library General Public License. */ #if !__FIRST_ARG_IN_AX__ #ifdef __AS386_16__ #ifdef __STANDALONE__ #include #include int errno; extern void (*__smart_putch)(); #define CTRL(x) ((x)&0x1F) static int last_attr = 0x07; static int con_mode; static unsigned char con_height = 24, con_width = 79; static int con_colour = 0; static unsigned char con_row, con_col; #ifdef ANSI_CON #define MAX_ARGS 8 static int colconv[] = { 0, 4, 2, 6, 1, 5, 3, 7 }; static int vidcnt = 0; static int ansi_2 = 0; static int ansi_argc = 0; static int ansi_argv[MAX_ARGS]; static void do_ansi(); ansi_putch(c) int c; { if( con_mode==0 ) asm_coninit(); __smart_putch = ansi_putch; if( vidcnt == 0 || c < ' ' || c > '~' ) { switch(c & 0xFF) { default: asm_colour(last_attr); asm_putc(c); break; case CTRL('I'): asm_gpos(); con_col = ((con_col+8)& -8); asm_cpos(con_row, con_col); break; case CTRL('L'): asm_cpos(0,0); asm_cls(); break; case CTRL('['): vidcnt=1; break; } return; } /* ... ansi/vt100 interpretation, this collects _all_ ansi control strings */ switch(vidcnt) { case 1: for(ansi_argc=0; ansi_argc= '0' && c <= '9' ) ansi_argv[ansi_argc] = ansi_argv[ansi_argc] * 10 + c - '0'; else if( c >= '@' ) { do_ansi(c+ansi_2, ++ansi_argc, ansi_argv); vidcnt = 0; } else ansi_2 = (c<<8); break; default: vidcnt = 0; /* This definitly won't happen ... definitly ... */ } } void do_ansi(ctrl, argc, argv) int ctrl, argc, *argv; { switch(ctrl) { case 'A': case 'B': case 'C': case 'D': asm_gpos(); if( argv[0] < 1 ) argv[0] = 1; switch(ctrl) { case 'A': if( argv[0]>con_row ) con_row=0; else con_row-=argv[0]; break; case 'B': if( argv[0]+con_row>con_height ) con_row = con_height; else con_row += argv[0]; break; case 'C': if( argv[0]+con_col>con_width ) con_col = con_width; else con_col += argv[0]; break; case 'D': if( argv[0]>con_col ) con_col=0; else con_col-=argv[0]; break; } asm_cpos(con_row, con_col); break; case 'H': if( --argv[0] < 0 ) argv[0] = 0; if( --argv[1] < 0 ) argv[1] = 0; asm_cpos(argv[0],argv[1]); break; case 'J': if( argv[0] == 2 ) asm_cls(); break; case 'm': { int ar; for(ar=0; ar 39 ) con_width = (con_mode>>8); if( (con_mode&0xFF) != 0x7) con_colour = 1; } static asm_putc(c) { #asm #if !__FIRST_ARG_IN_AX__ mov bx,sp mov ax,[bx+2] #endif cmp al,#$0A jne not_nl mov ax,#$0E0D mov bx,#7 int $10 mov al,#$0A not_nl: mov ah,#$0E mov bx,#7 int $10 #endasm } static asm_cls() { #asm push bp ! Bug in some old BIOS`s !mov ax,#$0500 !int $10 mov ax,#$0600 mov bh,_last_attr mov cx,#$0000 mov dl,_con_width mov dh,_con_height int $10 pop bp #endasm } static asm_cpos(r,c) { #asm #if __FIRST_ARG_IN_AX__ mov bx,sp mov dh,al mov ax,[bx+2] mov dl,al #else mov bx,sp mov ax,[bx+2] mov dh,al mov ax,[bx+4] mov dl,al #endif mov ah,#$02 mov bx,#7 int $10 #endasm } static asm_colour(c) { #asm #if __FIRST_ARG_IN_AX__ mov bx,ax #else mov bx,sp mov bx,[bx+2] #endif mov ah,#$08 int $10 mov ah,#$09 mov cx,#1 int $10 #endasm } static asm_gpos() { #asm mov ah,#$03 mov bx,#7 int $10 mov [_con_row],dh mov [_con_col],dl mov ax,cx #endasm } #endif #endif #endif dev86-0.16.21/libc/bios/bios.c000066400000000000000000000117521231050321700155620ustar00rootroot00000000000000/* Copyright (C) 1996 Robert de Bath * This file is part of the Linux-8086 C library and is distributed * under the GNU Library General Public License. */ #undef AOUT_STANDALONE #if !__FIRST_ARG_IN_AX__ #ifdef __AS386_16__ #ifdef __STANDALONE__ #include #include #include #ifdef L_bios_start char ** environ = { 0 }; int errno; void (*__cleanup)() = 0; #asm .data export ___argr ___argr: .word 0,0,0,0,0,0,0,0 ! A struct REGS: ax, bx, cx, dx, si, di, cflag, flags defarg: .word boot_str, 0 boot_str: .asciz "boot" loop_save: .word 0 .text export ___cstartup ! Crt0 startup ___cstartup: cli #ifndef AOUT_STANDALONE seg cs cmp word ptr [0],#$20CD ! "int 20h" at psp: CS:0000 jne not_dos ! DOS - only AX has a defined value. ! All the segment registers are pointing at the PSP ! SP points to the top of the segment so is probably useable. push ax ! Save AX mov ax,cs add ax,#$10 ! bump CS by 0x10 push ax mov ax,#is_dos ! resume address push ax retf ! continue at next instruction dos_flag: .word 0 ! Set to 1 if DOS is_dos: seg cs inc dos_flag pop ax ! restore saved AX not_dos: mov sp,cs add sp,#__segoff mov ds,sp mov ss,sp mov bp,#__heap_top mov sp,#___argr+14 seg cs push [dos_flag] ! Set the carry flag if we're under DOS. #else mov bp,sp mov sp,#___argr+12 #endif push di push si push dx push cx push bx push ax mov sp,bp sti zap_bss: ! Clear the BSS push ds pop es ! ES now data seg mov di,#__edata mov cx,#__end sub cx,di xor ax,ax cld rep stosb !mov bp,ax ! Top frame pointer, only needed if we get a debugger push [_environ] mov ax,#defarg ! Don`t define __mkargv, standalone programs don`t push ax ! get any arguments. mov ax,#1 push ax mov bx,#auto_start ! Pointer to first autostart function auto_run: mov [loop_save],bx mov bx,[bx] test bx,bx jz no_entry call bx ! Call the function no_entry: mov bx,[loop_save] inc bx ! next inc bx jmp auto_run ! And round for the next. call_exit: ! Last item called by above. pop bx ! Be tidy. push ax ! At the end the last called was main() push it`s call _exit ! return val and call exit(); bad_exit: jmp bad_exit ! Exit returned !! loc 2 .word _main ! Segment 2 is the trailing pointers, main and the .word call_exit ! routine to call exit. data_start: .text export _exit _exit: ! exit(rv) function mov bx,sp push [bx+2] ! Copy the `rv` for the exit fuctions. mov bx,[___cleanup] ! Call exit, normally this is `__do_exit` test bx,bx je no_clean ! But it`s default is null call bx no_clean: inc sp inc sp export __exit __exit: #ifndef AOUT_STANDALONE seg cs cmp [dos_flag],#0 ! Should we do a DOS exit je do_reboot mov ax,#$4c00 int $21 do_reboot: #endif xor ax,ax mov ds,ax mov ax,cs mov [$E6*4+2],ax mov ax,#iret_ins mov [$E6*4],ax mov ax,#$FFFF int $E6 ! Try to exit DOSEMU ! If we get here we`re not in dosemu. mov [$472],#$1234 ! Warm reboot. jmpi $0000,$FFFF iret_ins: iret #endasm #endif /****************************************************************************/ #ifdef L_bios_write write(fd,buf,len) int fd,len; char * buf; { register int v, c; if(fd == 1 || fd == 2) { for(v=len; v>0; v--) { c= *buf++; putch(c); } return len; } return (*__files)(CMD_WRITE, fd, buf, len); } #endif /****************************************************************************/ #ifdef L_bios_read read(fd,buf,len) int fd,len; char * buf; { if(fd == 0) return bios_rdline(buf, len); return (*__files)(CMD_READ, fd, buf, len); } #endif /****************************************************************************/ #ifdef L_bios_lseek long lseek(fd, offt, whence) int fd, whence; long offt; { if( fd >= 0 && fd <= 2 ) errno = ESPIPE; else { if( (*__files)(CMD_LSEEK, fd, &offt, whence) >= 0 ) return offt; } return -1L; } #endif /****************************************************************************/ #ifdef L_bios_close close(fd) int fd; { if( fd >= 0 && fd <= 2 ) errno = ENOSYS; else return (*__files)(CMD_CLOSE, fd); return -1; } #endif /****************************************************************************/ #ifdef L_bios_nofiles int (*__files)() = __nofiles; int __nofiles(cmd, fd, buf, len) int cmd, fd, len; char * buf; { errno = EBADF; return -1; } #endif /****************************************************************************/ #ifdef L_bios_isatty isatty(fd) int fd; { if( fd >= 0 && fd <= 2 ) return 1; return 0; } #endif /****************************************************************************/ #ifdef L_bios_abort abort() { static const char msg[] = "Program aborted, press return:"; write(2, msg, sizeof(msg)-1); getch(); _exit(255); } #endif /****************************************************************************/ #endif #endif #endif dev86-0.16.21/libc/bios/bios_disk.c000066400000000000000000000041571231050321700165750ustar00rootroot00000000000000 #if !__FIRST_ARG_IN_AX__ #ifdef __AS386_16__ #include #include #ifdef L_bios_disk_rd _bios_disk_read(drive, cyl, head, sect, length, buffer) { #asm push bp mov bp,sp push es push ds pop es mov dl,[bp+2+__bios_disk_read.drive] mov ch,[bp+2+__bios_disk_read.cyl] mov dh,[bp+2+__bios_disk_read.head] mov bx,[bp+2+__bios_disk_read.buffer] #if 0 mov ax,[bp+2+__bios_disk_read.cyl] ! Bits 10-11 of cylinder, AMI BIOS. mov cl,#4 sar ax,cl and al,#$C0 xor dh,al #endif mov cl,[bp+2+__bios_disk_read.sect] and cl,#$3F mov ax,[bp+2+__bios_disk_read.cyl] ! Bits 8-9 of cylinder. sar ax,#1 sar ax,#1 and al,#$C0 or cl,al mov al,[bp+2+__bios_disk_read.length] mov ah,#$02 int $13 jc read_err1 mov ax,#0 read_err1: xchg ah,al xor ah,ah pop es pop bp #endasm } #endif #ifdef L_bios_disk_wr _bios_disk_write(drive, cyl, head, sect, length, buffer) { #asm push bp mov bp,sp push es push ds pop es mov dl,[bp+2+__bios_disk_write.drive] mov ch,[bp+2+__bios_disk_write.cyl] mov dh,[bp+2+__bios_disk_write.head] mov bx,[bp+2+__bios_disk_write.buffer] #if 0 mov ax,[bp+2+__bios_disk_write.cyl] ! Bits 10-11 of cylinder, AMI BIOS. mov cl,#4 sar ax,cl and al,#$C0 xor dh,al #endif mov cl,[bp+2+__bios_disk_write.sect] and cl,#$3F mov ax,[bp+2+__bios_disk_write.cyl] ! Bits 8-9 of cylinder. sar ax,#1 sar ax,#1 and al,#$C0 or cl,al mov al,[bp+2+__bios_disk_write.length] mov ah,#$03 int $13 jc read_err2 mov ax,#0 read_err2: xchg ah,al xor ah,ah pop es pop bp #endasm } #endif #ifdef L_bios_get_dpt long _bios_get_dpt(drive) { #asm push bp mov bp,sp push di push es mov dl,[bp+2+__bios_get_dpt.drive] mov ah,#$08 int $13 jnc func_ok mov cx,ax mov dx,#-1 func_ok: mov ax,cx pop es pop di pop bp #endasm } #endif #ifdef L_bios_disk_rs _bios_disk_reset(drive) { #asm push bp mov bp,sp push di push es mov dl,[bp+2+__bios_disk_reset.drive] mov ah,#$08 int $13 jnc reset_ok mov cx,ax mov dx,#-1 reset_ok: mov ax,cx pop es pop di pop bp #endasm } #endif #endif #endif dev86-0.16.21/libc/bios/bios_min.c000066400000000000000000000015751231050321700164270ustar00rootroot00000000000000/* Copyright (C) 1996 Robert de Bath * This file is part of the Linux-8086 C library and is distributed * under the GNU Library General Public License. */ #ifdef __AS386_16__ #ifdef __STANDALONE__ #include #ifdef L_bios_putc bios_putc(c) { #asm #if !__FIRST_ARG_IN_AX__ mov bx,sp mov ax,[bx+2] #endif mov ah,#$0E mov bx,#7 int $10 #endasm } #endif /****************************************************************************/ #ifdef L_bios_getc bios_getc() { #asm xor ax,ax int $16 #endasm } #endif /****************************************************************************/ #ifdef L_bios_khit bios_khit() { #asm mov ah,#1 int $16 jz nokey cmp ax,#0 jnz dort mov ax,#3 dort: ret nokey: xor ax,ax #endasm } #endif /****************************************************************************/ #endif #endif dev86-0.16.21/libc/bios/bios_vid.c000066400000000000000000000065001231050321700164170ustar00rootroot00000000000000/* Copyright (C) 1996 Robert de Bath * This file is part of the Linux-8086 C library and is distributed * under the GNU Library General Public License. */ #if !__FIRST_ARG_IN_AX__ #ifdef __AS386_16__ #ifdef __STANDALONE__ #include #include int errno; #ifdef L_bios_putch void (*__smart_putch)() = 0; putch(c) int c; { static int col = 0; if (__smart_putch) (*__smart_putch)(c); else if (c&0xE0) { col++; asm_putc(c); } else switch(c) { case '\t': do putch(' '); while(col&7); break; case '\n': asm_putc('\r'); case '\r': col = 0; asm_putc(c); break; case '\f': col = 0; #asm mov ah,#$0F int $10 mov ah,#$00 int $10 #endasm break; } } static asm_putc(c) { #asm #if !__FIRST_ARG_IN_AX__ mov bx,sp mov ax,[bx+2] #endif mov ah,#$0E mov bx,#7 int $10 #endasm } #endif /****************************************************************************/ #ifdef L_bios_getch getch() { #asm xor ax,ax int $16 #endasm } #endif /****************************************************************************/ #ifdef L_bios_kbhit kbhit() { #asm mov ah,#1 int $16 jz nokey cmp ax,#0 jnz dort mov ax,#3 dort: ret nokey: xor ax,ax #endasm } #endif /****************************************************************************/ #ifdef L_bios_cputs cputs(str) char * str; { while(*str) putch(*str++); } #endif /****************************************************************************/ #ifdef L_bios_getche getche() { static char linebuf[80]; static int nextc = 0, endc=0; int rv; if (nextc >= endc) { endc = bios_readline(linebuf, sizeof(linebuf)); nextc= 0; } if (endc <= nextc) return 3; rv = linebuf[endc++]; if (endc == nextc) return '\r'; return rv; } #endif /****************************************************************************/ #ifdef L_bios_gotoxy static gotoxy(x,y) { #asm #if __FIRST_ARG_IN_AX__ mov bx,sp mov dl,al mov ax,[bx+2] mov dh,al #else mov bx,sp mov ax,[bx+4] mov dh,al mov ax,[bx+2] mov dl,al #endif mov ah,#$02 mov bx,#7 int $10 #endasm } #endif /****************************************************************************/ #ifdef L_bios_rdline bios_rdline(buf, len) char * buf; int len; { int ch; int pos=0; if( len < 0 ) { errno = EINVAL; return -1; } if( len == 0 ) { if( kbhit() == 0 ) return 0; errno = EINTR; return -1; } if( len == 1 ) { buf[0]=((ch=getch())&0xFF?ch&0xFF:((ch>>8)&0xFF|0x80)); return 1; } for(ch=0;;) { if(ch != '\003') { ch = getch(); if( pos == 0 && (ch&0xFF) == 0 ) { buf[0] = ((ch>>8)|0x80); return 1; } ch &= 0x7F; } if( ch == '\r' ) { putch('\n'); buf[pos++] = '\n'; return pos; } if( ch >= ' ' && ch != 0x7F && pos < len-1) putch(buf[pos++] = ch); else if( (ch == '\003' || ch == '\b') && pos > 0 ) { putch('\b'); putch(' '); putch('\b'); pos--; } else if( ch == '\003' ) return 0; else putch('\007'); } } #endif /****************************************************************************/ #endif #endif #endif dev86-0.16.21/libc/bios/fileops.c000066400000000000000000000073721231050321700162720ustar00rootroot00000000000000 #include #include #include #include "io.h" #include "rawio.h" static int op_open(); static int op_close(); static int op_read(); static int op_write(); static long op_lseek(); static int fileops(); int open(name, flags, mode) char * name; int flags, mode; { __files = fileops; return (*__files)(CMD_OPEN, flags, name, mode); } static int fileops(cmd, fd, buf, len) int cmd, fd, len; char * buf; { switch(cmd) { case CMD_OPEN: return op_open(buf, fd, len); case CMD_READ: return op_read(fd, buf, len); /* case CMD_WRITE: return op_write(fd, buf, len); case CMD_LSEEK: rv = op_lseek(fd, *(long*)buf, len); (*(long*)buf) = rv; if( rv == -1 ) return -1; else return 0; */ case CMD_CLOSE: return op_close(fd); } errno=EINVAL; return -1; } #define MAX_OPEN_FILES 5 ioblock _iob[MAX_OPEN_FILES]; static int op_read(fd,buf,len) int fd,len; char * buf; { ioblock* cur = &_iob[fd]; int amount_read = 0; int amount_left_in_buffer; int amount_to_copy; if (fd < 0 || fd >= MAX_OPEN_FILES || _iob[fd].block_read == 0) { errno = EBADF; return -1; } while (len > 0) { /* pull in next block as required */ if (cur->amount_left <= 0) { int read_len = cur->block_read(cur, cur->buffer, (long) cur->offset / sizeof(cur->buffer) ); #ifdef DEBUG fprintf(stderr, "br: returned %d\n", read_len); #endif if (read_len <= 0) break; cur->amount_left = read_len; } if (cur->amount_left > len) amount_to_copy = len; else amount_to_copy = cur->amount_left; #ifdef DEBUG fprintf(stderr, "r: len=%d, amount_left=%ld, offset=%ld, buf=%x\n", len, cur->amount_left, cur->offset, (int) cur->buffer[cur->offset % sizeof(cur->buffer)]); #endif memcpy(buf, &cur->buffer[cur->offset % sizeof(cur->buffer)], amount_to_copy); amount_read += amount_to_copy; len -= amount_to_copy; cur->offset += amount_to_copy; buf += amount_to_copy; cur->amount_left -= amount_to_copy; } return amount_read; } /****************************************************************************/ static int op_open(name, flags, mode) char * name; int flags, mode; { int fd; ioblock* cur; /* * discover whether the iob has been initialised or not */ if (_iob[0].flags == 0) { _iob[0].flags = O_RDONLY; _iob[1].flags = O_WRONLY; _iob[2].flags = O_WRONLY; } /* * discover next free iob */ for (fd = 3; fd < MAX_OPEN_FILES; ++fd) { if (_iob[fd].block_read == NULL && _iob[fd].block_write == NULL) break; } if (fd >= MAX_OPEN_FILES) { errno = EMFILE; /* too many open files */ return -1; } /* * try and find the file */ cur = &_iob[fd]; if (fsdos_open_file(cur, name, flags, mode) >= 0) { cur->amount_left = 0; cur->offset = 0; return fd; } cur->block_read = NULL; /* ensure that the file is closed */ cur->block_write = NULL; errno = ENOENT; return -1; } /****************************************************************************/ static int op_close(fd) int fd; { if (fd < 0 || fd >= MAX_OPEN_FILES || _iob[0].flags == 0) { errno = EBADF; return -1; } else { ioblock* cur = &_iob[fd]; cur->close(cur); cur->block_read = NULL; cur->block_write = NULL; cur->close = NULL; cur->flags = 0; return 0; } } /****************************************************************************/ dev86-0.16.21/libc/bios/fs_dos.c000066400000000000000000000177301231050321700161050ustar00rootroot00000000000000 #ifdef DEBUG #include #endif #include #include #include #include "io.h" #include "rawio.h" #define DOS_SECT(P) get_uint(P,0x0B) #define DOS_CLUST(P) get_byte(P,0x0D) #define DOS_RESV(P) get_uint(P,0x0E) #define DOS_NFAT(P) get_byte(P,0x10) #define DOS_NROOT(P) get_uint(P,0x11) #define DOS_MAXSECT(P) get_uint(P,0x13) #define DOS_MEDIA(P) get_byte(P,0x15) #define DOS_FATLEN(P) get_uint(P,0x16) #define DOS_SPT(P) get_uint(P,0x18) #define DOS_HEADS(P) get_uint(P,0x1A) #define DOS_HIDDEN(P) get_long(P,0x1C) #define DOS4_MAXSECT(P) get_long(P,0x20) #define DOS4_PHY_DRIVE(P) get_byte(P,0x24) #define DOS4_SERIAL(P) get_long(P,0x27) #define DOS4_FATTYPE(P) get_uint(P,0x39) /* These assume alignment is not a problem */ #define get_byte(P,Off) *((unsigned char*)((char*)(P)+(Off))) #define get_uint(P,Off) *((unsigned short*)((char*)(P)+(Off))) #define get_long(P,Off) *((long*)((char*)(P)+(Off))) static int read_bootblock(); static int dir_nentry, dir_sect; static int dos_clust0, dos_spc, dos_fatpos; static int last_serial = 0; struct filestatus { char fname[12]; unsigned short first_cluster; unsigned short cur_cluster; unsigned short sector_no; /* Max filesize = 32M */ long file_length; }; static int fsdos_read_block(); static int fsdos_close_file(); /* buffer to read into */ static char sect[512]; fsdos_open_file(iob, fname, flags, mode) ioblock* iob; char * fname; int flags; int mode; { extern union REGS __argr; char conv_name[12]; char *d, *s; int i; struct filestatus* cur_file; #ifdef DEBUG fprintf(stderr, "fsdos_open_file(%x, %s, %d, %d, %d)\n", iob, fname, flags, mode, sizeof(iob)); #endif iob->block_read = fsdos_read_block; iob->close = fsdos_close_file; /* Get the superblock */ if( read_bootblock() < 0 ) return -1; { /* Convert the name to MSDOS directory format */ strcpy(conv_name, " "); for(s=fname, d=conv_name; *s && *d && *s != '.' && *s != ' '; s++) { if( islower(*s) ) *d++ = toupper(*s); else *d++ = *s; } while( *s && *s != '.' ) s++; strcpy(d=(conv_name+8), " "); if( *s == '.' ) { for(s++; *s && *d; s++) { if( islower(*s) ) *d++ = toupper(*s); else *d++ = *s; } } } #ifdef DEBUG fprintf(stderr, "fsdos_open_file: converted filename=<%s>\n", conv_name); #endif /* Scan the root directory for the file */ s = sect; for(i=0; icontext = cur_file; if (iob->context == NULL) { errno = ENOMEM; return -1; } memset(cur_file, '\0', sizeof(*cur_file)); strcpy(cur_file->fname, conv_name); cur_file->first_cluster = get_uint(d,26); cur_file->file_length = get_long(d,28); cur_file->cur_cluster = cur_file->first_cluster; cur_file->sector_no = 0; return 0; } } return -1; } fsdos_rewind_file(iob) ioblock* iob; { struct filestatus* cur_file; if (iob == NULL || iob->context == NULL) { errno = EBADF; return -1; } cur_file = (struct filestatus*) iob->context; /* Is there an opened file ? */ if( cur_file->fname[0] == 0 ) return -1; cur_file->sector_no = 0; cur_file->cur_cluster = cur_file->first_cluster; return 0; } static int fsdos_close_file(iob) ioblock* iob; { struct filestatus* cur_file; if (iob == NULL || iob->context == NULL) { errno = EBADF; return -1; } cur_file = (struct filestatus*) iob->context; free(cur_file); iob->context = NULL; rawio_reset_disk(); return 0; } long fsdos_file_length(iob) ioblock* iob; { struct filestatus* cur_file; if (iob == NULL || iob->context == NULL) { errno = EBADF; return -1; } cur_file = (struct filestatus*) iob->context; /* Is there an opened file ? */ if( cur_file->fname[0] == 0 ) return -1; return cur_file->file_length; } static int fsdos_read_block(iob, buffer, block) ioblock* iob; char * buffer; long block; /* ignored for now */ { int s; char * ptr = buffer; struct filestatus* cur_file; long amount_left_in_file; long amount_to_read; #ifdef DEBUG fprintf(stderr, "rb: iob = %x, buf = %x, block = %ld\n", iob, buffer, block); #endif if (iob == NULL || iob->context == NULL) { #ifdef DEBUG fprintf(stderr, "rb: no context\n"); #endif errno = EBADF; return -1; } cur_file = (struct filestatus*) iob->context; /* Is there an opened file ? */ if( cur_file->fname[0] == 0 ) { #ifdef DEBUG fprintf(stderr, "fsdos_read_block: File is not currently open!\n"); #endif errno = EBADF; return -1; } amount_left_in_file = cur_file->file_length - block * 1024; if (amount_left_in_file < 0) { #ifdef DEBUG fprintf(stderr, "EOF\n"); #endif return 0; } /* Are we before the EOF ? NB: FAT12 ONLY! */ if( cur_file->cur_cluster >= 0xFF0 || cur_file->cur_cluster < 2 ) { #ifdef DEBUG fprintf(stderr, "Hit end of file; cluster 0x%03x\n", cur_file->cur_cluster); #endif return 0; } for(s=0; s<2; s++) { unsigned int sectno; if (amount_left_in_file <= 0) { #ifdef DEBUG fprintf(stderr, "r2: Hit end of file\n"); #endif break; } sectno = dos_clust0 + cur_file->cur_cluster * dos_spc + cur_file->sector_no % dos_spc; if (rawio_read_sector(sectno, ptr) <= 0) { #ifdef DEBUG fprintf(stderr, "r2: rawio failed\n"); #endif return -1; } cur_file->sector_no++; if( cur_file->sector_no % dos_spc == 0 ) { int odd = (cur_file->cur_cluster&1); unsigned int val, val2; val = cur_file->cur_cluster + (cur_file->cur_cluster>>1); if (rawio_read_sector(dos_fatpos+(val/512), sect) <= 0) return -1; if( val%512 == 511 ) { val2 = sect[511] & 0xFF; if (rawio_read_sector(dos_fatpos+(val/512)+1, sect) <= 0) return -1; val2 |= (sect[0]<<8); } else val2 = get_uint(sect, (val%512)); if( odd ) val2>>=4; val2 &= 0xFFF; cur_file->cur_cluster = val2; } amount_to_read = amount_left_in_file; if (amount_to_read > 512) amount_to_read = 512; ptr += amount_to_read; amount_left_in_file -= amount_to_read; } return ptr - buffer; } static int read_bootblock() { int rv, media_byte = 0; #ifdef DEBUG fprintf(stderr, "fs_dos:read_bootblock:\n"); #endif if (rawio_read_sector(1, sect) <= 0) return -1; media_byte = *(unsigned char*)sect; /* Valid media byte ? */ if( (media_byte & 0xF0) != 0xF0 ) return -1; if (rawio_read_sector(0, sect) <= 0) return -1; if( DOS_MEDIA(sect) != media_byte ) return -1; if( DOS_SPT(sect) > 63 ) return -1; if( DOS_SECT(sect) != 512 ) return -1; if( last_serial != DOS4_SERIAL(sect) ) fsdos_close_file(); last_serial = DOS4_SERIAL(sect); /* Collect important data */ dir_sect = DOS_RESV(sect) + DOS_NFAT(sect)*DOS_FATLEN(sect); dir_nentry = DOS_NROOT(sect); dos_fatpos = DOS_RESV(sect); dos_spc = DOS_CLUST(sect); if( dos_spc < 1 ) dos_spc = 1; dos_clust0 = dir_sect + (dir_nentry+15)/16 - 2*dos_spc; if( rawio_disk_cyls == 0 ) { rawio_disk_spt = DOS_SPT(sect); rawio_disk_heads = DOS_HEADS(sect); } #ifdef DEBUG fprintf(stderr, "read_bootblock: heads(%d), spt(%d), dir_sect(%d)\n", rawio_disk_heads, rawio_disk_spt, dir_sect); #endif return 0; } dev86-0.16.21/libc/bios/io.h000066400000000000000000000012311231050321700152310ustar00rootroot00000000000000#ifndef __io_h__ #define __io_h__ typedef struct { /* * both block_read/block_write should be defined as * int x(ioblock* iob, char* buffer, int blockno) * and it reads/writes 1k blocks * * close should be defined as int x(ioblock* ioblock); */ int (*block_read)(); /* read routine */ int (*block_write)(); /* write routine - not supported yet*/ int (*close)(); /* close routine */ long offset; /* current offset in file to read/write */ int flags; long amount_left; /* amount left in buffer */ char buffer[1024]; void* context; } ioblock; #endif dev86-0.16.21/libc/bios/rawio.c000066400000000000000000000165241231050321700157510ustar00rootroot00000000000000/* * rawio.c - plagiarised from ../../bootblocks/trk_buf.c */ #ifdef DEBUG #include #endif #include #include #include #include "rawio.h" int rawio_disk_drive = 0; int rawio_disk_spt = 7; int rawio_disk_heads = 2; int rawio_disk_cyls = 0; static int last_drive = 0; static int data_len = 0; static long data_trk1 = 0; static char * data_buf1 = 0; static long data_trk2 = 0; static char * data_buf2 = 0; static long bad_track = -1; /* Track number of last unsuccesful read */ static long rawio_get_dpt(); void rawio_reset_disk() { if( data_buf1 ) free(data_buf1); if( data_buf2 ) free(data_buf2); data_buf1 = data_buf2 = 0; last_drive = rawio_disk_drive; if( !(rawio_disk_drive & 0x80 ) ) { rawio_disk_spt = 7; /* Defaults for reading Boot area. */ rawio_disk_heads = 2; rawio_disk_cyls = 0; #ifdef DEBUG fprintf(stderr, "reset_disk (hard): spt = %d, heads = %d, cyls = %d\n", rawio_disk_spt, rawio_disk_heads, rawio_disk_cyls); #endif } #if defined(__MSDOS__) || defined(__STANDALONE__) else { /* Hard disk, get parameters from bios */ long dpt; int v; rawio_disk_spt = 17; /* Defaults for reading Boot area. */ rawio_disk_heads = 1; rawio_disk_cyls = 0; dpt = rawio_get_dpt(rawio_disk_drive); v = ((dpt>>16) & 0xFF); if( v == 0xFF || v <= (rawio_disk_drive&0x7F) ) return; /* Bad dpt */ rawio_disk_spt = (dpt & 0x3F); /* Max sector number 1-63 */ if( rawio_disk_spt == 0 ) rawio_disk_spt = 64; /* 1-64 ? */ rawio_disk_heads = ((dpt>>24) & 0xFF) + 1; /* Head count 1-256 */ rawio_disk_cyls = ((dpt>>8) & 0xFF) + ((dpt<<2) & 0x300) + 1; /* Cyls count, unchecked, only needs != 0, if AMI 386 bios can be * upto 4096 cylinder, otherwise BIOS limit is 1024 cyl. */ #ifdef DEBUG fprintf(stderr, "reset_disk (soft): spt = %d, heads = %d, cyls = %d\n", rawio_disk_spt, rawio_disk_heads, rawio_disk_cyls); #endif } #endif } int rawio_read_lsector(sectno, buffer) long sectno; char* buffer; { int tries = 6; int rv; int phy_s = 1; int phy_h = 0; int phy_c = 0; if( rawio_disk_drive != last_drive ) rawio_reset_disk(); if( rawio_disk_spt < 0 || rawio_disk_spt > 63 || rawio_disk_heads < 1 ) { phy_s = sectno; rawio_reset_disk(); #ifdef DEBUG fprintf(stderr, "read_sector(%ld = %d,%d,%d)\n", sectno, phy_c, phy_h, phy_s+1); #endif } else { phy_s = sectno%rawio_disk_spt; phy_h = sectno/rawio_disk_spt%rawio_disk_heads; phy_c = sectno/rawio_disk_spt/rawio_disk_heads; #ifdef DEBUG fprintf(stderr, "read_sector(%ld = %d,%d,%d)\n", sectno, phy_c, phy_h, phy_s+1); #endif if( rawio_fetch_track_buf(phy_c, phy_h, phy_s) >= 0 ) { #ifdef DEBUG fprintf(stderr, "read_sector: ftb worked\n"); #endif memcpy(buffer, data_buf1 + (phy_s % data_len) * 512, 512); return 512; } } data_len = -1; /* Zap the cache */ if( data_buf1 == 0 ) data_buf1 = malloc(512); if( data_buf1 == 0 ) { #ifdef DEBUG fprintf(stderr, "Cannot allocate memory for disk read!!!\n"); #endif return 0; } #ifdef DEBUG fprintf(stderr, "WARNING: Single sector read\n"); #endif do { rv = rawio_phy_read(rawio_disk_drive, phy_c, phy_h, phy_s+1, 1, data_buf1); tries--; #ifdef DEBUG if( rv ) fprintf(stderr, "Error in phy_read(%d,%d,%d,%d,%d,%d);\n", rawio_disk_drive, phy_c, phy_h, phy_s+1, 1, data_buf1); #endif } while(rv && tries > 0); if(rv) { #ifdef DEBUG fprintf(stderr, "rawio failed\n"); #endif return 0; } else { #ifdef DEBUG fprintf(stderr, "rawio worked\n"); #endif memcpy(buffer, data_buf1, 512); return 512; } } rawio_fetch_track_buf(phy_c, phy_h, phy_s) int phy_c, phy_h, phy_s; { long trk_no, t; char * p; int tries = 3; int rv, nlen; /* Big tracks get us short of memory so limit it. */ nlen = (rawio_disk_spt-1)/22; nlen = (rawio_disk_spt+nlen)/(nlen+1); trk_no = (long)phy_c*rawio_disk_heads*4+phy_h*4+phy_s/nlen+1; if( data_len != nlen ) { if( data_buf1 ) free(data_buf1); if( data_buf2 ) free(data_buf2); data_buf1 = data_buf2 = 0; data_len = rawio_disk_spt; } #ifdef DEBUG fprintf(stderr, "ftb: trk_no=%ld, data_trk1=%ld, data_buf1=%x\n", trk_no, data_trk1, data_buf1); #endif if( trk_no == bad_track ) return -1; if( data_buf1 && trk_no == data_trk1 ) return 0; /* Two cases: * 1) buffer2 has the one we want, need to swap to make it most recent * 2) Neither has it, need to swap to overwrite least recent. */ /* So we always swap */ p = data_buf1; data_buf1 = data_buf2; data_buf2 = p; t = data_trk1; data_trk1 = data_trk2; data_trk2 = t; #ifdef DEBUG fprintf(stderr, "ftb swap: trk_no=%ld, data_trk1=%ld, data_buf1=%x\n", trk_no, data_trk1, data_buf1); #endif /* The other one right ? */ if( data_buf1 && trk_no == data_trk1 ) return 0; /* If we get here we have to do a physical read ... */ /* into data_buf1. */ if( data_buf1 == 0 ) { data_buf1 = malloc(rawio_disk_spt*512); #ifdef __ELKS__ fprintf(stderr, "Allocated buffer to %d\n", data_buf1); #endif } if( data_buf1 == 0 ) { /* Is buf2 allocated ? Yes take it! */ data_buf1 = data_buf2; data_buf2 = 0; data_trk2 = -1; } bad_track = -1; data_trk1 = -1; #ifdef DEBUG fprintf(stderr, "ftb buf: trk_no=%ld, data_trk1=%ld, data_buf1=%x\n", trk_no, data_trk1, data_buf1); #endif /* Not enough memory for track read. */ if( data_buf1 == 0 ) return -1; do /* the physical read */ { rv = rawio_phy_read(rawio_disk_drive, phy_c, phy_h, phy_s/data_len+1, data_len, data_buf1); tries--; #ifdef DEBUG if( rv ) fprintf(stderr, "Error in phy_read(%d,%d,%d,%d,%d,%d);\n", rawio_disk_drive, phy_c, phy_h, phy_s/data_len+1, data_len, data_buf1); #endif } while(rv && tries > 0); /* Disk error, it'll try one at a time, _very_ slowly! */ if(rv) { bad_track = trk_no; return -1; } /* Yes! */ data_trk1 = trk_no; return 0; } #if defined(__MSDOS__) || defined(__STANDALONE__) rawio_phy_read(drive, cyl, head, sect, length, buffer) { #asm push bp mov bp,sp push es push ds pop es mov dl,[bp+2+_rawio_phy_read.drive] mov ch,[bp+2+_rawio_phy_read.cyl] mov dh,[bp+2+_rawio_phy_read.head] mov bx,[bp+2+_rawio_phy_read.buffer] mov ax,[bp+2+_rawio_phy_read.cyl] ! Bits 10-11 of cylinder, AMI BIOS. mov cl,#4 sar ax,cl and al,#$C0 xor dh,al mov cl,[bp+2+_rawio_phy_read.sect] and cl,#$3F mov ax,[bp+2+_rawio_phy_read.cyl] ! Bits 8-9 of cylinder. sar ax,#1 sar ax,#1 and al,#$C0 or cl,al mov al,[bp+2+_rawio_phy_read.length] mov ah,#$02 int $13 jc read_err mov ax,#0 read_err: pop es pop bp #endasm } long rawio_get_dpt(drive) { #asm push bp mov bp,sp push di push es mov dl,[bp+2+_rawio_get_dpt.drive] mov ah,#$08 int $13 jnc func_ok mov cx,ax mov dx,#-1 func_ok: mov ax,cx pop es pop di pop bp #endasm } #endif dev86-0.16.21/libc/bios/rawio.h000066400000000000000000000005771231050321700157570ustar00rootroot00000000000000#ifndef __readfs_h__ /* multi-inclusion protection */ #define __readfs_h__ #ifdef __STDC__ #define P(x) x #else #define P(x) () #endif #define rawio_read_sector(__sect, __buffer) rawio_read_lsector((unsigned long)__sect, __buffer) int rawio_read_lsector P((long sector, char* buffer)); extern int rawio_disk_cyls; extern int rawio_disk_heads; extern int rawio_disk_spt; #endif dev86-0.16.21/libc/bios/time.c000066400000000000000000000052031231050321700155560ustar00rootroot00000000000000/* * Time functions for standalone mode, on the first call to time() it tries * to query the RTC, on success it sets it's own day counter an the PC's * ticks since midnight clock. From the second call on it uses the day * counter and ticks clock. * * NOTES: * DOS's midnight bug is here too, it's actually in the bios. * If there's no RTC the clock will fall to Jan 3 1970. */ #include static int mdays[13] = { 0,31,31+28,31+28+31,31+28+31+30, 31+28+31+30+31,31+28+31+30+31+30,31+28+31+30+31+30+31, 31+28+31+30+31+30+31+31,31+28+31+30+31+30+31+31+30, 31+28+31+30+31+30+31+31+30+31,31+28+31+30+31+30+31+31+30+31+30, 365 }; #define SECSPERHOUR (60*60) #define SECSPERDAY (SECSPERHOUR*24L) /**************************************** * Return the number of seconds that have elapsed since the start * of 1970. * Input: * timer pointer to where to store result (or NULL) * Output: * *timer = result (unless timer == NULL) * Returns: * time */ static int xt_days = 0, ax_val, huns = 0; static long get_time(ah) { #asm #if !__FIRST_ARG_IN_AX__ mov bx,sp mov ax,[bx+2] #endif mov ah,al int $1A jnc intok mov cx,#-1 mov dx,cx intok: mov [_ax_val],ax mov ax,dx mov dx,cx #endasm } static int unbcd(bcdval) int bcdval; { return (bcdval&0xF) + 10*((bcdval>>4)&0xF); } time_t time(timer) time_t *timer; { unsigned day,month,year; long rv; time_t t; if( xt_days ) goto XT_time; rv = get_time(0x02); if(rv == -1) goto XT_time; huns = unbcd(rv & 0xFF); /* Save for stime */ rv >>= 8; t = unbcd(rv & 0xFF); rv >>= 8; t += unbcd(rv & 0xFF)*60; rv >>= 8; t += unbcd(rv & 0xFF)*3600; rv = get_time(0x04); if(rv == -1) goto XT_time; day = unbcd(rv & 0xFF); rv >>= 8; month = unbcd(rv & 0xFF) -1; rv >>= 8; year = unbcd(rv & 0xFF); rv >>= 8; year += unbcd(rv & 0xFF)*100; year -= 1970; if( year < 1950 && year >= 1900 ) year += 100; /* Century is not updated on RTC */ if (month <= 1 || year & 3) /* if before Feb or not a leap year */ day--; /* don't add day for leap year */ day += mdays[month]; /* day in year */ day += (year + 3) >> 2; /* add a day for each leap year */ t += ((year * 365L) + day) * SECSPERDAY; stime(t); if(0) { XT_time: rv = get_time(0); xt_days += (ax_val&0xFF); rv = xt_days*SECSPERDAY + rv * 1080 / 19663; } if (timer) *timer = t; return t; } static long ticks; stime(timer) time_t timer; { xt_days = (timer/SECSPERDAY); ticks = ((timer%SECSPERDAY) * 19663L + huns*196) / 1080; huns = 0; #asm mov cx,[_ticks+2] mov dx,[_ticks] mov ah,#1 int $1A #endasm return 0; } dev86-0.16.21/libc/bios/vt52.c000066400000000000000000000071101231050321700154170ustar00rootroot00000000000000/* Copyright (C) 1996 Robert de Bath * This file is part of the Linux-8086 C library and is distributed * under the GNU Library General Public License. */ #if !__FIRST_ARG_IN_AX__ #ifdef __AS386_16__ #ifdef __STANDALONE__ #include #include int errno; extern void (*__smart_putch)(); #define CTRL(x) ((x)&0x1F) static int last_attr = 0x07; static int con_mode; static unsigned char con_height = 24, con_width = 79; static int con_colour = 0; static unsigned char con_row, con_col; vt52_putch(c) int c; { static int ctrl = 0; int new_attr; __smart_putch = vt52_putch(); if( con_mode==0 ) asm_coninit(); switch( ctrl ) { case 1: ctrl=0; switch(c) { case 'A': if( con_row ) con_row--; asm_cpos(con_row, con_col); break; case 'B': if( con_row != con_height ) con_row++; asm_cpos(con_row, con_col); break; case 'C': if( con_col != con_height ) con_col++; asm_cpos(con_row, con_col); break; case 'D': if( con_col ) con_col--; asm_cpos(con_row, con_col); break; case 'E': last_attr = 0x07; asm_cls(); case 'H': asm_cpos(0,0); break; case 'J': asm_cls(); break; case 'K': break; case 'R': ctrl = 2; break; /* Foreground */ case 'S': ctrl = 3; break; /* Background */ case 'Y': ctrl = 4; break; /* ttypos */ } break; case 2: ctrl=0; new_attr = (last_attr & 0xF0) + (c&0xF); if(0) { case 3: ctrl=0; new_attr = (last_attr & 0x0F) + (c<<4); } switch(c) { case '_': if( !con_colour ) last_attr = (last_attr&0x88) + 1; break; case '!': last_attr = (last_attr&0x88) + 0x70; break; case ' ': last_attr = 0x07; break; case '+': last_attr |= 0x08; break; case '*': last_attr |= 0x80; break; default: if( con_colour ) last_attr = new_attr; } break; case 4: ctrl=5; con_col = c-' '; break; case 5: ctrl=0; con_row = c-' '; asm_cpos(con_row, con_col); break; break; default: if( c & 0xE0 ) { asm_colour(last_attr) ; asm_putc(c); } else switch(c) { default: asm_putc(c); break; case CTRL('I'): asm_gpos(); con_col = ((con_col+8)& -8); asm_cpos(con_row, con_col); break; case CTRL('L'): asm_cpos(0,0); asm_cls(); break; case CTRL('['): ctrl = 1; asm_gpos(); break; } break; } } static asm_coninit() { #asm mov ax,#$0F00 int $10 mov _con_mode,ax #endasm if( (con_mode &0xFF) > 39 ) con_width = (con_mode>>8); if( (con_mode&0xFF) != 0x7) con_colour = 1; } static asm_putc(c) { #asm #if !__FIRST_ARG_IN_AX__ mov bx,sp mov ax,[bx+2] #endif cmp al,#$0A jne not_nl mov ax,#$0E0D mov bx,#7 int $10 mov al,#$0A not_nl: mov ah,#$0E mov bx,#7 int $10 #endasm } static asm_cls() { #asm push bp ! Bug in some old BIOS`s !mov ax,#$0500 !int $10 mov ax,#$0600 mov bh,_last_attr mov cx,#$0000 mov dl,_con_width mov dh,_con_height int $10 pop bp #endasm } static asm_cpos(r,c) { #asm #if __FIRST_ARG_IN_AX__ mov bx,sp mov dh,al mov ax,[bx+2] mov dl,al #else mov bx,sp mov ax,[bx+2] mov dh,al mov ax,[bx+4] mov dl,al #endif mov ah,#$02 mov bx,#7 int $10 #endasm } static asm_colour(c) { #asm #if __FIRST_ARG_IN_AX__ mov bx,ax #else mov bx,sp mov bx,[bx+2] #endif mov ah,#$08 int $10 mov ah,#$09 mov cx,#1 int $10 #endasm } static asm_gpos() { #asm mov ah,#$03 mov bx,#7 int $10 mov [_con_row],dh mov [_con_col],dl mov ax,cx #endasm } #endif #endif #endif dev86-0.16.21/libc/conio/000077500000000000000000000000001231050321700146275ustar00rootroot00000000000000dev86-0.16.21/libc/conio/Config000066400000000000000000000000561231050321700157600ustar00rootroot00000000000000conio: Console io functions for BIOS and DOS. dev86-0.16.21/libc/conio/Makefile000066400000000000000000000015031231050321700162660ustar00rootroot00000000000000# Copyright (C) 1996 Robert de Bath # This file is part of the Linux-8086 C library and is distributed # under the GNU Library General Public License. ASRC=conio.c AOBJ=getch.o getche.o kbhit.o putch.o cputs.o gotoxy.o BIOSOBJ=cprintf.o DOSOBJ=$(AOBJ) cprintf.o CFLAGS=$(ARCH) $(CCFLAGS) $(DEFS) ifeq ($(LIB_CPU)-$(LIB_OS),i86-BIOS) all: $(LIBC)($(BIOSOBJ)) @$(RM) $(BIOSOBJ) else ifeq ($(LIB_CPU)-$(LIB_OS),i86-DOS) all: $(LIBC)($(DOSOBJ)) @$(RM) $(DOSOBJ) else all: @: endif endif $(LIBC)($(AOBJ)): $(ASRC) $(CC) $(CFLAGS) -DL_$* $< -c -o $*.o $(AR) $(ARFLAGS) $@ $*.o $(LIBC)($(BOBJ)): $(BSRC) $(CC) $(CFLAGS) -DL_$* $< -c -o $*.o $(AR) $(ARFLAGS) $@ $*.o $(LIBC)(cprintf.o): cprintf.c $(CC) -c -ansi $(ARCH) $(CCFLAGS) $(DEFS) $*.c $(AR) $(ARFLAGS) $@ $*.o clean: rm -f *.o libc.a dev86-0.16.21/libc/conio/conio.c000066400000000000000000000023231231050321700161020ustar00rootroot00000000000000/* Copyright (C) 1999 Robert de Bath * This file is part of the Linux-8086 C library and is distributed * under the GNU Library General Public License. */ #include /* * I'm not sure if these should be BIOS or dos calls, so I'll assume they're * BIOS calls but I may have to do something about Ctrl-C. * * Not implemented: cgets() cscanf() getpass() ungetch() */ #ifdef L_getch getch() { #asm xor ax,ax int $16 #endasm } #endif #ifdef L_getche getche() { int i = getch(); if( i & 0xFF ) putch(i); return i; } #endif #ifdef L_kbhit kbhit() { #asm mov ah,#1 int $16 jz nokey cmp ax,#0 jnz dort mov ax,#3 dort: ret nokey: xor ax,ax #endasm } #endif #ifdef L_putch putch() { #asm #if !__FIRST_ARG_IN_AX__ mov bx,sp mov ax,[bx+2] #endif mov ah,#$0E mov bx,#7 int $10 #endasm } #endif #ifdef L_cputs cputs(str) char * str; { while(*str) putch(*str++); } #endif #ifdef L_gotoxy static gotoxy(x,y) { #asm #if __FIRST_ARG_IN_AX__ mov bx,sp mov dl,al mov ax,[bx+2] mov dh,al #else mov bx,sp mov ax,[bx+4] mov dh,al mov ax,[bx+2] mov dl,al #endif mov ah,#$02 mov bx,#7 int $10 #endasm } #endif dev86-0.16.21/libc/conio/cprintf.c000066400000000000000000000073431231050321700164470ustar00rootroot00000000000000/* Copyright (C) 1999-2002 Robert de Bath * This file is part of the Linux-8086 C library and is distributed * under the GNU Library General Public License. */ #include #include static unsigned char * __numout(long i, int base); int cprintf(char * fmt, ...) { register int c; register int count = 0; int type, base; long val; char * cp; char padch=' '; int minsize, maxsize; va_list ap; va_start(ap, fmt); while(c=*fmt++) { count++; if(c!='%') putch(c); else { type=1; padch = *fmt; maxsize=minsize=0; if(padch == '-') fmt++; for(;;) { c=*fmt++; if( c<'0' || c>'9' ) break; minsize*=10; minsize+=c-'0'; } if( c == '.' ) for(;;) { c=*fmt++; if( c<'0' || c>'9' ) break; maxsize*=10; maxsize+=c-'0'; } if( padch == '-' ) minsize = -minsize; else if( padch != '0' ) padch=' '; if( c == 0 ) break; if(c=='h') { c=*fmt++; type = 0; } else if(c=='l') { c=*fmt++; type = 2; } switch(c) { case 'x': base=16; type |= 4; if(0) { case 'o': base= 8; type |= 4; } if(0) { case 'u': base=10; type |= 4; } if(0) { case 'd': base=-10; } switch(type) { case 0: val=va_arg(ap, short); break; case 1: val=va_arg(ap, int); break; case 2: val=va_arg(ap, long); break; case 4: val=va_arg(ap, unsigned short); break; case 5: val=va_arg(ap, unsigned int); break; case 6: val=va_arg(ap, unsigned long); break; default:val=0; break; } cp = __numout(val,base); if(0) { case 's': cp=va_arg(ap, char *); } count--; c = strlen(cp); if( !maxsize ) maxsize = c; if( minsize > 0 ) { minsize -= c; while(minsize>0) { putch(padch); count++; minsize--; } minsize=0; } if( minsize < 0 ) minsize= -minsize-c; while(*cp && maxsize-->0 ) { putch(*cp++); count++; } while(minsize>0) { putch(' '); count++; minsize--; } break; case 'c': putch(va_arg(ap, int)); break; default: putch(c); break; } } } va_end(ap); return count; } static char nstring[]="0123456789ABCDEF"; #ifndef __AS386_16__ #define NUMLTH 11 static unsigned char * __numout(long i, int base) { static unsigned char out[NUMLTH+1]; int n; int flg = 0; unsigned long val; if (base<0) { base = -base; if (i<0) { flg = 1; i = -i; } } val = i; out[NUMLTH] = '\0'; n = NUMLTH-1; do { out[n--] = nstring[val % base]; val /= base; } while(val); if(flg) out[n--] = '-'; return &out[n+1]; } #else #asm ! numout.s ! .bss ___out lcomm $C .text ___numout: push bp mov bp,sp push di push si add sp,*-4 mov byte ptr -8[bp],*$0 ! flg = 0 mov si,4[bp] ; i or val.lo mov di,6[bp] ; i or val.hi mov cx,8[bp] ; base test cx,cx ! base < 0 ? jge .3num neg cx ! base = -base or di,di ! i < 0 ? jns .5num mov byte ptr -8[bp],*1 ! flg = 1 neg di ! i = -i neg si sbb di,0 .5num: .3num: mov byte ptr [___out+$B],*$0 ! out[11] = nul mov -6[bp],*$A ! n = 10 .9num: !!! out[n--] = nstring[val % base]; xor dx,dx xchg ax,di div cx xchg ax,di xchg ax,si div cx xchg ax,si ! val(new) = val / base mov bx,dx ! dx = val % base mov al,_nstring[bx] mov bx,-6[bp] dec word ptr -6[bp] mov ___out[bx],al mov ax,si or ax,di ! while (val) jne .9num cmp byte ptr -8[bp],*$0 ! flg == 0 ? je .Dnum mov bx,-6[bp] dec word ptr -6[bp] mov byte ptr ___out[bx],*$2D ! out[n--] = minus .Dnum: mov ax,-6[bp] add ax,#___out+1 add sp,*4 pop si pop di pop bp ret #endasm #endif dev86-0.16.21/libc/crt0.c000066400000000000000000000027751231050321700145470ustar00rootroot00000000000000/* Copyright (C) 1995,1996 Robert de Bath * This file is part of the Linux-8086 C library and is distributed * under the GNU Library General Public License. */ #if defined(__AS386_16__) || defined(__AS386_32__) #define CRT0_OK /* * Change of aim here, to allow easy alteration for generation of COM files * this code has been moved into libc. This means only the linker needs to * to be told to fetch a different libc the crt0 is unaltered. * * This also allows us to deal with __FIRST_ARG_IN_AX__ and __CALLER_SAVES__ * in the same way. */ #asm .text entry startup ! Crt0 startup startup: br ___cstartup export no_op no_op: ! Generic no operation call ret .ascii __LIBC_VER__ ! Version id. loc 1 ! Segment 1 is where the pointers to the autostart ! functions are stored. #if !__AS386_32__ ZP_safety: .word 0 ! But first some zeros to avoid null pointer writes. .word 0 .word 0 .word 0 #endif export auto_start auto_start: #endasm #endif /* __AS386_16__ or __AS386_32__ */ #if defined(__GNUC__) && defined(__i386__) #ifdef __ELF__ #define CRT0_OK __asm__(".globl _start\n_start:"); __asm__("jmp __cstartup"); __asm__(".globl __no_op\n__no_op:"); __asm__("ret"); #else #error This library is for ELF only, sorry. __asm__(".globl startup\nstartup:"); __asm__("jmp ___cstartup"); __asm__(".globl no_op\nno_op:"); __asm__("ret"); #endif #endif /* defined(__GNUC__) && defined(__i386__) */ #ifndef CRT0_OK #error You are not going to get far without crt0.o! #endif dev86-0.16.21/libc/error/000077500000000000000000000000001231050321700146515ustar00rootroot00000000000000dev86-0.16.21/libc/error/Config000066400000000000000000000000351231050321700157770ustar00rootroot00000000000000 error: Unix error functions dev86-0.16.21/libc/error/Makefile000066400000000000000000000010551231050321700163120ustar00rootroot00000000000000# Copyright (C) 1996 Robert de Bath # This file is part of the Linux-8086 C library and is distributed # under the GNU Library General Public License. CFLAGS=$(ARCH) $(CCFLAGS) $(DEFS) ifeq ($(LIB_OS),ELKS) ifneq ($(LIB_CPU),i86) OBJ=error2.o perror.o sys_siglist.o __assert.o else OBJ=error.o sys_errlist.o perror.o sys_siglist.o __assert.o endif else OBJ=__assert.o endif all: $(LIBC)($(OBJ)) @$(RM) $(OBJ) clean: rm -f *.o libc.a error_list.h $(LIBC)(error2.o): error_list.h error_list.h: liberror.txt sh mktab.sh dev86-0.16.21/libc/error/README000066400000000000000000000006141231050321700155320ustar00rootroot00000000000000Copyright (C) 1996,2004 Robert de Bath This file is part of the Linux-8086 C library and is distributed under the GNU Library General Public License. The file "liberror.txt" is the master list of errors for ELKS only. WARNING: If you use the -Mf compile style this file must be in the filessystem as "/lib/liberror.txt" unless you're using elksemu. -Robert dev86-0.16.21/libc/error/__assert.c000066400000000000000000000011121231050321700166070ustar00rootroot00000000000000/* Copyright (C) 1996 Robert de Bath * This file is part of the Linux-8086 C library and is distributed * under the GNU Library General Public License. */ #include static void errput(str) const char * str; { write(2, str, strlen(str)); } void __assert(assertion, filename, linenumber) const char * assertion; const char * filename; int linenumber; { errput("Failed assertion '"); errput(assertion); errput("' in file "); errput(filename); errput(" at line "); errput(itoa(linenumber)); errput(".\n"); abort(); } dev86-0.16.21/libc/error/error.c000066400000000000000000000023151231050321700161470ustar00rootroot00000000000000/* Copyright (C) 1996 Robert de Bath * This file is part of the Linux-8086 C library and is distributed * under the GNU Library General Public License. */ #include char **__sys_errlist =0; int __sys_nerr = 0; char * strerror(err) int err; { int fd; static char retbuf[80]; char inbuf[256]; int cc; int bufoff = 0; if( __sys_nerr ) { if( err < 0 || err >= __sys_nerr ) goto unknown; return __sys_errlist[err]; } if( err <= 0 ) goto unknown; /* NB the <= allows comments in the file */ fd = open("/lib/liberror.txt", 0); if( fd < 0 ) goto unknown; while( (cc=read(fd, inbuf, sizeof(inbuf))) > 0 ) { int i; for(i=0; i= 0 ) close(fd); strcpy(retbuf, "Unknown error "); strcpy(retbuf+14, itoa(err)); return retbuf; } dev86-0.16.21/libc/error/error2.c000066400000000000000000000006771231050321700162420ustar00rootroot00000000000000/* Copyright (C) 1996,2004 Robert de Bath * This file is part of the Linux-8086 C library and is distributed * under the GNU Library General Public License. */ #include #include "error_list.h" char * strerror(err) int err; { static char retbuf[20]; if( err > 0 && err <= sys_nerr ) return sys_errlist[err]; strcpy(retbuf, "Error "); strcpy(retbuf+6, itoa(err)); return retbuf; } dev86-0.16.21/libc/error/liberror.txt000066400000000000000000000064041231050321700172360ustar00rootroot000000000000001 Operation not permitted 2 No such file or directory 3 No such process 4 Interrupted system call 5 I/O error 6 No such device or address 7 Arg list too long 8 Exec format error 9 Bad file number 10 No child processes 11 Try again 12 Out of memory 13 Permission denied 14 Bad address 15 Block device required 16 Device or resource busy 17 File exists 18 Cross-device link 19 No such device 20 Not a directory 21 Is a directory 22 Invalid argument 23 File table overflow 24 Too many open files 25 Not a typewriter 26 Text file busy 27 File too large 28 No space left on device 29 Illegal seek 30 Read-only file system 31 Too many links 32 Broken pipe 33 Math argument out of domain of func 34 Math result not representable 35 Resource deadlock would occur 36 File name too long 37 No record locks available 38 Function not implemented 39 Directory not empty 40 Too many symbolic links encountered 41 Operation would block 42 No message of desired type 43 Identifier removed 44 Channel number out of range 45 Level 2 not synchronized 46 Level 3 halted 47 Level 3 reset 48 Link number out of range 49 Protocol driver not attached 50 No CSI structure available 51 Level 2 halted 52 Invalid exchange 53 Invalid request descriptor 54 Exchange full 55 No anode 56 Invalid request code 57 Invalid slot 58 File locking deadlock error 59 Bad font file format 60 Device not a stream 61 No data available 62 Timer expired 63 Out of streams resources 64 Machine is not on the network 65 Package not installed 66 Object is remote 67 Link has been severed 68 Advertise error 69 Srmount error 70 Communication error on send 71 Protocol error 72 Multihop attempted 73 RFS specific error 74 Not a data message 75 Value too large for defined data type 76 Name not unique on network 77 File descriptor in bad state 78 Remote address changed 79 Can not access a needed shared library 80 Accessing a corrupted shared library 81 .lib section in a.out corrupted 82 Attempting to link in too many shared libraries 83 Cannot exec a shared library directly 84 Illegal byte sequence 85 Interrupted system call should be restarted 86 Streams pipe error 87 Too many users 88 Socket operation on non-socket 89 Destination address required 90 Message too long 91 Protocol wrong type for socket 92 Protocol not available 93 Protocol not supported 94 Socket type not supported 95 Operation not supported on transport endpoint 96 Protocol family not supported 97 Address family not supported by protocol 98 Address already in use 99 Cannot assign requested address 100 Network is down 101 Network is unreachable 102 Network dropped connection because of reset 103 Software caused connection abort 104 Connection reset by peer 105 No buffer space available 106 Transport endpoint is already connected 107 Transport endpoint is not connected 108 Cannot send after transport endpoint shutdown 109 Too many references: cannot splice 110 Connection timed out 111 Connection refused 112 Host is down 113 No route to host 114 Operation already in progress 115 Operation now in progress 116 Stale NFS file handle 117 Structure needs cleaning 118 Not a XENIX named type file 119 No XENIX semaphores available 120 Is a named type file 121 Remote I/O error dev86-0.16.21/libc/error/mktab.sh000066400000000000000000000010771231050321700163100ustar00rootroot00000000000000#!/bin/sh - awk '{ e=$0; sub("^[^ ]* ", "", e); sub(" [^ ]*$", "", e); n=0+$1; if (!(n in errlist)) errlist[n] = e; if(n > maxerr) maxerr=n; } END{ printf ("#define NR_ERRORS\t%d\n", maxerr+1); printf ("int sys_nerr = NR_ERRORS;\n"); printf ("char *sys_errlist[NR_ERRORS] = {\n"); for(i=0; i<=maxerr; i++) { if (errlist[i] == "") printf(" \"Error %d\"", i); else printf(" \"%s\"", errlist[i]); if (i != maxerr) printf(",\n"); else printf("\n"); } printf ("};\n"); }' < liberror.txt > error_list.h dev86-0.16.21/libc/error/perror.c000066400000000000000000000004271231050321700163310ustar00rootroot00000000000000 #include void perror(str) __const char * str; { register char * ptr; if(str) { write(2, str, strlen(str)); write(2, ": ", 2); } else write(2, "perror: ", 8); ptr = strerror(errno); write(2, ptr, strlen(ptr)); write(2, "\n", 1); } dev86-0.16.21/libc/error/sys_errlist.c000066400000000000000000000040701231050321700174000ustar00rootroot00000000000000/* Copyright (C) 1996 Robert de Bath * This file is part of the Linux-8086 C library and is distributed * under the GNU Library General Public License. */ /* This is a flash way of auto-initing the error array from an external file * I wouldn't be surprised tho if it's a lot better just to hard code the * error messages into the array. * * Of course the best of all is to use strerror(). */ #if defined(__AS386_16__) || defined(__AS386_32__) #define NR_ERRORS 128 extern char **__sys_errlist; extern int __sys_nerr; char *sys_errlist[NR_ERRORS]; int sys_nerr = NR_ERRORS; #ifdef __AS386_16__ #asm loc 1 ! Make sure the pointer is in the correct segment auto_func: ! Label for bcc -M to work. .word _init_vars ! Pointer to the autorun function .text ! So the function after is also in the correct seg. #endasm #else #asm loc 1 ! Make sure the pointer is in the correct segment auto_func: ! Label for bcc -M to work. .long _init_vars ! Pointer to the autorun function .text ! So the function after is also in the correct seg. #endasm #endif static void init_vars() { char inbuf[256]; char errbuf[80]; int i, cc, fd, err, len, bufoff=0; char * ptr; fd = open("/lib/liberror.txt", 0); if( fd < 0 ) return; for(i=0; i 0 ) { for(i=0; i 0 && err < NR_ERRORS ) { while(*ptr == ' ') ptr++; len = strlen(ptr)+1; sys_errlist[err] = (void*)sbrk(len); if( (int)sys_errlist[err] == -1 ) { sys_errlist[err] == ""; break; } memcpy(sys_errlist[err], ptr, len); } bufoff = 0; } else if( bufoff < sizeof(errbuf)-1 ) errbuf[bufoff++] = inbuf[i]; } } close(fd); __sys_errlist = sys_errlist; __sys_nerr = sys_nerr = NR_ERRORS; } #endif /* __AS386_??__ */ dev86-0.16.21/libc/error/sys_siglist.c000066400000000000000000000013641231050321700173750ustar00rootroot00000000000000 #include __const char * __const sys_siglist[NSIG] = { "Unknown signal", "Hangup", "Interrupt", "Quit", "Illegal instruction", "Trace/breakpoint trap", "IOT trap/Abort", "Bus error", "Floating point exception", "Killed", "User defined signal 1", "Segmentation fault", "User defined signal 2", "Broken pipe", "Alarm clock", "Terminated", "Stack fault", "Child exited", "Continued", "Stopped (signal)", "Stopped", "Stopped (tty input)", "Stopped (tty output)", "Possible I/O", "CPU time limit exceeded", "File size limit exceeded", "Virtual time alarm", "Profile signal", "Window size changed", "File lock lost", "Power failure", "Unused signal" }; dev86-0.16.21/libc/getent/000077500000000000000000000000001231050321700150065ustar00rootroot00000000000000dev86-0.16.21/libc/getent/Config000066400000000000000000000000671231050321700161410ustar00rootroot00000000000000getent: Managment for /etc/passwd /etc/group /etc/utmp dev86-0.16.21/libc/getent/Makefile000066400000000000000000000014531231050321700164510ustar00rootroot00000000000000# Copyright (C) 1996 Nat Friedman # This file is part of the Linux-8086 C library and is distributed # under the GNU Library General Public License. ifeq ($(PLATFORM),i386-ELKS) CFLAGS=$(ARCH) $(WALL) $(CCFLAGS) $(DEFS) else CFLAGS=$(ARCH) -ansi $(CCFLAGS) $(DEFS) endif PSRC=__getpwent.c pwent.c getpwnam.c getpwuid.c putpwent.c getpw.c fgetpwent.c GSRC=__getgrent.c grent.c getgrnam.c getgrgid.c fgetgrent.c initgroups.c \ config-grp.h USRC=utent.c POBJ=__getpwent.o pwent.o getpwnam.o getpwuid.o putpwent.o getpw.o fgetpwent.o GOBJ=__getgrent.o grent.o getgrnam.o getgrgid.o fgetgrent.o initgroups.o UOBJ=utent.o ifeq ($(LIB_OS),ELKS) OBJ=$(POBJ) $(GOBJ) $(UOBJ) all: $(LIBC)($(OBJ)) @$(RM) $(OBJ) $(LIBC)($(GOBJ)): config-grp.h else all: @: endif clean: rm -f *.o libc.a dev86-0.16.21/libc/getent/__getgrent.c000066400000000000000000000105441231050321700172730ustar00rootroot00000000000000/* * __getgrent.c - This file is part of the libc-8086/grp package for ELKS, * Copyright (C) 1995, 1996 Nat Friedman . * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ #include #include #include #include #include "config.h" /* * This is the core group-file read function. It behaves exactly like * getgrent() except that it is passed a file descriptor. getgrent() * is just a wrapper for this function. */ struct group * __getgrent(int grp_fd) { #ifndef GR_SCALE_DYNAMIC static char line_buff[GR_MAX_LINE_LEN]; static char * members[GR_MAX_MEMBERS]; #else static char * line_buff = NULL; static char ** members = NULL; short line_index; short buff_size; #endif static struct group group; register char * ptr; char * field_begin; short member_num; char * endptr; int line_len; /* We use the restart label to handle malformatted lines */ restart: #ifdef GR_SCALE_DYNAMIC line_index=0; buff_size=256; #endif #ifndef GR_SCALE_DYNAMIC /* Read the line into the static buffer */ if ((line_len=read(grp_fd, line_buff, GR_MAX_LINE_LEN))<=0) return NULL; field_begin=strchr(line_buff, '\n'); if (field_begin!=NULL) lseek(grp_fd, (long) (1+field_begin-(line_buff+line_len)), SEEK_CUR); else /* The line is too long - skip it :-\ */ { do { if ((line_len=read(grp_fd, line_buff, GR_MAX_LINE_LEN))<=0) return NULL; } while (!(field_begin=strchr(line_buff, '\n'))); lseek(grp_fd, (long) ((field_begin-line_buff)-line_len+1), SEEK_CUR); goto restart; } if (*line_buff=='#' || *line_buff==' ' || *line_buff=='\n' || *line_buff=='\t') goto restart; *field_begin='\0'; #else /* !GR_SCALE_DYNAMIC */ line_buff=realloc(line_buff, buff_size); while (1) { if ((line_len=read(grp_fd, line_buff+line_index, buff_size-line_index))<=0) return NULL; field_begin=strchr(line_buff, '\n'); if (field_begin!=NULL) { lseek(grp_fd, (long) (1+field_begin-(line_len+line_index+line_buff)), SEEK_CUR); *field_begin='\0'; if (*line_buff=='#' || *line_buff==' ' || *line_buff=='\n' || *line_buff=='\t') goto restart; break; } else /* Allocate some more space */ { line_index=buff_size; buff_size+=256; line_buff=realloc(line_buff, buff_size); } } #endif /* GR_SCALE_DYNAMIC */ /* Now parse the line */ group.gr_name=line_buff; ptr=strchr(line_buff, ':'); if (ptr==NULL) goto restart; *ptr++='\0'; group.gr_passwd=ptr; ptr=strchr(ptr, ':'); if (ptr==NULL) goto restart; *ptr++='\0'; field_begin=ptr; ptr=strchr(ptr, ':'); if (ptr==NULL) goto restart; *ptr++='\0'; group.gr_gid=(gid_t) strtoul(field_begin, &endptr, 10); if (*endptr!='\0') goto restart; member_num=0; field_begin=ptr; #ifndef GR_SCALE_DYNAMIC while ((ptr=strchr(ptr, ','))!=NULL) { *ptr='\0'; ptr++; members[member_num]=field_begin; field_begin=ptr; member_num++; } if (*field_begin=='\0') members[member_num]=NULL; else { members[member_num]=field_begin; members[member_num+1]=NULL; } #else /* !GR_SCALE_DYNAMIC */ if (members!=NULL) free (members); members=(char **) malloc(1*sizeof(char *)); while ((ptr=strchr(ptr, ','))!=NULL) { *ptr='\0'; ptr++; members[member_num]=field_begin; field_begin=ptr; member_num++; members=(char **)realloc((void *)members, (member_num+1)*sizeof(char *)); } if (*field_begin=='\0') members[member_num]=NULL; else { members[member_num]=field_begin; members[member_num+1]=NULL; } #endif /* GR_SCALE_DYNAMIC */ group.gr_mem=members; return &group; } dev86-0.16.21/libc/getent/__getpwent.c000066400000000000000000000060101231050321700173020ustar00rootroot00000000000000/* * __getpwent.c - This file is part of the libc-8086/pwd package for ELKS, * Copyright (C) 1995, 1996 Nat Friedman . * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ #include #include #include #include #include #define PWD_BUFFER_SIZE 256 /* This isn't as flash as my previous version -- it doesn't dynamically scale down the gecos on too-long lines, but it also makes fewer syscalls, so it's probably nicer. Write me if you want the old version. Maybe I should include it as a build-time option... ? -Nat */ struct passwd * __getpwent(int pwd_fd) { static char line_buff[PWD_BUFFER_SIZE]; static struct passwd passwd; char * field_begin; char * endptr; char * gid_ptr; char * uid_ptr; int line_len; int i; /* We use the restart label to handle malformatted lines */ restart: /* Read the passwd line into the static buffer using a minimal of syscalls. */ if ((line_len=read(pwd_fd, line_buff, PWD_BUFFER_SIZE))<=0) return NULL; field_begin=strchr(line_buff, '\n'); if (field_begin!=NULL) lseek(pwd_fd, (long) (1+field_begin-(line_buff+line_len)), SEEK_CUR); else /* The line is too long - skip it. :-\ */ { do { if ((line_len=read(pwd_fd, line_buff, PWD_BUFFER_SIZE))<=0) return NULL; } while (!(field_begin=strchr(line_buff, '\n'))); lseek(pwd_fd, (long) (field_begin-line_buff)-line_len+1, SEEK_CUR); goto restart; } if (*line_buff=='#' || *line_buff==' ' || *line_buff=='\n' || *line_buff=='\t') goto restart; *field_begin='\0'; /* We've read the line; now parse it. */ field_begin=line_buff; for (i=0;i<7;i++) { switch(i) { case 0: passwd.pw_name=field_begin; break; case 1: passwd.pw_passwd=field_begin; break; case 2: uid_ptr=field_begin; break; case 3: gid_ptr=field_begin; break; case 4: passwd.pw_gecos=field_begin; break; case 5: passwd.pw_dir=field_begin; break; case 6: passwd.pw_shell=field_begin; break; } if (i<6) { field_begin=strchr(field_begin, ':'); if (field_begin==NULL) goto restart; *field_begin++='\0'; } } passwd.pw_gid=(gid_t) strtoul(gid_ptr, &endptr, 10); if (*endptr!='\0') goto restart; passwd.pw_uid=(uid_t) strtoul(uid_ptr, &endptr, 10); if (*endptr!='\0') goto restart; return &passwd; } dev86-0.16.21/libc/getent/config-grp.h000066400000000000000000000044471231050321700172230ustar00rootroot00000000000000/* * config-grp.h - This file is part of the libc-8086/grp package for ELKS, * Copyright (C) 1995, 1996 Nat Friedman . * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ #ifndef _CONFIG_GRP_H #define _CONFIG_GRP_H /* * Define GR_SCALE_DYNAMIC if you want grp to dynamically scale its read buffer * so that lines of any length can be used. On very very small systems, * you may want to leave this undefined becasue it will make the grp functions * somewhat larger (because of the inclusion of malloc and the code necessary). * On larger systems, you will want to define this, because grp will _not_ * deal with long lines gracefully (they will be skipped). */ #define GR_SCALE_DYNAMIC #ifndef GR_SCALE_DYNAMIC /* * If scaling is not dynamic, the buffers will be statically allocated, and * maximums must be chosen. GR_MAX_LINE_LEN is the maximum number of * characters per line in the group file. GR_MAX_MEMBERS is the maximum * number of members of any given group. */ #define GR_MAX_LINE_LEN 128 /* GR_MAX_MEMBERS = (GR_MAX_LINE_LEN-(24+3+6))/9 */ #define GR_MAX_MEMBERS 11 #endif /* !GR_SCALE_DYNAMIC */ /* * Define GR_DYNAMIC_GROUP_LIST to make initgroups() dynamically allocate * space for it's GID array before calling setgroups(). This is probably * unnecessary scalage, so it's undefined by default. */ #undef GR_DYNAMIC_GROUP_LIST #ifndef GR_DYNAMIC_GROUP_LIST /* * GR_MAX_GROUPS is the size of the static array initgroups() uses for * its static GID array if GR_DYNAMIC_GROUP_LIST isn't defined. */ #define GR_MAX_GROUPS 64 #endif /* !GR_DYNAMIC_GROUP_LIST */ #endif /* !_CONFIG_GRP_H */ dev86-0.16.21/libc/getent/config.h000066400000000000000000000044471231050321700164350ustar00rootroot00000000000000/* * config-grp.h - This file is part of the libc-8086/grp package for ELKS, * Copyright (C) 1995, 1996 Nat Friedman . * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ #ifndef _CONFIG_GRP_H #define _CONFIG_GRP_H /* * Define GR_SCALE_DYNAMIC if you want grp to dynamically scale its read buffer * so that lines of any length can be used. On very very small systems, * you may want to leave this undefined becasue it will make the grp functions * somewhat larger (because of the inclusion of malloc and the code necessary). * On larger systems, you will want to define this, because grp will _not_ * deal with long lines gracefully (they will be skipped). */ #define GR_SCALE_DYNAMIC #ifndef GR_SCALE_DYNAMIC /* * If scaling is not dynamic, the buffers will be statically allocated, and * maximums must be chosen. GR_MAX_LINE_LEN is the maximum number of * characters per line in the group file. GR_MAX_MEMBERS is the maximum * number of members of any given group. */ #define GR_MAX_LINE_LEN 128 /* GR_MAX_MEMBERS = (GR_MAX_LINE_LEN-(24+3+6))/9 */ #define GR_MAX_MEMBERS 11 #endif /* !GR_SCALE_DYNAMIC */ /* * Define GR_DYNAMIC_GROUP_LIST to make initgroups() dynamically allocate * space for it's GID array before calling setgroups(). This is probably * unnecessary scalage, so it's undefined by default. */ #undef GR_DYNAMIC_GROUP_LIST #ifndef GR_DYNAMIC_GROUP_LIST /* * GR_MAX_GROUPS is the size of the static array initgroups() uses for * its static GID array if GR_DYNAMIC_GROUP_LIST isn't defined. */ #define GR_MAX_GROUPS 64 #endif /* !GR_DYNAMIC_GROUP_LIST */ #endif /* !_CONFIG_GRP_H */ dev86-0.16.21/libc/getent/fgetgrent.c000066400000000000000000000020771231050321700171450ustar00rootroot00000000000000/* * fgetgrent.c - This file is part of the libc-8086/grp package for ELKS, * Copyright (C) 1995, 1996 Nat Friedman . * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ #include #include #include struct group * fgetgrent(FILE * file) { if (file==NULL) { errno=EINTR; return NULL; } return __getgrent(fileno(file)); } dev86-0.16.21/libc/getent/fgetpwent.c000066400000000000000000000020761231050321700171620ustar00rootroot00000000000000/* * fgetpwent.c - This file is part of the libc-8086/pwd package for ELKS, * Copyright (C) 1995, 1996 Nat Friedman . * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ #include #include #include struct passwd * fgetpwent(FILE * file) { if (file==NULL) { errno=EINTR; return NULL; } return __getpwent(fileno(file)); } dev86-0.16.21/libc/getent/getgrgid.c000066400000000000000000000023621231050321700167510ustar00rootroot00000000000000/* * getgrgid.c - This file is part of the libc-8086/grp package for ELKS, * Copyright (C) 1995, 1996 Nat Friedman . * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ #include #include #include #include struct group * getgrgid(const gid_t gid) { struct group * group; int grp_fd; if ((grp_fd=open("/etc/group", O_RDONLY))<0) return NULL; while ((group=__getgrent(grp_fd))!=NULL) if (group->gr_gid==gid) { close(grp_fd); return group; } close(grp_fd); return NULL; } dev86-0.16.21/libc/getent/getgrnam.c000066400000000000000000000025211231050321700167560ustar00rootroot00000000000000/* * getgrnam.c - This file is part of the libc-8086/grp package for ELKS, * Copyright (C) 1995, 1996 Nat Friedman . * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ #include #include #include #include #include struct group * getgrnam(const char * name) { int grp_fd; struct group * group; if (name==NULL) { errno=EINVAL; return NULL; } if ((grp_fd=open("/etc/group", O_RDONLY))<0) return NULL; while ((group=__getgrent(grp_fd))!=NULL) if (!strcmp(group->gr_name, name)) { close(grp_fd); return group; } close(grp_fd); return NULL; } dev86-0.16.21/libc/getent/getpw.c000066400000000000000000000025431231050321700163040ustar00rootroot00000000000000/* * getpw.c - This file is part of the libc-8086/pwd package for ELKS, * Copyright (C) 1995, 1996 Nat Friedman . * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ #include #include #include #include int getpw(uid_t uid, char *buf) { struct passwd * passwd; if (buf==NULL) { errno=EINVAL; return -1; } if ((passwd=getpwuid(uid))==NULL) return -1; if (sprintf(buf, "%s:%s:%u:%u:%s:%s:%s", passwd->pw_name, passwd->pw_passwd, passwd->pw_gid, passwd->pw_uid, passwd->pw_gecos, passwd->pw_dir, passwd->pw_shell)<0) { errno=ENOBUFS; return -1; } return 0; } dev86-0.16.21/libc/getent/getpwnam.c000066400000000000000000000025531231050321700170010ustar00rootroot00000000000000/* * getpwnam.c - This file is part of the libc-8086/pwd package for ELKS, * Copyright (C) 1995, 1996 Nat Friedman . * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ #include #include #include #include #include struct passwd * getpwnam(const char * name) { int passwd_fd; struct passwd * passwd; if (name==NULL) { errno=EINVAL; return NULL; } if ((passwd_fd=open("/etc/passwd", O_RDONLY))<0) return NULL; while ((passwd=__getpwent(passwd_fd))!=NULL) if (!strcmp(passwd->pw_name, name)) { close(passwd_fd); return passwd; } close(passwd_fd); return NULL; } dev86-0.16.21/libc/getent/getpwuid.c000066400000000000000000000023741231050321700170100ustar00rootroot00000000000000/* * getpwuid.c - This file is part of the libc-8086/pwd package for ELKS, * Copyright (C) 1995, 1996 Nat Friedman . * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ #include #include #include #include struct passwd * getpwuid(uid_t uid) { int passwd_fd; struct passwd * passwd; if ((passwd_fd=open("/etc/passwd", O_RDONLY))<0) return NULL; while ((passwd=__getpwent(passwd_fd))!=NULL) if (passwd->pw_uid==uid) { close(passwd_fd); return passwd; } close (passwd_fd); return NULL; } dev86-0.16.21/libc/getent/grent.c000066400000000000000000000025751231050321700163020ustar00rootroot00000000000000/* * grent.c - This file is part of the libc-8086/grp package for ELKS, * Copyright (C) 1995, 1996 Nat Friedman . * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ /* * setgrent(), endgrent(), and getgrent() are mutually-dependent functions, * so they are all included in the same object file, and thus all linked * in together. */ #include #include #include static int grp_fd=-1; void setgrent(void) { if (grp_fd!=-1) close(grp_fd); grp_fd=open("/etc/group", O_RDONLY); } void endgrent(void) { if (grp_fd!=-1) close(grp_fd); grp_fd=-1; } struct group * getgrent(void) { if (grp_fd==-1) return NULL; return __getgrent(grp_fd); } dev86-0.16.21/libc/getent/initgroups.c000066400000000000000000000037471231050321700173700ustar00rootroot00000000000000/* * initgroups.c - This file is part of the libc-8086/grp package for ELKS, * Copyright (C) 1995, 1996 Nat Friedman . * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ #include #include #include #include #include "config.h" int initgroups(__const char * user, gid_t gid) { register struct group * group; #ifndef GR_DYNAMIC_GROUP_LIST gid_t group_list[GR_MAX_GROUPS]; #else gid_t * group_list=NULL; #endif register char ** tmp_mem; int num_groups; int grp_fd; if ((grp_fd=open("/etc/group", O_RDONLY))<0) return -1; num_groups=0; #ifdef GR_DYNAMIC_GROUP_LIST group_list=(gid_t *) realloc(group_list, 1); #endif group_list[num_groups]=gid; #ifndef GR_DYNAMIC_GROUP_LIST while (num_groupsgr_gid!=gid); { tmp_mem=group->gr_mem; while(*tmp_mem!=NULL) { if (!strcmp(*tmp_mem, user)) { num_groups++; #ifdef GR_DYNAMIC_GROUP_LIST group_list=(gid_t *)realloc(group_list, num_groups*sizeof(gid_t *)); #endif group_list[num_groups]=group->gr_gid; } tmp_mem++; } } } close(grp_fd); return setgroups(num_groups, group_list); } dev86-0.16.21/libc/getent/putpwent.c000066400000000000000000000024011231050321700170350ustar00rootroot00000000000000/* * putpwent.c - This file is part of the libc-8086/pwd package for ELKS, * Copyright (C) 1995, 1996 Nat Friedman . * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ #include #include #include int putpwent(const struct passwd * passwd, FILE * f) { if (passwd == NULL || f == NULL) { errno=EINVAL; return -1; } if (fprintf(f, "%s:%s:%u:%u:%s:%s:%s\n", passwd->pw_name, passwd->pw_passwd, passwd->pw_gid, passwd->pw_uid, passwd->pw_gecos, passwd->pw_dir, passwd->pw_shell)<0) return -1; return 0; } dev86-0.16.21/libc/getent/pwent.c000066400000000000000000000030241231050321700163060ustar00rootroot00000000000000/* * pwent.c - This file is part of the libc-8086/pwd package for ELKS, * Copyright (C) 1995, 1996 Nat Friedman . * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ #include #include #include #include #include /* * setpwent(), endpwent(), and getpwent() are included in the same object * file, since one cannot be used without the other two, so it makes sense to * link them all in together. */ /* file descriptor for the password file currently open */ static int pw_fd = -1; void setpwent(void) { if (pw_fd!=-1) close(pw_fd); pw_fd=open("/etc/passwd", O_RDONLY); } void endpwent(void) { if (pw_fd!=-1) close(pw_fd); pw_fd=-1; } struct passwd * getpwent(void) { if (pw_fd==-1) setpwent(); if (pw_fd!=-1) return __getpwent(pw_fd); return NULL; } dev86-0.16.21/libc/getent/test_grp.c000066400000000000000000000062711231050321700170070ustar00rootroot00000000000000/* * test_grp.c - This file is part of the libc-8086/grp package for ELKS, * Copyright (C) 1995, 1996 Nat Friedman . * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ #include #include #include #include int main(int argc, char ** argv) { struct group * group; char ** tmp_mem; int test_gid; fprintf(stderr, "Beginning test of libc/grp...\n"); fprintf(stderr, "=> Testing setgrent(), getgrent(), endgrent()...\n"); fprintf(stderr, "-> setgrent()...\n"); setgrent(); fprintf(stderr, "-> getgrent()...\n"); printf("********************************************************************************\n"); while ((group=getgrent())!=NULL) { printf("gr_name\t\t: %s\n", group->gr_name); printf("gr_passwd\t: %s\n", group->gr_passwd); printf("gr_gid\t\t: %d\n", (int) group->gr_gid); printf("gr_mem\t\t: "); fflush(stdout); tmp_mem=group->gr_mem; while(*tmp_mem!=NULL) { printf("%s, ", *tmp_mem); tmp_mem++; } printf("\n********************************************************************************\n"); } fprintf(stderr, "-> endgrent()...\n"); endgrent(); fprintf(stderr, "=> Test of setgrent(), getgrent(), endgrent() complete.\n"); fprintf(stderr, "=> Testing getgrid(), getgrnam()...\n"); fprintf(stderr, "-> getgrgid()...\n"); printf("********************************************************************************\n"); for(test_gid=0;test_gid<100;test_gid++) { fprintf(stderr, "-> getgrgid(%d)...\n", test_gid); group=getgrgid((gid_t) test_gid); if (group!=NULL) { printf("gr_name\t: %s\n", group->gr_name); printf("gr_passwd\t: %s\n", group->gr_passwd); printf("gr_gid\t: %d\n", (int) group->gr_gid); printf("gr_mem\t\t: "); fflush(stdout); tmp_mem=group->gr_mem; while(*tmp_mem!=NULL) { printf("%s, ", *tmp_mem); tmp_mem++; } } printf("\n********************************************************************************\n"); } fprintf(stderr, "-> getgrnam()...\n"); group=getgrnam("root"); if (group==NULL) { printf(">NULL<\n"); } else { printf("gr_name\t: %s\n", group->gr_name); printf("gr_passwd\t: %s\n", group->gr_passwd); printf("gr_gid\t: %d\n", (int) group->gr_gid); printf("gr_mem\t\t: "); fflush(stdout); tmp_mem=group->gr_mem; while(*tmp_mem!=NULL) { printf("%s, ", *tmp_mem); tmp_mem++; } printf("\n"); } return 0; } dev86-0.16.21/libc/getent/test_pwd.c000066400000000000000000000064601231050321700170110ustar00rootroot00000000000000/* * test_pwd.c - This file is part of the libc-8086/pwd package for ELKS, * Copyright (C) 1995, 1996 Nat Friedman . * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ #include #include #include #include int main(int argc, char ** argv) { struct passwd * passwd; int test_uid; fprintf(stderr, "Beginning test of libc/pwd...\n"); fprintf(stderr, "=> Testing setpwent(), getpwent(), endpwent()...\n"); fprintf(stderr, "-> setpwent()...\n"); setpwent(); fprintf(stderr, "-> getpwent()...\n"); printf("********************************************************************************\n"); while ((passwd=getpwent())!=NULL) { printf("pw_name\t\t: %s\n", passwd->pw_name); printf("pw_passwd\t: %s\n", passwd->pw_passwd); printf("pw_uid\t\t: %d\n", (int) passwd->pw_uid); printf("pw_gid\t\t: %d\n", (int) passwd->pw_gid); printf("pw_gecos\t: %s\n", passwd->pw_gecos); printf("pw_dir\t\t: %s\n", passwd->pw_dir); printf("pw_shell\t: %s\n", passwd->pw_shell); printf("********************************************************************************\n"); } fprintf(stderr, "-> endpwent()...\n"); endpwent(); fprintf(stderr, "=> Test of setpwent(), getpwent(), endpwent() complete.\n"); fprintf(stderr, "=> Testing getpwuid(), getpwnam()...\n"); fprintf(stderr, "-> getpwuid()...\n"); printf("********************************************************************************\n"); for(test_uid=0;test_uid<1000;test_uid++) { fprintf(stderr, "-> getpwuid(%d)...\n", test_uid); passwd=getpwuid((uid_t) test_uid); if (passwd!=NULL) { printf("pw_name\t\t: %s\n", passwd->pw_name); printf("pw_passwd\t: %s\n", passwd->pw_passwd); printf("pw_uid\t\t: %d\n", (int) passwd->pw_uid); printf("pw_gid\t\t: %d\n", (int) passwd->pw_gid); printf("pw_gecos\t: %s\n", passwd->pw_gecos); printf("pw_dir\t\t: %s\n", passwd->pw_dir); printf("pw_shell\t: %s\n", passwd->pw_shell); printf("********************************************************************************\n"); } } fprintf(stderr, "-> getpwnam()...\n"); passwd=getpwnam("root"); if (passwd==NULL) { printf(">NULL<\n"); } else { printf("pw_name\t\t: %s\n", passwd->pw_name); printf("pw_passwd\t: %s\n", passwd->pw_passwd); printf("pw_uid\t\t: %d\n", (int) passwd->pw_uid); printf("pw_gid\t\t: %d\n", (int) passwd->pw_gid); printf("pw_gecos\t: %s\n", passwd->pw_gecos); printf("pw_dir\t\t: %s\n", passwd->pw_dir); printf("pw_shell\t: %s\n", passwd->pw_shell); } return 0; } dev86-0.16.21/libc/getent/utent.c000066400000000000000000000067561231050321700163270ustar00rootroot00000000000000/* utent.c */ /* Let it be known that this is very possibly the worst standard ever. HP-UX does one thing, someone else does another, linux another... If anyone actually has the standard, please send it to me. Note that because of the way this stupid stupid standard works, you have to call endutent() to close the file even if you've not called setutent -- getutid and family use the same file descriptor. */ #include #include #include #include #include #include static const char * ut_name=_PATH_UTMP; static int ut_fd=-1; struct utmp * getutent(void) { static struct utmp utmp; if (ut_fd==-1) setutent(); if (ut_fd==-1) return NULL; if (read(ut_fd, (char *) &utmp, sizeof(struct utmp))!=sizeof(struct utmp)) return NULL; return &utmp; } void setutent(void) { int xerrno = errno; if (ut_fd!=-1) close(ut_fd); /* ... Should this be an Lseek ? */ if ((ut_fd=open(ut_name, O_RDWR))<0) { if (errno!=EACCES || (ut_fd=open(ut_name, O_RDONLY))<0) { /* No, this is a library function, it should not do this! */ /* perror("setutent: Can't open utmp file"); */ ut_fd=-1; } } if (ut_fd!= -1) errno=xerrno; } void endutent(void) { if (ut_fd!=-1) close(ut_fd); ut_fd=-1; } struct utmp * getutid(const struct utmp * utmp_entry) { struct utmp * utmp; while ((utmp=getutent())!=NULL) { if ((utmp_entry->ut_type==RUN_LVL || utmp_entry->ut_type==BOOT_TIME || utmp_entry->ut_type==NEW_TIME || utmp_entry->ut_type==OLD_TIME) && utmp->ut_type==utmp_entry->ut_type) return utmp; if ((utmp_entry->ut_type==INIT_PROCESS || utmp_entry->ut_type==DEAD_PROCESS || utmp_entry->ut_type==LOGIN_PROCESS || utmp_entry->ut_type==USER_PROCESS) && !strncmp(utmp->ut_id, utmp_entry->ut_id,sizeof(utmp->ut_id))) return utmp; } return NULL; } struct utmp * getutline(const struct utmp * utmp_entry) { struct utmp * utmp; #if 0 /* This is driving me nuts. It's not an implementation problem - it's a matter of how things _SHOULD_ behave. Groan. */ if (ut_fd!=-1) lseek(ut_fd, (off_t) -sizeof(struct utmp), SEEK_CUR); #endif while ((utmp=getutent())!=NULL) { if ((utmp->ut_type==USER_PROCESS || utmp->ut_type==LOGIN_PROCESS) && !strcmp(utmp->ut_line, utmp_entry->ut_line)) return utmp; } return NULL; } struct utmp * pututline(const struct utmp * utmp_entry) { struct utmp * ut; int xerrno=errno; #if 0 /* Ignore the return value. That way, if they've already positioned the file pointer where they want it, everything will work out. */ if (ut_fd!=-1) (void) lseek(ut_fd, (off_t) -sizeof(struct utmp), SEEK_CUR); #endif if ((ut=getutid(utmp_entry))!=NULL) lseek(ut_fd, (off_t) -sizeof(struct utmp), SEEK_CUR); else if( ut_fd==-1 ) return NULL; else lseek(ut_fd, (off_t) 0, SEEK_END); /* * At this point I could make sure the offset we're at is an exact multiple * of the sizeof struct utmp. Should I? Up or down? --RdB */ if (write(ut_fd, (char *) utmp_entry, sizeof(struct utmp)) != sizeof(struct utmp)) return NULL; /* I think this final lseek gets the result Nat was after ... RdB */ lseek(ut_fd, (off_t) -sizeof(struct utmp), SEEK_CUR); /* Ignoring untrapped errors */ errno=xerrno; return utmp_entry; } void utmpname(const char * new_ut_name) { endutent(); if (new_ut_name!=NULL) ut_name=new_ut_name; } dev86-0.16.21/libc/gnu_i386/000077500000000000000000000000001231050321700150625ustar00rootroot00000000000000dev86-0.16.21/libc/gnu_i386/Config000066400000000000000000000000541231050321700162110ustar00rootroot00000000000000gnu386: Linux-i386 system call routines GCC dev86-0.16.21/libc/gnu_i386/Makefile000066400000000000000000000022771231050321700165320ustar00rootroot00000000000000# Copyright (C) 1995,1996 Robert de Bath # This file is part of the Linux-8086 C library and is distributed # under the GNU Library General Public License. CSRC=cstartup.s COBJ=cstartup.o ESRC=exec.c EOBJ=execl.o execv.o execle.o execlp.o execvp.o DSRC=dirent.c DOBJ=opendir.o closedir.o readdir.o HSRC=heap.c HOBJ=__brk_addr.o brk.o sbrk.o ifeq ($(LIB_CPU)-$(LIB_OS),g386-ELKS) OBJ=$(COBJ) $(EOBJ) $(DOBJ) $(HOBJ) SYSCALLS=syscalls CFLAGS=$(ARCH) $(CCFLAGS) $(DEFS) all: $(SYSCALLS) $(LIBC)($(OBJ)) @$(RM) $(OBJ) syscalls: syscall.mak $(MAKE) -f syscall.mak LIBC="$(LIBC)" CFLAGS="$(CFLAGS)" syscall.mak: mksyscall syscall.dat sh mksyscall $(LIBC)($(LOBJ)): $(LSRC) $(CC) $(CFLAGS) -DL_$* $< -c -o $*.o $(AR) $(ARFLAGS) $@ $*.o $(LIBC)($(COBJ)): $(CSRC) $(CC) $(CFLAGS) -DL_$* $< -c -o $*.o $(AR) $(ARFLAGS) $@ $*.o $(LIBC)($(DOBJ)): $(DSRC) $(CC) $(CFLAGS) -DL_$* $< -c -o $*.o $(AR) $(ARFLAGS) $@ $*.o $(LIBC)($(EOBJ)): $(ESRC) $(CC) $(CFLAGS) -DL_$* $< -c -o $*.o $(AR) $(ARFLAGS) $@ $*.o $(LIBC)($(HOBJ)): $(HSRC) $(CC) $(CFLAGS) -DL_$* $< -c -o $*.o $(AR) $(ARFLAGS) $@ $*.o else all: @: endif clean: rm -f *.o libc.a rm -f syscall.c syscall.mak dev86-0.16.21/libc/gnu_i386/cstartup.s000066400000000000000000000025201231050321700171120ustar00rootroot00000000000000# # This is a startup for GCC compiling to an ELF executable. # # .file "cstartup.s" # void (*__cleanup)() = 0; .globl __cleanup .data .align 4 .type __cleanup,@object .size __cleanup,4 __cleanup: .long 0 .globl errno .align 4 .type errno,@object .size errno,4 errno: .long 0 # char ** environ; .comm environ,4,4 .text .align 16 .globl __cstartup .type __cstartup,@function __cstartup: # Crt0 startup (Linux style) cmpl $0,(%esp) jz call_exit # If argc == 0 this is being called by ldd, exit. popl %ecx movl %esp,%ebx # Points to the arguments movl %esp,%eax movl %ecx,%edx addl %edx,%edx addl %edx,%edx addl %edx,%eax addl $4,%eax # Now points to environ. pushl %eax # envp pushl %ebx # argp pushl %ecx # argc # mov 8(%esp),%eax mov %eax,environ call main push %eax # Main has returned, call_exit: call exit # return val and call exit(); bad_exit: jmp bad_exit # Exit returned !! # Exit - call __cleanup then _exit .align 16 .globl exit .type exit,@function exit: pushl %ebp movl %esp,%ebp pushl %ebx movl 8(%ebp),%ebx movl __cleanup,%eax testl %eax,%eax je .L8 pushl %ebx call *%eax addl $4,%esp .L8: pushl %ebx call _exit jmp bad_exit # _exit is an alias for __exit .align 16 .globl _exit .type _exit,@function _exit: jmp __exit dev86-0.16.21/libc/gnu_i386/dirent.c000066400000000000000000000027731231050321700165240ustar00rootroot00000000000000 #include #include #include #include #include #include #ifdef L_opendir DIR * opendir(dname) const char *dname; { struct stat st; int fd; DIR *p; if (stat(dname, &st) < 0) return 0; if (!S_ISDIR(st.st_mode)) { errno = ENOTDIR; return 0; } if ((fd = open(dname, O_RDONLY)) < 0) return 0; p = malloc(sizeof(DIR)); if (p == 0) { close(fd); return 0; } p->dd_buf = malloc(sizeof(struct dirent)); if (p->dd_buf == 0) { free(p); close(fd); return 0; } p->dd_fd = fd; p->dd_loc = p->dd_size = 0; return p; } #endif #ifdef L_closedir int closedir(dirp) DIR *dirp; { int fd; fd = dirp->dd_fd; free(dirp->dd_buf); free(dirp); return close(fd); } #endif #ifdef __AS386_16__ #ifdef L_readdir /* * This currently assumes we see a v. simple diectory structure, it's * probably faked! */ struct dirent * readdir(dirp) DIR *dirp; { int cc; cc = read(dirp->dd_fd, dirp->dd_buf, sizeof(struct dirent)); if (cc <= 0) return 0; if (cc != sizeof(struct dirent)) { errno = EBADF; return 0; } return dirp->dd_buf; } #endif #else /* This is for 386 linux */ #ifdef L_readdir struct dirent * readdir(dirp) DIR *dirp; { int cc; cc = __readdir(dirp->dd_fd, dirp->dd_buf, 1); if (cc <= 0) return 0; if (cc>1) dirp->dd_buf->d_name[cc] = 0; return dirp->dd_buf; } #endif #endif dev86-0.16.21/libc/gnu_i386/exec.c000066400000000000000000000125141231050321700161550ustar00rootroot00000000000000 #include #include extern char ** environ; #ifdef L_execl int execl(fname, arg0) char * fname, *arg0; { return execve(fname, &arg0, environ); } #endif #ifdef L_execv int execv(fname, argv) char * fname, **argv; { return execve(fname, argv, environ); } #endif #ifdef L_execle int execle(fname, arg0) char *fname, *arg0; { char ** envp = &arg0; while(*envp) envp++; return execve(fname, &arg0, envp+1); } #endif #ifdef L_execve int execve(fname, argv, envp) char * fname; char ** argv; char ** envp; { char **p; int argv_len=0, argv_count=0; int envp_len=0, envp_count=0; int stack_bytes; unsigned short * pip; char * pcp, * stk_ptr, *baseoff; int rv; /* How much space for argv */ for(p=argv; p && *p && argv_len >= 0; p++) { argv_count++; argv_len += strlen(*p)+1; } /* How much space for envp */ for(p=envp; p && *p && envp_len >= 0; p++) { envp_count++; envp_len += strlen(*p)+1; } /* tot it all up */ stack_bytes = 2 /* argc */ + argv_count * 2 + 2 /* argv */ + argv_len + envp_count * 2 + 2 /* envp */ + envp_len; /* Allocate it */ if( argv_len < 0 || envp_len < 0 || stack_bytes <= 0 || (int)(stk_ptr = (char*)sbrk(stack_bytes)) == -1) { errno = ENOMEM; return -1; } /* Sanity check printf("Argv = (%d,%d), Envp=(%d,%d), stack=%d\n", argv_count, argv_len, envp_count, envp_len, stack_bytes); */ /* Now copy in the strings */ pip=(unsigned short *) stk_ptr; pcp=stk_ptr+2*(1+argv_count+1+envp_count+1); /* baseoff = stk_ptr + stack_bytes; */ baseoff = stk_ptr; *pip++ = argv_count; for(p=argv; p && *p; p++) { int l; *pip++ = pcp-baseoff; l = strlen(*p)+1; memcpy(pcp, *p, l); pcp += l; } *pip++ = 0; for(p=envp; p && *p; p++) { int l; *pip++ = pcp-baseoff; l = strlen(*p)+1; memcpy(pcp, *p, l); pcp += l; } *pip++ = 0; rv = __exec(fname, stk_ptr, stack_bytes); /* FIXME: This will probably have to interpret '#!' style exe's */ sbrk(-stack_bytes); return rv; } #endif #ifdef L_execlp int execlp(fname, arg0) char * fname, *arg0; { return execvp(fname, &arg0); } #endif #ifdef L_execvp int execvp(fname, argv) char * fname, **argv; { char *pname = fname, *path; int besterr = ENOENT; int flen, plen; char * bp = sbrk(0); if( *fname != '/' && (path = getenv("PATH")) != 0 ) { flen = strlen(fname)+2; for(;path;) { if( *path == ':' || *path == '\0' ) { tryrun(fname, argv); if( errno == EACCES ) besterr = EACCES; if( *path ) path++; else break; } else { char * p = strchr(path, ':'); if(p) *p = '\0'; plen = strlen(path); pname = sbrk(plen+flen); strcpy(pname, path); strcat(pname, "/"); strcat(pname, fname); tryrun(pname, argv); if( errno == EACCES ) besterr = EACCES; brk(pname); pname = fname; if(p) *p++ = ':'; path=p; } } } tryrun(pname, argv); brk(bp); if( errno == ENOENT || errno == 0 ) errno = besterr; return -1; } static int tryrun(pname, argv) char * pname; char ** argv; { static char *shprog[] = {"/bin/sh", "", 0}; struct stat st; if( stat(pname, &st) < 0 ) return; if( !S_ISREG(st.st_mode) ) return; #ifdef __AS386_16__ __execvve(pname, (void*)0, argv, environ); if( errno == ENOEXEC ) { shprog[1] = pname; __execvve(shprog[0], shprog, argv, environ); } #else execve(pname, argv, environ); /* FIXME - running /bin/sh in 386 mode */ #endif } #ifdef __AS386_16__ static int __execvve(fname, interp, argv, envp) char * fname; char ** interp; char ** argv; char ** envp; { char **p; int argv_len=0, argv_count=0; int envp_len=0, envp_count=0; int stack_bytes; unsigned short * pip; char * pcp, * stk_ptr, *baseoff; int rv; /* How much space for argv */ for(p=interp; p && *p && argv_len >= 0; p++) { argv_count++; argv_len += strlen(*p)+1; } for(p=argv; p && *p && argv_len >= 0; p++) { argv_count++; argv_len += strlen(*p)+1; } /* How much space for envp */ for(p=envp; p && *p && envp_len >= 0; p++) { envp_count++; envp_len += strlen(*p)+1; } /* tot it all up */ stack_bytes = 2 /* argc */ + argv_count * 2 + 2 /* argv */ + argv_len + envp_count * 2 + 2 /* envp */ + envp_len; /* Allocate it */ if( argv_len < 0 || envp_len < 0 || stack_bytes <= 0 || (int)(stk_ptr = (char*)sbrk(stack_bytes)) == -1) { errno = ENOMEM; return -1; } /* Sanity check printf("Argv = (%d,%d), Envp=(%d,%d), stack=%d\n", argv_count, argv_len, envp_count, envp_len, stack_bytes); */ /* Now copy in the strings */ pip=(unsigned short *) stk_ptr; pcp=stk_ptr+2*(1+argv_count+1+envp_count+1); /* baseoff = stk_ptr + stack_bytes; */ baseoff = stk_ptr; *pip++ = argv_count; for(p=interp; p && *p; p++) { int l; *pip++ = pcp-baseoff; l = strlen(*p)+1; memcpy(pcp, *p, l); pcp += l; } for(p=argv; p && *p; p++) { int l; *pip++ = pcp-baseoff; l = strlen(*p)+1; memcpy(pcp, *p, l); pcp += l; } *pip++ = 0; for(p=envp; p && *p; p++) { int l; *pip++ = pcp-baseoff; l = strlen(*p)+1; memcpy(pcp, *p, l); pcp += l; } *pip++ = 0; rv = __exec(fname, stk_ptr, stack_bytes); /* FIXME: This will probably have to interpret '#!' style exe's */ sbrk(-stack_bytes); return rv; } #endif #endif dev86-0.16.21/libc/gnu_i386/heap.c000066400000000000000000000025711231050321700161500ustar00rootroot00000000000000/* Copyright (C) 1995-1997 Robert de Bath * This file is part of the Linux-8086 C library and is distributed * under the GNU Library General Public License. */ #include /****************************************************************************/ #if defined(__GNUC__) && defined(__i386__) extern char * __brk_addr; extern char * __brk(); #ifdef L___brk_addr char * __brk_addr = 0; /* This holds the current return for sbrk(0) */ /* "mov %ebx,4(%esp),%ebx\n\t" "mov $45,%eax\n\t" */ char * __brk(char * val) { char * retval; __asm__( "int $0x80" : "=a" (retval) : "0" (45), "b" (val) ); return retval; } __brk_addr_init() { if( __brk_addr == 0 && (__brk_addr = __brk(0)) == 0 ) { errno = ENOMEM; return -1; } return 0; } #endif #ifdef L_sbrk char * sbrk(brk_off) int brk_off; { char * new_brk; if( __brk_addr_init() ) return (char*)-1; if( brk_off == 0 ) return __brk_addr; new_brk = __brk_addr + brk_off; __brk_addr = __brk(new_brk); if( __brk_addr != new_brk ) { errno = ENOMEM; return (char*)-1; } return __brk_addr - brk_off; } #endif #ifdef L_brk int brk(new_brk) char * new_brk; { if( __brk_addr_init() ) return -1; __brk_addr = __brk(new_brk); if( __brk_addr == new_brk ) return 0; errno = ENOMEM; return -1; } #endif #endif dev86-0.16.21/libc/gnu_i386/mksyscall000066400000000000000000000074341231050321700170170ustar00rootroot00000000000000# Copyright (C) 1995-1997 Robert de Bath # This file is part of the Linux-8086 C library and is distributed # under the GNU Library General Public License. # # This script generates the 'simple' system calls for the 386 # # Each call is put into it's own object file, if the semantics of the # call are not correct UNIX then the 4th field in the dat file has a # marker and the function is generated with a __ prefix. # # # Different levels of squeeze # 0 = each is complete # 1 = Short codes calling common function rm -f syscall.c syscall.mak tr '[A-Z]' '[a-z]' < syscall.dat | \ awk 'BEGIN{ print "# Copyright (C) 1995-1997 Robert de Bath " > "syscall.mak"; print "# This file is part of the Linux-8086 C library and is distributed" > "syscall.mak"; print "# under the GNU Library General Public License." > "syscall.mak"; print "# " > "syscall.mak"; print "# This file is automatically generated\n" > "syscall.mak" print "# Copyright (C) 1995-1997 Robert de Bath "; print "# This file is part of the Linux-8086 C library and is distributed"; print "# under the GNU Library General Public License."; print "# "; print "# This file is automatically generated */\n" obj="OBJ="; print "# Standard start\n\n" printf("#ifndef __MSDOS__\n"); printf("#ifdef __AS386_32__\n"); printf(" .text\n"); printf(" .align 16\n"); COMPACT=0; } /^[ ]*#/ { next; } /^[ ]*$/ { next; } { if( $2 > max_call ) max_call = $2; if( $3 == "x" || $3 == "" ) next; else if( $4 == "-" ) next; else if( $4 == "*" ) funcname="__" $1; else funcname=$1; if( length(obj) > 60 ) { printf("%s\t\\\n", obj) > "syscall.mak"; obj=" "; } obj=obj funcname ".o "; printf "# CALL %s\n\n", $0; printf(".ifdef L_%s\n", funcname); printf(".globl %s\n", funcname); printf(".type %s,@function\n", funcname); printf("%s:\n", funcname); # Inline assembler max to 5 args (20 bytes) if( $3 != 4 && $3 != 5 && ( COMPACT || $3 > 5 )) { printf(" mov %%eax,#%d\n", $2); printf(" br sys_call%d\n", $3); } else { printf(" pushl %%ebp\n"); printf(" movl %%esp,%%ebp\n"); printf(" pushl %%ebx\n"); if( $3 >= 1 ) printf(" mov 8(%%ebp),%%ebx\n"); if( $3 >= 2 ) printf(" mov 12(%%ebp),%%ecx\n"); if( $3 >= 3 ) printf(" mov 16(%%ebp),%%edx\n"); if( $3 >= 4 ) printf(" push %%esi\n"); if( $3 >= 4 ) printf(" mov 20(%%ebp),%%esi\n"); if( $3 >= 5 ) printf(" push %%edi\n"); if( $3 >= 5 ) printf(" mov 24(%%ebp),%%edi\n"); printf(" mov $%d,%%eax\n", $2); printf(" int $0x80\n"); if( $3 >= 5 ) printf(" pop %%edi\n"); if( $3 >= 4 ) printf(" pop %%esi\n"); printf(" pop %%ebx\n"); printf(" test %%eax,%%eax\n"); printf(" jge syscall_ok\n"); printf(" neg %%eax\n"); printf(" mov %%eax,errno\n"); printf(" mov $-1,%%eax\n"); printf("syscall_ok:\n"); printf(" movl %%ebp,%%esp\n"); printf(" popl %%ebp\n"); printf(" ret\n"); } printf(".endif\n\n"); } END{ printf("#endif /* __AS386_32__ */\n\n"); printf("#endif /* __MSDOS__ */\n\n"); printf("%s\n", obj) > "syscall.mak"; printf "\n" > "syscall.mak"; }' > syscall.s cat >> syscall.mak <<\! CFLAGS=$(ARCH) $(CCFLAGS) $(DEFS) all: $(LIBC)($(OBJ)) @$(RM) $(OBJ) $(LIBC)($(OBJ)): syscall.dat mksyscall $(AS) --defsym L_$*=0 syscall.s -o $*.o $(AR) $(ARFLAGS) $@ $*.o ! exit $? dev86-0.16.21/libc/gnu_i386/syscall.dat000066400000000000000000000120161231050321700172260ustar00rootroot00000000000000 # # Name No Args Flag, comment # # . = Ok, with comment # * = Needs libc code (Prefix __) # - = Obsolete/not required # # Name N C setup 0 X exit 1 1 * fork 2 0 vfork 2 0 . Fake alias of fork read 3 3 write 4 3 open 5 3 close 6 1 waitpid 7 3 creat 8 2 link 9 2 unlink 10 1 execve 11 3 chdir 12 1 time 13 1 dv32_mknod 14 3 * Has correct args for 32bit dev_t chmod 15 2 chown 16 3 break 17 X - This is done in a special function oldstat 18 X - lseek 19 3 getpid 20 0 mount 21 5 umount 22 1 setuid 23 1 getuid 24 0 stime 25 1 ptrace 26 4 alarm 27 1 oldfstat 28 X - pause 29 0 utime 30 2 stty 31 X - gtty 32 X - access 33 2 nice 34 1 ftime 35 1 sync 36 0 kill 37 2 rename 38 2 mkdir 39 2 rmdir 40 1 dup 41 1 pipe 42 1 times 43 1 prof 44 X - brk 45 1 - need to save brk_addr & -ve is valid return. setgid 46 1 getgid 47 0 signal 48 2 geteuid 49 0 getegid 50 0 acct 51 1 phys 52 X - lock 53 X - ioctl 54 3 fcntl 55 3 mpx 56 X - setpgid 57 2 ulimit 58 2 oldolduname 59 X - umask 60 1 chroot 61 1 dv32_ustat 62 2 * Has correct args for 32bit dev_t dup2 63 2 getppid 64 0 getpgrp 65 0 setsid 66 0 sigaction 67 3 siggetmask 68 0 sigsetmask 69 1 setreuid 70 2 setregid 71 2 sigsuspend 72 1 sigpending 73 1 sethostname 74 2 setrlimit 75 2 getrlimit 76 2 getrusage 77 2 gettimeofday 78 2 settimeofday 79 2 getgroups 80 2 setgroups 81 2 select 82 1 * select's arg is &arg1 symlink 83 2 oldlstat 84 X - readlink 85 3 uselib 86 1 swapon 87 2 reboot 88 3 readdir 89 3 * Takes the fd not a ddptr mmap 90 1 * Is a pointer to a buffer with the 6 args. munmap 91 2 truncate 92 2 ftruncate 93 2 fchmod 94 2 fchown 95 2 getpriority 96 2 setpriority 97 3 profil 98 X - glibc has userspace statfs 99 2 fstatfs 100 2 ioperm 101 3 socketcall 102 2 * This is a lib internal for socket stuff klog 103 X setitimer 104 3 getitimer 105 2 dv32_stat 106 2 * Has correct args for 32 bit dev_t dv32_lstat 107 2 * Has correct args for 32 bit dev_t dv32_fstat 108 2 * Has correct args for 32 bit dev_t olduname 109 X - iopl 110 1 vhangup 111 0 idle 112 0 - System internal vm86 113 1 wait4 114 4 swapoff 115 1 sysinfo 116 1 ipc 117 5 * SYSV ipc entry point fsync 118 1 sigreturn 119 1 * Signal internal clone 120 2 setdomainname 121 2 uname 122 1 modify_ldt 123 X adjtimex 124 1 mprotect 125 3 sigprocmask 126 3 create_module 127 X - Module handling, NO WAY! init_module 128 X delete_module 129 X get_kernel_syms 130 X quotactl 131 X getpgid 132 1 fchdir 133 1 bdflush 134 2 sysfs 135 3 personality 136 1 * Linux specific. afs_syscall 137 X setfsuid 138 1 setfsgid 139 1 _llseek 140 X getdents 141 3 * New style readdir ? _newselect 142 X flock 143 2 syscall_flock 143 X dev86-0.16.21/libc/gnu_i386/syscall.s000066400000000000000000001277501231050321700167340ustar00rootroot00000000000000# Copyright (C) 1995-1997 Robert de Bath # This file is part of the Linux-8086 C library and is distributed # under the GNU Library General Public License. # # This file is automatically generated */ # Standard start #ifndef __MSDOS__ #ifdef __AS386_32__ .text .align 16 # CALL exit 1 1 * .ifdef L___exit .globl __exit .type __exit,@function __exit: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov $1,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL fork 2 0 .ifdef L_fork .globl fork .type fork,@function fork: pushl %ebp movl %esp,%ebp pushl %ebx mov $2,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL vfork 2 0 . fake alias of fork .ifdef L_vfork .globl vfork .type vfork,@function vfork: pushl %ebp movl %esp,%ebp pushl %ebx mov $2,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL read 3 3 .ifdef L_read .globl read .type read,@function read: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov 12(%ebp),%ecx mov 16(%ebp),%edx mov $3,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL write 4 3 .ifdef L_write .globl write .type write,@function write: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov 12(%ebp),%ecx mov 16(%ebp),%edx mov $4,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL open 5 3 .ifdef L_open .globl open .type open,@function open: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov 12(%ebp),%ecx mov 16(%ebp),%edx mov $5,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL close 6 1 .ifdef L_close .globl close .type close,@function close: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov $6,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL waitpid 7 3 .ifdef L_waitpid .globl waitpid .type waitpid,@function waitpid: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov 12(%ebp),%ecx mov 16(%ebp),%edx mov $7,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL creat 8 2 .ifdef L_creat .globl creat .type creat,@function creat: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov 12(%ebp),%ecx mov $8,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL link 9 2 .ifdef L_link .globl link .type link,@function link: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov 12(%ebp),%ecx mov $9,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL unlink 10 1 .ifdef L_unlink .globl unlink .type unlink,@function unlink: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov $10,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL execve 11 3 .ifdef L_execve .globl execve .type execve,@function execve: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov 12(%ebp),%ecx mov 16(%ebp),%edx mov $11,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL chdir 12 1 .ifdef L_chdir .globl chdir .type chdir,@function chdir: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov $12,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL time 13 1 .ifdef L_time .globl time .type time,@function time: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov $13,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL dv32_mknod 14 3 * has correct args for 32bit dev_t .ifdef L___dv32_mknod .globl __dv32_mknod .type __dv32_mknod,@function __dv32_mknod: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov 12(%ebp),%ecx mov 16(%ebp),%edx mov $14,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL chmod 15 2 .ifdef L_chmod .globl chmod .type chmod,@function chmod: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov 12(%ebp),%ecx mov $15,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL chown 16 3 .ifdef L_chown .globl chown .type chown,@function chown: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov 12(%ebp),%ecx mov 16(%ebp),%edx mov $16,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL lseek 19 3 .ifdef L_lseek .globl lseek .type lseek,@function lseek: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov 12(%ebp),%ecx mov 16(%ebp),%edx mov $19,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL getpid 20 0 .ifdef L_getpid .globl getpid .type getpid,@function getpid: pushl %ebp movl %esp,%ebp pushl %ebx mov $20,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL mount 21 5 .ifdef L_mount .globl mount .type mount,@function mount: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov 12(%ebp),%ecx mov 16(%ebp),%edx push %esi mov 20(%ebp),%esi push %edi mov 24(%ebp),%edi mov $21,%eax int $0x80 pop %edi pop %esi pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL umount 22 1 .ifdef L_umount .globl umount .type umount,@function umount: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov $22,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL setuid 23 1 .ifdef L_setuid .globl setuid .type setuid,@function setuid: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov $23,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL getuid 24 0 .ifdef L_getuid .globl getuid .type getuid,@function getuid: pushl %ebp movl %esp,%ebp pushl %ebx mov $24,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL stime 25 1 .ifdef L_stime .globl stime .type stime,@function stime: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov $25,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL ptrace 26 4 .ifdef L_ptrace .globl ptrace .type ptrace,@function ptrace: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov 12(%ebp),%ecx mov 16(%ebp),%edx push %esi mov 20(%ebp),%esi mov $26,%eax int $0x80 pop %esi pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL alarm 27 1 .ifdef L_alarm .globl alarm .type alarm,@function alarm: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov $27,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL pause 29 0 .ifdef L_pause .globl pause .type pause,@function pause: pushl %ebp movl %esp,%ebp pushl %ebx mov $29,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL utime 30 2 .ifdef L_utime .globl utime .type utime,@function utime: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov 12(%ebp),%ecx mov $30,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL access 33 2 .ifdef L_access .globl access .type access,@function access: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov 12(%ebp),%ecx mov $33,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL nice 34 1 .ifdef L_nice .globl nice .type nice,@function nice: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov $34,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL ftime 35 1 .ifdef L_ftime .globl ftime .type ftime,@function ftime: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov $35,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL sync 36 0 .ifdef L_sync .globl sync .type sync,@function sync: pushl %ebp movl %esp,%ebp pushl %ebx mov $36,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL kill 37 2 .ifdef L_kill .globl kill .type kill,@function kill: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov 12(%ebp),%ecx mov $37,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL rename 38 2 .ifdef L_rename .globl rename .type rename,@function rename: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov 12(%ebp),%ecx mov $38,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL mkdir 39 2 .ifdef L_mkdir .globl mkdir .type mkdir,@function mkdir: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov 12(%ebp),%ecx mov $39,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL rmdir 40 1 .ifdef L_rmdir .globl rmdir .type rmdir,@function rmdir: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov $40,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL dup 41 1 .ifdef L_dup .globl dup .type dup,@function dup: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov $41,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL pipe 42 1 .ifdef L_pipe .globl pipe .type pipe,@function pipe: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov $42,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL times 43 1 .ifdef L_times .globl times .type times,@function times: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov $43,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL setgid 46 1 .ifdef L_setgid .globl setgid .type setgid,@function setgid: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov $46,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL getgid 47 0 .ifdef L_getgid .globl getgid .type getgid,@function getgid: pushl %ebp movl %esp,%ebp pushl %ebx mov $47,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL signal 48 2 .ifdef L_signal .globl signal .type signal,@function signal: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov 12(%ebp),%ecx mov $48,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL geteuid 49 0 .ifdef L_geteuid .globl geteuid .type geteuid,@function geteuid: pushl %ebp movl %esp,%ebp pushl %ebx mov $49,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL getegid 50 0 .ifdef L_getegid .globl getegid .type getegid,@function getegid: pushl %ebp movl %esp,%ebp pushl %ebx mov $50,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL acct 51 1 .ifdef L_acct .globl acct .type acct,@function acct: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov $51,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL ioctl 54 3 .ifdef L_ioctl .globl ioctl .type ioctl,@function ioctl: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov 12(%ebp),%ecx mov 16(%ebp),%edx mov $54,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL fcntl 55 3 .ifdef L_fcntl .globl fcntl .type fcntl,@function fcntl: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov 12(%ebp),%ecx mov 16(%ebp),%edx mov $55,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL setpgid 57 2 .ifdef L_setpgid .globl setpgid .type setpgid,@function setpgid: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov 12(%ebp),%ecx mov $57,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL ulimit 58 2 .ifdef L_ulimit .globl ulimit .type ulimit,@function ulimit: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov 12(%ebp),%ecx mov $58,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL umask 60 1 .ifdef L_umask .globl umask .type umask,@function umask: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov $60,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL chroot 61 1 .ifdef L_chroot .globl chroot .type chroot,@function chroot: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov $61,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL dv32_ustat 62 2 * has correct args for 32bit dev_t .ifdef L___dv32_ustat .globl __dv32_ustat .type __dv32_ustat,@function __dv32_ustat: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov 12(%ebp),%ecx mov $62,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL dup2 63 2 .ifdef L_dup2 .globl dup2 .type dup2,@function dup2: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov 12(%ebp),%ecx mov $63,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL getppid 64 0 .ifdef L_getppid .globl getppid .type getppid,@function getppid: pushl %ebp movl %esp,%ebp pushl %ebx mov $64,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL getpgrp 65 0 .ifdef L_getpgrp .globl getpgrp .type getpgrp,@function getpgrp: pushl %ebp movl %esp,%ebp pushl %ebx mov $65,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL setsid 66 0 .ifdef L_setsid .globl setsid .type setsid,@function setsid: pushl %ebp movl %esp,%ebp pushl %ebx mov $66,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL sigaction 67 3 .ifdef L_sigaction .globl sigaction .type sigaction,@function sigaction: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov 12(%ebp),%ecx mov 16(%ebp),%edx mov $67,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL siggetmask 68 0 .ifdef L_siggetmask .globl siggetmask .type siggetmask,@function siggetmask: pushl %ebp movl %esp,%ebp pushl %ebx mov $68,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL sigsetmask 69 1 .ifdef L_sigsetmask .globl sigsetmask .type sigsetmask,@function sigsetmask: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov $69,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL setreuid 70 2 .ifdef L_setreuid .globl setreuid .type setreuid,@function setreuid: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov 12(%ebp),%ecx mov $70,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL setregid 71 2 .ifdef L_setregid .globl setregid .type setregid,@function setregid: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov 12(%ebp),%ecx mov $71,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL sigsuspend 72 1 .ifdef L_sigsuspend .globl sigsuspend .type sigsuspend,@function sigsuspend: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov $72,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL sigpending 73 1 .ifdef L_sigpending .globl sigpending .type sigpending,@function sigpending: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov $73,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL sethostname 74 2 .ifdef L_sethostname .globl sethostname .type sethostname,@function sethostname: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov 12(%ebp),%ecx mov $74,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL setrlimit 75 2 .ifdef L_setrlimit .globl setrlimit .type setrlimit,@function setrlimit: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov 12(%ebp),%ecx mov $75,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL getrlimit 76 2 .ifdef L_getrlimit .globl getrlimit .type getrlimit,@function getrlimit: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov 12(%ebp),%ecx mov $76,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL getrusage 77 2 .ifdef L_getrusage .globl getrusage .type getrusage,@function getrusage: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov 12(%ebp),%ecx mov $77,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL gettimeofday 78 2 .ifdef L_gettimeofday .globl gettimeofday .type gettimeofday,@function gettimeofday: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov 12(%ebp),%ecx mov $78,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL settimeofday 79 2 .ifdef L_settimeofday .globl settimeofday .type settimeofday,@function settimeofday: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov 12(%ebp),%ecx mov $79,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL getgroups 80 2 .ifdef L_getgroups .globl getgroups .type getgroups,@function getgroups: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov 12(%ebp),%ecx mov $80,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL setgroups 81 2 .ifdef L_setgroups .globl setgroups .type setgroups,@function setgroups: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov 12(%ebp),%ecx mov $81,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL select 82 1 * select's arg is &arg1 .ifdef L___select .globl __select .type __select,@function __select: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov $82,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL symlink 83 2 .ifdef L_symlink .globl symlink .type symlink,@function symlink: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov 12(%ebp),%ecx mov $83,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL readlink 85 3 .ifdef L_readlink .globl readlink .type readlink,@function readlink: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov 12(%ebp),%ecx mov 16(%ebp),%edx mov $85,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL uselib 86 1 .ifdef L_uselib .globl uselib .type uselib,@function uselib: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov $86,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL swapon 87 2 .ifdef L_swapon .globl swapon .type swapon,@function swapon: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov 12(%ebp),%ecx mov $87,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL reboot 88 3 .ifdef L_reboot .globl reboot .type reboot,@function reboot: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov 12(%ebp),%ecx mov 16(%ebp),%edx mov $88,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL readdir 89 3 * takes the fd not a ddptr .ifdef L___readdir .globl __readdir .type __readdir,@function __readdir: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov 12(%ebp),%ecx mov 16(%ebp),%edx mov $89,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL mmap 90 1 * is a pointer to a buffer with the 6 args. .ifdef L___mmap .globl __mmap .type __mmap,@function __mmap: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov $90,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL munmap 91 2 .ifdef L_munmap .globl munmap .type munmap,@function munmap: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov 12(%ebp),%ecx mov $91,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL truncate 92 2 .ifdef L_truncate .globl truncate .type truncate,@function truncate: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov 12(%ebp),%ecx mov $92,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL ftruncate 93 2 .ifdef L_ftruncate .globl ftruncate .type ftruncate,@function ftruncate: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov 12(%ebp),%ecx mov $93,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL fchmod 94 2 .ifdef L_fchmod .globl fchmod .type fchmod,@function fchmod: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov 12(%ebp),%ecx mov $94,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL fchown 95 2 .ifdef L_fchown .globl fchown .type fchown,@function fchown: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov 12(%ebp),%ecx mov $95,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL getpriority 96 2 .ifdef L_getpriority .globl getpriority .type getpriority,@function getpriority: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov 12(%ebp),%ecx mov $96,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL setpriority 97 3 .ifdef L_setpriority .globl setpriority .type setpriority,@function setpriority: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov 12(%ebp),%ecx mov 16(%ebp),%edx mov $97,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL statfs 99 2 .ifdef L_statfs .globl statfs .type statfs,@function statfs: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov 12(%ebp),%ecx mov $99,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL fstatfs 100 2 .ifdef L_fstatfs .globl fstatfs .type fstatfs,@function fstatfs: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov 12(%ebp),%ecx mov $100,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL ioperm 101 3 .ifdef L_ioperm .globl ioperm .type ioperm,@function ioperm: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov 12(%ebp),%ecx mov 16(%ebp),%edx mov $101,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL socketcall 102 2 * this is a lib internal for socket stuff .ifdef L___socketcall .globl __socketcall .type __socketcall,@function __socketcall: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov 12(%ebp),%ecx mov $102,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL setitimer 104 3 .ifdef L_setitimer .globl setitimer .type setitimer,@function setitimer: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov 12(%ebp),%ecx mov 16(%ebp),%edx mov $104,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL getitimer 105 2 .ifdef L_getitimer .globl getitimer .type getitimer,@function getitimer: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov 12(%ebp),%ecx mov $105,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL dv32_stat 106 2 * has correct args for 32 bit dev_t .ifdef L___dv32_stat .globl __dv32_stat .type __dv32_stat,@function __dv32_stat: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov 12(%ebp),%ecx mov $106,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL dv32_lstat 107 2 * has correct args for 32 bit dev_t .ifdef L___dv32_lstat .globl __dv32_lstat .type __dv32_lstat,@function __dv32_lstat: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov 12(%ebp),%ecx mov $107,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL dv32_fstat 108 2 * has correct args for 32 bit dev_t .ifdef L___dv32_fstat .globl __dv32_fstat .type __dv32_fstat,@function __dv32_fstat: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov 12(%ebp),%ecx mov $108,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL iopl 110 1 .ifdef L_iopl .globl iopl .type iopl,@function iopl: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov $110,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL vhangup 111 0 .ifdef L_vhangup .globl vhangup .type vhangup,@function vhangup: pushl %ebp movl %esp,%ebp pushl %ebx mov $111,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL vm86 113 1 .ifdef L_vm86 .globl vm86 .type vm86,@function vm86: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov $113,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL wait4 114 4 .ifdef L_wait4 .globl wait4 .type wait4,@function wait4: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov 12(%ebp),%ecx mov 16(%ebp),%edx push %esi mov 20(%ebp),%esi mov $114,%eax int $0x80 pop %esi pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL swapoff 115 1 .ifdef L_swapoff .globl swapoff .type swapoff,@function swapoff: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov $115,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL sysinfo 116 1 .ifdef L_sysinfo .globl sysinfo .type sysinfo,@function sysinfo: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov $116,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL ipc 117 5 * sysv ipc entry point .ifdef L___ipc .globl __ipc .type __ipc,@function __ipc: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov 12(%ebp),%ecx mov 16(%ebp),%edx push %esi mov 20(%ebp),%esi push %edi mov 24(%ebp),%edi mov $117,%eax int $0x80 pop %edi pop %esi pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL fsync 118 1 .ifdef L_fsync .globl fsync .type fsync,@function fsync: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov $118,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL sigreturn 119 1 * signal internal .ifdef L___sigreturn .globl __sigreturn .type __sigreturn,@function __sigreturn: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov $119,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL clone 120 2 .ifdef L_clone .globl clone .type clone,@function clone: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov 12(%ebp),%ecx mov $120,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL setdomainname 121 2 .ifdef L_setdomainname .globl setdomainname .type setdomainname,@function setdomainname: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov 12(%ebp),%ecx mov $121,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL uname 122 1 .ifdef L_uname .globl uname .type uname,@function uname: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov $122,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL adjtimex 124 1 .ifdef L_adjtimex .globl adjtimex .type adjtimex,@function adjtimex: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov $124,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL mprotect 125 3 .ifdef L_mprotect .globl mprotect .type mprotect,@function mprotect: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov 12(%ebp),%ecx mov 16(%ebp),%edx mov $125,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL sigprocmask 126 3 .ifdef L_sigprocmask .globl sigprocmask .type sigprocmask,@function sigprocmask: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov 12(%ebp),%ecx mov 16(%ebp),%edx mov $126,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL getpgid 132 1 .ifdef L_getpgid .globl getpgid .type getpgid,@function getpgid: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov $132,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL fchdir 133 1 .ifdef L_fchdir .globl fchdir .type fchdir,@function fchdir: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov $133,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL bdflush 134 2 .ifdef L_bdflush .globl bdflush .type bdflush,@function bdflush: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov 12(%ebp),%ecx mov $134,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL sysfs 135 3 .ifdef L_sysfs .globl sysfs .type sysfs,@function sysfs: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov 12(%ebp),%ecx mov 16(%ebp),%edx mov $135,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL personality 136 1 * linux specific. .ifdef L___personality .globl __personality .type __personality,@function __personality: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov $136,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL setfsuid 138 1 .ifdef L_setfsuid .globl setfsuid .type setfsuid,@function setfsuid: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov $138,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL setfsgid 139 1 .ifdef L_setfsgid .globl setfsgid .type setfsgid,@function setfsgid: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov $139,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL getdents 141 3 * new style readdir ? .ifdef L___getdents .globl __getdents .type __getdents,@function __getdents: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov 12(%ebp),%ecx mov 16(%ebp),%edx mov $141,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif # CALL flock 143 2 .ifdef L_flock .globl flock .type flock,@function flock: pushl %ebp movl %esp,%ebp pushl %ebx mov 8(%ebp),%ebx mov 12(%ebp),%ecx mov $143,%eax int $0x80 pop %ebx test %eax,%eax jge syscall_ok neg %eax mov %eax,errno mov $-1,%eax syscall_ok: movl %ebp,%esp popl %ebp ret .endif #endif /* __AS386_32__ */ #endif /* __MSDOS__ */ dev86-0.16.21/libc/gtermcap/000077500000000000000000000000001231050321700153225ustar00rootroot00000000000000dev86-0.16.21/libc/gtermcap/COPYING000066400000000000000000000430761231050321700163670ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 675 Mass Ave, Cambridge, MA 02139, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS Appendix: How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 19yy This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19yy name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. dev86-0.16.21/libc/gtermcap/ChangeLog000066400000000000000000000027661231050321700171070ustar00rootroot00000000000000Sat Apr 17 13:50:10 1993 H.J. Lu (hlu@nighthawk) * modify termcap.c and tparam.c for Linux. Thu Apr 15 12:45:10 1993 David J. MacKenzie (djm@kropotkin.gnu.ai.mit.edu) * Version 1.2. * tparam.c [!emacs] (xmalloc, xrealloc, memory_out): New functions. (tparam1): Use them. * termcap.c, tparam.c: Use NULL or '\0' where appropriate instead of 0. Rename some vars. * termcap.c (tgetent): If EOF is reached on termcap file, free allocated resources before returning. * termcap.c (tgetent): Use /etc/termcap if TERMCAP is an entry for a term type other than TERM. From pjr@jet.UK (Paul J Rippin). Sat Apr 10 23:55:12 1993 Richard Stallman (rms@mole.gnu.ai.mit.edu) * tparam.c (tparam1): Don't set the 0200 bit on a non-0 character code. From junio@twinsun.COM (Junio Hamano). Tue Dec 8 22:02:15 1992 David J. MacKenzie (djm@kropotkin.gnu.ai.mit.edu) * termcap.c, tparam.c: Use HAVE_STRING_H instead of USG. Thu Dec 3 13:47:56 1992 David J. MacKenzie (djm@nutrimat.gnu.ai.mit.edu) * termcap.c, tparam.c [HAVE_CONFIG_H]: Include config.h. Fri Oct 23 12:35:29 1992 David J. MacKenzie (djm@goldman.gnu.ai.mit.edu) * termcap.h [__STDC__]: Add consts. From Franc,ois Pinard. Tue Oct 13 15:52:21 1992 David J. MacKenzie (djm@goldman.gnu.ai.mit.edu) * Version 1.1. Tue Sep 29 21:04:39 1992 David J. MacKenzie (djm@geech.gnu.ai.mit.edu) * termcap.[ch], tparam.c: Fix some lint. * version.c: New file. Local Variables: mode: indented-text left-margin: 8 version-control: never End: dev86-0.16.21/libc/gtermcap/Config000066400000000000000000000000361231050321700164510ustar00rootroot00000000000000gtermcap:GNU termcap routines dev86-0.16.21/libc/gtermcap/Makefile000066400000000000000000000005371231050321700167670ustar00rootroot00000000000000# Copyright (C) 1995,1996 Robert de Bath # This file is part of the Linux-8086 C library and is distributed # under the GNU Library General Public License. CFLAGS=$(ARCH) $(CCFLAGS) $(DEFS) ifeq ($(LIB_OS),ELKS) OBJ=termcap.o tparam.o all: $(LIBC)($(OBJ)) @$(RM) $(OBJ) else all: @: endif clean: rm -f *.o libc.a dev86-0.16.21/libc/gtermcap/NEWS000066400000000000000000000004471231050321700160260ustar00rootroot00000000000000Major changes in release 1.2: For `%.', only set the high bit on NUL. Fix a file descriptor and memory leak. Add const in termcap.h prototypes. Configuration improvements. Major changes in release 1.1: Fix portability problems. Improve configuration and installation. Fix compiler warnings. dev86-0.16.21/libc/gtermcap/README000066400000000000000000000012551231050321700162050ustar00rootroot00000000000000This is the GNU termcap library -- a library of C functions that enable programs to send control strings to terminals in a way independent of the terminal type. Most of this package is also distributed with GNU Emacs, but it is available in this separate distribution to make it easier to install as -ltermcap. The GNU termcap library does not place an arbitrary limit on the size of termcap entries, unlike most other termcap libraries. See the file INSTALL for compilation and installation instructions. Please report any bugs in this library to bug-gnu-emacs@prep.ai.mit.edu. You can check which version of the library you have by using the RCS `ident' command on libtermcap.a. dev86-0.16.21/libc/gtermcap/termcap.c000066400000000000000000000424111231050321700171230ustar00rootroot00000000000000/* Work-alike for termcap, plus extra features. Copyright (C) 1985, 1986, 1993 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ /* Emacs config.h may rename various library functions such as malloc. */ #ifdef HAVE_CONFIG_H #include "config.h" #else /* not HAVE_CONFIG_H */ #ifdef __linux__ #undef STDC_HEADERS #define STDC_HEADERS #define HAVE_UNISTD_H #define HAVE_SYS_IOCTL_H #else #if defined(HAVE_STRING_H) || defined(STDC_HEADERS) #define bcopy(s, d, n) memcpy ((d), (s), (n)) #endif #endif #ifdef STDC_HEADERS #include #include #else char *getenv (); char *malloc (); char *realloc (); #endif #ifdef HAVE_UNISTD_H #include #endif #ifdef _POSIX_VERSION #include #endif #ifdef HAVE_SYS_IOCTL_H #include #include #endif #endif /* not HAVE_CONFIG_H */ #ifndef NULL #define NULL (char *) 0 #endif /* BUFSIZE is the initial size allocated for the buffer for reading the termcap file. It is not a limit. Make it large normally for speed. Make it variable when debugging, so can exercise increasing the space dynamically. */ #ifndef BUFSIZE #ifdef DEBUG #define BUFSIZE bufsize int bufsize = 128; #else #define BUFSIZE 2048 #endif #endif #ifdef TIOCGWINSZ #define ADJUST_WIN_EXTENT #endif #ifndef emacs static void memory_out () { write (2, "virtual memory exhausted\n", 25); exit (1); } static char * xmalloc (size) unsigned size; { register char *tem = malloc (size); if (!tem) memory_out (); return tem; } static char * xrealloc (ptr, size) char *ptr; unsigned size; { register char *tem = realloc (ptr, size); if (!tem) memory_out (); return tem; } #endif /* not emacs */ /* Looking up capabilities in the entry already found. */ /* The pointer to the data made by tgetent is left here for tgetnum, tgetflag and tgetstr to find. */ static char *term_entry; static char *tgetst1 (); /* Search entry BP for capability CAP. Return a pointer to the capability (in BP) if found, 0 if not found. */ static char * find_capability (bp, cap) register char *bp, *cap; { for (; *bp; bp++) if (bp[0] == ':' && bp[1] == cap[0] && bp[2] == cap[1]) return &bp[4]; return NULL; } int tgetnum (cap) char *cap; { register char *ptr = find_capability (term_entry, cap); if (!ptr || ptr[-1] != '#') return -1; return atoi (ptr); } int tgetflag (cap) char *cap; { register char *ptr = find_capability (term_entry, cap); return ptr && ptr[-1] == ':'; } /* Look up a string-valued capability CAP. If AREA is non-null, it points to a pointer to a block in which to store the string. That pointer is advanced over the space used. If AREA is null, space is allocated with `malloc'. */ char * tgetstr (cap, area) char *cap; char **area; { register char *ptr = find_capability (term_entry, cap); if (!ptr || (ptr[-1] != '=' && ptr[-1] != '~')) return NULL; return tgetst1 (ptr, area); } /* Table, indexed by a character in range 0100 to 0140 with 0100 subtracted, gives meaning of character following \, or a space if no special meaning. Eight characters per line within the string. */ static char esctab[] = " \007\010 \033\014 \ \012 \ \015 \011 \013 \ "; /* PTR points to a string value inside a termcap entry. Copy that value, processing \ and ^ abbreviations, into the block that *AREA points to, or to newly allocated storage if AREA is NULL. Return the address to which we copied the value, or NULL if PTR is NULL. */ static char * tgetst1 (ptr, area) char *ptr; char **area; { register char *p, *r; register int c; register int size; char *ret; register int c1; if (!ptr) return NULL; /* `ret' gets address of where to store the string. */ if (!area) { /* Compute size of block needed (may overestimate). */ p = ptr; while ((c = *p++) && c != ':' && c != '\n') ; ret = (char *) xmalloc (p - ptr + 1); } else ret = *area; /* Copy the string value, stopping at null or colon. Also process ^ and \ abbreviations. */ p = ptr; r = ret; while ((c = *p++) && c != ':' && c != '\n') { if (c == '^') c = *p++ & 037; else if (c == '\\') { c = *p++; if (c >= '0' && c <= '7') { c -= '0'; size = 0; while (++size < 3 && (c1 = *p) >= '0' && c1 <= '7') { c *= 8; c += c1 - '0'; p++; } } else if (c >= 0100 && c < 0200) { c1 = esctab[(c & ~040) - 0100]; if (c1 != ' ') c = c1; } } *r++ = c; } *r = '\0'; /* Update *AREA. */ if (area) *area = r + 1; return ret; } /* Outputting a string with padding. */ #ifdef __linux__ speed_t ospeed; #else short ospeed; #endif /* If OSPEED is 0, we use this as the actual baud rate. */ int tputs_baud_rate; char PC; /* Actual baud rate if positive; - baud rate / 100 if negative. */ static short speeds[] = { #ifdef VMS 0, 50, 75, 110, 134, 150, -3, -6, -12, -18, -20, -24, -36, -48, -72, -96, -192 #else /* not VMS */ 0, 50, 75, 110, 135, 150, -2, -3, -6, -12, -18, -24, -48, -96, -192, -384 #endif /* not VMS */ }; void tputs (str, nlines, outfun) register char *str; int nlines; register int (*outfun) (); { register int padcount = 0; register int speed; #ifdef emacs extern baud_rate; speed = baud_rate; #else if (ospeed == 0) speed = tputs_baud_rate; else speed = speeds[ospeed]; #endif if (!str) return; while (*str >= '0' && *str <= '9') { padcount += *str++ - '0'; padcount *= 10; } if (*str == '.') { str++; padcount += *str++ - '0'; } if (*str == '*') { str++; padcount *= nlines; } while (*str) (*outfun) (*str++); /* padcount is now in units of tenths of msec. */ padcount *= speeds[ospeed]; padcount += 500; padcount /= 1000; if (speeds[ospeed] < 0) padcount = -padcount; else { padcount += 50; padcount /= 100; } while (padcount-- > 0) (*outfun) (PC); } /* Finding the termcap entry in the termcap data base. */ struct buffer { char *beg; int size; char *ptr; int ateof; int full; }; /* Forward declarations of static functions. */ static int scan_file (); static char *gobble_line (); static int compare_contin (); static int name_match (); #ifdef ADJUST_WIN_EXTENT #ifdef TIOCGWINSZ static int get_win_extent(li, co) int *li, *co; { struct winsize ws; /* Some TIOCGWINSZ may be broken. Make sure ws.ws_row and * ws.ws_col are not zero. */ if (ioctl(0, TIOCGWINSZ, &ws) != 0 || !ws.ws_row || !ws.ws_col) return -1; *li = ws.ws_row; *co = ws.ws_col; return 0; } #endif /* TIOCGWINSZ */ static int adjust_win_extent(bpp, howalloc, li, co) char **bpp; int howalloc; /* 0 must do in place, 1 must use malloc, 2 must use realloc */ int li, co; { int licolen, o_len, t, colon; char *licobuf, *s; if (li < 0 || co < 0) return 0; for (s = *bpp, colon = -1; *s; ++s) if (*s == ':' && colon < 0) colon = s - *bpp; o_len = s - *bpp; licolen = 11; for (t = li; (t /= 10) > 0; ++licolen); for (t = co; (t /= 10) > 0; ++licolen); licobuf = xmalloc(licolen + 1); sprintf(licobuf, ":li#%d:co#%d:", li, co); if (howalloc == 0) { bcopy(*bpp + colon, *bpp + colon + licolen, o_len - colon + 1); bcopy(licobuf, *bpp + colon, licolen); } else if (howalloc == 1) { char *newbp; newbp = xmalloc(o_len + licolen + 1); bcopy(*bpp, newbp, colon); bcopy(licobuf, newbp + colon, licolen); strcpy(newbp + colon + licolen, *bpp + colon); *bpp = newbp; } else /* (howalloc == 2) */ { char *newbp; newbp = xrealloc(*bpp, o_len + licolen + 1); bcopy(newbp + colon, newbp + colon + licolen, o_len - colon + 1); bcopy(licobuf, newbp + colon, licolen); *bpp = newbp; } free(licobuf); return 1; } #endif /* ADJUST_WIN_EXTENT */ #ifdef VMS #include #include #include static int valid_filename_p (fn) char *fn; { struct FAB fab = cc$rms_fab; struct NAM nam = cc$rms_nam; char esa[NAM$C_MAXRSS]; fab.fab$l_fna = fn; fab.fab$b_fns = strlen(fn); fab.fab$l_nam = &nam; fab.fab$l_fop = FAB$M_NAM; nam.nam$l_esa = esa; nam.nam$b_ess = sizeof esa; return SYS$PARSE(&fab, 0, 0) == RMS$_NORMAL; } #else /* !VMS */ #define valid_filename_p(fn) (*(fn) == '/') #endif /* !VMS */ /* Find the termcap entry data for terminal type NAME and store it in the block that BP points to. Record its address for future use. If BP is null, space is dynamically allocated. Return -1 if there is some difficulty accessing the data base of terminal types, 0 if the data base is accessible but the type NAME is not defined in it, and some other value otherwise. */ int tgetent (bp, name) char *bp, *name; { register char *termcap_name; register int fd; struct buffer buf; register char *bp1; char *bp2; char *term; int malloc_size = 0; register int c; char *tcenv; /* TERMCAP value, if it contains :tc=. */ char *indirect = NULL; /* Terminal type in :tc= in TERMCAP value. */ int filep; #ifdef ADJUST_WIN_EXTENT int li, co; /* #lines and columns on this tty */ if (get_win_extent(&li, &co) != 0) li = co = -1; #endif /* ADJUST_WIN_EXTENT */ termcap_name = getenv ("TERMCAP"); if (termcap_name && *termcap_name == '\0') termcap_name = NULL; filep = termcap_name && valid_filename_p (termcap_name); /* If termcap_name is non-null and starts with / (in the un*x case, that is), it is a file name to use instead of /etc/termcap. If it is non-null and does not start with /, it is the entry itself, but only if the name the caller requested matches the TERM variable. */ if (termcap_name && !filep && !strcmp (name, getenv ("TERM"))) { indirect = tgetst1 (find_capability (termcap_name, "tc"), (char **) 0); if (!indirect) { if (!bp) { bp = termcap_name; #ifdef ADJUST_WIN_EXTENT if (adjust_win_extent(&bp, 1, li, co)) malloc_size = 1; /* force return of bp */ #endif /* ADJUST_WIN_EXTENT */ } else { strcpy (bp, termcap_name); #ifdef ADJUST_WIN_EXTENT adjust_win_extent(&bp, 0, li, co); #endif /* ADJUST_WIN_EXTENT */ } goto ret; } else { /* It has tc=. Need to read /etc/termcap. */ tcenv = termcap_name; termcap_name = NULL; } } if (!termcap_name || !filep) #ifdef VMS termcap_name = "emacs_library:[etc]termcap.dat"; #else termcap_name = "/etc/termcap"; #endif /* Here we know we must search a file and termcap_name has its name. */ fd = open (termcap_name, 0, 0); if (fd < 0) return -1; buf.size = BUFSIZE; /* Add 1 to size to ensure room for terminating null. */ buf.beg = (char *) xmalloc (buf.size + 1); term = indirect ? indirect : name; if (!bp) { malloc_size = indirect ? strlen (tcenv) + 1 : buf.size; bp = (char *) xmalloc (malloc_size); } bp1 = bp; if (indirect) /* Copy the data from the environment variable. */ { strcpy (bp, tcenv); bp1 += strlen (tcenv); } while (term) { /* Scan the file, reading it via buf, till find start of main entry. */ if (scan_file (term, fd, &buf) == 0) { close (fd); free (buf.beg); if (malloc_size) free (bp); return 0; } /* Free old `term' if appropriate. */ if (term != name) free (term); /* If BP is malloc'd by us, make sure it is big enough. */ if (malloc_size) { malloc_size = bp1 - bp + buf.size; termcap_name = (char *) xrealloc (bp, malloc_size); bp1 += termcap_name - bp; bp = termcap_name; } bp2 = bp1; /* Copy the line of the entry from buf into bp. */ termcap_name = buf.ptr; while ((*bp1++ = c = *termcap_name++) && c != '\n') /* Drop out any \ newline sequence. */ if (c == '\\' && *termcap_name == '\n') { bp1--; termcap_name++; } *bp1 = '\0'; /* Does this entry refer to another terminal type's entry? If something is found, copy it into heap and null-terminate it. */ term = tgetst1 (find_capability (bp2, "tc"), (char **) 0); } close (fd); free (buf.beg); if (malloc_size) bp = (char *) xrealloc (bp, bp1 - bp + 1); #ifdef ADJUST_WIN_EXTENT adjust_win_extent(&bp, malloc_size ? 2 : 0, li, co); #endif /* ADJUST_WIN_EXTENT */ ret: term_entry = bp; if (malloc_size) return (int) bp; return 1; } /* Given file open on FD and buffer BUFP, scan the file from the beginning until a line is found that starts the entry for terminal type STR. Return 1 if successful, with that line in BUFP, or 0 if no entry is found in the file. */ static int scan_file (str, fd, bufp) char *str; int fd; register struct buffer *bufp; { register char *end; bufp->ptr = bufp->beg; bufp->full = 0; bufp->ateof = 0; *bufp->ptr = '\0'; lseek (fd, 0L, 0); while (!bufp->ateof) { /* Read a line into the buffer. */ end = NULL; do { /* if it is continued, append another line to it, until a non-continued line ends. */ end = gobble_line (fd, bufp, end); } while (!bufp->ateof && end[-2] == '\\'); if (*bufp->ptr != '#' && name_match (bufp->ptr, str)) return 1; /* Discard the line just processed. */ bufp->ptr = end; } return 0; } /* Return nonzero if NAME is one of the names specified by termcap entry LINE. */ static int name_match (line, name) char *line, *name; { register char *tem; if (!compare_contin (line, name)) return 1; /* This line starts an entry. Is it the right one? */ for (tem = line; *tem && *tem != '\n' && *tem != ':'; tem++) if (*tem == '|' && !compare_contin (tem + 1, name)) return 1; return 0; } static int compare_contin (str1, str2) register char *str1, *str2; { register int c1, c2; while (1) { c1 = *str1++; c2 = *str2++; while (c1 == '\\' && *str1 == '\n') { str1++; while ((c1 = *str1++) == ' ' || c1 == '\t'); } if (c2 == '\0') { /* End of type being looked up. */ if (c1 == '|' || c1 == ':') /* If end of name in data base, we win. */ return 0; else return 1; } else if (c1 != c2) return 1; } } /* Make sure that the buffer <- BUFP contains a full line of the file open on FD, starting at the place BUFP->ptr points to. Can read more of the file, discard stuff before BUFP->ptr, or make the buffer bigger. Return the pointer to after the newline ending the line, or to the end of the file, if there is no newline to end it. Can also merge on continuation lines. If APPEND_END is non-null, it points past the newline of a line that is continued; we add another line onto it and regard the whole thing as one line. The caller decides when a line is continued. */ static char * gobble_line (fd, bufp, append_end) int fd; register struct buffer *bufp; char *append_end; { register char *end; register int nread; register char *buf = bufp->beg; register char *tem; if (!append_end) append_end = bufp->ptr; while (1) { end = append_end; while (*end && *end != '\n') end++; if (*end) break; if (bufp->ateof) return buf + bufp->full; if (bufp->ptr == buf) { if (bufp->full == bufp->size) { bufp->size *= 2; /* Add 1 to size to ensure room for terminating null. */ tem = (char *) xrealloc (buf, bufp->size + 1); bufp->ptr = (bufp->ptr - buf) + tem; append_end = (append_end - buf) + tem; bufp->beg = buf = tem; } } else { append_end -= bufp->ptr - buf; bcopy (bufp->ptr, buf, bufp->full -= bufp->ptr - buf); bufp->ptr = buf; } if (!(nread = read (fd, buf + bufp->full, bufp->size - bufp->full))) bufp->ateof = 1; bufp->full += nread; buf[bufp->full] = '\0'; } return end + 1; } #ifdef TEST #ifdef NULL #undef NULL #endif #include main (argc, argv) int argc; char **argv; { char *term; char *buf; term = argv[1]; printf ("TERM: %s\n", term); buf = (char *) tgetent (0, term); if ((int) buf <= 0) { printf ("No entry.\n"); return 0; } printf ("Entry: %s\n", buf); tprint ("cm"); tprint ("AL"); printf ("co: %d\n", tgetnum ("co")); printf ("am: %d\n", tgetflag ("am")); } tprint (cap) char *cap; { char *x = tgetstr (cap, 0); register char *y; printf ("%s: ", cap); if (x) { for (y = x; *y; y++) if (*y <= ' ' || *y == 0177) printf ("\\%0o", *y); else putchar (*y); free (x); } else printf ("none"); putchar ('\n'); } #endif /* TEST */ dev86-0.16.21/libc/gtermcap/tparam.c000066400000000000000000000170241231050321700167560ustar00rootroot00000000000000/* Merge parameters into a termcap entry string. Copyright (C) 1985, 1987, 1993 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ /* Emacs config.h may rename various library functions such as malloc. */ #ifdef HAVE_CONFIG_H #include "config.h" #else /* not HAVE_CONFIG_H */ #ifdef __linux__ #undef STDC_HEADERS #define STDC_HEADERS #define HAVE_UNISTD_H #if defined(HAVE_STRING_H) || defined(STDC_HEADERS) #define bcopy(s, d, n) memcpy ((d), (s), (n)) #endif #endif #ifdef STDC_HEADERS #include #include #else char *malloc (); char *realloc (); #endif #endif /* not HAVE_CONFIG_H */ #ifndef NULL #define NULL (char *) 0 #endif #ifndef emacs static void memory_out () { write (2, "virtual memory exhausted\n", 25); exit (1); } static char * xmalloc (size) unsigned size; { register char *tem = malloc (size); if (!tem) memory_out (); return tem; } static char * xrealloc (ptr, size) char *ptr; unsigned size; { register char *tem = realloc (ptr, size); if (!tem) memory_out (); return tem; } #endif /* not emacs */ /* Assuming STRING is the value of a termcap string entry containing `%' constructs to expand parameters, merge in parameter values and store result in block OUTSTRING points to. LEN is the length of OUTSTRING. If more space is needed, a block is allocated with `malloc'. The value returned is the address of the resulting string. This may be OUTSTRING or may be the address of a block got with `malloc'. In the latter case, the caller must free the block. The fourth and following args to tparam serve as the parameter values. */ static char *tparam1 (); /* VARARGS 2 */ char * tparam (string, outstring, len, arg0, arg1, arg2, arg3) char *string; char *outstring; int len; int arg0, arg1, arg2, arg3; { #ifdef NO_ARG_ARRAY int arg[4]; arg[0] = arg0; arg[1] = arg1; arg[2] = arg2; arg[3] = arg3; return tparam1 (string, outstring, len, NULL, NULL, arg); #else return tparam1 (string, outstring, len, NULL, NULL, &arg0); #endif } char *BC; char *UP; static char tgoto_buf[50]; char * tgoto (cm, hpos, vpos) char *cm; int hpos, vpos; { int args[2]; if (!cm) return NULL; args[0] = vpos; args[1] = hpos; return tparam1 (cm, tgoto_buf, 50, UP, BC, args); } static char * tparam1 (string, outstring, len, up, left, argp) char *string; char *outstring; int len; char *up, *left; register int *argp; { register int c; register char *p = string; register char *op = outstring; char *outend; int outlen = 0; register int tem; int *old_argp = argp; int doleft = 0; int doup = 0; outend = outstring + len; while (1) { /* If the buffer might be too short, make it bigger. */ if (op + 5 >= outend) { register char *new; if (outlen == 0) { outlen = len + 40; new = (char *) xmalloc (outlen); outend += 40; bcopy (outstring, new, op - outstring); } else { outend += outlen; outlen *= 2; new = (char *) xrealloc (outstring, outlen); } op += new - outstring; outend += new - outstring; outstring = new; } c = *p++; if (!c) break; if (c == '%') { c = *p++; tem = *argp; switch (c) { case 'd': /* %d means output in decimal. */ if (tem < 10) goto onedigit; if (tem < 100) goto twodigit; case '3': /* %3 means output in decimal, 3 digits. */ if (tem > 999) { *op++ = tem / 1000 + '0'; tem %= 1000; } *op++ = tem / 100 + '0'; case '2': /* %2 means output in decimal, 2 digits. */ twodigit: tem %= 100; *op++ = tem / 10 + '0'; onedigit: *op++ = tem % 10 + '0'; argp++; break; case 'C': /* For c-100: print quotient of value by 96, if nonzero, then do like %+. */ if (tem >= 96) { *op++ = tem / 96; tem %= 96; } case '+': /* %+x means add character code of char x. */ tem += *p++; case '.': /* %. means output as character. */ if (left) { /* If want to forbid output of 0 and \n and \t, and this is one of them, increment it. */ while (tem == 0 || tem == '\n' || tem == '\t') { tem++; if (argp == old_argp) doup++, outend -= strlen (up); else doleft++, outend -= strlen (left); } } *op++ = tem ? tem : 0200; case 'f': /* %f means discard next arg. */ argp++; break; case 'b': /* %b means back up one arg (and re-use it). */ argp--; break; case 'r': /* %r means interchange following two args. */ argp[0] = argp[1]; argp[1] = tem; old_argp++; break; case '>': /* %>xy means if arg is > char code of x, */ if (argp[0] > *p++) /* then add char code of y to the arg, */ argp[0] += *p; /* and in any case don't output. */ p++; /* Leave the arg to be output later. */ break; case 'a': /* %a means arithmetic. */ /* Next character says what operation. Add or subtract either a constant or some other arg. */ /* First following character is + to add or - to subtract or = to assign. */ /* Next following char is 'p' and an arg spec (0100 plus position of that arg relative to this one) or 'c' and a constant stored in a character. */ tem = p[2] & 0177; if (p[1] == 'p') tem = argp[tem - 0100]; if (p[0] == '-') argp[0] -= tem; else if (p[0] == '+') argp[0] += tem; else if (p[0] == '*') argp[0] *= tem; else if (p[0] == '/') argp[0] /= tem; else argp[0] = tem; p += 3; break; case 'i': /* %i means add one to arg, */ argp[0] ++; /* and leave it to be output later. */ argp[1] ++; /* Increment the following arg, too! */ break; case '%': /* %% means output %; no arg. */ goto ordinary; case 'n': /* %n means xor each of next two args with 140. */ argp[0] ^= 0140; argp[1] ^= 0140; break; case 'm': /* %m means xor each of next two args with 177. */ argp[0] ^= 0177; argp[1] ^= 0177; break; case 'B': /* %B means express arg as BCD char code. */ argp[0] += 6 * (tem / 10); break; case 'D': /* %D means weird Delta Data transformation. */ argp[0] -= 2 * (tem % 16); break; } } else /* Ordinary character in the argument string. */ ordinary: *op++ = c; } *op = 0; while (doup-- > 0) strcat (op, up); while (doleft-- > 0) strcat (op, left); return outstring; } #ifdef DEBUG main (argc, argv) int argc; char **argv; { char buf[50]; int args[3]; args[0] = atoi (argv[2]); args[1] = atoi (argv[3]); args[2] = atoi (argv[4]); tparam1 (argv[1], buf, "LEFT", "UP", args); printf ("%s\n", buf); return 0; } #endif /* DEBUG */ dev86-0.16.21/libc/gtermcap/version.c000066400000000000000000000002041231050321700171470ustar00rootroot00000000000000/* Make the library identifiable with the RCS ident command. */ static char *version_string = "\n$Version: GNU termcap 1.2.2 $\n"; dev86-0.16.21/libc/i386fp/000077500000000000000000000000001231050321700145375ustar00rootroot00000000000000dev86-0.16.21/libc/i386fp/Config000066400000000000000000000000361231050321700156660ustar00rootroot00000000000000386fp: Bcc 386 floating point dev86-0.16.21/libc/i386fp/Makefile000066400000000000000000000014721231050321700162030ustar00rootroot00000000000000# Makefile for bcc 386 software floating point library .SUFFIXES: .x # .x files are .s files that need C-preprocessing .x.o: $(CC) $(CFLAGS) -c $< -o $@ FPDIST =Makefile $(FPSRC) test.c bccfp.tex FPSRC =fadd.x fcomp.x fdiv.x fmul.x fbsr.x \ fperr.c fperror.x fptoi.x fpushd.x fpulld.x \ fpushi.x fpushf.x fpullf.x frexp.x ftst.x \ gcclib.x \ fabs.x ldexp.x ecvt.c \ fperr.h fplib.h FPOBJ =fadd.o fcomp.o fdiv.o fmul.o fpbsr.o \ fperr.o fperror.o fptoi.o fpushd.o fpulld.o \ fpushi.o fpushf.o fpullf.o frexp.o ftst.o \ fabs.o ldexp.o ecvt.o LIB =. CFLAGS=$(ARCH) $(CCFLAGS) $(DEFS) ifeq ($(LIB_CPU),i386) all: $(LIBC)($(FPOBJ)) rm -f $(FPOBJ) else all: @: endif $(LIBC)($(FPOBJ)): fplib.h $(LIBC)(fperr.o fperror.o): fperr.h clean: rm -f $(FPOBJ) test rm -f $(LIB)/libfp.a bccfp.tar.Z bccfp.uue dev86-0.16.21/libc/i386fp/bccfp.tex000066400000000000000000000000001231050321700163240ustar00rootroot00000000000000dev86-0.16.21/libc/i386fp/changes000066400000000000000000000020001231050321700160620ustar00rootroot00000000000000fcomp: Fixes for negative 0 (perhaps this shouldn't be generated, like denormals and infinities (these would cause even more trouble) but Fsub routine or something generated one). frexp.x: Deleted 3rd arg (used to return value when bcc wasn't doing it right). Fixed frexp(value = 0) and ldexp(value = 0) returning nonzero. Most files: Changed comment symbol to '!' for new assembler (not the native ';' in case this is ported to ACK someday). Avoided using ebp and unnecessary register saves. Changed assembler style to make it a bit more portable or like I do it (no '$' for hex, 8[esp] instead of [esp+8], use only .define and not export or .globl, use '#' (could use nothing) instead of '*' for immediate). The partly-supported 8(ebp) and .globl would be still more portable. Changed terminology 'mantissa' to 'fraction'. Round to even. Required for 'paranioa' not to find any defects. Used preprocessor. Parametrized most of the magic numbers. Phew! Supported denormals. Now 'paranioa' doesn't find any flaws. dev86-0.16.21/libc/i386fp/ecvt.c000066400000000000000000000054671231050321700156600ustar00rootroot00000000000000 #define DIGMAX 30 /* max # of digits in string */ #define DIGPREC 17 /* max # of significant digits */ #define ECVT 0 #define FCVT 1 static char digstr[DIGMAX + 1 + 1]; /* +1 for end of string */ /* +1 in case rounding adds */ /* another digit */ static double negtab[] = { 1e-256, 1e-128, 1e-64, 1e-32, 1e-16, 1e-8, 1e-4, 1e-2, 1e-1, 1.0 }; static double postab[] = { 1e+256, 1e+128, 1e+64, 1e+32, 1e+16, 1e+8, 1e+4, 1e+2, 1e+1 }; static char *_cvt(); /************************* * Convert double val to a string of * decimal digits. * ndig = # of digits in resulting string * Returns: * *pdecpt = position of decimal point from left of first digit * *psign = nonzero if value was negative */ char * ecvt(val, ndig, pdecpt, psign) double val; int ndig, *pdecpt, *psign; { return _cvt(ECVT, val, ndig, pdecpt, psign); } char * fcvt(val, nfrac, pdecpt, psign) double val; int nfrac, *pdecpt, *psign; { return _cvt(FCVT, val, nfrac, pdecpt, psign); } static char * _cvt(cnvflag, val, ndig, pdecpt, psign) double val; int ndig, *pdecpt, *psign; { int decpt, pow, i; char *p; *psign = (val < 0) ? ((val = -val), 1) : 0; ndig = (ndig < 0) ? 0 : (ndig < DIGMAX) ? ndig : DIGMAX; if (val == 0) { for (p = &digstr[0]; p < &digstr[ndig]; p++) *p = '0'; decpt = 0; } else { /* Adjust things so that 1 <= val < 10 */ /* in these loops if val == MAXDOUBLE) */ decpt = 1; pow = 256; i = 0; while (val < 1) { while (val < negtab[i + 1]) { val /= negtab[i]; decpt -= pow; } pow >>= 1; i++; } pow = 256; i = 0; while (val >= 10) { while (val >= postab[i]) { val /= postab[i]; decpt += pow; } pow >>= 1; i++; } if (cnvflag == FCVT) { ndig += decpt; ndig = (ndig < 0) ? 0 : (ndig < DIGMAX) ? ndig : DIGMAX; } /* Pick off digits 1 by 1 and stuff into digstr[] */ /* Do 1 extra digit for rounding purposes */ for (p = &digstr[0]; p <= &digstr[ndig]; p++) { int n; /* 'twould be silly to have zillions of digits */ /* when only DIGPREC are significant */ if (p >= &digstr[DIGPREC]) *p = '0'; else { n = val; *p = n + '0'; val = (val - n) * 10; /* get next digit */ } } if (*--p >= '5') { /* if we need to round */ while (1) { if (p == &digstr[0]) { /* if at start */ ndig += cnvflag; decpt++; /* shift dec pnt */ digstr[0] = '1'; /* "100000..." */ break; } *p = '0'; --p; if (*p != '9') { (*p)++; break; } } /* while */ } /* if */ } /* else */ *pdecpt = decpt; digstr[ndig] = 0; /* terminate string */ return &digstr[0]; } dev86-0.16.21/libc/i386fp/fabs.x000066400000000000000000000006621231050321700156470ustar00rootroot00000000000000! bcc 386 floating point routines (version 2) -- _fabs ! author: Bruce Evans #include "fplib.h" ! double fabs(double value); ! returns the absolute value of a number ! this works for all NaNs, like the 80*87 fabs, but perhaps we should check ! for exceptions that can happen when an 80*87 register is loaded .globl _fabs .align ALIGNMENT _fabs: mov eax,PC_SIZE+D_LOW[esp] mov edx,PC_SIZE+D_HIGH[esp] and edx,~D_SIGN_MASK ret dev86-0.16.21/libc/i386fp/fadd.x000066400000000000000000000234511231050321700156330ustar00rootroot00000000000000! bcc 386 floating point routines (version 2) ! -- Fadd, Faddd, Faddf, Fsub, Fsubd, Fsubf, normalize2 ! author: Bruce Evans #include "fplib.h" #define FRAME_SIZE (3 * GENREG_SIZE + PC_SIZE) .extern Fpushf .extern fpdenormal .extern fpoverflow .extern fpunderflow .globl Fadd .align ALIGNMENT Fadd: push ebp push edi push esi mov eax,FRAME_SIZE+D_LOW[esp] mov edx,FRAME_SIZE+D_HIGH[esp] mov ebx,FRAME_SIZE+D_SIZE+D_LOW[esp] mov ecx,FRAME_SIZE+D_SIZE+D_HIGH[esp] call addition mov FRAME_SIZE+D_SIZE+D_LOW[esp],eax mov FRAME_SIZE+D_SIZE+D_HIGH[esp],edx pop esi pop edi pop ebp ret #D_SIZE .globl Faddd .align ALIGNMENT Faddd: push ebp push edi push esi mov eax,FRAME_SIZE+D_LOW[esp] mov edx,FRAME_SIZE+D_HIGH[esp] mov ecx,D_HIGH[ebx] mov ebx,D_LOW[ebx] call addition mov FRAME_SIZE+D_LOW[esp],eax mov FRAME_SIZE+D_HIGH[esp],edx pop esi pop edi pop ebp ret .globl Faddf .align ALIGNMENT Faddf: push ebp push edi push esi call Fpushf pop ebx ! yl pop ecx ! yu mov eax,FRAME_SIZE+D_LOW[esp] ! xl mov edx,FRAME_SIZE+D_HIGH[esp] ! xu call addition mov FRAME_SIZE+D_LOW[esp],eax mov FRAME_SIZE+D_HIGH[esp],edx pop esi pop edi pop ebp ret .globl Fsub .align ALIGNMENT Fsub: push ebp push edi push esi mov eax,FRAME_SIZE+D_LOW[esp] mov edx,FRAME_SIZE+D_HIGH[esp] mov ebx,FRAME_SIZE+D_SIZE+D_LOW[esp] mov ecx,FRAME_SIZE+D_SIZE+D_HIGH[esp] xor ecx,#D_SIGN_MASK ! complement sign call addition mov FRAME_SIZE+D_SIZE+D_LOW[esp],eax mov FRAME_SIZE+D_SIZE+D_HIGH[esp],edx pop esi pop edi pop ebp ret #D_SIZE .globl Fsubd .align ALIGNMENT Fsubd: push ebp push edi push esi mov eax,FRAME_SIZE+D_LOW[esp] mov edx,FRAME_SIZE+D_HIGH[esp] mov ecx,D_HIGH[ebx] mov ebx,D_LOW[ebx] xor ecx,#D_SIGN_MASK ! complement sign call addition mov FRAME_SIZE+D_LOW[esp],eax mov FRAME_SIZE+D_HIGH[esp],edx pop esi pop edi pop ebp ret .globl Fsubf .align ALIGNMENT Fsubf: push ebp push edi push esi call Fpushf pop ebx ! yl pop ecx ! yu mov eax,FRAME_SIZE+D_LOW[esp] ! xl mov edx,FRAME_SIZE+D_HIGH[esp] ! xu xor ecx,#D_SIGN_MASK ! complement sign call addition mov FRAME_SIZE+D_LOW[esp],eax mov FRAME_SIZE+D_HIGH[esp],edx pop esi pop edi pop ebp ret .align ALIGNMENT exp_y_0: ! Check for x denormal, to split off special case where both are denormal, ! so the norm bit (or 1 higher) is known to be set for addition, so addition ! can be done faster test esi,#D_EXP_MASK jnz x_normal_exp_y_0 test esi,esi ! test top bits of x fraction jnz both_denorm ! denormal iff nonzero fraction with zero exp test eax,eax ! test rest of fraction jz return_edx_eax ! everything 0 (XXX - do signs matter?) both_denorm: call fpdenormal test ebp,#D_SIGN_MASK jnz denorm_subtract ! Add denormal x to denormal or zero y #if D_NORM_BIT != D_EXP_SHIFT #include "error, carry into norm bit does not go into exponent" #endif add eax,ebx adc esi,edi or edx,esi ret denorm_subtract: sub eax,ebx sbb esi,edi or edx,esi ret .align ALIGNMENT x_normal_exp_y_0: test edi,edi ! this is like the check for x denormal jnz y_denorm test ebx,ebx jz return_edx_eax ! y = 0 y_denorm: call fpdenormal or ecx,#1 << D_EXP_SHIFT ! normalize y by setting exponent to 1 jmp got_y .align ALIGNMENT return_edx_eax: ret .align ALIGNMENT add_bigshift: cmp ecx,#D_FRAC_BIT+2 jae return_edx_eax ! x dominates y sub ecx,#REG_BIT shrd ebp,ebx,cl shrd ebx,edi,cl shr edi,cl add eax,edi adc esi,#0 xchg ebp,ebx br normalize .align ALIGNMENT addition: mov esi,edx ! this mainly for consistent naming and esi,#D_EXP_MASK | D_FRAC_MASK ! discard sign so comparison is simple mov edi,ecx ! free cl for shifts and edi,#D_EXP_MASK | D_FRAC_MASK cmp esi,edi ja xbigger jb swap cmp eax,ebx jae xbigger swap: xchg edx,ecx xchg eax,ebx xchg esi,edi xbigger: ! edx holds sign of result from here on ! and exponent of result before the normalization step mov ebp,edx ! prepare difference of signs xor ebp,ecx and ecx,#D_EXP_MASK ! extract exp_y and check for y 0 or denormal beq exp_y_0 ! otherwise x is not 0 or denormal either and edi,#D_FRAC_MASK ! extract fraction or edi,#D_NORM_MASK ! normalize got_y: and esi,#D_FRAC_MASK ! extract fraction or esi,#D_NORM_MASK ! normalize sub ecx,edx ! carries from non-exp bits in edx killed later neg ecx and ecx,#D_EXP_MASK shr ecx,#D_EXP_SHIFT ! difference of exponents got_x_and_y: and ebp,#D_SIGN_MASK ! see if signs are same bne subtract ! else roundoff reg ebp has been cleared cmp cl,#REG_BIT bhis add_bigshift shrd ebp,ebx,cl shrd ebx,edi,cl shr edi,cl add eax,ebx adc esi,edi ! result edx(D_SIGN_MASK | D_EXP_MASK bits):esi:eax:ebp but needs normalization mov edi,edx and edi,#D_EXP_MASK test esi,#D_NORM_MASK << 1 jnz add_loverflow add_round: cmp ebp,#1 << (REG_BIT-1) ! test roundoff register jb add_done ! no rounding jz tie add_roundup: add eax,#1 adc esi,#0 test esi,#D_NORM_MASK << 1 jnz pre_add_loverflow ! rounding may cause overflow! add_done: mov ecx,edx ! duplicated code from 'done' and edx,#D_SIGN_MASK or edx,edi and esi,#D_FRAC_MASK or edx,esi ret .align ALIGNMENT tie: test al,#1 ! tie case, round to even jz add_done ! even, no rounding jmp add_roundup .align ALIGNMENT pre_add_loverflow: sub ebp,ebp ! clear rounding register ! probably avoiding tests for more rounding add_loverflow: shrd ebp,eax,#1 jnc over_set_sticky_bit or ebp,#1 over_set_sticky_bit: shrd eax,esi,#1 shr esi,#1 add edi,1 << D_EXP_SHIFT cmp edi,#D_EXP_INFINITE << D_EXP_SHIFT jl add_round overflow: call fpoverflow mov eax,ecx ! XXX - wrong reg ret ! result edx(D_SIGN_MASK | D_EXP_MASK bits): ! esi((D_NORM_MASK << 1) | D_NORM_MASK | D_FRAC_MASK bits):eax:ebp:ebx ! but needs normalization .align ALIGNMENT normalize: mov edi,edx and edi,#D_EXP_MASK test esi,#D_NORM_MASK << 1 bne loverflow ! result edx(D_SIGN_MASK bit):edi(D_EXP_MASK bits): ! esi(D_NORM_MASK | D_FRAC_MASK bits):eax:ebp:ebx ! but needs normalization .globl normalize2 normalize2: test esi,#D_NORM_MASK ! already-normalized is very common jz normalize3 round: cmp ebp,#1 << (REG_BIT-1) ! test roundoff register jb done ! no rounding jz near_tie roundup: add eax,#1 adc esi,#0 test esi,#D_NORM_MASK << 1 bne pre_loverflow ! rounding may cause overflow! done: cmp edi,#D_EXP_INFINITE << D_EXP_SHIFT jae overflow and edx,#D_SIGN_MASK ! extract sign of largest and result or edx,edi ! include exponent with sign and esi,#D_FRAC_MASK ! discard norm bit or edx,esi ! include fraction with sign and exponent ret .align ALIGNMENT near_tie: test ebx,ebx jnz roundup test al,#1 ! tie case, round to even jz done ! even, no rounding jmp roundup .align ALIGNMENT not_in_8_below: shld ecx,esi,#REG_BIT-D_NORM_BIT+16 ! in 9 to 16 below? jz not_in_16_below ! must be way below (17-20 for usual D_NORM_BIT) mov cl,bsr_table[ecx] ! bsr(esi) - (D_NORM_BIT-16) neg ecx ! (D_NORM_BIT-16) - bsr(esi) add ecx,#16 jmp got_shift .align ALIGNMENT not_in_16_below: mov cl,bsr_table[esi] ! bsr(esi) directly neg ecx ! -bsr(esi) add ecx,#D_NORM_BIT ! D_NORM_BIT - bsr(esi) jmp got_shift .align ALIGNMENT normalize3: test esi,esi jz shift32 ! Find first nonzero bit in esi ! Don't use bsr, it is very slow (const + 3 * bit_found) ! We know that there is some nonzero bit, and the norm bit and above are clear sub ecx,ecx ! prepare unsigned extension of cl shld ecx,esi,#REG_BIT-D_NORM_BIT+8 ! any bits in 8 below norm bit? jz not_in_8_below mov cl,bsr_table[ecx] ! bsr(esi) - (D_NORM_BIT-8) neg ecx ! (D_NORM_BIT-8) - bsr(esi) add ecx,#8 ! D_NORM_BIT - bsr(esi) got_shift: shld esi,eax,cl shld eax,ebp,cl shld ebp,ebx,cl shl ebx,cl shl ecx,D_EXP_SHIFT sub edi,ecx bhi round ! XXX - can rounding change the exponent to > 0? ! not bgt since edi may be 0x80000000 neg edi shr edi,#D_EXP_SHIFT inc edi br fpunderflow .align ALIGNMENT pre_loverflow: sub ebp,ebp ! clear rounding registers sub ebx,ebx ! probably avoiding tests for more rounding loverflow: shr esi,#1 ! carry bit stayed in the reg rcr eax,#1 rcr ebp,#1 rcr ebx,#1 add edi,1 << D_EXP_SHIFT cmp edi,#D_EXP_INFINITE << D_EXP_SHIFT blt round call fpoverflow mov eax,ecx ! XXX - wrong reg ret .align ALIGNMENT shift32: test eax,eax jz shift64 mov esi,eax mov eax,ebp mov ebp,ebx sub ebx,ebx sub edi,#REG_BIT << D_EXP_SHIFT shiftxx: test esi,#~(D_NORM_MASK | D_FRAC_MASK) jz over_adjust ! else too big already shrd ebx,ebp,#D_BIT-D_FRAC_BIT shrd ebp,eax,#D_BIT-D_FRAC_BIT shrd eax,esi,#D_BIT-D_FRAC_BIT shr esi,#D_BIT-D_FRAC_BIT add edi,#(D_BIT-D_FRAC_BIT) << D_EXP_SHIFT over_adjust: test edi,edi bgt normalize2 neg edi shr edi,#D_EXP_SHIFT inc edi br fpunderflow .align ALIGNMENT shift64: test ebp,ebp jz shift96 mov esi,ebp mov eax,ebx sub ebp,ebp mov ebx,ebp sub edi,#(2*REG_BIT) << D_EXP_SHIFT jmp shiftxx .align ALIGNMENT shift96: test ebx,ebx ! XXX - this test is probably unnecessary ! since the shift must be small unless we ! are subtracting 2 almost-equal numbers, ! and then the bits beyond 64 will mostly ! be 0 jz return_esi_eax ! all zero mov esi,ebx sub ebx,ebx sub edi,#(3*REG_BIT) << D_EXP_SHIFT jmp shiftxx .align ALIGNMENT return_esi_eax: mov edx,esi ret .align ALIGNMENT subtract: sub ebp,ebp ! set up roundoff register cmp ecx,#REG_BIT jae subtract_bigshift shrd ebp,ebx,cl shrd ebx,edi,cl shr edi,cl neg ebp ! begin subtraction esi:eax:0 - edi:ebx:ebp sbb eax,ebx sbb esi,edi sub ebx,ebx mov edi,edx and edi,#D_EXP_MASK br normalize2 .align ALIGNMENT subtract_bigshift: cmp ecx,#D_FRAC_BIT+2 bhis return_edx_eax ! x dominates y sub ecx,#REG_BIT shrd ebp,ebx,cl shrd ebx,edi,cl shr edi,cl not ebp ! begin subtraction esi:eax:0:0 - 0:edi:ebx:ebp not ebx add ebp,#1 adc ebx,#0 cmc sbb eax,edi sbb esi,#0 xchg ebp,ebx mov edi,edx and edi,#D_EXP_MASK br normalize2 .data .extern bsr_table dev86-0.16.21/libc/i386fp/fcomp.x000066400000000000000000000045301231050321700160360ustar00rootroot00000000000000! bcc 386 floating point routines (version 2) -- Fcomp, Fcompd, Fcompf ! authors: Timothy Murphy (tim@maths.tcd.ie), Bruce Evans #include "fplib.h" .extern Fpushf ! Pop 2 doubles from stack and compare them, return result in flags so ! normal signed branches work (unlike 80x87 which returns the result in ! the zero and carry flags). .globl Fcomp .align ALIGNMENT Fcomp: pop ecx ! get return address pop eax ! xl pop edx ! xu push ecx ! put back ret address - pop 2nd double later ! All this popping is bad on 486's since plain mov takes 1+ cycle and pop ! takes 4 cycles. But this code is designed for 386's where popping is ! nominally the same speed and saves code space and so maybe instruction ! fetch time as well as the instruction to adjust the stack (ret #n takes ! no longer than plain ret but inhibits gotos). mov ebx,PC_SIZE+D_LOW[esp] ! yl mov ecx,PC_SIZE+D_HIGH[esp] ! yu jmp compare ! Pop double from stack and compare with double at [ebx] .globl Fcompd .align ALIGNMENT Fcompd: mov eax,PC_SIZE+D_LOW[esp] ! xl mov edx,PC_SIZE+D_HIGH[esp] ! xu mov ecx,D_HIGH[ebx] ! yu mov ebx,D_LOW[ebx] ! yl compare: test edx,#D_SIGN_MASK ! is x >= 0? jz cmp0 ! yes; just compare x and y test ecx,#D_SIGN_MASK ! no; but is y >= 0? jz cmp0 ! yes; just compare x and y xchg edx,ecx ! x, y < 0, so ... xchg eax,ebx ! ... swap x and y ... xor edx,#D_SIGN_MASK ! ... and toggle signs xor ecx,#D_SIGN_MASK cmp0: cmp edx,ecx ! compare upper dwords jnz checkneg0 ! if upper dwords differ, job is almost done mov edx,eax ! upper dwords equal, so ... mov ecx,ebx ! ... must make unsigned comparison of lower dwords shr edx,#1 ! shift past sign shr ecx,#1 cmp edx,ecx ! compare top 31 bits of lower dwords jnz return ! if these differ, job is done and eax,#1 ! compare lowest bits and ebx,#1 cmp eax,ebx return: ret #D_SIZE ! return, popping 1 double from stack checkneg0: test edx,#D_EXP_MASK | D_FRAC_MASK ! check to catch unusual case ... jnz recheck test eax,eax jnz recheck test ecx,#D_EXP_MASK | D_FRAC_MASK jnz recheck test ebx,ebx jz return ! ... both are (+-) zero, return 'z' recheck: cmp edx,ecx ! the upper words were really different ret #D_SIZE .globl Fcompf .align ALIGNMENT Fcompf: call Fpushf pop ebx ! yl pop ecx ! yu mov eax,PC_SIZE+D_LOW[esp] ! xl mov edx,PC_SIZE+D_HIGH[esp] ! xu jmp compare dev86-0.16.21/libc/i386fp/fdiv.x000066400000000000000000000200361231050321700156610ustar00rootroot00000000000000#define EF_SIZE 4 ! bcc 386 floating point routines (version 2) -- Fdiv, Fdivd, Fdivf ! authors: Timothy Murphy (tim@maths.tcd.ie), Bruce Evans #include "fplib.h" #define FRAME_SIZE (3 * GENREG_SIZE + PC_SIZE) .extern Fpushf .extern fpdivzero .extern fpoverflow .extern fpunderflow ! double Fdiv(double x, double y) returns x / y ! pop 2 doubles from stack, divide first by second, and push quotient on stack ! we denote upper and lower dwords of x and y (or their fractions) ! by (xu,xl), (yu,yl) .globl Fdivf .align ALIGNMENT Fdivf: sub esp,#D_SIZE ! make space for dummy double on stack push ebp push edi ! save some regs push esi mov eax,FRAME_SIZE-PC_SIZE+D_SIZE[esp] ! move return address ... mov FRAME_SIZE-PC_SIZE[esp],eax ! ... to usual spot call Fpushf pop esi ! yl pop edi ! yu mov eax,FRAME_SIZE+D_SIZE+D_LOW[esp] ! xl mov edx,FRAME_SIZE+D_SIZE+D_HIGH[esp] ! xu jmp division .globl Fdiv .align ALIGNMENT Fdiv: push ebp push edi ! save some regs push esi mov eax,FRAME_SIZE+D_LOW[esp] ! xl mov edx,FRAME_SIZE+D_HIGH[esp] ! xu mov esi,FRAME_SIZE+D_SIZE+D_LOW[esp] ! yl mov edi,FRAME_SIZE+D_SIZE+D_HIGH[esp] ! yu jmp division .align ALIGNMENT exp_y_0: mov ebx,edi or ebx,esi beq zerodivide mov ebx,#1 fix_y: test edi,edi ! XXX - sloow js y_unpacked shld edi,esi,#1 shl esi,#1 dec bx jmp fix_y .align ALIGNMENT exp_x_0: mov ecx,edx or ecx,eax beq retz mov ecx,#1 ! change exponent from 0 to 1 fix_x: test edx,#1 << (REG_BIT-1-2) ! XXX - sloow jnz x_unpacked shld edx,eax,#1 shl eax,#1 dec cx jmp fix_x ! Fdivd pops double from stack, divides it by double at [ebx], ! and pushes quotient back on stack .globl Fdivd .align ALIGNMENT Fdivd: sub esp,#D_SIZE ! make space for dummy double on stack push ebp push edi ! save some regs push esi mov eax,FRAME_SIZE-PC_SIZE+D_SIZE[esp] ! move return address ... mov FRAME_SIZE-PC_SIZE[esp],eax ! ... to usual spot mov eax,FRAME_SIZE+D_SIZE+D_LOW[esp] ! xl mov edx,FRAME_SIZE+D_SIZE+D_HIGH[esp] ! xu mov esi,D_LOW[ebx] ! yl mov edi,D_HIGH[ebx] ! yu division: ! The full calculations are ! (xu,xl,0) = yu * (zu,zl) + (0,r,0) (normal 96/32 -> 64 bit division) ! yl * zu = yu * q1 + r1 (32*32 -> 64 bit mul and 64/32 -> 32 bit div) ! so ! (xu,xl,0,0) = (yu,yl) * (zu,zl-q1) + (0,0,r-r1,yl*(q1-zl)) ! where the calculations zl-q1, r-r1 and yl*(q1-zl) are more complicated ! than the notation suggests. They may be negative and the one with the ! multiplication may not fit in 32 bits and in both cases the overflow ! has to be moved into higher bit positions. ! See Knuth for why (zu,zl-q1) is the correct 64-bit quotient to within ! 1 bit either way (assuming the normalization x < 2 * y). ! We only need to calculate the remainder (0,0,r-r1,yl*(q1-zl)) to resolve ! tie cases. It tells whether the approximate quotient is too high or too ! low. #define NTEMPS 5 sub esp,#NTEMPS*GENREG_SIZE ! space to remember values for rounding of tie case ! Offsets from esp for these values (offsets using FRAME_SIZE are invalid ! while these temps are active) r = 0 q1 = 4 r1 = 8 yl = 12 zl = 16 ! Step 1: unpack and normalize x to fraction in edx:eax (left shifted as ! far as possible less 2 so that x < y, and later z < y); unpack and normalize ! y to a fraction in edi:esi (left shifted as far as possible), put difference ! of signs (= sign of quotient) in ecx(D_SIGN_MASK) and difference of exponents ! (= exponent of quotient before normalization) in cx. mov ebp,edx ! xu xor ebp,edi ! xu ^ yu and ebp,#D_SIGN_MASK ! sign of result is difference of signs ! Unpack y first to trap 0 / 0 mov ebx,edi ! remember yu for exponent of y shld edi,esi,#D_BIT-D_FRAC_BIT ! extract fraction of y ... shl esi,#D_BIT-D_FRAC_BIT and ebx,#D_EXP_MASK ! exponent of y jz exp_y_0 shr ebx,#D_EXP_SHIFT ! in ebx (actually in bx, with high bits 0) or edi,#D_NORM_MASK << (D_BIT-D_FRAC_BIT) ! normalize y_unpacked: ! Unpack x mov ecx,edx ! remember xu for exponent of x shld edx,eax,#D_BIT-D_FRAC_BIT-2 ! extract fraction of x ... shl eax,#D_BIT-D_FRAC_BIT-2 and edx,#(D_NORM_MASK << (D_BIT-D_FRAC_BIT-2+1))-1 ! XXX - above may be shifted 1 extra unnecessarily and ecx,#D_EXP_MASK ! exponent of x jz exp_x_0 shr ecx,#D_EXP_SHIFT ! in ecx (actually in cx, with high bits 0) or edx,#D_NORM_MASK << (D_BIT-D_FRAC_BIT-2) ! normalize x_unpacked: sub cx,bx ! not ecx,ebx because we want to use high bit for sign add cx,#D_EXP_BIAS ! adjust exponent of quotient or ecx,ebp ! include sign with exponent ! Step 2: quotient of fractions -> (edx,eax) ! 2a: (xu,xl,0) div yu = (zu,zl) -> (ebx,esi) div eax,edi ! (xu,xl) div yu = zu in eax; remainder (rem) in edx mov ebx,eax ! save zu in ebx sub eax,eax ! clear eax: (edx,eax) = (rem,0) div eax,edi ! (rem,0) div yu = zl in eax mov r[esp],edx mov zl[esp],eax xchg eax,esi ! store zl in esi; save yl in eax mov yl[esp],eax ! 2b: (yl * zu) div yu -> (0,eax) mul eax,ebx ! yl * zu -> (edx,eax) div eax,edi ! (yl * zu) div yu in eax mov q1[esp],eax mov r1[esp],edx ! 2c: (xu,xl) / (yu,yl) = (zu,zl) - (yl * zu) div yu -> (edx,eax) mov edx,ebx ! zu xchg eax,esi ! eax <- zl; esi <- (yl * zu) div yu sub eax,esi sbb edx,#0 ! Step 3: normalise quotient test edx,#1 << (REG_BIT-2) ! is fraction too small? (can only be by 1 bit) jnz div4 shld edx,eax,#1 ! yes; multiply fraction ... shl eax,#1 ! ... by 2 ... dec cx ! ... and decrement exponent ! Step 4: shift and round div4: mov ebx,eax ! save for rounding shrd eax,edx,#D_BIT-D_FRAC_BIT-1 ! shift fraction of result ... shr edx,#D_BIT-D_FRAC_BIT-1 ! ... to proper position and ebx,#(1 << (D_BIT-D_FRAC_BIT-1))-1 ! look at bits shifted out cmp ebx,#D_NORM_MASK >> (D_BIT-D_FRAC_BIT) ! compare with middle value jb div5 ! below middle, don't round up ja roundup ! above middle, round up ! The low bits don't contain enough information to resolve the tie case, ! because the quotient itself is only an approximation. ! Calculate the exact remainder. ! This case is not very common, so don't worry much about speed. ! Unfortunately we had to save extra in all cases to prepare for it. push edx push eax sub esi,esi ! the calculation requires 33 bits - carry to here mov eax,2*GENREG_SIZE+q1[esp] sub eax,2*GENREG_SIZE+zl[esp] pushfd mul dword EF_SIZE+2*GENREG_SIZE+yl[esp] popfd jnc foo sub edx,2*GENREG_SIZE+yl[esp] sbb esi,#0 foo: add edx,2*GENREG_SIZE+r[esp] adc esi,#0 sub edx,2*GENREG_SIZE+r1[esp] sbb esi,#0 mov ebx,eax mov edi,edx pop eax pop edx ! Can finally decide rounding of tie case js div5 ! remainder < 0 from looking at top 64 bits jnz roundup ! remainder > 0 from looking at top 64 bits or edi,ebx ! test bottom 64 bits jnz roundup ! remainder > 0 test al,#1 ! at last we know it is the tie case, check parity bit jz div5 ! already even, otherwise round up to make even roundup: add eax,#1 ! add rounding bit adc edx,#0 test edx,#D_NORM_MASK << 1 ! has fraction overflowed (very unlikely) jz div5 ! Why were the shifts commented out? shrd eax,edx,#1 ! yes, divide fraction ... shr edx,#1 ! ... by 2 ... inc cx ! ... and increment exponent ! Step 5: put it all together div5: mov ebx,ecx ! extract sign and ebx,D_SIGN_MASK cmp cx,#D_EXP_INFINITE ! is exponent too big? jge overflow test cx,cx jle underflow shl ecx,#D_EXP_SHIFT and edx,#D_FRAC_MASK ! remove norm bit or edx,ecx ! include exponent ... or edx,ebx ! ... and sign return: add esp,#NTEMPS*GENREG_SIZE ! reclaim temp space mov FRAME_SIZE+D_SIZE+D_LOW[esp],eax ! "push" lower dword of product ... mov FRAME_SIZE+D_SIZE+D_HIGH[esp],edx ! ... and upper dword pop esi ! restore registers pop edi pop ebp ret #D_SIZE retz: sub edx,edx ! clear upper dword sub eax,eax ! ... and lower dword jmp return overflow: mov edx,ecx ! put sign in usual reg call fpoverflow mov eax,ecx ! XXX - wrong reg jmp return underflow: mov esi,edx ! put upper part of fraction in usual reg mov edx,ecx ! sign movsx edi,cx ! put shift in usual reg neg edi inc edi call fpunderflow jmp return zerodivide: mov edx,ebp ! sign call fpdivzero mov eax,ecx ! XXX - wrong reg jmp return dev86-0.16.21/libc/i386fp/fmul.x000066400000000000000000000064141231050321700157000ustar00rootroot00000000000000! bcc 386 floating point routines (version 2) -- Fmul, Fmuld, Fmulf ! author: Bruce Evans #include "fplib.h" #define FRAME_SIZE (3 * GENREG_SIZE + PC_SIZE) .extern Fpushf .extern fpoverflow .extern fpunderflow .extern normalize2 .globl Fmul .align ALIGNMENT Fmul: push ebp push edi push esi mov eax,FRAME_SIZE+D_LOW[esp] mov edx,FRAME_SIZE+D_HIGH[esp] mov ebx,FRAME_SIZE+D_SIZE+D_LOW[esp] mov ecx,FRAME_SIZE+D_SIZE+D_HIGH[esp] call multiplication mov FRAME_SIZE+D_SIZE+D_LOW[esp],eax mov FRAME_SIZE+D_SIZE+D_HIGH[esp],edx pop esi pop edi pop ebp ret #D_SIZE .globl Fmuld .align ALIGNMENT Fmuld: push ebp push edi push esi mov eax,FRAME_SIZE+D_LOW[esp] mov edx,FRAME_SIZE+D_HIGH[esp] mov ecx,D_HIGH[ebx] mov ebx,D_LOW[ebx] call multiplication mov FRAME_SIZE+D_LOW[esp],eax mov FRAME_SIZE+D_HIGH[esp],edx pop esi pop edi pop ebp ret .globl Fmulf .align ALIGNMENT Fmulf: push ebp push edi push esi call Fpushf pop ebx ! yl pop ecx ! xu mov eax,FRAME_SIZE+D_LOW[esp] ! xl mov edx,FRAME_SIZE+D_HIGH[esp] ! xu call multiplication mov FRAME_SIZE+D_LOW[esp],eax mov FRAME_SIZE+D_HIGH[esp],edx pop esi pop edi pop ebp ret .align ALIGNMENT exp_x_0: mov edx,#1 << D_EXP_SHIFT ! change exponent from 0 to 1 jmp x_unpacked ! XXX - check for denormal? .align ALIGNMENT exp_y_0: mov ecx,#1 << D_EXP_SHIFT jmp y_unpacked .align ALIGNMENT multiplication: mov ebp,edx ! xu xor ebp,ecx ! xu ^ yu and ebp,#D_SIGN_MASK ! sign of result is difference of signs mov esi,edx ! free edx for multiplications and esi,#D_FRAC_MASK ! discard sign and exponent and edx,#D_EXP_MASK ! exponent(x) jz exp_x_0 or esi,#D_NORM_MASK ! normalize x_unpacked: mov edi,ecx ! this mainly for consistent naming and edi,#D_FRAC_MASK and ecx,#D_EXP_MASK ! exponent(y) jz exp_y_0 or edi,#D_NORM_MASK y_unpacked: add ecx,edx ! add exponents ! exponent is in ecx, sign in ebp, operands in esi:eax and edi:ebx, edx is free ! product to go in esi:eax:ebp:ebx ! terminology: x * y = (xu,xl) * (yu,yl) ! = (xu * yu,0,0) + (0,xu * yl + xl * yu,0) + (0,0,xl * yl) push ecx push ebp mov ecx,eax mul ebx ! xl * yl mov ebp,edx ! (xl * yl).u in ebp xchg ebx,eax ! (xl * yl).l in ebx (final), yl in eax mul esi ! xu * yl push eax ! (xu * yl).l on stack push edx ! (xu * yl).u on stack mov eax,esi ! xu mul edi ! xu * yu mov esi,edx ! (xu * yu).u in esi (final except carries) xchg ecx,eax ! (xu * yu).l in ecx, xl in eax mul edi ! xl * yu add ebp,eax ! (xl * yl).u + (xl * yu).l pop eax ! (xu * yl).u adc eax,edx ! (xu * yl).u + (xl * yu).u adc esi,#0 pop edx ! (xu * yl).l add ebp,edx ! ((xl * yl).u + (xl * yu).l) + (xu * yl).l adc eax,ecx ! ((xu * yl).u + (xl * yu).u) + (xu * yu).l adc esi,#0 pop edx ! sign pop edi ! exponent sub edi,#(D_EXP_BIAS+1-(D_EXP_BIT+2)) << D_EXP_SHIFT ! adjust ! cmp edi,#(D_EXP_INFINITE-1+(D_EXP_BIT+2)) << D_EXP_SHIFT ! jae outofbounds ! 0 will be caught as underflow by normalize2 cmp edi,#(2*D_EXP_INFINITE-(D_EXP_BIAS+1)+(D_EXP_BIT+2)) << D_EXP_SHIFT ja underflow br normalize2 .align ALIGNMENT overflow: mov edx,ebp ! put sign in usual reg call fpoverflow mov eax,ecx ! XXX - wrong reg ret .align ALIGNMENT underflow: mov edx,ebp ! put sign in usual reg neg edi shr edi,#D_EXP_SHIFT inc edi br fpunderflow dev86-0.16.21/libc/i386fp/fpbsr.x000066400000000000000000000020251231050321700160430ustar00rootroot00000000000000! bcc 386 floating point routines (version 2) -- bsr_table ! author: Bruce Evans #include "fplib.h" .globl bsr_table .data .align ALIGNMENT bsr_table: ! table to replace bsr on range 0-255 .byte -1, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3 .byte 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 .byte 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 .byte 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 .byte 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6 .byte 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6 .byte 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6 .byte 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6 .byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 .byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 .byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 .byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 .byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 .byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 .byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 .byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 dev86-0.16.21/libc/i386fp/fperr.c000066400000000000000000000011521231050321700160200ustar00rootroot00000000000000#include #include #include "fperr.h" void fperr(errno) int errno; { #if defined(DEBUG) || 0 switch(errno) { case EFDENORMAL: fputs("\nDenormal - ", stderr); break; case EFINFINITY: fputs("\nInfinity - ", stderr); break; case EFNAN: fputs("\nNaN - ", stderr); break; case EFOVERFLOW: fputs("\nOverflow - ", stderr); break; case EFUNDERFLOW: fputs("\nUnderflow - ", stderr); break; case EFDIVZERO: fputs("\nZero divide - ", stderr); break; default: fprintf(stderr, "\nUnknown error 0x%x - ", errno); } fflush(stderr); #endif kill(getpid(), SIGFPE); } dev86-0.16.21/libc/i386fp/fperr.h000066400000000000000000000002111231050321700160200ustar00rootroot00000000000000/* fperr.h */ #define EFDENORMAL 1 #define EFINFINITY 2 #define EFNAN 3 #define EFOVERFLOW 4 #define EFUNDERFLOW 5 #define EFDIVZERO 6 dev86-0.16.21/libc/i386fp/fperror.x000066400000000000000000000047201231050321700164120ustar00rootroot00000000000000! bcc 386 floating point routines (version 2) ! --- fpdenormal, fperror, fpinfinity, fpNaN, fpoverflow, fpunderflow,fpdivzero ! author: Bruce Evans #include "fperr.h" #include "fplib.h" .extern _fperr ! Cause a denormal-operand exception ! Preserves all general registers if signal handler returns .globl fpdenormal .align ALIGNMENT fpdenormal: #if 0 push eax mov eax,#EFDENORMAL call fperror pop eax #endif ret ! Cause an exception with error code eax, preserving all genregs except eax .globl fperror .align ALIGNMENT fperror: push ebp ! set up usual frame ... mov ebp,esp ! ... for debugging push edx ! save default push ecx push eax ! error code is arg to C routine call _fperr add esp,#GENREG_SIZE pop ecx ! restore default pop edx pop ebp ret .align ALIGNMENT fphuge: mov ecx,#D_HUGE_LOW ! prepare number +-HUGEVAL or edx,#D_HUGE_HIGH ! ... in case signal handler returns jmp fperror ! Cause an infinite-operand exception ! Return +-HUGEVAL in edx:ecx with sign from edx .globl fpinfinity .align ALIGNMENT fpinfinity: mov eax,#EFINFINITY jmp fphuge ! almost right ! Cause an NaN-operand exception ! Return +-HUGEVAL in edx:ecx with sign from edx .globl fpNaN .align ALIGNMENT fpNaN: mov eax,#EFNAN ! there are different types of NaNs but... jmp fphuge ! WRONG ! Cause an overflow exception ! Return +-HUGEVAL in edx:ecx with sign from edx .globl fpoverflow .align ALIGNMENT fpoverflow: mov eax,#EFOVERFLOW jmp fphuge ! almost right ! Cause an underflow exception (actually assume it is masked for now) ! Return denormal or 0.0 in edx:ecx ! XXX - this should cause a denormal exception or none for the denormal case ! Args: sign in edx, fraction in esi:eax, right shift in edi ! Returns: denormalized number in edx:eax .globl fpunderflow .align ALIGNMENT fpunderflow: #if 0 mov eax,#EFUNDERFLOW jmp fperror #endif cmp edi,#REG_BIT jb denormalize1 mov eax,esi sub esi,esi sub edi,#REG_BIT cmp edi,#REG_BIT jb denormalize1 denormalize_underflow: #if 0 mov eax,#EFUNDERFLOW jmp fperror #endif sub eax,eax mov edx,eax ret .align ALIGNMENT denormalize1: mov ecx,edi shrd eax,esi,cl shr esi,cl mov ecx,esi or ecx,eax jz denormalize_underflow and edx,#D_SIGN_MASK or edx,esi ret ! Cause an fp division by zero exception ! Return +-HUGEVAL in edx:ecx with sign from edx .globl fpdivzero .align ALIGNMENT fpdivzero: mov eax,#EFDIVZERO test edx,#D_EXP_MASK jnz fphuge ! almost right sub ecx,ecx mov edx,ecx jmp fperror dev86-0.16.21/libc/i386fp/fplib.h000066400000000000000000000026071231050321700160110ustar00rootroot00000000000000#define ALIGNMENT 4 #define CHAR_BIT 8 #define D_BIT (D_SIZE * CHAR_BIT) #define D_EXP_BIAS ((1 << (D_EXP_BIT - 1)) - 1) #define D_EXP_BIT 11 #define D_EXP_INFINITE ((1 << D_EXP_BIT) - 1) #define D_EXP_MASK (((1 << D_EXP_BIT) - 1) << D_EXP_SHIFT) #define D_EXP_SHIFT (REG_BIT - (1 + D_EXP_BIT)) #define D_FRAC_BIT 53 #define D_FRAC_MASK (D_NORM_MASK - 1) #define D_HIGH 4 #define D_HUGE_HIGH (D_EXP_MASK - 1) #define D_HUGE_LOW 0xFFFFFFFF #define D_LOW 0 #define D_NORM_BIT (D_FRAC_BIT - 1 - REG_BIT) #define D_NORM_MASK (1 << D_NORM_BIT) #define D_SIGN_BIT 63 #define D_SIGN_MASK (1 << (D_SIGN_BIT - REG_BIT)) #define D_SIZE 8 #define F_BIT (F_SIZE * CHAR_BIT) #define F_EXP_BIAS ((1 << (F_EXP_BIT - 1)) - 1) #define F_EXP_BIT 8 #define F_EXP_INFINITE ((1 << F_EXP_BIT) - 1) #define F_EXP_MASK (((1 << F_EXP_BIT) - 1) << F_EXP_SHIFT) #define F_EXP_SHIFT (REG_BIT - (1 + F_EXP_BIT)) #define F_FRAC_BIT 24 #define F_FRAC_MASK (F_NORM_MASK - 1) #define F_HIGH 0 #define F_HUGE_HIGH (F_EXP_MASK - 1) #define F_NORM_BIT (F_FRAC_BIT - 1) #define F_NORM_MASK (1 << F_NORM_BIT) #define F_SIGN_BIT 31 #define F_SIGN_MASK (1 << F_SIGN_BIT) #define F_SIZE 4 #define FREE_D_SIGN_BIT_TEST (D_SIGN_BIT % REG_BIT == REG_BIT - 1) #define GENREG_SIZE 4 #define INT_BIT 32 #define INT_MAX 0x7FFFFFFF #define INT_MIN (-0x7FFFFFFF - 1) #define PC_SIZE 4 #define REG_BIT 32 #define SHORT_BIT 16 #define UINT_MAX 0xFFFFFFFF dev86-0.16.21/libc/i386fp/fptoi.x000066400000000000000000000044341231050321700160560ustar00rootroot00000000000000! bcc 386 floating point routines (version 2) ! -- dtoi, dtol, dtoui, dtoul, ftoi, ftol (todo: ftoui, ftoul) ! authors: Timothy Murphy (tim@maths.tcd.ie), Bruce Evans #include "fplib.h" .extern fpoverflow .extern Fpushf ! Convert double x at [ebx] to int and return in eax .globl dtoi .globl dtol .align ALIGNMENT dtoi: dtol: mov eax,D_HIGH[ebx] mov ecx,eax and ecx,#D_EXP_MASK ! extract exponent jz retz ! if 0 return 0 test eax,#D_SIGN_MASK jnz negative call into_dtoui cmp eax,#INT_MAX ja overflow_int_max ret .align ALIGNMENT negative: and eax,#~D_SIGN_MASK call into_dtoui cmp eax,#INT_MIN ja overflow_int_min neg eax ret .align ALIGNMENT overflow_int_max: call fpoverflow mov eax,#INT_MAX ret .align ALIGNMENT overflow_int_min: js return ! actually INT_MIN is OK call fpoverflow mov eax,#INT_MIN return: ret .align ALIGNMENT retz: sub eax,eax ! clear return value ret ! Convert double x at [ebx] to unsigned and return in eax .globl dtoui .globl dtoul .align ALIGNMENT dtoui: dtoul: mov eax,D_HIGH[ebx] mov ecx,eax and ecx,#D_EXP_MASK ! extract exponent jz retz ! if 0 return 0 test eax,#D_SIGN_MASK jnz overflow_0 into_dtoui: mov edx,D_LOW[ebx] and eax,#D_FRAC_MASK ! extract fraction or eax,#D_NORM_MASK ! restore normalization bit shr ecx,#D_EXP_SHIFT ! convert exponent to number sub ecx,#D_EXP_BIAS+D_NORM_BIT ! adjust radix point jl dtoui_rightshift ! should we shift left or right? cmp ecx,#D_BIT-D_FRAC_BIT ! can shift left by at most this ja overflow_uint_max ! if more, overflow shld eax,edx,cl ret .align ALIGNMENT dtoui_rightshift: neg ecx ! make shift count > 0 cmp ecx,#REG_BIT ! big shifts would be taken mod REG_BIT ... jae retz ! ... no good shr eax,cl ! otherwise it is faster to do the shift ... ret ! ... then to jump for the slightly smaller ! ... shift counts that shift out all bits .align ALIGNMENT overflow_0: call fpoverflow sub eax,eax ret .align ALIGNMENT overflow_uint_max: call fpoverflow mov eax,#UINT_MAX ret ! ftoi is like dtoi except ebx points to a float instead of a double. ! This is a quickly-written slowish version that does not take advantage ! of the float being smaller. .globl ftoi .globl ftol .align ALIGNMENT ftoi: ftol: call Fpushf mov ebx,esp call dtoi add esp,#D_SIZE ret dev86-0.16.21/libc/i386fp/fpulld.x000066400000000000000000000012251231050321700162160ustar00rootroot00000000000000! bcc 386 floating point routines (version 2) -- Fpulld ! authors: Timothy Murphy (tim@maths.tcd.ie), Bruce Evans #include "fplib.h" ! Pop double from stack and store at address [ebx] .globl Fpulld .align ALIGNMENT Fpulld: pop ecx pop dword D_LOW[ebx] pop dword D_HIGH[ebx] jmp ecx ! return ! This popping method is much slower on 486's because popping to memory ! takes 5+ while moving twice takes 2 and the return address doesn't ! have to be moved. However, popping is a little faster on a non-cached ! 386/20 with static column RAM although the memory access pattern is ! better for a double-width move than for popping. What about a cached 386? dev86-0.16.21/libc/i386fp/fpullf.x000066400000000000000000000053541231050321700162270ustar00rootroot00000000000000! bcc 386 floating point routines (version 2) -- Fpullf ! authors: Timothy Murphy (tim@maths.tcd.ie), Bruce Evans #include "fplib.h" .extern fpoverflow .extern fpunderflow ! pop double from stack, convert to float and store at address [ebx] .globl Fpullf .align ALIGNMENT Fpullf: ! Step 1: load and shift left mov eax,PC_SIZE+D_LOW[esp] ! lower dword mov edx,PC_SIZE+D_HIGH[esp] ! upper dword mov ecx,edx ! copy upper dword into ecx ... and ecx,#D_SIGN_MASK ! ... and extract sign and edx,#D_EXP_MASK | D_FRAC_MASK ! extract exponent and fraction sub edx,#(D_EXP_BIAS-F_EXP_BIAS) << D_EXP_SHIFT ! adjust exponent bias jz underflow cmp edx,#F_EXP_INFINITE << D_EXP_SHIFT ! check if exponent lies in reduced range jae outofbounds shld edx,eax,#D_EXP_BIT-F_EXP_BIT ! shift exponent and fraction ! Step 2: round test eax,#1 << (REG_BIT-1-(D_EXP_BIT-F_EXP_BIT)) ! test upper rounding bit jz step3 ! below middle, don't round up test eax,#(1 << (REG_BIT-1-(D_EXP_BIT-F_EXP_BIT)))-1 ! test other rounding bits jnz roundup ! above middle, round up test dl,#1 ! in middle, check parity bit jz step3 ! already even, otherwise round up to make even roundup: inc edx ! carry 1 test edx,#F_FRAC_MASK ! is fraction now 0? (carry into F_EXPMASK) jnz step3 ! no -- carry complete cmp edx,#(F_EXP_INFINITE << F_EXP_SHIFT) & ~F_NORM_MASK ! yes (very unlikely): check for overflow ! XXX - I think these tests say 0x7e7fffff overflows jae overflow ! Step 3: put it all together step3: or edx,ecx ! include sign mov F_HIGH[ebx],edx ! store the result in [ebx] ret #D_SIZE ! return and release double from stack .align ALIGNMENT outofbounds: jns overflow ! have just compared exponent with the max underflow: ! call fpunderflow ! XXX push ecx ! save sign mov ecx,edx and ecx,#~D_FRAC_MASK ! assume fraction is below exp cmp ecx,#-((D_EXP_BIAS-F_EXP_BIAS) << D_EXP_SHIFT) ! was exp = 0? jz exp_x_0 shr ecx,#D_EXP_SHIFT neg ecx and edx,#D_FRAC_MASK or edx,#D_NORM_MASK shld edx,eax,#D_EXP_BIT-F_EXP_BIT-1 shl eax,#D_EXP_BIT-F_EXP_BIT-1 push ebx ! save to use for rounding sub ebx,ebx shrd ebx,eax,cl shrd eax,edx,cl shr edx,cl cmp eax,#1 << (REG_BIT-1) jb over_denorm_roundup ja denorm_roundup test dl,#1 jz over_denorm_roundup denorm_roundup: #if F_NORM_BIT != F_EXP_SHIFT #include "carry into norm bit doesn't go into low exp bit" #endif inc edx over_denorm_roundup: pop ebx pop ecx or edx,ecx mov F_HIGH[ebx],edx ret #D_SIZE .align ALIGNMENT exp_x_0: ! XXX check for denormals - they underflow pop ecx mov dword F_HIGH[ebx],#0 ret #D_SIZE .align ALIGNMENT overflow: mov edx,ebx ! put sign in usual reg call fpoverflow mov F_HIGH[ebx],dword #F_HUGE_HIGH ! XXX - should use infinity ret #D_SIZE ! ... if fpoverflow does dev86-0.16.21/libc/i386fp/fpushd.x000066400000000000000000000026111231050321700162210ustar00rootroot00000000000000! bcc 386 floating point routines (version 2) -- dtof, Fpushd, Fneg, Fnegd ! authors: Timothy Murphy (tim@maths.tcd.ie), Bruce Evans #include "fplib.h" .extern Fpullf ! dtof converts the double at [ebx] to a float and pushes the float onto ! the stack (D_SIZE bytes are allocated for the float although only the bottom ! F_SIZE are used). ! This is a quickly-written slowish version. .globl dtof .align ALIGNMENT dtof: pop eax sub esp,#D_SIZE ! build result here push eax ! put back return address call Fpushd lea ebx,D_SIZE+PC_SIZE[esp] call Fpullf ret ! Push double at address [ebx] onto stack .globl Fpushd .align ALIGNMENT Fpushd: pop ecx push dword D_HIGH[ebx] push dword D_LOW[ebx] jmp ecx ! return ! Push double at address [ebx] onto stack, negating it on the way. ! Don't worry about generating -0 because other routines have to allow for ! it anyway. ! Perhaps this and Fneg should check for denormals and illegal operands ! (I think only signalling NaNs are illegal). ! fchs doesn't check, but fld does. ! Our Fpushd is not quite like fld because no conversions are involved. .globl Fnegd .align ALIGNMENT Fnegd: pop ecx mov eax,D_HIGH[ebx] xor eax,#D_SIGN_MASK ! toggle sign push eax push dword D_LOW[ebx] jmp ecx ! return ! Negate double on stack .globl Fneg .align ALIGNMENT Fneg: xorb PC_SIZE+D_SIZE-1[esp],D_SIGN_MASK >> (REG_BIT-CHAR_BIT) ! toggle sign ret dev86-0.16.21/libc/i386fp/fpushf.x000066400000000000000000000030531231050321700162240ustar00rootroot00000000000000! bcc 386 floating point routines (version 2) -- Fpushf, Fnegf ! authors: Timothy Murphy (tim@maths.tcd.ie), Bruce Evans #include "fplib.h" .extern fpdenormal ! Load float at [ebx], convert to double and push on stack .globl Fpushf .align ALIGNMENT Fpushf: mov edx,F_HIGH[ebx] into_Fpushf: test edx,#F_EXP_MASK ! is exponent 0? jz exp_x_0 mov ecx,edx ! extract sign and ecx,#F_SIGN_MASK and edx,#F_EXP_MASK | F_FRAC_MASK ! extract exponent and fraction sub eax,eax ! clear lower dword shrd eax,edx,#D_EXP_BIT-F_EXP_BIT ! shift exponent and fraction to new position shr edx,#D_EXP_BIT-F_EXP_BIT add edx,#(D_EXP_BIAS-F_EXP_BIAS) << D_EXP_SHIFT ! adjust exponent bias or edx,ecx ! include sign pop ecx push edx ! upper dword push eax ! lower dword jmp ecx ! return .align ALIGNMENT exp_x_0: mov eax,edx and eax,#F_FRAC_MASK jnz x_denorm pop ecx push eax ! upper dword = 0 push eax ! lower dword = 0 jmp ecx ! return .align ALIGNMENT x_denorm: call fpdenormal bsr ecx,eax ! zzzz neg ecx add ecx,#F_NORM_BIT shl eax,cl and eax,#F_FRAC_MASK neg ecx add ecx,#D_EXP_BIAS-F_EXP_BIAS+1 shl ecx,#D_EXP_SHIFT and edx,#F_SIGN_MASK ! assumed same as D_SIGN_MASK or edx,ecx sub ecx,ecx shrd ecx,eax,#D_EXP_BIT-F_EXP_BIT shr eax,#D_EXP_BIT-F_EXP_BIT or edx,eax pop eax push edx ! upper dword push ecx ! lower dword jmp eax ! return ! Fnegf: as Fpushf, but negate double before pushing onto stack .globl Fnegf .align ALIGNMENT Fnegf: mov edx,F_HIGH[ebx] xor edx,#F_SIGN_MASK ! toggle sign jmp into_Fpushf ! join Fpushf dev86-0.16.21/libc/i386fp/fpushi.x000066400000000000000000000056671231050321700162440ustar00rootroot00000000000000! bcc 386 floating point routines (version 2) ! -- Fpushi, Fpushl, Fpushs, Fpushc, Fpushuc, Fpushui, Fpushul, Fpushus ! authors: Timothy Murphy (tim@maths.tcd.ie), Bruce Evans #include "fplib.h" ! Convert the short in ax to double and push on stack .globl Fpushs .align ALIGNMENT Fpushs: cwde add eax,#0 ! fast 3-byte instruction to align ! Convert the int or long in eax to double and push on stack .globl Fpushi .globl Fpushl ! .align ALIGNMENT ! don't do this until it pads with nop's Fpushi: Fpushl: test eax,eax jz return_eax ! got 0 in eax mov ebx,#(D_EXP_BIAS+D_NORM_BIT) << D_EXP_SHIFT ! set no-sign and exponent jns normalize ! sign and fraction bits already set up mov ebx,#D_SIGN_MASK | ((D_EXP_BIAS+D_NORM_BIT) << D_EXP_SHIFT) ! adjust sign neg eax ! adjust fraction jmp normalize .align ALIGNMENT ret1: mov eax,#D_EXP_BIAS << D_EXP_SHIFT add eax,#0 ! fast 3-byte instruction to align ! .align ALIGNMENT ! don't do this until it pads with nop's return_eax: pop ecx push eax ! upper dword push dword #0 ! lower dword = 0 jmp ecx ! return ! Convert the (unsigned) char in al to double and push on stack .globl Fpushc .globl Fpushuc .align ALIGNMENT Fpushc: Fpushuc: and eax,#(1 << CHAR_BIT)-1 add eax,#0 ! fast 3-byte instruction to align ! Convert the unsigned short in ax to double and push on stack .globl Fpushus ! .align ALIGNMENT ! don't do this until it pads with nop's Fpushus: and eax,#(1 << SHORT_BIT)-1 add eax,#0 ! fast 3-byte instruction to align ! Convert the unsigned int or long in eax to double and push on stack .globl Fpushui .globl Fpushul ! .align ALIGNMENT ! don't do this until it pads with nop's Fpushui: Fpushul: cmp eax,#1 ! this tests for both 0 and 1 jb return_eax ! got 0 in eax jz ret1 mov ebx,#(D_EXP_BIAS+D_NORM_BIT) << D_EXP_SHIFT ! set no-sign and exponent ! .align ALIGNMENT ! don't do this until it pads with nop's normalize: sub edx,edx ! clear lower dword of result ! Find first nonzero bit ! Don't use bsr, it is slow (const + 3n on 386, const + n on 486) sub ecx,ecx ! prepare unsigned extension of cl test eax,#~D_FRAC_MASK jnz large test eax,#0xFF << (D_NORM_BIT-8) jnz middle shl eax,#8 sub ebx,#8 << D_EXP_SHIFT test eax,#0xFF << (D_NORM_BIT-8) jnz middle shl eax,#8 sub ebx,#8 << D_EXP_SHIFT middle: shld ecx,eax,#D_NORM_BIT mov cl,bsr_table[ecx] add ecx,#REG_BIT-D_NORM_BIT-D_NORM_BIT neg ecx shl eax,cl shl ecx,#D_EXP_SHIFT sub ebx,ecx return: and eax,#D_FRAC_MASK ! remove normalization bit or eax,ebx ! include exponent (and sign) to fraction pop ecx push eax ! upper dword push edx ! lower dword jmp ecx ! return .align ALIGNMENT large: shld ecx,eax,#REG_BIT-(D_NORM_BIT+8) jnz huge shld ecx,eax,#REG_BIT-D_NORM_BIT mov cl,bsr_table[ecx] got_shift_right: shrd edx,eax,cl shr eax,cl shl ecx,#D_EXP_SHIFT add ebx,ecx jmp return .align ALIGNMENT huge: mov cl,bsr_table[ecx] add cl,#8 jmp got_shift_right .data .extern bsr_table dev86-0.16.21/libc/i386fp/frexp.x000066400000000000000000000026121231050321700160550ustar00rootroot00000000000000! bcc 386 floating point routines (version 2) -- _frexp ! authors: Timothy Murphy (tim@maths.tcd.ie), Bruce Evans #include "fplib.h" .extern fpdenormal ! void frexp(double value, int *exponent); ! splits a double into exponent and fraction (where 0.5 <= fraction < 1.0) .globl _frexp .align ALIGNMENT _frexp: push ebx #undef PC_SIZE #define PC_SIZE 8 mov eax,PC_SIZE+D_LOW[esp] ! lower dword of x mov ebx,PC_SIZE+D_HIGH[esp] ! upper dword of x mov edx,PC_SIZE+D_SIZE[esp] ! exponent pointer mov ecx,ebx ! extract exponent here and ecx,#D_EXP_MASK jz exp_x_0 shr ecx,#D_EXP_SHIFT ! exponent + bias got_x: sub ecx,#D_EXP_BIAS-1 ! D_EXP_BIAS is for 1.x form, we want 0.1x form mov [edx],ecx ! return exponent and ebx,#D_SIGN_MASK | D_FRAC_MASK ! extract sign and fraction or ebx,#(D_EXP_BIAS-1) << D_EXP_SHIFT ! set new exponent for 0.1x mov edx,ebx pop ebx ret .align ALIGNMENT exp_x_0: test ebx,#D_FRAC_MASK jnz xu_denorm test eax,eax jnz xl_denorm mov [edx],ecx ! return zero exponent mov ebx,ecx ! guard against -0 (may not be necessary) mov edx,ebx pop ebx ret .align ALIGNMENT xl_denorm: call fpdenormal bsr ecx,eax ! zzzz neg ecx add ecx,#REG_BIT-1 shl eax,cl shld ebx,eax,#D_NORM_BIT+1 shl eax,#D_NORM_BIT+1 sub ecx,#D_NORM_BIT+1 jmp got_x .align ALIGNMENT xu_denorm: call fpdenormal bsr ecx,ebx neg ecx add ecx,#D_NORM_BIT shld ebx,eax,cl shl eax,cl jmp got_x dev86-0.16.21/libc/i386fp/ftst.x000066400000000000000000000011221231050321700157040ustar00rootroot00000000000000! bcc 386 floating point routines (version 2) -- Ftst, Ftstd, Ftstf ! authors: Timothy Murphy (tim@maths.tcd.ie), Bruce Evans #include "fplib.h" #if 0 /* bcc doesn't generate Ftst (but it might in future) */ .globl Ftst #endif .align ALIGNMENT Ftst: cmp dword PC_SIZE+D_HIGH[esp],#0 ! need only test upper dword of x ret #D_SIZE ! Compare double at address [ebx] with 0 .globl Ftstd .align ALIGNMENT Ftstd: cmp dword D_HIGH[ebx],#0 ! need only test upper dword of x ret ! Compare float at address [ebx] with 0 .globl Ftstf .align ALIGNMENT Ftstf: cmp dword F_HIGH[ebx],#0 ret dev86-0.16.21/libc/i386fp/ldexp.x000066400000000000000000000034361231050321700160520ustar00rootroot00000000000000! bcc 386 floating point routines (version 2) -- _ldexp ! authors: Timothy Murphy (tim@maths.tcd.ie), Bruce Evans #include "fplib.h" .extern fpoverflow .extern fpunderflow ! void ldexp(double value, int exponent); ! returns value * (2 ** exponent) .globl _ldexp .align ALIGNMENT _ldexp: push ebx #undef PC_SIZE #define PC_SIZE 8 mov ebx,PC_SIZE+D_HIGH[esp] ! upper dword of x mov ecx,PC_SIZE+D_SIZE[esp] ! exponent arg mov eax,ebx ! extract exponent (of x) here and eax,#D_EXP_MASK ! jz exp_y_0 ! may need check for preposterous exponent arg too shr eax,#D_EXP_SHIFT ! shift to low bits just for testing jz underflow ! denormal? add eax,ecx ! test-add the exponents jz underflow ! XXX probably need to fiddle norm bit cmp eax,#D_EXP_INFINITE ! check if still within range jae outofbounds ! the unsigned compare catches all overflow cases ! because the exponent of x is non-negative shl ecx,#D_EXP_SHIFT ! shift exponent arg bits into final position ... add ebx,ecx ! ... safe to add it to exponent of x now mov eax,PC_SIZE+D_LOW[esp] ! lower dword of x mov edx,ebx pop ebx ret .align ALIGNMENT outofbounds: test ecx,ecx ! overflow or underflow? jns overflow underflow: mov edx,ebx ! put sign in usual reg push edi push esi mov edi,eax ! put exponent in usual reg mov eax,2*GENREG_SIZE+PC_SIZE+D_LOW[esp] ! put lower dword of x in usual reg mov esi,ebx ! put upper dword of x in usual reg and esi,#D_EXP_MASK | D_FRAC_MASK test esi,#D_EXP_MASK jz foo and esi,#D_FRAC_MASK or esi,#D_NORM_MASK foo: neg edi ! inc edi ! XXX ? call fpunderflow pop esi pop edi mov ebx,edx ! XXX = wrong reg pop ebx ret .align ALIGNMENT overflow: mov edx,ebx ! put sign in usual reg call fpoverflow mov eax,ecx ! XXX = wrong reg mov ebx,edx ! XXX = wrong reg pop ebx ret dev86-0.16.21/libc/i386fp/modf.c000066400000000000000000000002571231050321700156340ustar00rootroot00000000000000#include /* Slooow version. */ double modf(x, pint) double x; double *pint; { if (x >= 0) *pint = floor(x); else *pint = ceil(x); return x - *pint; } dev86-0.16.21/libc/i386fp/test.c000066400000000000000000000053211231050321700156630ustar00rootroot00000000000000#include #include #include #include #define CONVTYPE int #define MAX (MIN + NITER - 1) #define MIN INT_MIN #define NITER 1000000 double one = 1; double two = 2; double big = 1e99; double d; double d1; float f; int main() { CONVTYPE cti; CONVTYPE cto; clock_t delta; struct tms finish; int i; struct tms start; #if 0 times(&start); for (cti = MIN; cti <= MAX; ++cti) { d = cti; cto = d; if (cti != cto) printf("%08x %08x\n", cti, cto); if (cti % 10000000 == 0) { printf("%8x ok ", cti); fflush(stdout); } } times(&finish); delta = finish.tms_utime - start.tms_utime; printf("Time for %d i -> d and d -> i conversions was %g s (%d t)\n", MAX - MIN + 1, delta / (double) CLOCKS_PER_SEC, delta); #endif times(&start); for (cti = MIN; cti <= MAX; ++cti) d = cti; times(&finish); delta = finish.tms_utime - start.tms_utime; printf("Time for %d i -> d conversions was %g s (%d t)\n", MAX - MIN + 1, delta / (double) CLOCKS_PER_SEC, delta); times(&start); for (cti = MIN; cti <= MAX; ++cti) { d = cti; cto = d; } times(&finish); delta = finish.tms_utime - start.tms_utime - delta; printf("Time for %d d -> i conversions was %g s (%d t)\n", MAX - MIN + 1, delta / (double) CLOCKS_PER_SEC, delta); d = 0; times(&start); for (i = 0; i < NITER; ++i) d = d + 1; times(&finish); delta = finish.tms_utime - start.tms_utime; printf("Time for adding %d 1.0's to 0.0 was %g s (%d t), result = %g\n", NITER, delta / (double) CLOCKS_PER_SEC, delta, d); d = 0; times(&start); for (; d < NITER;) d = d + 1; times(&finish); delta = finish.tms_utime - start.tms_utime; printf("Time for adding %d 1.0's to 0.0 (d index) was %g s (%d t), result = %g\n", NITER, delta / (double) CLOCKS_PER_SEC, delta, d); times(&start); for (i = 1; i <= NITER; ++i) { d1 = i; d = d1 * d1; } times(&finish); delta = finish.tms_utime - start.tms_utime; printf("Time for %d mults was %g s (%d t), result = %g\n", NITER, delta / (double) CLOCKS_PER_SEC, delta, d); times(&start); for (i = 1; i <= NITER; ++i) { d1 = i; d = 1 / d1; } times(&finish); delta = finish.tms_utime - start.tms_utime; printf("Time for %d divs was %g s (%d t), result = %g\n", NITER, delta / (double) CLOCKS_PER_SEC, delta, d); f = 0; times(&start); for (i = 0; i < NITER; ++i) f = f + 1; times(&finish); delta = finish.tms_utime - start.tms_utime; printf("Time for adding %d 1.0f's to 0.0f was %g s (%d t), result = %g\n", NITER, delta / (double) CLOCKS_PER_SEC, delta, f); return 0; } dev86-0.16.21/libc/i386sys/000077500000000000000000000000001231050321700147505ustar00rootroot00000000000000dev86-0.16.21/libc/i386sys/Config000066400000000000000000000000501231050321700160730ustar00rootroot00000000000000sys386: Linux-i386 system call routines dev86-0.16.21/libc/i386sys/Makefile000066400000000000000000000017371231050321700164200ustar00rootroot00000000000000# Copyright (C) 1995,1996 Robert de Bath # This file is part of the Linux-8086 C library and is distributed # under the GNU Library General Public License. LSRC=cstartup.c LOBJ=__cstart3.o ESRC=exec.c EOBJ=execl.o execv.o execle.o execlp.o execvp.o DSRC=dirent.c DOBJ=opendir.o closedir.o readdir.o ifeq ($(LIB_CPU)-$(LIB_OS),i386-ELKS) OBJ=$(LOBJ) $(EOBJ) $(DOBJ) setjmp3.o SYSCALLS=syscalls CFLAGS=$(ARCH) $(CCFLAGS) $(DEFS) all: $(SYSCALLS) $(LIBC)($(OBJ)) @$(RM) $(OBJ) syscalls: syscall.mak $(MAKE) -f syscall.mak LIBC="$(LIBC)" CFLAGS="$(CFLAGS)" syscall.mak: mksyscall syscall.dat sh mksyscall $(LIBC)($(LOBJ)): $(LSRC) $(CC) $(CFLAGS) -DL_$* $< -c -o $*.o $(AR) $(ARFLAGS) $@ $*.o $(LIBC)($(DOBJ)): $(DSRC) $(CC) $(CFLAGS) -DL_$* $< -c -o $*.o $(AR) $(ARFLAGS) $@ $*.o $(LIBC)($(EOBJ)): $(ESRC) $(CC) $(CFLAGS) -DL_$* $< -c -o $*.o $(AR) $(ARFLAGS) $@ $*.o else all: @: endif clean: rm -f *.o libc.a rm -f syscall.c syscall.mak dev86-0.16.21/libc/i386sys/cstartup.c000066400000000000000000000041561231050321700167670ustar00rootroot00000000000000/* Copyright (C) 1996 Robert de Bath * This file is part of the Linux-8086 C library and is distributed * under the GNU Library General Public License. */ #include #include #include #include #ifdef __unix__ #ifdef __AS386_32__ /********************** Function __cstartup *******************************/ void (*__cleanup)() = 0; char ** environ; #asm loc 2 call_main: .long _main ! Segment 2 is the trailing pointers, main and the .long call_exit ! routine to call exit. #if __FIRST_ARG_IN_AX__ .data saved_arg1: .long 0 #endif .data loop_safe: .long 0 .text export ___mkargv ___mkargv: ! BCC Tells linker to init argv ... none needed. export ___cstartup ___cstartup: ! Crt0 startup (Linux style) mov eax,[esp] test eax,eax jz call_exit ! If argc == 0 this is being called by ldd, exit. mov eax,[esp+8] mov [_environ],eax #if __FIRST_ARG_IN_AX__ pop [saved_arg1] ! Argc will go into eax #endif mov ebx,#auto_start ! Pointer to first autostart function auto_run: #if __FIRST_ARG_IN_AX__ mov eax,[saved_arg1] #endif mov [loop_safe],ebx mov ebx,[ebx] test ebx,ebx jz no_func call ebx ! Call the function no_func: mov ebx,[loop_safe] add ebx,#4 ! next jmp auto_run ! And round for the next. call_exit: ! Last item called by above. pop ebx ! Be tidy. #if !__FIRST_ARG_IN_AX__ push eax ! At the end the last called was main() push it`s #endif call _exit ! return val and call exit(); bad_exit: jmp bad_exit ! Exit returned !! export _exit export __exit _exit: ! exit(rv) function #if __FIRST_ARG_IN_AX__ mov [saved_arg1],eax #else push [esp+4] ! Copy the `rv` for the exit fuctions. #endif mov ebx,[___cleanup] ! Call exit, normally this is `__do_exit` test ebx,ebx je no_clean ! But it`s default is null call ebx no_clean: #if __FIRST_ARG_IN_AX__ mov eax,[saved_arg1] #else add esp,#4 #endif __exit: ! _exit(rv) br ___exit ! This is just an alias for __exit(); #endasm /********************** THE END ********************************************/ #endif /* __unix__ */ #endif dev86-0.16.21/libc/i386sys/dirent.c000066400000000000000000000027731231050321700164120ustar00rootroot00000000000000 #include #include #include #include #include #include #ifdef L_opendir DIR * opendir(dname) const char *dname; { struct stat st; int fd; DIR *p; if (stat(dname, &st) < 0) return 0; if (!S_ISDIR(st.st_mode)) { errno = ENOTDIR; return 0; } if ((fd = open(dname, O_RDONLY)) < 0) return 0; p = malloc(sizeof(DIR)); if (p == 0) { close(fd); return 0; } p->dd_buf = malloc(sizeof(struct dirent)); if (p->dd_buf == 0) { free(p); close(fd); return 0; } p->dd_fd = fd; p->dd_loc = p->dd_size = 0; return p; } #endif #ifdef L_closedir int closedir(dirp) DIR *dirp; { int fd; fd = dirp->dd_fd; free(dirp->dd_buf); free(dirp); return close(fd); } #endif #ifdef __AS386_16__ #ifdef L_readdir /* * This currently assumes we see a v. simple diectory structure, it's * probably faked! */ struct dirent * readdir(dirp) DIR *dirp; { int cc; cc = read(dirp->dd_fd, dirp->dd_buf, sizeof(struct dirent)); if (cc <= 0) return 0; if (cc != sizeof(struct dirent)) { errno = EBADF; return 0; } return dirp->dd_buf; } #endif #else /* This is for 386 linux */ #ifdef L_readdir struct dirent * readdir(dirp) DIR *dirp; { int cc; cc = __readdir(dirp->dd_fd, dirp->dd_buf, 1); if (cc <= 0) return 0; if (cc>1) dirp->dd_buf->d_name[cc] = 0; return dirp->dd_buf; } #endif #endif dev86-0.16.21/libc/i386sys/exec.c000066400000000000000000000125141231050321700160430ustar00rootroot00000000000000 #include #include extern char ** environ; #ifdef L_execl int execl(fname, arg0) char * fname, *arg0; { return execve(fname, &arg0, environ); } #endif #ifdef L_execv int execv(fname, argv) char * fname, **argv; { return execve(fname, argv, environ); } #endif #ifdef L_execle int execle(fname, arg0) char *fname, *arg0; { char ** envp = &arg0; while(*envp) envp++; return execve(fname, &arg0, envp+1); } #endif #ifdef L_execve int execve(fname, argv, envp) char * fname; char ** argv; char ** envp; { char **p; int argv_len=0, argv_count=0; int envp_len=0, envp_count=0; int stack_bytes; unsigned short * pip; char * pcp, * stk_ptr, *baseoff; int rv; /* How much space for argv */ for(p=argv; p && *p && argv_len >= 0; p++) { argv_count++; argv_len += strlen(*p)+1; } /* How much space for envp */ for(p=envp; p && *p && envp_len >= 0; p++) { envp_count++; envp_len += strlen(*p)+1; } /* tot it all up */ stack_bytes = 2 /* argc */ + argv_count * 2 + 2 /* argv */ + argv_len + envp_count * 2 + 2 /* envp */ + envp_len; /* Allocate it */ if( argv_len < 0 || envp_len < 0 || stack_bytes <= 0 || (int)(stk_ptr = (char*)sbrk(stack_bytes)) == -1) { errno = ENOMEM; return -1; } /* Sanity check printf("Argv = (%d,%d), Envp=(%d,%d), stack=%d\n", argv_count, argv_len, envp_count, envp_len, stack_bytes); */ /* Now copy in the strings */ pip=(unsigned short *) stk_ptr; pcp=stk_ptr+2*(1+argv_count+1+envp_count+1); /* baseoff = stk_ptr + stack_bytes; */ baseoff = stk_ptr; *pip++ = argv_count; for(p=argv; p && *p; p++) { int l; *pip++ = pcp-baseoff; l = strlen(*p)+1; memcpy(pcp, *p, l); pcp += l; } *pip++ = 0; for(p=envp; p && *p; p++) { int l; *pip++ = pcp-baseoff; l = strlen(*p)+1; memcpy(pcp, *p, l); pcp += l; } *pip++ = 0; rv = __exec(fname, stk_ptr, stack_bytes); /* FIXME: This will probably have to interpret '#!' style exe's */ sbrk(-stack_bytes); return rv; } #endif #ifdef L_execlp int execlp(fname, arg0) char * fname, *arg0; { return execvp(fname, &arg0); } #endif #ifdef L_execvp int execvp(fname, argv) char * fname, **argv; { char *pname = fname, *path; int besterr = ENOENT; int flen, plen; char * bp = sbrk(0); if( *fname != '/' && (path = getenv("PATH")) != 0 ) { flen = strlen(fname)+2; for(;path;) { if( *path == ':' || *path == '\0' ) { tryrun(fname, argv); if( errno == EACCES ) besterr = EACCES; if( *path ) path++; else break; } else { char * p = strchr(path, ':'); if(p) *p = '\0'; plen = strlen(path); pname = sbrk(plen+flen); strcpy(pname, path); strcat(pname, "/"); strcat(pname, fname); tryrun(pname, argv); if( errno == EACCES ) besterr = EACCES; brk(pname); pname = fname; if(p) *p++ = ':'; path=p; } } } tryrun(pname, argv); brk(bp); if( errno == ENOENT || errno == 0 ) errno = besterr; return -1; } static int tryrun(pname, argv) char * pname; char ** argv; { static char *shprog[] = {"/bin/sh", "", 0}; struct stat st; if( stat(pname, &st) < 0 ) return; if( !S_ISREG(st.st_mode) ) return; #ifdef __AS386_16__ __execvve(pname, (void*)0, argv, environ); if( errno == ENOEXEC ) { shprog[1] = pname; __execvve(shprog[0], shprog, argv, environ); } #else execve(pname, argv, environ); /* FIXME - running /bin/sh in 386 mode */ #endif } #ifdef __AS386_16__ static int __execvve(fname, interp, argv, envp) char * fname; char ** interp; char ** argv; char ** envp; { char **p; int argv_len=0, argv_count=0; int envp_len=0, envp_count=0; int stack_bytes; unsigned short * pip; char * pcp, * stk_ptr, *baseoff; int rv; /* How much space for argv */ for(p=interp; p && *p && argv_len >= 0; p++) { argv_count++; argv_len += strlen(*p)+1; } for(p=argv; p && *p && argv_len >= 0; p++) { argv_count++; argv_len += strlen(*p)+1; } /* How much space for envp */ for(p=envp; p && *p && envp_len >= 0; p++) { envp_count++; envp_len += strlen(*p)+1; } /* tot it all up */ stack_bytes = 2 /* argc */ + argv_count * 2 + 2 /* argv */ + argv_len + envp_count * 2 + 2 /* envp */ + envp_len; /* Allocate it */ if( argv_len < 0 || envp_len < 0 || stack_bytes <= 0 || (int)(stk_ptr = (char*)sbrk(stack_bytes)) == -1) { errno = ENOMEM; return -1; } /* Sanity check printf("Argv = (%d,%d), Envp=(%d,%d), stack=%d\n", argv_count, argv_len, envp_count, envp_len, stack_bytes); */ /* Now copy in the strings */ pip=(unsigned short *) stk_ptr; pcp=stk_ptr+2*(1+argv_count+1+envp_count+1); /* baseoff = stk_ptr + stack_bytes; */ baseoff = stk_ptr; *pip++ = argv_count; for(p=interp; p && *p; p++) { int l; *pip++ = pcp-baseoff; l = strlen(*p)+1; memcpy(pcp, *p, l); pcp += l; } for(p=argv; p && *p; p++) { int l; *pip++ = pcp-baseoff; l = strlen(*p)+1; memcpy(pcp, *p, l); pcp += l; } *pip++ = 0; for(p=envp; p && *p; p++) { int l; *pip++ = pcp-baseoff; l = strlen(*p)+1; memcpy(pcp, *p, l); pcp += l; } *pip++ = 0; rv = __exec(fname, stk_ptr, stack_bytes); /* FIXME: This will probably have to interpret '#!' style exe's */ sbrk(-stack_bytes); return rv; } #endif #endif dev86-0.16.21/libc/i386sys/mksyscall000066400000000000000000000104071231050321700166770ustar00rootroot00000000000000# Copyright (C) 1995,1996 Robert de Bath # This file is part of the Linux-8086 C library and is distributed # under the GNU Library General Public License. # # This script generates the 'simple' system calls for the 386 # # Each call is put into it's own object file, if the semantics of the # call are not correct UNIX then the 4th field in the dat file has a # marker and the function is generated with a __ prefix. # # # Different levels of squeeze # 0 = each is complete # 1 = Short codes calling common function rm -f syscall.c syscall.mak tr '[A-Z]' '[a-z]' < syscall.dat | \ awk 'BEGIN{ print "# Copyright (C) 1995,1996 Robert de Bath " > "syscall.mak"; print "# This file is part of the Linux-8086 C library and is distributed" > "syscall.mak"; print "# under the GNU Library General Public License." > "syscall.mak"; print "# " > "syscall.mak"; print "# This file is automatically generated\n" > "syscall.mak" print "/* Copyright (C) 1995,1996 Robert de Bath "; print " * This file is part of the Linux-8086 C library and is distributed"; print " * under the GNU Library General Public License."; print " * "; print " * This file is automatically generated */\n" obj="OBJ="; print "/* Standard start */\n\n" printf("#ifndef __MSDOS__\n"); printf("#ifdef __AS386_32__\n"); printf("#asm\n"); printf(" .text\n"); printf(" .align 4\n"); printf("#endasm\n\n"); COMPACT=0; } /^[ ]*#/ { next; } /^[ ]*$/ { next; } { if( $2 > max_call ) max_call = $2; if( $3 == "x" || $3 == "" ) next; else if( $4 == "-" ) next; else if( $4 == "*" ) funcname="__" $1; else funcname=$1; if( length(obj) > 60 ) { printf("%s\t\\\n", obj) > "syscall.mak"; obj=" "; } obj=obj funcname ".o "; printf "/* CALL %s */\n\n", $0; printf("#ifdef L_%s\n", funcname); printf("#asm\n"); printf("export _%s\n", funcname); printf("_%s:\n", funcname); # Inline assembler max to 5 args (20 bytes) if( $3 != 4 && $3 != 5 && ( COMPACT || $3 > 5 )) { if( $3 == 0 ) { printf(" mov eax,#%d\n", $2); } else { printf("#if __FIRST_ARG_IN_AX__\n"); printf(" mov edx,#%d\n", $2); printf("#else\n"); printf(" mov eax,#%d\n", $2); printf("#endif\n"); } printf(" br sys_call%d\n", $3); } else { if( $3 >= 1 ) printf("#if __FIRST_ARG_IN_AX__\n"); if( $3 >= 1 ) printf(" mov ebx,eax\n"); if( $3 >= 2 ) printf(" mov ecx,[esp+4]\n"); if( $3 >= 3 ) printf(" mov edx,[esp+8]\n"); if( $3 >= 4 ) printf(" push esi\n"); if( $3 >= 4 ) printf(" mov esi,[esp+16]\n"); if( $3 >= 5 ) printf(" push edi\n"); if( $3 >= 5 ) printf(" mov edi,[esp+24]\n"); if( $3 >= 1 ) printf("#else\n"); if( $3 >= 1 ) printf(" mov ebx,[esp+4]\n"); if( $3 >= 2 ) printf(" mov ecx,[esp+8]\n"); if( $3 >= 3 ) printf(" mov edx,[esp+12]\n"); if( $3 >= 4 ) printf(" push esi\n"); if( $3 >= 4 ) printf(" mov esi,[esp+20]\n"); if( $3 >= 5 ) printf(" push edi\n"); if( $3 >= 5 ) printf(" mov edi,[esp+28]\n"); if( $3 >= 1 ) printf("#endif\n"); printf(" mov eax,#%d\n", $2); printf(" int $80\n"); if( $3 >= 5 ) printf(" pop edi\n"); if( $3 >= 4 ) printf(" pop esi\n"); printf(" test eax,eax\n"); printf(" jl syscall_err\n"); printf(" ret\n"); printf("syscall_err:\n"); printf(" neg eax\n"); printf(" mov [_errno],eax\n"); printf(" mov eax,#-1\n"); printf(" ret\n"); } printf("#endasm\n"); printf("#endif\n\n"); } END{ printf("#endif /* __AS386_32__ */\n\n"); printf("#endif /* __MSDOS__ */\n\n"); printf("%s\n", obj) > "syscall.mak"; printf "\n" > "syscall.mak"; }' > syscall.c cat >> syscall.mak <<\! CFLAGS=$(ARCH) $(CCFLAGS) $(DEFS) all: $(LIBC)($(OBJ)) @$(RM) $(OBJ) $(LIBC)($(OBJ)): syscall.dat $(CC) $(CFLAGS) -DL_$* syscall.c -c -o $*.o $(AR) $(ARFLAGS) $@ $*.o ! exit $? dev86-0.16.21/libc/i386sys/setjmp3.c000066400000000000000000000013541231050321700165040ustar00rootroot00000000000000 #include #if __AS386_32__ int setjmp(env) jmp_buf env; { #asm export __setjmp __setjmp: pop ecx ! PC #if __FIRST_ARG_IN_AX__ mov ebx,eax #else mov ebx,esp mov ebx,[ebx] ! TOS is prt -> env #endif mov [ebx+0],ecx ! PC mov [ebx+4],esp ! This registers are all that may be constant. mov [ebx+8],ebp mov [ebx+12],esi ! Is saving these the "right thing" ? mov [ebx+16],edi xor eax,eax jmp ecx #endasm } void longjmp(env, rv) jmp_buf env; int rv; { #asm export __longjmp __longjmp: pop ecx ! pc #if __FIRST_ARG_IN_AX__ mov ebx,eax ! env-> #else pop ebx ! env-> #endif pop eax ! rv mov ecx,[ebx+0] ! PC mov esp,[ebx+4] mov ebp,[ebx+8] mov esi,[ebx+12] mov edi,[ebx+16] jmp ecx #endasm } #endif dev86-0.16.21/libc/i386sys/syscall.dat000066400000000000000000000220211231050321700171110ustar00rootroot00000000000000# # Name No Args Flag, comment # # . = Ok, with comment # * = Needs libc code (Prefix __) # - = Obsolete/not required # # Last updated 2005-01-01 # # Name N C setup 0 X exit 1 1 * fork 2 0 vfork 2 0 . Fake alias of fork read 3 3 write 4 3 open 5 3 close 6 1 waitpid 7 3 creat 8 2 link 9 2 unlink 10 1 execve 11 3 chdir 12 1 time 13 1 dv32_mknod 14 3 * Has correct args for 32bit dev_t chmod 15 2 chown 16 3 break 17 X - This is done in a special function oldstat 18 X - lseek 19 3 getpid 20 0 mount 21 5 umount 22 1 setuid 23 1 getuid 24 0 stime 25 1 ptrace 26 4 alarm 27 1 oldfstat 28 X - pause 29 0 utime 30 2 stty 31 X - gtty 32 X - access 33 2 nice 34 1 ftime 35 1 sync 36 0 kill 37 2 rename 38 2 mkdir 39 2 rmdir 40 1 dup 41 1 pipe 42 1 times 43 1 prof 44 X - brk 45 1 - need to save brk_addr & -ve is valid return. setgid 46 1 getgid 47 0 signal 48 2 geteuid 49 0 getegid 50 0 acct 51 1 umount2 52 X - lock 53 X - ioctl 54 3 fcntl 55 3 mpx 56 X - setpgid 57 2 ulimit 58 2 oldolduname 59 X - umask 60 1 chroot 61 1 dv32_ustat 62 2 * Has correct args for 32bit dev_t dup2 63 2 getppid 64 0 getpgrp 65 0 setsid 66 0 sigaction 67 3 siggetmask 68 0 sigsetmask 69 1 setreuid 70 2 setregid 71 2 sigsuspend 72 1 sigpending 73 1 sethostname 74 2 setrlimit 75 2 getrlimit 76 2 getrusage 77 2 gettimeofday 78 2 settimeofday 79 2 getgroups 80 2 setgroups 81 2 select 82 1 * select's arg is &arg1 symlink 83 2 oldlstat 84 X - readlink 85 3 uselib 86 1 swapon 87 2 reboot 88 3 readdir 89 3 * Takes the fd not a ddptr mmap 90 1 * Is a pointer to a buffer with the 6 args. munmap 91 2 truncate 92 2 ftruncate 93 2 fchmod 94 2 fchown 95 2 getpriority 96 2 setpriority 97 3 profil 98 X - glibc has userspace statfs 99 2 fstatfs 100 2 ioperm 101 3 socketcall 102 2 * This is a lib internal for socket stuff syslog 103 X setitimer 104 3 getitimer 105 2 dv32_stat 106 2 * Has correct args for 32 bit dev_t dv32_lstat 107 2 * Has correct args for 32 bit dev_t dv32_fstat 108 2 * Has correct args for 32 bit dev_t olduname 109 X - iopl 110 1 vhangup 111 0 idle 112 0 - System internal vm86 113 1 * WARNING now vm86old wait4 114 4 swapoff 115 1 sysinfo 116 1 ipc 117 5 * SYSV ipc entry point fsync 118 1 sigreturn 119 1 * Signal internal clone 120 2 setdomainname 121 2 uname 122 1 modify_ldt 123 X adjtimex 124 1 mprotect 125 3 sigprocmask 126 3 create_module 127 X - Module handling, NO WAY! init_module 128 X delete_module 129 X get_kernel_syms 130 X quotactl 131 X getpgid 132 1 fchdir 133 1 bdflush 134 2 sysfs 135 3 personality 136 1 * Linux specific. afs_syscall 137 X setfsuid 138 1 setfsgid 139 1 _llseek 140 X getdents 141 3 * New style readdir ? _newselect 142 X flock 143 2 msync 144 X readv 145 X writev 146 X getsid 147 X fdatasync 148 X _sysctl 149 X mlock 150 X munlock 151 X mlockall 152 X munlockall 153 X sched_setparam 154 X sched_getparam 155 X sched_setscheduler 156 X sched_getscheduler 157 X sched_yield 158 X sched_get_priority_max 159 X sched_get_priority_min 160 X sched_rr_get_interval 161 X nanosleep 162 2 mremap 163 X setresuid 164 X getresuid 165 X vm86 166 X query_module 167 X poll 168 X nfsservctl 169 X setresgid 170 X getresgid 171 X prctl 172 X rt_sigreturn 173 X rt_sigaction 174 X rt_sigprocmask 175 X rt_sigpending 176 X rt_sigtimedwait 177 X rt_sigqueueinfo 178 X rt_sigsuspend 179 X pread64 180 X pwrite64 181 X chown 182 X getcwd 183 X capget 184 X capset 185 X sigaltstack 186 X sendfile 187 X getpmsg 188 X putpmsg 189 X vfork 190 X ugetrlimit 191 X mmap2 192 X truncate64 193 X ftruncate64 194 X stat64 195 X lstat64 196 X fstat64 197 X lchown32 198 X getuid32 199 X getgid32 200 X geteuid32 201 X getegid32 202 X setreuid32 203 X setregid32 204 X getgroups32 205 X setgroups32 206 X fchown32 207 X setresuid32 208 X getresuid32 209 X setresgid32 210 X getresgid32 211 X chown32 212 X setuid32 213 X setgid32 214 X setfsuid32 215 X setfsgid32 216 X pivot_root 217 X mincore 218 X madvise 219 X madvise1 219 X getdents64 220 X fcntl64 221 X Unused 223 X - /* is unused */ gettid 224 X readahead 225 X setxattr 226 X lsetxattr 227 X fsetxattr 228 X getxattr 229 X lgetxattr 230 X fgetxattr 231 X listxattr 232 X llistxattr 233 X flistxattr 234 X removexattr 235 X lremovexattr 236 X fremovexattr 237 X tkill 238 X sendfile64 239 X futex 240 X sched_setaffinity 241 X sched_getaffinity 242 X set_thread_area 243 X get_thread_area 244 X io_setup 245 X io_destroy 246 X io_getevents 247 X io_submit 248 X io_cancel 249 X fadvise64 250 X Unused 251 X - /* is unused */ exit_group 252 X lookup_dcookie 253 X epoll_create 254 X epoll_ctl 255 X epoll_wait 256 X remap_file_pages 257 X set_tid_address 258 X timer_create 259 X timer_settime (__NR_timer_create+1) X timer_gettime (__NR_timer_create+2) X timer_getoverrun (__NR_timer_create+3) X timer_delete (__NR_timer_create+4) X clock_settime (__NR_timer_create+5) X clock_gettime (__NR_timer_create+6) X clock_getres (__NR_timer_create+7) X clock_nanosleep (__NR_timer_create+8) X statfs64 268 X fstatfs64 269 X tgkill 270 X utimes 271 X fadvise64_64 272 X vserver 273 X dev86-0.16.21/libc/include/000077500000000000000000000000001231050321700151435ustar00rootroot00000000000000dev86-0.16.21/libc/include/a.out.h000066400000000000000000000077731231050321700163600ustar00rootroot00000000000000/* Copyright (C) 1990-1996 * This file is part of the ld86 command for Linux-86 * It is distributed under the GNU Library General Public License. * * - This may actually be BSD or Minix code, can someone clarify please. -RDB */ #ifndef __AOUT_H #define __AOUT_H struct exec { /* a.out header */ unsigned char a_magic[2]; /* magic number */ unsigned char a_flags; /* flags, see below */ unsigned char a_cpu; /* cpu id */ unsigned char a_hdrlen; /* length of header */ unsigned char a_unused; /* reserved for future use */ unsigned short a_version; /* version stamp (not used at present) */ long a_text; /* size of text segement in bytes */ long a_data; /* size of data segment in bytes */ long a_bss; /* size of bss segment in bytes */ long a_entry; /* entry point */ long a_total; /* total memory allocated */ long a_syms; /* size of symbol table */ /* SHORT FORM ENDS HERE */ long a_trsize; /* text relocation size */ long a_drsize; /* data relocation size */ long a_tbase; /* text relocation base */ long a_dbase; /* data relocation base */ }; #define A_MAGIC0 (unsigned char) 0x01 #define A_MAGIC1 (unsigned char) 0x03 #define BADMAG(X) ((X).a_magic[0] != A_MAGIC0 ||(X).a_magic[1] != A_MAGIC1) /* CPU Id of TARGET machine (byte order coded in low order two bits) */ #define A_NONE 0x00 /* unknown */ #define A_I8086 0x04 /* intel i8086/8088 */ #define A_M68K 0x0B /* motorola m68000 */ #define A_NS16K 0x0C /* national semiconductor 16032 */ #define A_I80386 0x10 /* intel i80386 */ #define A_SPARC 0x17 /* Sun SPARC */ #define A_BLR(cputype) ((cputype&0x01)!=0) /* TRUE if bytes left-to-right */ #define A_WLR(cputype) ((cputype&0x02)!=0) /* TRUE if words left-to-right */ /* Flags. */ #define A_UZP 0x01 /* unmapped zero page (pages) */ #define A_PAL 0x02 /* page aligned executable */ #define A_NSYM 0x04 /* new style symbol table */ #define A_STAND 0x08 /* standalone executable */ #define A_EXEC 0x10 /* executable */ #define A_SEP 0x20 /* separate I/D */ #define A_PURE 0x40 /* pure text */ #define A_TOVLY 0x80 /* text overlay */ /* Offsets of various things. */ #define A_MINHDR 32 #define A_TEXTPOS(X) ((long)(X).a_hdrlen) #define A_DATAPOS(X) (A_TEXTPOS(X) + (X).a_text) #define A_HASRELS(X) ((X).a_hdrlen > (unsigned char) A_MINHDR) #define A_HASEXT(X) ((X).a_hdrlen > (unsigned char) (A_MINHDR + 8)) #define A_HASLNS(X) ((X).a_hdrlen > (unsigned char) (A_MINHDR + 16)) #define A_HASTOFF(X) ((X).a_hdrlen > (unsigned char) (A_MINHDR + 24)) #define A_TRELPOS(X) (A_DATAPOS(X) + (X).a_data) #define A_DRELPOS(X) (A_TRELPOS(X) + (X).a_trsize) #define A_SYMPOS(X) (A_TRELPOS(X) + (A_HASRELS(X) ? \ ((X).a_trsize + (X).a_drsize) : 0)) struct reloc { long r_vaddr; /* virtual address of reference */ unsigned short r_symndx; /* internal segnum or extern symbol num */ unsigned short r_type; /* relocation type */ }; /* r_tyep values: */ #define R_ABBS 0 #define R_RELLBYTE 2 #define R_PCRBYTE 3 #define R_RELWORD 4 #define R_PCRWORD 5 #define R_RELLONG 6 #define R_PCRLONG 7 #define R_REL3BYTE 8 #define R_KBRANCHE 9 /* r_symndx for internal segments */ #define S_ABS ((unsigned short)-1) #define S_TEXT ((unsigned short)-2) #define S_DATA ((unsigned short)-3) #define S_BSS ((unsigned short)-4) struct nlist { /* symbol table entry */ char n_name[8]; /* symbol name */ long n_value; /* value */ unsigned char n_sclass; /* storage class */ unsigned char n_numaux; /* number of auxiliary entries (not used) */ unsigned short n_type; /* language base and derived type (not used) */ }; /* Low bits of storage class (section). */ #define N_SECT 07 /* section mask */ #define N_UNDF 00 /* undefined */ #define N_ABS 01 /* absolute */ #define N_TEXT 02 /* text */ #define N_DATA 03 /* data */ #define N_BSS 04 /* bss */ #define N_COMM 05 /* (common) */ /* High bits of storage class. */ #define N_CLASS 0370 /* storage class mask */ #define C_NULL #define C_EXT 0020 /* external symbol */ #define C_STAT 0030 /* static */ #endif /* _AOUT_H */ dev86-0.16.21/libc/include/ar.h000066400000000000000000000003571231050321700157230ustar00rootroot00000000000000#ifndef __AR_H #define __AR_H #define ARMAG "!\n" #define SARMAG 8 #define ARFMAG "`\n" struct ar_hdr { char ar_name[16], ar_date[12], ar_uid[6], ar_gid[6], ar_mode[8], ar_size[10], ar_fmag[2]; }; #endif /* __AR_H */ dev86-0.16.21/libc/include/asm/000077500000000000000000000000001231050321700157235ustar00rootroot00000000000000dev86-0.16.21/libc/include/asm/limits.h000066400000000000000000000040231231050321700173740ustar00rootroot00000000000000/* Copyright (C) 1996 Robert de Bath * This file is part of the Linux-8086 C library and is distributed * under the GNU Library General Public License. */ #ifndef __ASM_LIMITS_H #define __ASM_LIMITS_H /* Common defines for current processors */ #define MB_LEN_MAX 1 /* Longest multi-byte character */ #define CHAR_BIT 8 /* number of bits in a char */ #define SHRT_MAX 32767 /* maximum (signed) short value */ #define SHRT_MIN (-32768) /* minimum (signed) short value */ #define LONG_MAX 2147483647 /* maximum (signed) long value */ #define LONG_MIN (-2147483648) /* minimum (signed) long value */ #define UCHAR_MAX 255 /* maximum unsigned char value */ #define USHRT_MAX 0xffff /* maximum unsigned short value */ #define ULONG_MAX 0xffffffff /* maximum unsigned long value */ #ifdef __BCC__ #define CHAR_MAX 255 /* maximum char value */ #define CHAR_MIN (0) /* mimimum char value */ #ifdef __AS386_32__ #define INT_MAX 2147483647 /* maximum (signed) int value */ #define INT_MIN (-2147483648) /* minimum (signed) int value */ #define UINT_MAX 0xffffffff /* maximum unsigned int value */ #else #define INT_MAX 32767 /* maximum (signed) int value */ #define INT_MIN (-32768) /* minimum (signed) int value */ #define UINT_MAX 0xffff /* maximum unsigned int value */ #endif /* BCC does have signed char now. */ #define SCHAR_MAX 127 /* maximum signed char value */ #define SCHAR_MIN (-128) /* minimum signed char value */ #endif #if defined(__GNUC__) && defined(__i386__) #define CHAR_MAX 127 /* maximum char value */ #define CHAR_MIN (-128) /* mimimum char value */ #define SCHAR_MAX 127 /* maximum signed char value */ #define SCHAR_MIN (-128) /* minimum signed char value */ #define INT_MAX 2147483647 /* maximum (signed) int value */ #define INT_MIN (-2147483648) /* minimum (signed) int value */ #define UINT_MAX 0xffffffff /* maximum unsigned int value */ #endif #ifndef RAND_MAX #define RAND_MAX INT_MAX #endif #ifndef INT_MAX #error "Limits.h not fully implemented, INT_MAX undefined!" #endif #endif dev86-0.16.21/libc/include/asm/types.h000066400000000000000000000012771231050321700172470ustar00rootroot00000000000000 /* asm/types.h - Basic sized C data types. */ #ifndef __ASM_8086_TYPES #define __ASM_8086_TYPES /* First we define all of the __u and __s types...*/ typedef unsigned char __u8; typedef unsigned char * __pu8; #ifndef __BCC__ /* NOTE! BCC does _not_ have a signed char type! */ typedef char __s8; typedef char * __ps8; #endif typedef unsigned short __u16; typedef unsigned short * __pu16; typedef short __s16; typedef short * __ps16; typedef unsigned long __u32; typedef unsigned long * __pu32; typedef long __s32; typedef long * __ps32; /* __uint == 16bit on 8086 32bit on i386 */ typedef unsigned int __uint; typedef int __sint; typedef unsigned int * __puint; typedef int * __psint; #endif dev86-0.16.21/libc/include/assert.h000066400000000000000000000007651231050321700166250ustar00rootroot00000000000000#ifndef __ASSERT_H #define __ASSERT_H #include /* If NDEBUG is defined, do nothing. If not, and EXPRESSION is zero, print an error message and abort. */ #ifdef NDEBUG #define assert(expr) ((void) 0) #else /* Not NDEBUG. */ extern void __assert __P((const char *, const char *, int)); #define assert(expr) \ ((void) ((expr) || \ (__assert (__STRING(expr), \ __FILE__, __LINE__), 0))) #endif /* NDEBUG. */ #endif /* __ASSERT_H */ dev86-0.16.21/libc/include/bios.h000066400000000000000000000013531231050321700162520ustar00rootroot00000000000000 #ifndef __BIOS_H #define __BIOS_H #include union REGS { struct { unsigned int ax, bx, cx, dx, si, di, cflag, flags; } x; struct { unsigned char al, ah, bl, bh, cl, ch, dl, dh; } h; }; struct SREGS { unsigned int es, cs, ss, ds; }; unsigned int __get_cs __P((void)); unsigned int __get_ds __P((void)); unsigned int __get_es __P((void)); void __set_es __P((unsigned int seg)); int __peek_es __P((unsigned int off)); int __deek_es __P((unsigned int off)); #define movedata __movedata long _bios_get_dpt(drive); #ifdef __LIBC__ extern int __nofiles(); extern int (*__files)(); #define CMD_OPEN 0 #define CMD_READ 1 #define CMD_WRITE 2 #define CMD_LSEEK 3 #define CMD_CLOSE 4 #endif #endif dev86-0.16.21/libc/include/bsd/000077500000000000000000000000001231050321700157135ustar00rootroot00000000000000dev86-0.16.21/libc/include/bsd/bsd.h000066400000000000000000000017461231050321700166440ustar00rootroot00000000000000/* bsd.h - simplify porting BSD programs to Linux - rick sladkey */ /* make sure BSD features are enabled, i.e. __USE_BSD and _FAVOR_BSD */ /* cpp in gcc 2.3.3 is broken. #ifndef _BSD_BSD_H #define _BSD_BSD_H */ #define _BSD_SOURCE 1 #include #include /* some BSD progs expect MIN and MAX to be defined */ #define MIN(a, b) ((a) < (b) ? (a) : (b)) #define MAX(a, b) ((a) > (b) ? (a) : (b)) /* make sure we get L_SET and L_INCR, which is in a different place */ #include /* BSD has slight non-POSIX names (and meanings :-) for some things */ #define FAPPEND O_APPEND #include /* (absolute) max # characters in exec arglist */ #define NCARGS ARG_MAX /* ftpd uses this as bits per byte, I don't know why it's called NBBY */ #define NBBY CHAR_BIT /* gloss over slight differences between BSD direct and POSIX dirent */ #define d_namlen d_reclen #if 0 /* See */ typedef void sig_t; #endif /* #endif _BSD_BSD_H */ dev86-0.16.21/libc/include/bsd/errno.h000066400000000000000000000002741231050321700172140ustar00rootroot00000000000000/* make sure EWOULDBLOCK doesn't screw us up */ #ifndef _BSD_ERRNO_H #define _BSD_ERRNO_H #include_next #undef EWOULDBLOCK #define EWOULDBLOCK EAGAIN #endif /* _BSD_ERRNO_H */ dev86-0.16.21/libc/include/bsd/sgtty.h000066400000000000000000000043411231050321700172400ustar00rootroot00000000000000/* sgtty.h */ /* This file contains defintions to help make linux termios look like bsd sgtty. */ /* Copyright (c) 1992 Ross Biro This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef _BSD_SGTTY_H #define _BSD_SGTTY_H #include #define TIOCGETP 0x5481 #define TIOCSETP 0x5482 #define TIOCGETC 0x5483 #define TIOCSETC 0x5484 #define TIOCGLTC 0x5485 #define TIOCSLTC 0x5486 #define TIOCLGET 0x5487 #define TIOCLSET 0x5488 #define TIOCFLUSH 0x5489 #define TIOCSETN 0x548a struct sgttyb { unsigned short sg_flags; char sg_ispeed; char sg_ospeed; char sg_erase; char sg_kill; struct termios t; int check; }; struct tchars { char t_intrc; char t_quitc; char t_eofc; char t_startc; char t_stopc; char t_brkc; }; struct ltchars { char t_werasc; char t_suspc; char t_dsuspc; char t_rprntc; char t_flushc; char t_lnextc; }; #define O_RAW 1 #define O_LCASE 2 #define O_CRMOD 4 #define O_ECHO 8 #define O_ODDP 16 #define O_EVENP 32 #define O_CBREAK 64 /* these don't do anything yet. */ #define O_TBDELAY 0 #define O_LLITOUT 0 #define O_XTABS 0 #define O_ANYP 0 #ifndef _SGTTY_SOURCE #undef ioctl #define ioctl bsd_ioctl #undef RAW #define RAW O_RAW #undef LCASE #define LCASE O_LCASE #undef ECHO #define ECHO O_ECHO #undef CRMOD #define CRMOD O_CRMOD #undef ODDP #define ODDP O_ODDP #undef EVENP #define EVENP O_EVENP #undef CBREAK #define CBREAK O_CBREAK #undef TBDELAY #define TBDELAY O_TBDELAY #undef LLITOUT #define LLITOUT O_LLITOUT #undef XTABS #define XTABS O_XTABS #undef ANYP #define ANYP O_ANYP #endif #endif /* _BSD_SGTTY_H */ dev86-0.16.21/libc/include/bsd/signal.h000066400000000000000000000011331231050321700173370ustar00rootroot00000000000000#ifndef _BSD_SIGNAL_H #define _BSD_SIGNAL_H /* make sure we get BSD style signals (that don't need to be reset) */ #define __USE_BSD_SIGNAL #include_next /* use rough approximation of sigaction to sigvec, not completely safe! */ #define sigvec sigaction #define sv_mask sa_mask #define sv_flags sa_flags #define sv_handler sa_handler #define sv_onstack sa_mask /* ouch, this one really hurts */ /* BSD uses some non-POSIX signals without ifdefs */ #define SIGSYS SIGUNUSED /* BSD wants this typedef for signal handlers */ #define sig_t __sighandler_t #endif /* _BSD_SIGNAL_H */ dev86-0.16.21/libc/include/bsd/stdlib.h000066400000000000000000000003671231050321700173530ustar00rootroot00000000000000/* some things shouldn't be macros, get out your barf bag */ #ifndef _BSD_STDLIB_H #define _BSD_STDLIB_H #undef __MALLOC_0_RETURNS_NULL #define __MALLOC_0_RETURNS_NULL #include_next #undef atoi #undef atol #endif /* _BSD_STDLIB_H */ dev86-0.16.21/libc/include/bsd/sys/000077500000000000000000000000001231050321700165315ustar00rootroot00000000000000dev86-0.16.21/libc/include/bsd/sys/ttychars.h000066400000000000000000000001321231050321700205370ustar00rootroot00000000000000#ifndef _BSD_SYS_TTYCHARS_H #define _BSD_SYS_TTYCHARS_H #endif /* _BSD_SYS_TTYCHARS_H */ dev86-0.16.21/libc/include/bsd/tzfile.h000066400000000000000000000003501231050321700173570ustar00rootroot00000000000000#ifndef _BSD_TZFILE_H #define _BSD_TZFILE_H #define SECSPERDAY (60*60*24) #define DAYSPERNYEAR 365 #define DAYSPERLYEAR 366 #define isleap(y) (((y) % 4) == 0 && ((y) % 100) != 0 || ((y) % 400) == 0) #endif /* _BSD_TZFILE_H */ dev86-0.16.21/libc/include/bsd/unistd.h000066400000000000000000000001301231050321700173640ustar00rootroot00000000000000#include_next #include #include #include dev86-0.16.21/libc/include/conio.h000066400000000000000000000010401231050321700164160ustar00rootroot00000000000000 #ifndef __CONIO_H #define __CONIO_H #include int cprintf __P((char *, ...)); int cputs __P((char *)); int getch __P((void)); int getche __P((void)); int kbhit __P((void)); int putch __P((int)); int gotoxy __P((int, int)); #if 0 /* Unimplemented as yet */ char * cgets __P((char *)); int ungetch __P((int)); int cscanf __P((char *, ...)); #endif #if 0 /* Hummm */ unsigned outpw __P((unsigned int, unsigned int)); unsigned inpw __P((unsigned int)); int outp __P((unsigned int, int)); int inp __P((unsigned int)); #endif #endif dev86-0.16.21/libc/include/ctype.h000066400000000000000000000024601231050321700164420ustar00rootroot00000000000000/* * ctype.h Character classification and conversion */ #ifndef __CTYPE_H #define __CTYPE_H extern unsigned char __ctype[]; #define __CT_d 0x01 /* numeric digit */ #define __CT_u 0x02 /* upper case */ #define __CT_l 0x04 /* lower case */ #define __CT_c 0x08 /* control character */ #define __CT_s 0x10 /* whitespace */ #define __CT_p 0x20 /* punctuation */ #define __CT_x 0x40 /* hexadecimal */ /* Define these as simple old style ascii versions */ #define toupper(c) (((c)>='a'&&(c)<='z') ? (c)^0x20 : (c)) #define tolower(c) (((c)>='A'&&(c)<='Z') ? (c)^0x20 : (c)) #define _toupper(c) ((c)^0x20) #define _tolower(c) ((c)^0x20) #define toascii(c) ((c)&0x7F) #define __CT(c) (__ctype[1+(unsigned char)c]) /* Note the '!!' is a cast to 'bool' and even BCC deletes it in an if() */ #define isalnum(c) (!!(__CT(c)&(__CT_u|__CT_l|__CT_d))) #define isalpha(c) (!!(__CT(c)&(__CT_u|__CT_l))) #define isascii(c) (!((c)&~0x7F)) #define iscntrl(c) (!!(__CT(c)&__CT_c)) #define isdigit(c) (!!(__CT(c)&__CT_d)) #define isgraph(c) (!(__CT(c)&(__CT_c|__CT_s))) #define islower(c) (!!(__CT(c)&__CT_l)) #define isprint(c) (!(__CT(c)&__CT_c)) #define ispunct(c) (!!(__CT(c)&__CT_p)) #define isspace(c) (!!(__CT(c)&__CT_s)) #define isupper(c) (!!(__CT(c)&__CT_u)) #define isxdigit(c) (!!(__CT(c)&__CT_x)) #endif /* __CTYPE_H */ dev86-0.16.21/libc/include/dirent.h000066400000000000000000000027041231050321700166040ustar00rootroot00000000000000 #ifndef __DIRENT_H #define __DIRENT_H #include #include #ifndef MAXNAMLEN #define MAXNAMLEN 255 #endif /* Directory stream type. */ typedef struct { int dd_fd; /* file descriptor */ int dd_loc; /* offset in buffer */ int dd_size; /* # of valid entries in buffer */ struct dirent *dd_buf; /* -> directory buffer */ } DIR; /* stream data from opendir() */ typedef int (*__dir_select_fn_t) __P ((__const struct dirent *)); typedef int (*__dir_compar_fn_t) __P (( __const struct dirent * __const *, __const struct dirent * __const * )); struct dirent { long d_ino; off_t d_off; unsigned short d_reclen; char d_name[MAXNAMLEN+1]; }; extern DIR *opendir __P ((__const char *__name)); extern int closedir __P ((DIR * __dirp)); extern struct dirent *readdir __P ((DIR * __dirp)); extern void rewinddir __P ((DIR * __dirp)); extern void seekdir __P ((DIR * __dirp, off_t __pos)); extern off_t telldir __P ((DIR * __dirp)); /* Scan the directory DIR, calling SELECT on each directory entry. Entries for which SELECT returns nonzero are individually malloc'd, sorted using qsort with CMP, and collected in a malloc'd array in *NAMELIST. Returns the number of entries selected, or -1 on error. */ extern int scandir __P ((__const char *__dir, struct dirent ***__namelist, __dir_select_fn_t __select, __dir_compar_fn_t __compar)); #endif /* dirent.h */ dev86-0.16.21/libc/include/dos.h000066400000000000000000000005261231050321700161040ustar00rootroot00000000000000 #ifndef __DOS_H #define __DOS_H #include #include #ifdef __MSDOS__ extern unsigned int __envseg; extern unsigned int __psp; char * __fconv __P((char * fname)); unsigned int __segalloc __P((unsigned int paracount)); void __setvect __P((int i, long j)); long __getvect __P((int vecno)); #endif #endif dev86-0.16.21/libc/include/errno.h000066400000000000000000000000271231050321700164400ustar00rootroot00000000000000#include dev86-0.16.21/libc/include/fcntl.h000066400000000000000000000006051231050321700164230ustar00rootroot00000000000000#ifndef __FCNTL__H #define __FCNTL__H #include #include #include __SYSINC__(fcntl.h) #ifndef FNDELAY #define FNDELAY O_NDELAY #endif __BEGIN_DECLS extern int creat __P ((__const char * __filename, mode_t __mode)); extern int fcntl __P ((int __fildes,int __cmd, ...)); extern int open __P ((__const char * __filename, int __flags, ...)); __END_DECLS #endif dev86-0.16.21/libc/include/features.h000066400000000000000000000014601231050321700171330ustar00rootroot00000000000000 #ifndef __FEATURES_H #define __FEATURES_H #ifdef __STDC__ #define __P(x) x #define __const const /* Not really ansi */ #ifdef __BCC__ #define const #define volatile #endif #else /* K&R */ #define __P(x) () #define __const #define const #define volatile #endif /* Pick an OS sysinclude directory */ /* Use with #include __SYSINC__(errno.h) */ #ifdef __ELKS__ #define __SYSINC__(_h_file_) #endif #ifdef __linux__ #undef linux /* Eyuk! */ #define __SYSINC__(_h_file_) #endif #ifdef __MSDOS__ #define __SYSINC__(_h_file_) #endif #ifndef __SYSINC__ #define __SYSINC__(_h_file_) #endif /* No C++ */ #define __BEGIN_DECLS #define __END_DECLS /* GNUish things */ #define __CONSTVALUE #define __CONSTVALUE2 #include #endif dev86-0.16.21/libc/include/generic/000077500000000000000000000000001231050321700165575ustar00rootroot00000000000000dev86-0.16.21/libc/include/generic/errno.h000066400000000000000000000137341231050321700200650ustar00rootroot00000000000000#ifndef _I86_ERRNO_H #define _I86_ERRNO_H #define EPERM 1 /* Operation not permitted */ #define ENOENT 2 /* No such file or directory */ #define ESRCH 3 /* No such process */ #define EINTR 4 /* Interrupted system call */ #define EIO 5 /* I/O error */ #define ENXIO 6 /* No such device or address */ #define E2BIG 7 /* Arg list too long */ #define ENOEXEC 8 /* Exec format error */ #define EBADF 9 /* Bad file number */ #define ECHILD 10 /* No child processes */ #define EAGAIN 11 /* Try again */ #define ENOMEM 12 /* Out of memory */ #define EACCES 13 /* Permission denied */ #define EFAULT 14 /* Bad address */ #define ENOTBLK 15 /* Block device required */ #define EBUSY 16 /* Device or resource busy */ #define EEXIST 17 /* File exists */ #define EXDEV 18 /* Cross-device link */ #define ENODEV 19 /* No such device */ #define ENOTDIR 20 /* Not a directory */ #define EISDIR 21 /* Is a directory */ #define EINVAL 22 /* Invalid argument */ #define ENFILE 23 /* File table overflow */ #define EMFILE 24 /* Too many open files */ #define ENOTTY 25 /* Not a typewriter */ #define ETXTBSY 26 /* Text file busy */ #define EFBIG 27 /* File too large */ #define ENOSPC 28 /* No space left on device */ #define ESPIPE 29 /* Illegal seek */ #define EROFS 30 /* Read-only file system */ #define EMLINK 31 /* Too many links */ #define EPIPE 32 /* Broken pipe */ #define EDOM 33 /* Math argument out of domain of func */ #define ERANGE 34 /* Math result not representable */ #define EDEADLK 35 /* Resource deadlock would occur */ #define ENAMETOOLONG 36 /* File name too long */ #define ENOLCK 37 /* No record locks available */ #define ENOSYS 38 /* Function not implemented */ #define ENOTEMPTY 39 /* Directory not empty */ #define ELOOP 40 /* Too many symbolic links encountered */ #define EWOULDBLOCK EAGAIN /* Operation would block */ #if 0 #define ENOMSG 42 /* No message of desired type */ #define EIDRM 43 /* Identifier removed */ #define ECHRNG 44 /* Channel number out of range */ #define EL2NSYNC 45 /* Level 2 not synchronized */ #define EL3HLT 46 /* Level 3 halted */ #define EL3RST 47 /* Level 3 reset */ #define ELNRNG 48 /* Link number out of range */ #define EUNATCH 49 /* Protocol driver not attached */ #define ENOCSI 50 /* No CSI structure available */ #define EL2HLT 51 /* Level 2 halted */ #define EBADE 52 /* Invalid exchange */ #define EBADR 53 /* Invalid request descriptor */ #define EXFULL 54 /* Exchange full */ #define ENOANO 55 /* No anode */ #define EBADRQC 56 /* Invalid request code */ #define EBADSLT 57 /* Invalid slot */ #define EDEADLOCK 58 /* File locking deadlock error */ #define EBFONT 59 /* Bad font file format */ #define ENOSTR 60 /* Device not a stream */ #define ENODATA 61 /* No data available */ #define ETIME 62 /* Timer expired */ #define ENOSR 63 /* Out of streams resources */ #define ENONET 64 /* Machine is not on the network */ #define ENOPKG 65 /* Package not installed */ #define EREMOTE 66 /* Object is remote */ #define ENOLINK 67 /* Link has been severed */ #define EADV 68 /* Advertise error */ #define ESRMNT 69 /* Srmount error */ #define ECOMM 70 /* Communication error on send */ #define EPROTO 71 /* Protocol error */ #define EMULTIHOP 72 /* Multihop attempted */ #define EDOTDOT 73 /* RFS specific error */ #define EBADMSG 74 /* Not a data message */ #define EOVERFLOW 75 /* Value too large for defined data type */ #define ENOTUNIQ 76 /* Name not unique on network */ #define EBADFD 77 /* File descriptor in bad state */ #define EREMCHG 78 /* Remote address changed */ #define ELIBACC 79 /* Can not access a needed shared library */ #define ELIBBAD 80 /* Accessing a corrupted shared library */ #define ELIBSCN 81 /* .lib section in a.out corrupted */ #define ELIBMAX 82 /* Attempting to link in too many shared libraries */ #define ELIBEXEC 83 /* Cannot exec a shared library directly */ #define EILSEQ 84 /* Illegal byte sequence */ #define ERESTART 85 /* Interrupted system call should be restarted */ #define ESTRPIPE 86 /* Streams pipe error */ #define EUSERS 87 /* Too many users */ #define ENOTSOCK 88 /* Socket operation on non-socket */ #define EDESTADDRREQ 89 /* Destination address required */ #define EMSGSIZE 90 /* Message too long */ #define EPROTOTYPE 91 /* Protocol wrong type for socket */ #define ENOPROTOOPT 92 /* Protocol not available */ #define EPROTONOSUPPORT 93 /* Protocol not supported */ #define ESOCKTNOSUPPORT 94 /* Socket type not supported */ #define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */ #define EPFNOSUPPORT 96 /* Protocol family not supported */ #define EAFNOSUPPORT 97 /* Address family not supported by protocol */ #define EADDRINUSE 98 /* Address already in use */ #define EADDRNOTAVAIL 99 /* Cannot assign requested address */ #define ENETDOWN 100 /* Network is down */ #define ENETUNREACH 101 /* Network is unreachable */ #define ENETRESET 102 /* Network dropped connection because of reset */ #define ECONNABORTED 103 /* Software caused connection abort */ #define ECONNRESET 104 /* Connection reset by peer */ #define ENOBUFS 105 /* No buffer space available */ #define EISCONN 106 /* Transport endpoint is already connected */ #define ENOTCONN 107 /* Transport endpoint is not connected */ #define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */ #define ETOOMANYREFS 109 /* Too many references: cannot splice */ #define ETIMEDOUT 110 /* Connection timed out */ #define ECONNREFUSED 111 /* Connection refused */ #define EHOSTDOWN 112 /* Host is down */ #define EHOSTUNREACH 113 /* No route to host */ #define EALREADY 114 /* Operation already in progress */ #define EINPROGRESS 115 /* Operation now in progress */ #define ESTALE 116 /* Stale NFS file handle */ #define EUCLEAN 117 /* Structure needs cleaning */ #define ENOTNAM 118 /* Not a XENIX named type file */ #define ENAVAIL 119 /* No XENIX semaphores available */ #define EISNAM 120 /* Is a named type file */ #define EREMOTEIO 121 /* Remote I/O error */ #define EDQUOT 122 /* Quota exceeded */ #endif #endif dev86-0.16.21/libc/include/generic/fcntl.h000066400000000000000000000031171231050321700200400ustar00rootroot00000000000000#ifndef __UNK_FCNTL_H #define __UNK_FCNTL_H /* * Definitions taken from the i386 Linux kernel. */ /* open/fcntl */ #define O_ACCMODE 0003 #define O_RDONLY 00 #define O_WRONLY 01 #define O_RDWR 02 #define O_CREAT 0100 /* not fcntl */ #define O_EXCL 0200 /* not fcntl */ #define O_TRUNC 01000 /* not fcntl */ #define O_APPEND 02000 #if 0 #define O_NOCTTY 0400 /* not fcntl */ #define O_NONBLOCK 04000 #define O_NDELAY O_NONBLOCK #define O_SYNC 010000 /* Not supported */ #define FASYNC 020000 /* Not supported */ #endif #define F_DUPFD 0 /* dup */ #define F_GETFD 1 /* get f_flags */ #define F_SETFD 2 /* set f_flags */ #define F_GETFL 3 /* more flags (cloexec) */ #define F_SETFL 4 #define F_GETLK 5 #define F_SETLK 6 #define F_SETLKW 7 #if 0 #define F_SETOWN 8 /* for sockets. */ #define F_GETOWN 9 /* for sockets. */ /* for F_[GET|SET]FL */ #define FD_CLOEXEC 1 /* actually anything with low bit set goes */ /* for posix fcntl() and lockf() */ #define F_RDLCK 0 #define F_WRLCK 1 #define F_UNLCK 2 /* for old implementation of bsd flock () */ #define F_EXLCK 4 /* or 3 */ #define F_SHLCK 8 /* or 4 */ /* operations for bsd flock(), also used by the kernel implementation */ #define LOCK_SH 1 /* shared lock */ #define LOCK_EX 2 /* exclusive lock */ #define LOCK_NB 4 /* or'd with one of the above to prevent blocking */ #define LOCK_UN 8 /* remove lock */ #ifdef __KERNEL__ #define F_POSIX 1 #define F_FLOCK 2 #endif /* __KERNEL__ */ struct flock { short l_type; short l_whence; off_t l_start; off_t l_len; pid_t l_pid; }; #endif #endif dev86-0.16.21/libc/include/generic/types.h000066400000000000000000000005411231050321700200740ustar00rootroot00000000000000 /* arch/i86/include/asm/types.h - Basic Linux/MT data types. */ #ifndef __GENERIC_TYPES_H #define __GENERIC_TYPES_H #include typedef __u32 off_t; typedef __u32 time_t; typedef __u16 mode_t; typedef __u32 loff_t; typedef __u32 speed_t; typedef __u32 tcflag_t; typedef __u8 cc_t; typedef int ptrdiff_t; typedef int size_t; #endif dev86-0.16.21/libc/include/getopt.h000066400000000000000000000006351231050321700166220ustar00rootroot00000000000000/* Copyright (C) 1996 Robert de Bath * This file is part of the Linux-8086 C library and is distributed * under the GNU Library General Public License. */ #ifndef __GETOPT_H #define __GETOPT_H #include extern char *optarg; extern int opterr; extern int optind; extern int getopt __P((int argc, char *const *argv, const char *shortopts)); #endif /* __GETOPT_H */ dev86-0.16.21/libc/include/grp.h000066400000000000000000000014421231050321700161050ustar00rootroot00000000000000#ifndef __GRP_H #define __GRP_H #include #include #include /* The group structure */ struct group { char *gr_name; /* Group name. */ char *gr_passwd; /* Password. */ gid_t gr_gid; /* Group ID. */ char **gr_mem; /* Member list. */ }; extern void setgrent __P ((void)); extern void endgrent __P ((void)); extern struct group * getgrent __P ((void)); extern struct group * getgrgid __P ((__const gid_t gid)); extern struct group * getgrnam __P ((__const char * name)); extern struct group * fgetgrent __P ((FILE * file)); extern int setgroups __P ((size_t n, __const gid_t * groups)); extern int initgroups __P ((__const char * user, gid_t gid)); #ifdef __LIBC__ extern struct group * __getgrent __P ((int grp_fd)); #endif #endif /* _GRP_H */ dev86-0.16.21/libc/include/limits.h000066400000000000000000000004021231050321700166110ustar00rootroot00000000000000/* Copyright (C) 1996 Robert de Bath * This file is part of the Linux-8086 C library and is distributed * under the GNU Library General Public License. */ #ifndef __LIMITS_H #define __LIMITS_H #include #endif dev86-0.16.21/libc/include/linux/000077500000000000000000000000001231050321700163025ustar00rootroot00000000000000dev86-0.16.21/libc/include/linux/errno.h000066400000000000000000000137161231050321700176100ustar00rootroot00000000000000#ifndef _I86_ERRNO_H #define _I86_ERRNO_H #define EPERM 1 /* Operation not permitted */ #define ENOENT 2 /* No such file or directory */ #define ESRCH 3 /* No such process */ #define EINTR 4 /* Interrupted system call */ #define EIO 5 /* I/O error */ #define ENXIO 6 /* No such device or address */ #define E2BIG 7 /* Arg list too long */ #define ENOEXEC 8 /* Exec format error */ #define EBADF 9 /* Bad file number */ #define ECHILD 10 /* No child processes */ #define EAGAIN 11 /* Try again */ #define ENOMEM 12 /* Out of memory */ #define EACCES 13 /* Permission denied */ #define EFAULT 14 /* Bad address */ #define ENOTBLK 15 /* Block device required */ #define EBUSY 16 /* Device or resource busy */ #define EEXIST 17 /* File exists */ #define EXDEV 18 /* Cross-device link */ #define ENODEV 19 /* No such device */ #define ENOTDIR 20 /* Not a directory */ #define EISDIR 21 /* Is a directory */ #define EINVAL 22 /* Invalid argument */ #define ENFILE 23 /* File table overflow */ #define EMFILE 24 /* Too many open files */ #define ENOTTY 25 /* Not a typewriter */ #define ETXTBSY 26 /* Text file busy */ #define EFBIG 27 /* File too large */ #define ENOSPC 28 /* No space left on device */ #define ESPIPE 29 /* Illegal seek */ #define EROFS 30 /* Read-only file system */ #define EMLINK 31 /* Too many links */ #define EPIPE 32 /* Broken pipe */ #define EDOM 33 /* Math argument out of domain of func */ #define ERANGE 34 /* Math result not representable */ #define EDEADLK 35 /* Resource deadlock would occur */ #define ENAMETOOLONG 36 /* File name too long */ #define ENOLCK 37 /* No record locks available */ #define ENOSYS 38 /* Function not implemented */ #define ENOTEMPTY 39 /* Directory not empty */ #define ELOOP 40 /* Too many symbolic links encountered */ #define EWOULDBLOCK EAGAIN /* Operation would block */ #define ENOMSG 42 /* No message of desired type */ #define EIDRM 43 /* Identifier removed */ #define ECHRNG 44 /* Channel number out of range */ #define EL2NSYNC 45 /* Level 2 not synchronized */ #define EL3HLT 46 /* Level 3 halted */ #define EL3RST 47 /* Level 3 reset */ #define ELNRNG 48 /* Link number out of range */ #define EUNATCH 49 /* Protocol driver not attached */ #define ENOCSI 50 /* No CSI structure available */ #define EL2HLT 51 /* Level 2 halted */ #define EBADE 52 /* Invalid exchange */ #define EBADR 53 /* Invalid request descriptor */ #define EXFULL 54 /* Exchange full */ #define ENOANO 55 /* No anode */ #define EBADRQC 56 /* Invalid request code */ #define EBADSLT 57 /* Invalid slot */ #define EDEADLOCK 58 /* File locking deadlock error */ #define EBFONT 59 /* Bad font file format */ #define ENOSTR 60 /* Device not a stream */ #define ENODATA 61 /* No data available */ #define ETIME 62 /* Timer expired */ #define ENOSR 63 /* Out of streams resources */ #define ENONET 64 /* Machine is not on the network */ #define ENOPKG 65 /* Package not installed */ #define EREMOTE 66 /* Object is remote */ #define ENOLINK 67 /* Link has been severed */ #define EADV 68 /* Advertise error */ #define ESRMNT 69 /* Srmount error */ #define ECOMM 70 /* Communication error on send */ #define EPROTO 71 /* Protocol error */ #define EMULTIHOP 72 /* Multihop attempted */ #define EDOTDOT 73 /* RFS specific error */ #define EBADMSG 74 /* Not a data message */ #define EOVERFLOW 75 /* Value too large for defined data type */ #define ENOTUNIQ 76 /* Name not unique on network */ #define EBADFD 77 /* File descriptor in bad state */ #define EREMCHG 78 /* Remote address changed */ #define ELIBACC 79 /* Can not access a needed shared library */ #define ELIBBAD 80 /* Accessing a corrupted shared library */ #define ELIBSCN 81 /* .lib section in a.out corrupted */ #define ELIBMAX 82 /* Attempting to link in too many shared libraries */ #define ELIBEXEC 83 /* Cannot exec a shared library directly */ #define EILSEQ 84 /* Illegal byte sequence */ #define ERESTART 85 /* Interrupted system call should be restarted */ #define ESTRPIPE 86 /* Streams pipe error */ #define EUSERS 87 /* Too many users */ #define ENOTSOCK 88 /* Socket operation on non-socket */ #define EDESTADDRREQ 89 /* Destination address required */ #define EMSGSIZE 90 /* Message too long */ #define EPROTOTYPE 91 /* Protocol wrong type for socket */ #define ENOPROTOOPT 92 /* Protocol not available */ #define EPROTONOSUPPORT 93 /* Protocol not supported */ #define ESOCKTNOSUPPORT 94 /* Socket type not supported */ #define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */ #define EPFNOSUPPORT 96 /* Protocol family not supported */ #define EAFNOSUPPORT 97 /* Address family not supported by protocol */ #define EADDRINUSE 98 /* Address already in use */ #define EADDRNOTAVAIL 99 /* Cannot assign requested address */ #define ENETDOWN 100 /* Network is down */ #define ENETUNREACH 101 /* Network is unreachable */ #define ENETRESET 102 /* Network dropped connection because of reset */ #define ECONNABORTED 103 /* Software caused connection abort */ #define ECONNRESET 104 /* Connection reset by peer */ #define ENOBUFS 105 /* No buffer space available */ #define EISCONN 106 /* Transport endpoint is already connected */ #define ENOTCONN 107 /* Transport endpoint is not connected */ #define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */ #define ETOOMANYREFS 109 /* Too many references: cannot splice */ #define ETIMEDOUT 110 /* Connection timed out */ #define ECONNREFUSED 111 /* Connection refused */ #define EHOSTDOWN 112 /* Host is down */ #define EHOSTUNREACH 113 /* No route to host */ #define EALREADY 114 /* Operation already in progress */ #define EINPROGRESS 115 /* Operation now in progress */ #define ESTALE 116 /* Stale NFS file handle */ #define EUCLEAN 117 /* Structure needs cleaning */ #define ENOTNAM 118 /* Not a XENIX named type file */ #define ENAVAIL 119 /* No XENIX semaphores available */ #define EISNAM 120 /* Is a named type file */ #define EREMOTEIO 121 /* Remote I/O error */ #define EDQUOT 122 /* Quota exceeded */ #endif dev86-0.16.21/libc/include/linux/fcntl.h000066400000000000000000000031051231050321700175600ustar00rootroot00000000000000#ifndef __LINUX_FCNTL_H #define __LINUX_FCNTL_H /* * Definitions taken from the i386 Linux kernel. */ /* open/fcntl */ #define O_ACCMODE 0003 #define O_RDONLY 00 #define O_WRONLY 01 #define O_RDWR 02 #define O_CREAT 0100 /* not fcntl */ #define O_EXCL 0200 /* not fcntl */ #define O_NOCTTY 0400 /* not fcntl */ #define O_TRUNC 01000 /* not fcntl */ #define O_APPEND 02000 #define O_NONBLOCK 04000 #define O_NDELAY O_NONBLOCK #if 0 #define O_SYNC 010000 /* Not supported */ #define FASYNC 020000 /* Not supported */ #endif #define F_DUPFD 0 /* dup */ #define F_GETFD 1 /* get f_flags */ #define F_SETFD 2 /* set f_flags */ #define F_GETFL 3 /* more flags (cloexec) */ #define F_SETFL 4 #define F_GETLK 5 #define F_SETLK 6 #define F_SETLKW 7 #define F_SETOWN 8 /* for sockets. */ #define F_GETOWN 9 /* for sockets. */ /* for F_[GET|SET]FL */ #define FD_CLOEXEC 1 /* actually anything with low bit set goes */ /* for posix fcntl() and lockf() */ #define F_RDLCK 0 #define F_WRLCK 1 #define F_UNLCK 2 /* for old implementation of bsd flock () */ #define F_EXLCK 4 /* or 3 */ #define F_SHLCK 8 /* or 4 */ /* operations for bsd flock(), also used by the kernel implementation */ #define LOCK_SH 1 /* shared lock */ #define LOCK_EX 2 /* exclusive lock */ #define LOCK_NB 4 /* or'd with one of the above to prevent blocking */ #define LOCK_UN 8 /* remove lock */ #ifdef __KERNEL__ #define F_POSIX 1 #define F_FLOCK 2 #endif /* __KERNEL__ */ struct flock { short l_type; short l_whence; off_t l_start; off_t l_len; pid_t l_pid; }; #endif dev86-0.16.21/libc/include/linux/ioctl.h000066400000000000000000000000001231050321700175530ustar00rootroot00000000000000dev86-0.16.21/libc/include/linux/mman.h000066400000000000000000000033411231050321700174040ustar00rootroot00000000000000#ifndef _SYS_MMAN_H #define _SYS_MMAN_H #include #include #define PROT_READ 0x1 /* page can be read */ #define PROT_WRITE 0x2 /* page can be written */ #define PROT_EXEC 0x4 /* page can be executed */ #define PROT_NONE 0x0 /* page can not be accessed */ #define MAP_SHARED 0x01 /* Share changes */ #define MAP_PRIVATE 0x02 /* Changes are private */ #define MAP_TYPE 0x0f /* Mask for type of mapping */ #define MAP_FIXED 0x10 /* Interpret addr exactly */ #define MAP_ANONYMOUS 0x20 /* don't use a file */ #define MAP_GROWSDOWN 0x0100 /* stack-like segment */ #define MAP_DENYWRITE 0x0800 /* ETXTBSY */ #define MAP_EXECUTABLE 0x1000 /* mark it as a executable */ #define MAP_LOCKED 0x2000 /* pages are locked */ #define MS_ASYNC 1 /* sync memory asynchronously */ #define MS_INVALIDATE 2 /* invalidate the caches */ #define MS_SYNC 4 /* synchronous memory sync */ #define MCL_CURRENT 1 /* lock all current mappings */ #define MCL_FUTURE 2 /* lock all future mappings */ /* compatibility flags */ #define MAP_ANON MAP_ANONYMOUS #define MAP_FILE 0 #define MREMAP_MAYMOVE 1 extern __ptr_t mmap __P((__ptr_t __addr, size_t __len, int __prot, int __flags, int __fd, off_t __off)); extern int munmap __P((__ptr_t __addr, size_t __len)); extern int mprotect __P ((__const __ptr_t __addr, size_t __len, int __prot)); extern int msync __P((__ptr_t __addr, size_t __len, int __flags)); extern int mlock __P((__const __ptr_t __addr, size_t __len)); extern int munlock __P((__const __ptr_t __addr, size_t __len)); extern int mlockall __P((int __flags)); extern int munlockall __P((void)); extern __ptr_t mremap __P((__ptr_t __addr, size_t __old_len, size_t __new_len, int __may_move)); #endif /* _SYS_MMAN_H */ dev86-0.16.21/libc/include/linux/resource.h000066400000000000000000000041441231050321700203050ustar00rootroot00000000000000/* * Resource control/accounting header file for linux-86 */ #ifndef __LINUX_RESOURCE_H #define __LINUX_RESOURCE_H #include #include #include #define RUSAGE_SELF 0 #define RUSAGE_CHILDREN (-1) #define RUSAGE_BOTH (-2) /* sys_wait4() uses this */ struct rusage { struct timeval ru_utime; /* user time used */ struct timeval ru_stime; /* system time used */ long ru_maxrss; /* maximum resident set size */ long ru_ixrss; /* integral shared memory size */ long ru_idrss; /* integral unshared data size */ long ru_isrss; /* integral unshared stack size */ long ru_minflt; /* page reclaims */ long ru_majflt; /* page faults */ long ru_nswap; /* swaps */ long ru_inblock; /* block input operations */ long ru_oublock; /* block output operations */ long ru_msgsnd; /* messages sent */ long ru_msgrcv; /* messages received */ long ru_nsignals; /* signals received */ long ru_nvcsw; /* voluntary context switches */ long ru_nivcsw; /* involuntary " */ }; #define RLIM_INFINITY ((long)(~0UL>>1)) struct rlimit { long rlim_cur; long rlim_max; }; #define PRIO_MIN (-20) #define PRIO_MAX 20 #define PRIO_PROCESS 0 #define PRIO_PGRP 1 #define PRIO_USER 2 #define RLIMIT_CPU 0 /* CPU time in ms */ #define RLIMIT_FSIZE 1 /* Maximum filesize */ #define RLIMIT_DATA 2 /* max data size */ #define RLIMIT_STACK 3 /* max stack size */ #define RLIMIT_CORE 4 /* max core file size */ #define RLIMIT_RSS 5 /* max resident set size */ #define RLIMIT_NPROC 6 /* max number of processes */ #define RLIMIT_NOFILE 7 /* max number of open files */ #define RLIMIT_MEMLOCK 8 /* max locked-in-memory address space */ #define RLIM_NLIMITS 9 extern int getrlimit __P ((int __resource, struct rlimit *__rlp)); extern int setrlimit __P ((int __resource, __const struct rlimit *__rlp)); extern int getpriority __P((int __which, int __who)); extern int setpriority __P((int __which, int __who, int __prio)); extern int __getrusage __P ((int __who, struct rusage *__rusage)); extern int getrusage __P ((int __who, struct rusage *__rusage)); #endif /* __LINUX_RESOURCE_H */ dev86-0.16.21/libc/include/linux/stat.h000066400000000000000000000033701231050321700174310ustar00rootroot00000000000000#ifndef _LINUX_STAT_H #define _LINUX_STAT_H /* This is for Linux-386, ho hum, I wish BCC could compile the proper one */ #define mknod __dv32_mknod #define stat __dv32_stat #define lstat __dv32_lstat #define fstat __dv32_fstat struct stat { dev_t st_dev; ino_t st_ino; umode_t st_mode; nlink_t st_nlink; uid_t st_uid; gid_t st_gid; dev_t st_rdev; unsigned short __pad2; off_t st_size; unsigned long st_blksize; unsigned long st_blocks; time_t st_atime; unsigned long __unused1; time_t st_mtime; unsigned long __unused2; time_t st_ctime; unsigned long __unused3; unsigned long __unused4; unsigned long __unused5; }; #define S_IFMT 00170000 #define S_IFSOCK 0140000 #define S_IFLNK 0120000 #define S_IFREG 0100000 #define S_IFBLK 0060000 #define S_IFDIR 0040000 #define S_IFCHR 0020000 #define S_IFIFO 0010000 #define S_ISUID 0004000 #define S_ISGID 0002000 #define S_ISVTX 0001000 #define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) #define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) #define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) #define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR) #define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK) #define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO) #define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK) #define S_IRWXU 00700 #define S_IRUSR 00400 #define S_IWUSR 00200 #define S_IXUSR 00100 #define S_IRWXG 00070 #define S_IRGRP 00040 #define S_IWGRP 00020 #define S_IXGRP 00010 #define S_IRWXO 00007 #define S_IROTH 00004 #define S_IWOTH 00002 #define S_IXOTH 00001 #ifdef __KERNEL__ #define S_IRWXUGO (S_IRWXU|S_IRWXG|S_IRWXO) #define S_IALLUGO (S_ISUID|S_ISGID|S_ISVTX|S_IRWXUGO) #define S_IRUGO (S_IRUSR|S_IRGRP|S_IROTH) #define S_IWUGO (S_IWUSR|S_IWGRP|S_IWOTH) #define S_IXUGO (S_IXUSR|S_IXGRP|S_IXOTH) #endif #endif dev86-0.16.21/libc/include/linux/termios.h000066400000000000000000000152301231050321700201360ustar00rootroot00000000000000#ifndef __LINUX_TERMIOS_H #define __LINUX_TERMIOS_H /* This is just a magic number to make these relatively unique ('T') */ #define __TERMIOS_MAJ ('T'<<8) #define TCGETS (__TERMIOS_MAJ+0x01) #define TCSETS (__TERMIOS_MAJ+0x02) #define TCSETSW (__TERMIOS_MAJ+0x03) #define TCSETSF (__TERMIOS_MAJ+0x04) #define TCGETA (__TERMIOS_MAJ+0x05) #define TCSETA (__TERMIOS_MAJ+0x06) #define TCSETAW (__TERMIOS_MAJ+0x07) #define TCSETAF (__TERMIOS_MAJ+0x08) #define TCSBRK (__TERMIOS_MAJ+0x09) #define TCXONC (__TERMIOS_MAJ+0x0A) #define TCFLSH (__TERMIOS_MAJ+0x0B) #define TIOCEXCL (__TERMIOS_MAJ+0x0C) #define TIOCNXCL (__TERMIOS_MAJ+0x0D) #define TIOCSCTTY (__TERMIOS_MAJ+0x0E) #define TIOCGPGRP (__TERMIOS_MAJ+0x0F) #define TIOCSPGRP (__TERMIOS_MAJ+0x10) #define TIOCOUTQ (__TERMIOS_MAJ+0x11) #define TIOCSTI (__TERMIOS_MAJ+0x12) #define TIOCGWINSZ (__TERMIOS_MAJ+0x13) #define TIOCSWINSZ (__TERMIOS_MAJ+0x14) #define TIOCMGET (__TERMIOS_MAJ+0x15) #define TIOCMBIS (__TERMIOS_MAJ+0x16) #define TIOCMBIC (__TERMIOS_MAJ+0x17) #define TIOCMSET (__TERMIOS_MAJ+0x18) #define TIOCGSOFTCAR (__TERMIOS_MAJ+0x19) #define TIOCSSOFTCAR (__TERMIOS_MAJ+0x1A) #define FIONREAD (__TERMIOS_MAJ+0x1B) #define TIOCINQ FIONREAD #define TIOCLINUX (__TERMIOS_MAJ+0x1C) #define TIOCCONS (__TERMIOS_MAJ+0x1D) #define TIOCGSERIAL (__TERMIOS_MAJ+0x1E) #define TIOCSSERIAL (__TERMIOS_MAJ+0x1F) #define TIOCPKT (__TERMIOS_MAJ+0x20) #define FIONBIO (__TERMIOS_MAJ+0x21) #define TIOCNOTTY (__TERMIOS_MAJ+0x22) #define TIOCSETD (__TERMIOS_MAJ+0x23) #define TIOCGETD (__TERMIOS_MAJ+0x24) #define TCSBRKP (__TERMIOS_MAJ+0x25) /* Needed for POSIX tcsendbreak */ #define TIOCTTYGSTRUCT (__TERMIOS_MAJ+0x26) /* For debugging only */ #define FIONCLEX (__TERMIOS_MAJ+0x50) /* these numbers need to be adjusted. */ #define FIOCLEX (__TERMIOS_MAJ+0x51) #define FIOASYNC (__TERMIOS_MAJ+0x52) #define TIOCSERCONFIG (__TERMIOS_MAJ+0x53) #define TIOCSERGWILD (__TERMIOS_MAJ+0x54) #define TIOCSERSWILD (__TERMIOS_MAJ+0x55) #define TIOCGLCKTRMIOS (__TERMIOS_MAJ+0x56) #define TIOCSLCKTRMIOS (__TERMIOS_MAJ+0x57) #define TIOCSERGSTRUCT (__TERMIOS_MAJ+0x58) /* For debugging only */ #define TIOCSERGETLSR (__TERMIOS_MAJ+0x59) /* Get line status register */ #define TIOCSERGETMULTI (__TERMIOS_MAJ+0x5A) /* Get multiport config */ #define TIOCSERSETMULTI (__TERMIOS_MAJ+0x5B) /* Set multiport config */ /* Used for packet mode */ #define TIOCPKT_DATA 0 #define TIOCPKT_FLUSHREAD 1 #define TIOCPKT_FLUSHWRITE 2 #define TIOCPKT_STOP 4 #define TIOCPKT_START 8 #define TIOCPKT_NOSTOP 16 #define TIOCPKT_DOSTOP 32 struct winsize { unsigned short ws_row; unsigned short ws_col; unsigned short ws_xpixel; unsigned short ws_ypixel; }; #define NCC 8 struct termio { unsigned short c_iflag; /* input mode flags */ unsigned short c_oflag; /* output mode flags */ unsigned short c_cflag; /* control mode flags */ unsigned short c_lflag; /* local mode flags */ unsigned char c_line; /* line discipline */ unsigned char c_cc[NCC]; /* control characters */ }; #define NCCS 19 struct termios { tcflag_t c_iflag; /* input mode flags */ tcflag_t c_oflag; /* output mode flags */ tcflag_t c_cflag; /* control mode flags */ tcflag_t c_lflag; /* local mode flags */ cc_t c_line; /* line discipline */ cc_t c_cc[NCCS]; /* control characters */ }; /* c_cc characters */ #define VINTR 0 #define VQUIT 1 #define VERASE 2 #define VKILL 3 #define VEOF 4 #define VTIME 5 #define VMIN 6 #define VSWTC 7 #define VSTART 8 #define VSTOP 9 #define VSUSP 10 #define VEOL 11 #define VREPRINT 12 #define VDISCARD 13 #define VWERASE 14 #define VLNEXT 15 #define VEOL2 16 /* c_iflag bits */ #define IGNBRK 0000001 #define BRKINT 0000002 #define IGNPAR 0000004 #define PARMRK 0000010 #define INPCK 0000020 #define ISTRIP 0000040 #define INLCR 0000100 #define IGNCR 0000200 #define ICRNL 0000400 #define IUCLC 0001000 #define IXON 0002000 #define IXANY 0004000 #define IXOFF 0010000 #define IMAXBEL 0020000 /* c_oflag bits */ #define OPOST 0000001 #define OLCUC 0000002 #define ONLCR 0000004 #define OCRNL 0000010 #define ONOCR 0000020 #define ONLRET 0000040 #define OFILL 0000100 #define OFDEL 0000200 #define NLDLY 0000400 #define NL0 0000000 #define NL1 0000400 #define CRDLY 0003000 #define CR0 0000000 #define CR1 0001000 #define CR2 0002000 #define CR3 0003000 #define TABDLY 0014000 #define TAB0 0000000 #define TAB1 0004000 #define TAB2 0010000 #define TAB3 0014000 #define XTABS 0014000 #define BSDLY 0020000 #define BS0 0000000 #define BS1 0020000 #define VTDLY 0040000 #define VT0 0000000 #define VT1 0040000 #define FFDLY 0100000 #define FF0 0000000 #define FF1 0100000 /* c_cflag bit meaning */ #define CBAUD 0010017 #define B0 0000000 /* hang up */ #define B50 0000001 #define B75 0000002 #define B110 0000003 #define B134 0000004 #define B150 0000005 #define B200 0000006 #define B300 0000007 #define B600 0000010 #define B1200 0000011 #define B1800 0000012 #define B2400 0000013 #define B4800 0000014 #define B9600 0000015 #define B19200 0000016 #define B38400 0000017 #define EXTA B19200 #define EXTB B38400 #define CSIZE 0000060 #define CS5 0000000 #define CS6 0000020 #define CS7 0000040 #define CS8 0000060 #define CSTOPB 0000100 #define CREAD 0000200 #define PARENB 0000400 #define PARODD 0001000 #define HUPCL 0002000 #define CLOCAL 0004000 #define CBAUDEX 0010000 #define B57600 0010001 #define B115200 0010002 #define B230400 0010003 #define CIBAUD 002003600000 /* input baud rate (not used) */ #define CRTSCTS 020000000000 /* flow control */ /* c_lflag bits */ #define ISIG 0000001 #define ICANON 0000002 #define XCASE 0000004 #define ECHO 0000010 #define ECHOE 0000020 #define ECHOK 0000040 #define ECHONL 0000100 #define NOFLSH 0000200 #define TOSTOP 0000400 #define ECHOCTL 0001000 #define ECHOPRT 0002000 #define ECHOKE 0004000 #define FLUSHO 0010000 #define PENDIN 0040000 #define IEXTEN 0100000 /* modem lines */ #define TIOCM_LE 0x001 #define TIOCM_DTR 0x002 #define TIOCM_RTS 0x004 #define TIOCM_ST 0x008 #define TIOCM_SR 0x010 #define TIOCM_CTS 0x020 #define TIOCM_CAR 0x040 #define TIOCM_RNG 0x080 #define TIOCM_DSR 0x100 #define TIOCM_CD TIOCM_CAR #define TIOCM_RI TIOCM_RNG /* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */ #define TIOCSER_TEMT 0x01 /* Transmitter physically empty */ /* tcflow() and TCXONC use these */ #define TCOOFF 0 #define TCOON 1 #define TCIOFF 2 #define TCION 3 /* tcflush() and TCFLSH use these */ #define TCIFLUSH 0 #define TCOFLUSH 1 #define TCIOFLUSH 2 /* tcsetattr uses these */ #define TCSANOW 0 #define TCSADRAIN 1 #define TCSAFLUSH 2 /* line disciplines */ #define N_TTY 0 #define N_SLIP 1 #define N_MOUSE 2 #define N_PPP 3 #endif /* __LINUXMT_TERMIOS_H */ dev86-0.16.21/libc/include/linux/types.h000066400000000000000000000006641231050321700176250ustar00rootroot00000000000000#ifndef __LINUX_TYPES_H #define __LINUX_TYPES_H #include typedef __u32 off_t; typedef __u16 pid_t; typedef __u16 uid_t; typedef __u16 gid_t; typedef __u32 time_t; typedef __u16 umode_t; typedef __u16 nlink_t; typedef __u16 mode_t; typedef __u32 loff_t; typedef __u32 speed_t; typedef __u32 dev_t; typedef __u32 ino_t; typedef __u32 tcflag_t; typedef __u8 cc_t; typedef __u32 size_t; typedef int ptrdiff_t; #endif dev86-0.16.21/libc/include/linux/utsname.h000066400000000000000000000003741231050321700201330ustar00rootroot00000000000000#ifndef __LINUX_UTSNAME_H #define __LINUX_UTSNAME_H struct utsname { char sysname[65]; char nodename[65]; char release[65]; char version[65]; char machine[65]; char domainname[65]; }; extern int uname __P ((struct utsname * __utsbuf)); #endif dev86-0.16.21/libc/include/linux/vm86.h000066400000000000000000000052771231050321700172660ustar00rootroot00000000000000#if !__AS386_16__ #ifndef _SYS_VM86_H #define _SYS_VM86_H #include #ifndef _LINUX_VM86_H #define _LINUX_VM86_H /* * I'm guessing at the VIF/VIP flag usage, but hope that this is how * the Pentium uses them. Linux will return from vm86 mode when both * VIF and VIP is set. * * On a Pentium, we could probably optimize the virtual flags directly * in the eflags register instead of doing it "by hand" in vflags... * * Linus */ #define TF_MASK 0x00000100 #define IF_MASK 0x00000200 #define IOPL_MASK 0x00003000 #define NT_MASK 0x00004000 #define VM_MASK 0x00020000 #define AC_MASK 0x00040000 #define VIF_MASK 0x00080000 /* virtual interrupt flag */ #define VIP_MASK 0x00100000 /* virtual interrupt pending */ #define ID_MASK 0x00200000 #define BIOSSEG 0x0f000 #define CPU_086 0 #define CPU_186 1 #define CPU_286 2 #define CPU_386 3 #define CPU_486 4 #define CPU_586 5 /* * Return values for the 'vm86()' system call */ #define VM86_TYPE(retval) ((retval) & 0xff) #define VM86_ARG(retval) ((retval) >> 8) #define VM86_SIGNAL 0 /* return due to signal */ #define VM86_UNKNOWN 1 /* unhandled GP fault - IO-instruction or similar */ #define VM86_INTx 2 /* int3/int x instruction (ARG = x) */ #define VM86_STI 3 /* sti/popf/iret instruction enabled virtual interrupts */ /* * This is the stack-layout when we have done a "SAVE_ALL" from vm86 * mode - the main change is that the old segment descriptors aren't * useful any more and are forced to be zero by the kernel (and the * hardware when a trap occurs), and the real segment descriptors are * at the end of the structure. Look at ptrace.h to see the "normal" * setup. */ struct vm86_regs { /* * normal regs, with special meaning for the segment descriptors.. */ long ebx; long ecx; long edx; long esi; long edi; long ebp; long eax; long __null_ds; long __null_es; long __null_fs; long __null_gs; long orig_eax; long eip; unsigned short cs, __csh; long eflags; long esp; unsigned short ss, __ssh; /* * these are specific to v86 mode: */ unsigned short es, __esh; unsigned short ds, __dsh; unsigned short fs, __fsh; unsigned short gs, __gsh; }; struct revectored_struct { unsigned long __map[8]; /* 256 bits */ }; struct vm86_struct { struct vm86_regs regs; unsigned long flags; unsigned long screen_bitmap; unsigned long cpu_type; struct revectored_struct int_revectored; struct revectored_struct int21_revectored; }; /* * flags masks */ #define VM86_SCREEN_BITMAP 0x0001 #ifdef __KERNEL__ void handle_vm86_fault(struct vm86_regs *, long); void handle_vm86_debug(struct vm86_regs *, long); #endif #endif __BEGIN_DECLS extern vm86(struct vm86_struct * __info); __END_DECLS #endif /*_SYS_VM86_H */ #endif dev86-0.16.21/libc/include/math.h000066400000000000000000000000001231050321700162330ustar00rootroot00000000000000dev86-0.16.21/libc/include/memory.h000066400000000000000000000000241231050321700166200ustar00rootroot00000000000000#include dev86-0.16.21/libc/include/msdos/000077500000000000000000000000001231050321700162705ustar00rootroot00000000000000dev86-0.16.21/libc/include/msdos/errno.h000066400000000000000000000035441231050321700175740ustar00rootroot00000000000000#ifndef __MSDOS_ERRNO_H #define __MSDOS_ERRNO_H #define EPERM 1 /* Operation not permitted */ #define ENOENT 2 /* No such file or directory */ #define ESRCH 3 /* No such process */ #define EINTR 4 /* Interrupted system call */ #define EIO 5 /* I/O error */ #define ENXIO 6 /* No such device or address */ #define E2BIG 7 /* Arg list too long */ #define ENOEXEC 8 /* Exec format error */ #define EBADF 9 /* Bad file number */ #define ECHILD 10 /* No child processes */ #define EAGAIN 11 /* Try again */ #define ENOMEM 12 /* Out of memory */ #define EACCES 13 /* Permission denied */ #define EFAULT 14 /* Bad address */ #define ENOTBLK 15 /* Block device required */ #define EBUSY 16 /* Device or resource busy */ #define EEXIST 17 /* File exists */ #define EXDEV 18 /* Cross-device link */ #define ENODEV 19 /* No such device */ #define ENOTDIR 20 /* Not a directory */ #define EISDIR 21 /* Is a directory */ #define EINVAL 22 /* Invalid argument */ #define ENFILE 23 /* File table overflow */ #define EMFILE 24 /* Too many open files */ #define ENOTTY 25 /* Not a typewriter */ #define ETXTBSY 26 /* Text file busy */ #define EFBIG 27 /* File too large */ #define ENOSPC 28 /* No space left on device */ #define ESPIPE 29 /* Illegal seek */ #define EROFS 30 /* Read-only file system */ #define EMLINK 31 /* Too many links */ #define EPIPE 32 /* Broken pipe */ #define EDOM 33 /* Math argument out of domain of func */ #define ERANGE 34 /* Math result not representable */ #define EDEADLK 35 /* Resource deadlock would occur */ #define ENAMETOOLONG 36 /* File name too long */ #define ENOLCK 37 /* No record locks available */ #define ENOSYS 38 /* Function not implemented */ #define ENOTEMPTY 39 /* Directory not empty */ #define ELOOP 40 /* Too many symbolic links encountered */ #define EWOULDBLOCK EAGAIN /* Operation would block */ #endif dev86-0.16.21/libc/include/msdos/fcntl.h000066400000000000000000000014731231050321700175540ustar00rootroot00000000000000#ifndef __MSDOS_FCNTL_H #define __MSDOS_FCNTL_H /* Definitions taken from Ralf Brown interrupt list and Linux kernel */ #define O_ACCMODE 0x03 #define O_RDONLY 0x00 #define O_WRONLY 0x01 #define O_RDWR 0x02 #define O_DENYMODE 0x70 #define O_DENYALL 0x10 #define O_DENYWRITE 0x20 #define O_DENYREAD 0x30 #define O_DENYNONE 0x40 #define O_SETFD 0x80 /* Close on exec flag for open */ #define O_CREAT 0x100 /* Moved on DOS to avoid DENY's */ #define O_TRUNC 0x200 #define O_APPEND 0x400 #define O_EXCL 0x800 #define O_BINARY 0x0000 #define O_TEXT 0x8000 /* This right ? Who cares! */ #define F_DUPFD 0 /* dup */ #define F_GETFD 1 /* get f_flags */ #define F_SETFD 2 /* set f_flags */ #define F_GETFL 3 /* more flags (cloexec) */ #define F_SETFL 4 #define F_GETLK 5 #define F_SETLK 6 #define F_SETLKW 7 #endif dev86-0.16.21/libc/include/msdos/types.h000066400000000000000000000005331231050321700176060ustar00rootroot00000000000000 /* arch/i86/include/asm/types.h - Basic Linux/MT data types. */ #ifndef __MSDOS_TYPES #define __MSDOS_TYPES #include typedef __u32 off_t; typedef __u32 time_t; typedef __u16 mode_t; typedef __u32 loff_t; typedef __u32 speed_t; typedef __u32 tcflag_t; typedef __u8 cc_t; typedef __u16 size_t; typedef int ptrdiff_t; #endif dev86-0.16.21/libc/include/paths.h000066400000000000000000000010551231050321700164340ustar00rootroot00000000000000/* paths.h */ #ifndef ___PATHS_H #define ___PATHS_H #define _PATH_CONSOLE "/dev/console" #define _PATH_TTY "/dev/tty" #define _PATH_NOLOGIN "/etc/nologin" #define _PATH_LOGIN "/bin/login" #define _PATH_BSHELL "/bin/sh" #define _PATH_UTMP "/var/run/utmp" #define _PATH_WTMP "/var/log/wtmp" #define _PATH_DEFPATH "/bin:/usr/bin:/usr/local/bin:." #define _PATH_DEV "/dev/" #define _PATH_DEVNULL "/dev/null" #define _PATH_TMP "/tmp/" #define _PATH_LASTLOG "/var/log/lastlog" #define _PATH_LOCALE "/usr/lib/locale" #endif /* __PATHS_H */ dev86-0.16.21/libc/include/pwd.h000066400000000000000000000016311231050321700161070ustar00rootroot00000000000000#ifndef __PWD_H #define __PWD_H #include #include #include /* The passwd structure. */ struct passwd { char *pw_name; /* Username. */ char *pw_passwd; /* Password. */ uid_t pw_uid; /* User ID. */ gid_t pw_gid; /* Group ID. */ char *pw_gecos; /* Real name. */ char *pw_dir; /* Home directory. */ char *pw_shell; /* Shell program. */ }; extern void setpwent __P ((void)); extern void endpwent __P ((void)); extern struct passwd * getpwent __P ((void)); extern int putpwent __P ((__const struct passwd * __p, FILE * __f)); extern int getpw __P ((uid_t uid, char *buf)); extern struct passwd * fgetpwent __P ((FILE * file)); extern struct passwd * getpwuid __P ((__const uid_t)); extern struct passwd * getpwnam __P ((__const char *)); #ifdef __LIBC__ extern struct passwd * __getpwent __P ((__const int passwd_fd)); #endif #endif /* pwd.h */ dev86-0.16.21/libc/include/search.h000066400000000000000000000055531231050321700165710ustar00rootroot00000000000000/* Copyright (C) 1993 Ulrich Drepper This file is intended to be included in the GNU C Library and the Linux C Library. So the copyright notice will be: Copyright (C) 1993 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the GNU C Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. For now the file can be distributed under the LGPL. */ #ifndef _SEARCH_H #define _SEARCH_H #include #define __need_size_t #define __need_NULL #include __BEGIN_DECLS #ifndef __COMPAR_FN_T #define __COMPAR_FN_T typedef int (*__compar_fn_t) __P ((__const __ptr_t, __const __ptr_t)); #endif /* for use with hsearch(3) */ typedef struct entry { char *key; char *data; } ENTRY; typedef enum { FIND, ENTER } ACTION; extern ENTRY * hsearch __P((ENTRY __item, ACTION __action)); extern int hcreate __P((unsigned __nel)); extern void hdestroy __P((void)); /* The tsearch routines are very interesting. They make many * assumptions about the compiler. It assumpts that the first field * in node must be the "key" field, which points to the datum. * Everything depends on that. It is a very tricky stuff. H.J. */ /* For tsearch */ typedef enum { preorder, postorder, endorder, leaf } VISIT; extern void *tsearch __P((__const void * __key, void **__rootp, __compar_fn_t compar)); extern void *tfind __P((__const void * __key, __const void ** __rootp, __compar_fn_t compar)); extern void *tdelete __P((__const void * __key, void ** __rootp, __compar_fn_t compar)); #ifndef __ACTION_FN_T #define __ACTION_FN_T /* FYI, the first argument should be a pointer to "key". * Please read the man page for details. */ typedef void (*__action_fn_t) __P((__const void *__nodep, __const VISIT __value, __const int __level)); #endif extern void twalk __P((__const void * __root, __action_fn_t action)); extern void * lfind __P((__const void * __key, __const void * __base, size_t * __nmemb, size_t __size, __compar_fn_t __compar)); extern void * lsearch __P((__const void * __key, __const void * __base, size_t * __nmemb, size_t __size, __compar_fn_t __compar)); __END_DECLS #endif /* search.h */ dev86-0.16.21/libc/include/setjmp.h000066400000000000000000000011651231050321700166210ustar00rootroot00000000000000 #ifndef __SETJMP_H #define __SETJMP_H #include /* * I know most systems use an array of ints here, but I prefer this - RDB */ typedef struct { unsigned int pc; unsigned int sp; unsigned int bp; unsigned int si; unsigned int di; } jmp_buf[1]; int _setjmp __P((jmp_buf env)); void _longjmp __P((jmp_buf env, int rv)); /* LATER: Seems GNU beat me to it, must be OK then :-) * Humm, what's this about setjmp being a macro !? * Ok, use the BSD names as normal use the ANSI as macros */ #define setjmp(a_env) _setjmp(a_env) #define longjmp(a_env, a_rv) _longjmp(a_env, a_rv) #endif dev86-0.16.21/libc/include/signal.h000066400000000000000000000041411231050321700165710ustar00rootroot00000000000000 #ifndef __SIGNAL_H #define __SIGNAL_H #include typedef unsigned long sigset_t; /* at least 32 bits */ #define _NSIG 32 #define NSIG _NSIG #define SIGHUP 1 #define SIGINT 2 #define SIGQUIT 3 #define SIGILL 4 #define SIGTRAP 5 #define SIGABRT 6 #define SIGIOT 6 #define SIGBUS 7 #define SIGFPE 8 #define SIGKILL 9 #define SIGUSR1 10 #define SIGSEGV 11 #define SIGUSR2 12 #define SIGPIPE 13 #define SIGALRM 14 #define SIGTERM 15 #define SIGSTKFLT 16 #define SIGCHLD 17 #define SIGCONT 18 #define SIGSTOP 19 #define SIGTSTP 20 #define SIGTTIN 21 #define SIGTTOU 22 #define SIGURG 23 #define SIGXCPU 24 #define SIGXFSZ 25 #define SIGVTALRM 26 #define SIGPROF 27 #define SIGWINCH 28 #define SIGIO 29 #define SIGPOLL SIGIO /* #define SIGLOST 29 */ #define SIGPWR 30 #define SIGUNUSED 31 /* * sa_flags values: SA_STACK is not currently supported, but will allow the * usage of signal stacks by using the (now obsolete) sa_restorer field in * the sigaction structure as a stack pointer. This is now possible due to * the changes in signal handling. LBT 010493. * SA_INTERRUPT is a no-op, but left due to historical reasons. Use the * SA_RESTART flag to get restarting signals (which were the default long ago) */ #define SA_NOCLDSTOP 1 #define SA_STACK 0x08000000 #define SA_RESTART 0x10000000 #define SA_INTERRUPT 0x20000000 #define SA_NOMASK 0x40000000 #define SA_ONESHOT 0x80000000 #define SIG_BLOCK 0 /* for blocking signals */ #define SIG_UNBLOCK 1 /* for unblocking signals */ #define SIG_SETMASK 2 /* for setting the signal mask */ /* Type of a signal handler. */ typedef void (*__sighandler_t)(/* int */); #define SIG_DFL ((__sighandler_t)0) /* default signal handling */ #define SIG_IGN ((__sighandler_t)1) /* ignore signal */ #define SIG_ERR ((__sighandler_t)-1) /* error return from signal */ struct sigaction { __sighandler_t sa_handler; sigset_t sa_mask; unsigned long sa_flags; void (*sa_restorer)( /*void*/ ); }; /* BSDisms */ #ifdef BSD extern __const char * __const sys_siglist[]; #define sig_t __sighandler_t #endif #endif dev86-0.16.21/libc/include/stdarg.h000066400000000000000000000031011231050321700165730ustar00rootroot00000000000000 /* * @(#) stdarg.h 1.2 91/11/30 21:10:39 * * Sample stdarg.h file for use with the unproto filter. * * This file serves two purposes. * * 1 - As an include file for use with ANSI-style C source that implements * variadic functions. * * 2 - To configure the unproto filter itself. If the _VA_ALIST_ macro is * defined, its value will appear in the place of the "..." in argument * lists of variadic function *definitions* (not declarations). * * Compilers that pass arguments via the stack can use the default code at the * end of this file (this usually applies for the VAX, MC68k and 80*86 * architectures). * * RISC-based systems often need special tricks. An example of the latter is * given for the SPARC architecture. Read your /usr/include/varargs.h for * more information. * * You can use the varargs.c program provided with the unproto package to * verify that the stdarg.h file has been set up correctly. */ #ifndef __STDARG_H #define __STDARG_H #include #ifdef sparc # define _VA_ALIST_ "__builtin_va_alist" typedef char *va_list; # define va_start(ap, p) (ap = (char *) &__builtin_va_alist) # define va_arg(ap, type) ((type *) __builtin_va_arg_incr((type *) ap))[0] # define va_end(ap) #else /* vax, mc68k, 80*86 */ typedef char *va_list; # define va_start(ap, p) (ap = (char *) (&(p)+1)) # define va_arg(ap, type) ((type *) (ap += sizeof(type)))[-1] # define va_end(ap) #endif #endif /* __STDARG_H */ #if __FIRST_ARG_IN_AX__ #warning First arg is in a register, stdarg.h cannot take its address #endif dev86-0.16.21/libc/include/stddef.h000066400000000000000000000005621231050321700165700ustar00rootroot00000000000000/* Copyright (C) 1996 Robert de Bath * This file is part of the Linux-8086 C library and is distributed * under the GNU Library General Public License. */ /* We don't care, ignore GCC's __need hackery */ #ifndef __STDDEF_H #define __STDDEF_H #include #ifndef NULL #define NULL ((void*)0) #endif #endif /* __STDDEF_H */ dev86-0.16.21/libc/include/stdlib.h000066400000000000000000000022251231050321700165760ustar00rootroot00000000000000/* stdlib.h */ #include #include #ifndef __STDLIB_H #define __STDLIB_H /* Don't overwrite user definitions of NULL */ #ifndef NULL #define NULL ((void *) 0) #endif /* For program termination */ #define EXIT_FAILURE 1 #define EXIT_SUCCESS 0 #include extern int rand __P ((void)); extern void srand __P ((unsigned int seed)); extern long strtol __P ((const char * nptr, char ** endptr, int base)); extern unsigned long strtoul __P ((const char * nptr, char ** endptr, int base)); #ifndef __HAS_NO_FLOATS__ extern double strtod __P ((const char * nptr, char ** endptr)); extern double atof __P ((__const char *__nptr)); #endif extern long int atol __P ((__const char *__nptr)); extern int atoi __P ((__const char *__nptr)); /* Returned by `div'. */ typedef struct { int quot; /* Quotient. */ int rem; /* Remainder. */ } div_t; /* Returned by `ldiv'. */ typedef struct { long int quot; /* Quotient. */ long int rem; /* Remainder. */ } ldiv_t; extern char *getenv __P ((__const char *__name)); extern char *mktemp __P ((char *__template)); #endif /* __STDLIB_H */ dev86-0.16.21/libc/include/strings.h000066400000000000000000000000241231050321700170010ustar00rootroot00000000000000#include dev86-0.16.21/libc/include/sys/000077500000000000000000000000001231050321700157615ustar00rootroot00000000000000dev86-0.16.21/libc/include/sys/cdefs.h000066400000000000000000000011111231050321700172100ustar00rootroot00000000000000 #ifndef __SYS_CDEFS_H #define __SYS_CDEFS_H #include #if __STDC__ #define __CONCAT(x,y) x ## y #define __STRING(x) #x /* This is not a typedef so `const __ptr_t' does the right thing. */ #define __ptr_t void * #ifndef __HAS_NO_FLOATS__ typedef long double __long_double_t; #endif #else #define __CONCAT(x,y) x/**/y #define __STRING(x) "x" #define __ptr_t char * #ifndef __HAS_NO_FLOATS__ typedef double __long_double_t; #endif #endif /* No C++ */ #define __BEGIN_DECLS #define __END_DECLS /* GNUish things */ #define __CONSTVALUE #define __CONSTVALUE2 #endif dev86-0.16.21/libc/include/sys/errno.h000066400000000000000000000006001231050321700172530ustar00rootroot00000000000000#ifndef __ERRNO_H #define __ERRNO_H #include #include __SYSINC__(errno.h) #ifdef __USE_BSD extern int sys_nerr; extern char *sys_errlist[]; #endif #ifdef __USE_GNU extern int _sys_nerr; extern char *_sys_errlist[]; #endif extern int errno; __BEGIN_DECLS extern void perror __P ((__const char* __s)); extern char* strerror __P ((int __errno)); __END_DECLS #endif dev86-0.16.21/libc/include/sys/fcntl.h000066400000000000000000000000231231050321700172330ustar00rootroot00000000000000#include dev86-0.16.21/libc/include/sys/file.h000066400000000000000000000014131231050321700170500ustar00rootroot00000000000000#ifndef _SYS_FILE_H #define _SYS_FILE_H #include #include #ifndef L_SET #define L_SET 0 /* absolute offset */ #define L_INCR 1 /* relative to current offset */ #define L_XTND 2 /* relative to end of file */ #endif #ifndef LOCK_SH /* Operations for the `flock' call. */ #define LOCK_SH 1 /* Shared lock. */ #define LOCK_EX 2 /* Exclusive lock. */ #define LOCK_UN 8 /* Unlock. */ /* Can be OR'd in to one of the above. */ #define LOCK_NB 4 /* Don't block when locking. */ #endif __BEGIN_DECLS /* Apply or remove an advisory lock, according to OPERATION, on the file FD refers to. */ extern int flock __P ((int __fd, int __operation)); __END_DECLS #endif dev86-0.16.21/libc/include/sys/ioctl.h000066400000000000000000000002351231050321700172440ustar00rootroot00000000000000 #ifndef _SYS_IOCTL_H #define _SYS_IOCTL_H #include #include __SYSINC__(ioctl.h) extern int ioctl __P((int __fildes, int __cmd, ...)); #endif dev86-0.16.21/libc/include/sys/mman.h000066400000000000000000000001441231050321700170610ustar00rootroot00000000000000 #ifndef __SYS_MMAN_H #define __SYS_MMAN_H #include #include __SYSINC__(mman.h) #endif dev86-0.16.21/libc/include/sys/param.h000066400000000000000000000005211231050321700172300ustar00rootroot00000000000000/* Copyright (C) 1996 Robert de Bath * This file is part of the Linux-8086 C library and is distributed * under the GNU Library General Public License. */ #ifndef _PARAM_H #define _PARAM_H #include #ifndef NR_OPEN #define NR_OPEN 32 #endif #ifndef NR_FILE #define NR_FILE 32 #endif #endif dev86-0.16.21/libc/include/sys/resource.h000066400000000000000000000001601231050321700177560ustar00rootroot00000000000000 #ifndef __SYS_RESOURCE_H #define __SYS_RESOURCE_H #include #include __SYSINC__(resource.h) #endif dev86-0.16.21/libc/include/sys/signal.h000066400000000000000000000000241231050321700174030ustar00rootroot00000000000000#include dev86-0.16.21/libc/include/sys/socket.h000066400000000000000000000001521231050321700174200ustar00rootroot00000000000000 #ifndef __SYS_SOCKET_H #define __SYS_SOCKET_H #include #include __SYSINC__(socket.h) #endif dev86-0.16.21/libc/include/sys/stat.h000066400000000000000000000007661231050321700171160ustar00rootroot00000000000000#ifndef _SYS_STAT_H #define _SYS_STAT_H #include #include #include __SYSINC__(stat.h) int stat __P((__const char * __path, struct stat * __statbuf)); int lstat __P((__const char * __path, struct stat * __statbuf)); int fstat __P((int __fd, struct stat * __statbuf)); /* hysterical raisins */ #define S_IREAD S_IRUSR /* read permission, owner */ #define S_IWRITE S_IWUSR /* write permission, owner */ #define S_IEXEC S_IXUSR /* execute/search permission, owner */ #endif dev86-0.16.21/libc/include/sys/time.h000066400000000000000000000000221231050321700170620ustar00rootroot00000000000000#include dev86-0.16.21/libc/include/sys/times.h000066400000000000000000000004421231050321700172530ustar00rootroot00000000000000#ifndef _SYS_TIMES_H #define _SYS_TIMES_H #include #include #include struct tms { clock_t tms_utime; clock_t tms_stime; clock_t tms_cutime; clock_t tms_cstime; }; __BEGIN_DECLS extern clock_t times __P ((struct tms * __tp)); __END_DECLS #endif dev86-0.16.21/libc/include/sys/types.h000066400000000000000000000001071231050321700172740ustar00rootroot00000000000000#include #include #include __SYSINC__(types.h) dev86-0.16.21/libc/include/sys/utsname.h000066400000000000000000000002051231050321700176030ustar00rootroot00000000000000#ifndef __SYS_UTSNAME_H #define __SYS_UTSNAME_H #include #include #include __SYSINC__(utsname.h) #endif dev86-0.16.21/libc/include/sys/vm86.h000066400000000000000000000001431231050321700167300ustar00rootroot00000000000000#ifndef __SYS_VM86_H #define __SYS_VM86_H #include #include __SYSINC__(vm86.h) #endif dev86-0.16.21/libc/include/sys/wait.h000066400000000000000000000060151231050321700171000ustar00rootroot00000000000000 #ifndef _SYS_WAIT_H #define _SYS_WAIT_H #include /* Bits in the third argument to `waitpid'. */ #define WNOHANG 1 /* Don't block waiting. */ #define WUNTRACED 2 /* Report status of stopped children. */ /* Everything extant so far uses these same bits. */ /* If WIFEXITED(STATUS), the low-order 8 bits of the status. */ #define WEXITSTATUS(status) (((status) & 0xff00) >> 8) /* If WIFSIGNALED(STATUS), the terminating signal. */ #define WTERMSIG(status) ((status) & 0x7f) /* If WIFSTOPPED(STATUS), the signal that stopped the child. */ #define WSTOPSIG(status) WEXITSTATUS(status) /* Nonzero if STATUS indicates normal termination. */ #define WIFEXITED(status) (((status) & 0xff) == 0) /* Nonzero if STATUS indicates termination by a signal. */ #define WIFSIGNALED(status) (((unsigned int)((status)-1) & 0xFFFF) < 0xFF) /* Nonzero if STATUS indicates the child is stopped. */ #define WIFSTOPPED(status) (((status) & 0xff) == 0x7f) /* Nonzero if STATUS indicates the child dumped core. */ #define WCOREDUMP(status) ((status) & 0200) /* Macros for constructing status values. */ #define W_EXITCODE(ret, sig) ((ret) << 8 | (sig)) #define W_STOPCODE(sig) ((sig) << 8 | 0x7f) /* Wait for a child to die. When one does, put its status in *STAT_LOC and return its process ID. For errors, return (pid_t) -1. */ extern pid_t wait __P ((__WAIT_STATUS __stat_loc)); /* Special values for the PID argument to `waitpid' and `wait4'. */ #define WAIT_ANY (-1) /* Any process. */ #define WAIT_MYPGRP 0 /* Any process in my process group. */ /* Wait for a child matching PID to die. If PID is greater than 0, match any process whose process ID is PID. If PID is (pid_t) -1, match any process. If PID is (pid_t) 0, match any process with the same process group as the current process. If PID is less than -1, match any process whose process group is the absolute value of PID. If the WNOHANG bit is set in OPTIONS, and that child is not already dead, return (pid_t) 0. If successful, return PID and store the dead child's status in STAT_LOC. Return (pid_t) -1 for errors. If the WUNTRACED bit is set in OPTIONS, return status for stopped children; otherwise don't. */ extern pid_t waitpid __P ((pid_t __pid, int *__stat_loc, int __options)); /* This being here makes the prototypes valid whether or not we have already included to define `struct rusage'. */ struct rusage; /* Wait for a child to exit. When one does, put its status in *STAT_LOC and return its process ID. For errors return (pid_t) -1. If USAGE is not nil, store information about the child's resource usage there. If the WUNTRACED bit is set in OPTIONS, return status for stopped children; otherwise don't. */ extern pid_t wait3 __P ((__WAIT_STATUS __stat_loc, int __options, struct rusage * __usage)); /* PID is like waitpid. Other args are like wait3. */ extern pid_t wait4 __P ((pid_t __pid, __WAIT_STATUS __stat_loc, int __options, struct rusage *__usage)); #endif /* sys/wait.h */ dev86-0.16.21/libc/include/termcap.h000066400000000000000000000007251231050321700167530ustar00rootroot00000000000000 #ifndef _TERMCAP_H #define _TERMCAP_H #include #include extern char PC; extern char *UP; extern char *BC; extern int ospeed; extern int tgetent __P((char *, const char *)); extern int tgetflag __P((const char *)); extern int tgetnum __P((const char *)); extern char *tgetstr __P((const char *, char **)); extern int tputs __P((const char *, int, int (*)(int))); extern char *tgoto __P((const char *, int, int)); #endif /* _TERMCAP_H */ dev86-0.16.21/libc/include/termio.h000066400000000000000000000000251231050321700166100ustar00rootroot00000000000000#include dev86-0.16.21/libc/include/termios.h000066400000000000000000000016511231050321700170010ustar00rootroot00000000000000#ifndef __TERMIOS_H #define __TERMIOS_H #include #include #include __SYSINC__(termios.h) extern speed_t cfgetispeed __P ((struct termios *__termios_p)); extern speed_t cfgetospeed __P ((struct termios *__termios_p)); extern int cfsetispeed __P ((struct termios *__termios_p, speed_t __speed)); extern int cfsetospeed __P ((struct termios *__termios_p, speed_t __speed)); extern void cfmakeraw __P ((struct termios *__t)); extern int tcsetattr __P ((int __fd, int __opt, struct termios *__termios_p)); extern int tcgetattr __P ((int __fildes, struct termios *__termios_p)); extern int tcdrain __P ((int __fildes)); extern int tcflow __P ((int __fildes, int __action)); extern int tcflush __P ((int __fildes, int __queue_selector)); extern int tcsendbreak __P ((int __fildes, int __duration)); extern pid_t tcgetpgrp __P ((int __fildes)); extern int tcsetpgrp __P ((int __fildes, pid_t __pgrp_id)); #endif dev86-0.16.21/libc/include/time.h000066400000000000000000000026161231050321700162570ustar00rootroot00000000000000#ifndef __TIME_H #define __TIME_H #include #include #include #ifndef _CLOCK_T #define _CLOCK_T typedef long clock_t; #endif #define CLOCKS_PER_SEC 100 #define CLK_TCK 100 /* That must be the same as HZ ???? */ struct timeval { long tv_sec; long tv_usec; }; struct tm { int tm_sec; int tm_min; int tm_hour; int tm_mday; int tm_mon; int tm_year; int tm_wday; int tm_yday; int tm_isdst; }; struct timezone { int tz_minuteswest; /* minutes west of Greenwich */ int tz_dsttime; /* type of dst correction */ }; #define __isleap(year) \ ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0)) extern char *tzname[2]; extern int daylight; extern long int timezone; __BEGIN_DECLS extern int stime __P ((time_t* __tptr)); extern clock_t clock __P ((void)); extern time_t time __P ((time_t * __tp)); #ifndef __HAS_NO_FLOATS__ extern __CONSTVALUE double difftime __P ((time_t __time2, time_t __time1)) __CONSTVALUE2; #endif extern time_t mktime __P ((struct tm * __tp)); extern char * asctime __P ((__const struct tm * __tp)); extern char * ctime __P ((__const time_t * __tp)); extern size_t strftime __P ((char * __s, size_t __smax, __const char * __fmt, __const struct tm * __tp)); extern void tzset __P ((void)); extern struct tm* gmtime __P ((__const time_t *__tp)); extern struct tm* localtime __P ((__const time_t * __tp)); __END_DECLS #endif dev86-0.16.21/libc/include/unistd.h000066400000000000000000000020171231050321700166220ustar00rootroot00000000000000/* unistd.h */ #include #include #ifndef __UNISTD_H #define __UNISTD_H #define STDIN_FILENO 0 #define STDOUT_FILENO 1 #define STDERR_FILENO 2 extern int close __P ((int)); extern size_t read __P ((int __fd, char * __buf, size_t __nbytes)); extern size_t write __P ((int __fd, __const char * __buf, size_t __n)); extern off_t lseek __P ((int __fd, off_t __n, int __whence)); extern int pipe __P ((int __pipedes[2])); extern unsigned int alarm __P ((unsigned int __seconds)); extern unsigned int sleep __P ((unsigned int __seconds)); extern int pause __P ((void)); extern char* crypt __P((__const char *__key, __const char *__salt)); #ifndef SEEK_SET #define SEEK_SET 0 #define SEEK_CUR 1 #define SEEK_END 2 #endif #ifndef R_OK #define R_OK 4 /* Test for read permission. */ #define W_OK 2 /* Test for write permission. */ #define X_OK 1 /* Test for execute permission. */ #define F_OK 0 /* Test for existence. */ #endif #define _POSIX_VDISABLE '\0' #endif /* __UNISTD_H */ dev86-0.16.21/libc/include/utime.h000066400000000000000000000003311231050321700164340ustar00rootroot00000000000000#ifndef __UTIME_H #define __UTIME_H #include #include struct utimbuf { time_t actime; time_t modtime; }; extern int utime __P ((char *__filename, struct utimbuf *__utimebuf)); #endif dev86-0.16.21/libc/include/utmp.h000066400000000000000000000026131231050321700163030ustar00rootroot00000000000000/* utmp.h */ #ifndef __UTMP_H #define __UTMP_H #include #include #include #include #define UT_UNKNOWN 0 #define UT_LINESIZE 12 #define UT_NAMESIZE 8 #define UT_HOSTSIZE 16 #define RUN_LVL 1 #define BOOT_TIME 2 #define NEW_TIME 3 #define OLD_TIME 4 #define INIT_PROCESS 5 #define LOGIN_PROCESS 6 #define USER_PROCESS 7 #define DEAD_PROCESS 8 struct utmp { short ut_type; /* type of login */ pid_t ut_pid; /* pid of login-process */ char ut_line[UT_LINESIZE]; /* devicename of tty -"/dev/", null-term */ char ut_id[2]; /* abbrev. ttyname, as 01, s1 etc. */ time_t ut_time; /* login time */ char ut_user[UT_NAMESIZE]; /* username, not null-term */ char ut_host[UT_HOSTSIZE]; /* hostname for remote login... */ long ut_addr; /* IP addr of remote host */ }; extern void setutent __P ((void)); extern void utmpname __P ((__const char *)); extern struct utmp * getutent __P ((void)); extern struct utmp * getutid __P ((__const struct utmp *)); extern struct utmp * getutline __P ((__const struct utmp *)); extern struct utmp * pututline __P ((__const struct utmp *)); extern void endutent __P ((void)); #ifdef __LIBC__ struct utmp * __getutent __P ((int)); #endif #endif /* __UTMP_H */ dev86-0.16.21/libc/include/varargs.h000066400000000000000000000003471231050321700167650ustar00rootroot00000000000000 #ifndef __VARARGS_H #define __VARARGS_H typedef char *va_list; #define va_dcl va_list va_alist; #define va_start(ap) ap = (va_list)&va_alist #define va_arg(ap,t) ((t *)(ap += sizeof(t)))[-1] #define va_end(ap) ap = NULL #endif dev86-0.16.21/libc/kinclude/000077500000000000000000000000001231050321700153165ustar00rootroot00000000000000dev86-0.16.21/libc/kinclude/Config000066400000000000000000000000631231050321700164450ustar00rootroot00000000000000kinc: Example kernel include files and syscall.dat dev86-0.16.21/libc/kinclude/Makefile000066400000000000000000000005671231050321700167660ustar00rootroot00000000000000# Copyright (C) 1995,1996 Robert de Bath # This file is part of the Linux-8086 C library and is distributed # under the GNU Library General Public License. all: @: transfer: -@rm -f ../include/linuxmt ../include/arch ln -s ../kinclude/linuxmt ../include ln -s ../kinclude/arch ../include clean: -rm -f ../include/linuxmt ../include/arch dev86-0.16.21/libc/kinclude/arch/000077500000000000000000000000001231050321700162335ustar00rootroot00000000000000dev86-0.16.21/libc/kinclude/arch/errno.h000066400000000000000000000137341231050321700175410ustar00rootroot00000000000000#ifndef __ARCH_8086_ERRNO_H #define __ARCH_8086_ERRNO_H #define EPERM 1 /* Operation not permitted */ #define ENOENT 2 /* No such file or directory */ #define ESRCH 3 /* No such process */ #define EINTR 4 /* Interrupted system call */ #define EIO 5 /* I/O error */ #define ENXIO 6 /* No such device or address */ #define E2BIG 7 /* Arg list too long */ #define ENOEXEC 8 /* Exec format error */ #define EBADF 9 /* Bad file number */ #define ECHILD 10 /* No child processes */ #define EAGAIN 11 /* Try again */ #define ENOMEM 12 /* Out of memory */ #define EACCES 13 /* Permission denied */ #define EFAULT 14 /* Bad address */ #define ENOTBLK 15 /* Block device required */ #define EBUSY 16 /* Device or resource busy */ #define EEXIST 17 /* File exists */ #define EXDEV 18 /* Cross-device link */ #define ENODEV 19 /* No such device */ #define ENOTDIR 20 /* Not a directory */ #define EISDIR 21 /* Is a directory */ #define EINVAL 22 /* Invalid argument */ #define ENFILE 23 /* File table overflow */ #define EMFILE 24 /* Too many open files */ #define ENOTTY 25 /* Not a typewriter */ #define ETXTBSY 26 /* Text file busy */ #define EFBIG 27 /* File too large */ #define ENOSPC 28 /* No space left on device */ #define ESPIPE 29 /* Illegal seek */ #define EROFS 30 /* Read-only file system */ #define EMLINK 31 /* Too many links */ #define EPIPE 32 /* Broken pipe */ #define EDOM 33 /* Math argument out of domain of func */ #define ERANGE 34 /* Math result not representable */ #define EDEADLK 35 /* Resource deadlock would occur */ #define ENAMETOOLONG 36 /* File name too long */ #define ENOLCK 37 /* No record locks available */ #define ENOSYS 38 /* Function not implemented */ #define ENOTEMPTY 39 /* Directory not empty */ #define ELOOP 40 /* Too many symbolic links encountered */ #define EWOULDBLOCK EAGAIN /* Operation would block */ #define ENOMSG 42 /* No message of desired type */ #define EIDRM 43 /* Identifier removed */ #define ECHRNG 44 /* Channel number out of range */ #define EL2NSYNC 45 /* Level 2 not synchronized */ #define EL3HLT 46 /* Level 3 halted */ #define EL3RST 47 /* Level 3 reset */ #define ELNRNG 48 /* Link number out of range */ #define EUNATCH 49 /* Protocol driver not attached */ #define ENOCSI 50 /* No CSI structure available */ #define EL2HLT 51 /* Level 2 halted */ #define EBADE 52 /* Invalid exchange */ #define EBADR 53 /* Invalid request descriptor */ #define EXFULL 54 /* Exchange full */ #define ENOANO 55 /* No anode */ #define EBADRQC 56 /* Invalid request code */ #define EBADSLT 57 /* Invalid slot */ #define EDEADLOCK 58 /* File locking deadlock error */ #define EBFONT 59 /* Bad font file format */ #define ENOSTR 60 /* Device not a stream */ #define ENODATA 61 /* No data available */ #define ETIME 62 /* Timer expired */ #define ENOSR 63 /* Out of streams resources */ #define ENONET 64 /* Machine is not on the network */ #define ENOPKG 65 /* Package not installed */ #define EREMOTE 66 /* Object is remote */ #define ENOLINK 67 /* Link has been severed */ #define EADV 68 /* Advertise error */ #define ESRMNT 69 /* Srmount error */ #define ECOMM 70 /* Communication error on send */ #define EPROTO 71 /* Protocol error */ #define EMULTIHOP 72 /* Multihop attempted */ #define EDOTDOT 73 /* RFS specific error */ #define EBADMSG 74 /* Not a data message */ #define EOVERFLOW 75 /* Value too large for defined data type */ #define ENOTUNIQ 76 /* Name not unique on network */ #define EBADFD 77 /* File descriptor in bad state */ #define EREMCHG 78 /* Remote address changed */ #define ELIBACC 79 /* Can not access a needed shared library */ #define ELIBBAD 80 /* Accessing a corrupted shared library */ #define ELIBSCN 81 /* .lib section in a.out corrupted */ #define ELIBMAX 82 /* Attempting to link in too many shared libraries */ #define ELIBEXEC 83 /* Cannot exec a shared library directly */ #define EILSEQ 84 /* Illegal byte sequence */ #define ERESTART 85 /* Interrupted system call should be restarted */ #define ESTRPIPE 86 /* Streams pipe error */ #define EUSERS 87 /* Too many users */ #define ENOTSOCK 88 /* Socket operation on non-socket */ #define EDESTADDRREQ 89 /* Destination address required */ #define EMSGSIZE 90 /* Message too long */ #define EPROTOTYPE 91 /* Protocol wrong type for socket */ #define ENOPROTOOPT 92 /* Protocol not available */ #define EPROTONOSUPPORT 93 /* Protocol not supported */ #define ESOCKTNOSUPPORT 94 /* Socket type not supported */ #define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */ #define EPFNOSUPPORT 96 /* Protocol family not supported */ #define EAFNOSUPPORT 97 /* Address family not supported by protocol */ #define EADDRINUSE 98 /* Address already in use */ #define EADDRNOTAVAIL 99 /* Cannot assign requested address */ #define ENETDOWN 100 /* Network is down */ #define ENETUNREACH 101 /* Network is unreachable */ #define ENETRESET 102 /* Network dropped connection because of reset */ #define ECONNABORTED 103 /* Software caused connection abort */ #define ECONNRESET 104 /* Connection reset by peer */ #define ENOBUFS 105 /* No buffer space available */ #define EISCONN 106 /* Transport endpoint is already connected */ #define ENOTCONN 107 /* Transport endpoint is not connected */ #define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */ #define ETOOMANYREFS 109 /* Too many references: cannot splice */ #define ETIMEDOUT 110 /* Connection timed out */ #define ECONNREFUSED 111 /* Connection refused */ #define EHOSTDOWN 112 /* Host is down */ #define EHOSTUNREACH 113 /* No route to host */ #define EALREADY 114 /* Operation already in progress */ #define EINPROGRESS 115 /* Operation now in progress */ #define ESTALE 116 /* Stale NFS file handle */ #define EUCLEAN 117 /* Structure needs cleaning */ #define ENOTNAM 118 /* Not a XENIX named type file */ #define ENAVAIL 119 /* No XENIX semaphores available */ #define EISNAM 120 /* Is a named type file */ #define EREMOTEIO 121 /* Remote I/O error */ #define EDQUOT 122 /* Quota exceeded */ #endif dev86-0.16.21/libc/kinclude/arch/ioctl.h000066400000000000000000000001701231050321700175140ustar00rootroot00000000000000/* * Nothing here yet. */ #ifndef __ARCH_8086_IOCTL_H #define __ARCH_8086_IOCTL_H #endif /* __ARCH_8086_IOCTL_H */ dev86-0.16.21/libc/kinclude/arch/stat.h000066400000000000000000000004061231050321700173570ustar00rootroot00000000000000#ifndef __ARCH_8086_STAT_H #define __ARCH_8086_STAT_H struct stat { dev_t st_dev; ino_t st_ino; mode_t st_mode; nlink_t st_nlink; uid_t st_uid; gid_t st_gid; dev_t st_rdev; off_t st_size; time_t st_atime; time_t st_mtime; time_t st_ctime; }; #endif dev86-0.16.21/libc/kinclude/arch/types.h000066400000000000000000000007631231050321700175560ustar00rootroot00000000000000/* arch/i86/include/asm/types.h - Basic Linux/MT data types. */ #ifndef __ARCH_8086_TYPES #define __ARCH_8086_TYPES #include struct _registers { __u16 ksp, sp, ss, ax, bx, cx, dx, di, si, ds, es, bp, ip, cs, flags; }; typedef struct _registers __registers; typedef struct _registers * __pregisters; typedef __u32 __pptr; struct _mminit { __u16 cs, endcs, ds, endds, ss, endss, lowss; }; typedef struct _mminit __arch_mminit; typedef struct _mminit * __parch_mminit; #endif dev86-0.16.21/libc/kinclude/linuxmt/000077500000000000000000000000001231050321700170165ustar00rootroot00000000000000dev86-0.16.21/libc/kinclude/linuxmt/errno.h000066400000000000000000000000301231050321700203050ustar00rootroot00000000000000#include dev86-0.16.21/libc/kinclude/linuxmt/fcntl.h000066400000000000000000000031111231050321700202710ustar00rootroot00000000000000#ifndef __LINUXMT_FCNTL_H #define __LINUXMT_FCNTL_H /* * Definitions taken from the i386 Linux kernel. */ /* open/fcntl */ #define O_ACCMODE 0003 #define O_RDONLY 00 #define O_WRONLY 01 #define O_RDWR 02 #define O_CREAT 0100 /* not fcntl */ #define O_EXCL 0200 /* not fcntl */ #define O_NOCTTY 0400 /* not fcntl */ #define O_TRUNC 01000 /* not fcntl */ #define O_APPEND 02000 #define O_NONBLOCK 04000 #define O_NDELAY O_NONBLOCK #if 0 #define O_SYNC 010000 /* Not supported */ #define FASYNC 020000 /* Not supported */ #endif #define F_DUPFD 0 /* dup */ #define F_GETFD 1 /* get f_flags */ #define F_SETFD 2 /* set f_flags */ #define F_GETFL 3 /* more flags (cloexec) */ #define F_SETFL 4 #define F_GETLK 5 #define F_SETLK 6 #define F_SETLKW 7 #define F_SETOWN 8 /* for sockets. */ #define F_GETOWN 9 /* for sockets. */ /* for F_[GET|SET]FL */ #define FD_CLOEXEC 1 /* actually anything with low bit set goes */ /* for posix fcntl() and lockf() */ #define F_RDLCK 0 #define F_WRLCK 1 #define F_UNLCK 2 /* for old implementation of bsd flock () */ #define F_EXLCK 4 /* or 3 */ #define F_SHLCK 8 /* or 4 */ /* operations for bsd flock(), also used by the kernel implementation */ #define LOCK_SH 1 /* shared lock */ #define LOCK_EX 2 /* exclusive lock */ #define LOCK_NB 4 /* or'd with one of the above to prevent blocking */ #define LOCK_UN 8 /* remove lock */ #ifdef __KERNEL__ #define F_POSIX 1 #define F_FLOCK 2 #endif /* __KERNEL__ */ struct flock { short l_type; short l_whence; off_t l_start; off_t l_len; pid_t l_pid; }; #endif dev86-0.16.21/libc/kinclude/linuxmt/ioctl.h000066400000000000000000000000301231050321700202720ustar00rootroot00000000000000#include dev86-0.16.21/libc/kinclude/linuxmt/resource.h000066400000000000000000000041521231050321700210200ustar00rootroot00000000000000/* * Resource control/accounting header file for linux-86 */ #ifndef __LINUXMT_RESOURCE_H #define __LINUXMT_RESOURCE_H #include #include #include #define RUSAGE_SELF 0 #define RUSAGE_CHILDREN (-1) #define RUSAGE_BOTH (-2) /* sys_wait4() uses this */ struct rusage { struct timeval ru_utime; /* user time used */ struct timeval ru_stime; /* system time used */ long ru_maxrss; /* maximum resident set size */ long ru_ixrss; /* integral shared memory size */ long ru_idrss; /* integral unshared data size */ long ru_isrss; /* integral unshared stack size */ long ru_minflt; /* page reclaims */ long ru_majflt; /* page faults */ long ru_nswap; /* swaps */ long ru_inblock; /* block input operations */ long ru_oublock; /* block output operations */ long ru_msgsnd; /* messages sent */ long ru_msgrcv; /* messages received */ long ru_nsignals; /* signals received */ long ru_nvcsw; /* voluntary context switches */ long ru_nivcsw; /* involuntary " */ }; #define RLIM_INFINITY ((long)(~0UL>>1)) struct rlimit { long rlim_cur; long rlim_max; }; #define PRIO_MIN (-20) #define PRIO_MAX 20 #define PRIO_PROCESS 0 #define PRIO_PGRP 1 #define PRIO_USER 2 #define RLIMIT_CPU 0 /* CPU time in ms */ #define RLIMIT_FSIZE 1 /* Maximum filesize */ #define RLIMIT_DATA 2 /* max data size */ #define RLIMIT_STACK 3 /* max stack size */ #define RLIMIT_CORE 4 /* max core file size */ #define RLIMIT_RSS 5 /* max resident set size */ #define RLIMIT_NPROC 6 /* max number of processes */ #define RLIMIT_NOFILE 7 /* max number of open files */ #define RLIMIT_MEMLOCK 8 /* max locked-in-memory address space */ #define RLIM_NLIMITS 9 extern int getrlimit __P ((int __resource, struct rlimit *__rlp)); extern int setrlimit __P ((int __resource, __const struct rlimit *__rlp)); extern int getpriority __P((int __which, int __who)); extern int setpriority __P((int __which, int __who, int __prio)); extern int __getrusage __P ((int __who, struct rusage *__rusage)); extern int getrusage __P ((int __who, struct rusage *__rusage)); #endif /* __LINUXMT_RESOURCE_H */ dev86-0.16.21/libc/kinclude/linuxmt/stat.h000066400000000000000000000023771231050321700201530ustar00rootroot00000000000000#ifndef __LINUXMT_STAT_H #define __LINUXMT_STAT_H #include #define S_IFMT 00170000 #ifdef __LINUXMT_NETWORK__ #define S_IFSOCK 0140000 #endif #define S_IFLNK 0120000 #define S_IFREG 0100000 #define S_IFBLK 0060000 #define S_IFDIR 0040000 #define S_IFCHR 0020000 #define S_IFIFO 0010000 #define S_ISUID 0004000 #define S_ISGID 0002000 #define S_ISVTX 0001000 #define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) #define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) #define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) #define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR) #define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK) #define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO) #ifdef __LINUXMT_NETWORK__ #define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK) #endif #define S_IRWXU 00700 #define S_IRUSR 00400 #define S_IWUSR 00200 #define S_IXUSR 00100 #define S_IRWXG 00070 #define S_IRGRP 00040 #define S_IWGRP 00020 #define S_IXGRP 00010 #define S_IRWXO 00007 #define S_IROTH 00004 #define S_IWOTH 00002 #define S_IXOTH 00001 #ifdef __KERNEL__ #define S_IRWXUGO (S_IRWXU|S_IRWXG|S_IRWXO) #define S_IALLUGO (S_ISUID|S_ISGID|S_ISVTX|S_IRWXUGO) #define S_IRUGO (S_IRUSR|S_IRGRP|S_IROTH) #define S_IWUGO (S_IWUSR|S_IWGRP|S_IWOTH) #define S_IXUGO (S_IXUSR|S_IXGRP|S_IXOTH) #endif #endif dev86-0.16.21/libc/kinclude/linuxmt/termios.h000066400000000000000000000153251231050321700206570ustar00rootroot00000000000000#ifndef __LINUXMT_TERMIOS_H #define __LINUXMT_TERMIOS_H #include /* This is just a magic number to make these relatively unique ('T') */ #define __TERMIOS_MAJ ('T'<<8) #define TCGETS (__TERMIOS_MAJ+0x01) #define TCSETS (__TERMIOS_MAJ+0x02) #define TCSETSW (__TERMIOS_MAJ+0x03) #define TCSETSF (__TERMIOS_MAJ+0x04) #define TCGETA (__TERMIOS_MAJ+0x05) #define TCSETA (__TERMIOS_MAJ+0x06) #define TCSETAW (__TERMIOS_MAJ+0x07) #define TCSETAF (__TERMIOS_MAJ+0x08) #define TCSBRK (__TERMIOS_MAJ+0x09) #define TCXONC (__TERMIOS_MAJ+0x0A) #define TCFLSH (__TERMIOS_MAJ+0x0B) #define TIOCEXCL (__TERMIOS_MAJ+0x0C) #define TIOCNXCL (__TERMIOS_MAJ+0x0D) #define TIOCSCTTY (__TERMIOS_MAJ+0x0E) #define TIOCGPGRP (__TERMIOS_MAJ+0x0F) #define TIOCSPGRP (__TERMIOS_MAJ+0x10) #define TIOCOUTQ (__TERMIOS_MAJ+0x11) #define TIOCSTI (__TERMIOS_MAJ+0x12) #define TIOCGWINSZ (__TERMIOS_MAJ+0x13) #define TIOCSWINSZ (__TERMIOS_MAJ+0x14) #define TIOCMGET (__TERMIOS_MAJ+0x15) #define TIOCMBIS (__TERMIOS_MAJ+0x16) #define TIOCMBIC (__TERMIOS_MAJ+0x17) #define TIOCMSET (__TERMIOS_MAJ+0x18) #define TIOCGSOFTCAR (__TERMIOS_MAJ+0x19) #define TIOCSSOFTCAR (__TERMIOS_MAJ+0x1A) #define FIONREAD (__TERMIOS_MAJ+0x1B) #define TIOCINQ FIONREAD #define TIOCLINUX (__TERMIOS_MAJ+0x1C) #define TIOCCONS (__TERMIOS_MAJ+0x1D) #define TIOCGSERIAL (__TERMIOS_MAJ+0x1E) #define TIOCSSERIAL (__TERMIOS_MAJ+0x1F) #define TIOCPKT (__TERMIOS_MAJ+0x20) #define FIONBIO (__TERMIOS_MAJ+0x21) #define TIOCNOTTY (__TERMIOS_MAJ+0x22) #define TIOCSETD (__TERMIOS_MAJ+0x23) #define TIOCGETD (__TERMIOS_MAJ+0x24) #define TCSBRKP (__TERMIOS_MAJ+0x25) /* Needed for POSIX tcsendbreak */ #define TIOCTTYGSTRUCT (__TERMIOS_MAJ+0x26) /* For debugging only */ #define FIONCLEX (__TERMIOS_MAJ+0x50) /* these numbers need to be adjusted. */ #define FIOCLEX (__TERMIOS_MAJ+0x51) #define FIOASYNC (__TERMIOS_MAJ+0x52) #define TIOCSERCONFIG (__TERMIOS_MAJ+0x53) #define TIOCSERGWILD (__TERMIOS_MAJ+0x54) #define TIOCSERSWILD (__TERMIOS_MAJ+0x55) #define TIOCGLCKTRMIOS (__TERMIOS_MAJ+0x56) #define TIOCSLCKTRMIOS (__TERMIOS_MAJ+0x57) #define TIOCSERGSTRUCT (__TERMIOS_MAJ+0x58) /* For debugging only */ #define TIOCSERGETLSR (__TERMIOS_MAJ+0x59) /* Get line status register */ #define TIOCSERGETMULTI (__TERMIOS_MAJ+0x5A) /* Get multiport config */ #define TIOCSERSETMULTI (__TERMIOS_MAJ+0x5B) /* Set multiport config */ /* Used for packet mode */ #define TIOCPKT_DATA 0 #define TIOCPKT_FLUSHREAD 1 #define TIOCPKT_FLUSHWRITE 2 #define TIOCPKT_STOP 4 #define TIOCPKT_START 8 #define TIOCPKT_NOSTOP 16 #define TIOCPKT_DOSTOP 32 struct winsize { unsigned short ws_row; unsigned short ws_col; unsigned short ws_xpixel; unsigned short ws_ypixel; }; #define NCC 8 struct termio { unsigned short c_iflag; /* input mode flags */ unsigned short c_oflag; /* output mode flags */ unsigned short c_cflag; /* control mode flags */ unsigned short c_lflag; /* local mode flags */ unsigned char c_line; /* line discipline */ unsigned char c_cc[NCC]; /* control characters */ }; #define NCCS 19 struct termios { tcflag_t c_iflag; /* input mode flags */ tcflag_t c_oflag; /* output mode flags */ tcflag_t c_cflag; /* control mode flags */ tcflag_t c_lflag; /* local mode flags */ cc_t c_line; /* line discipline */ cc_t c_cc[NCCS]; /* control characters */ }; /* c_cc characters */ #define VINTR 0 #define VQUIT 1 #define VERASE 2 #define VKILL 3 #define VEOF 4 #define VTIME 5 #define VMIN 6 #define VSWTC 7 #define VSTART 8 #define VSTOP 9 #define VSUSP 10 #define VEOL 11 #define VREPRINT 12 #define VDISCARD 13 #define VWERASE 14 #define VLNEXT 15 #define VEOL2 16 /* c_iflag bits */ #define IGNBRK 0000001 #define BRKINT 0000002 #define IGNPAR 0000004 #define PARMRK 0000010 #define INPCK 0000020 #define ISTRIP 0000040 #define INLCR 0000100 #define IGNCR 0000200 #define ICRNL 0000400 #define IUCLC 0001000 #define IXON 0002000 #define IXANY 0004000 #define IXOFF 0010000 #define IMAXBEL 0020000 /* c_oflag bits */ #define OPOST 0000001 #define OLCUC 0000002 #define ONLCR 0000004 #define OCRNL 0000010 #define ONOCR 0000020 #define ONLRET 0000040 #define OFILL 0000100 #define OFDEL 0000200 #define NLDLY 0000400 #define NL0 0000000 #define NL1 0000400 #define CRDLY 0003000 #define CR0 0000000 #define CR1 0001000 #define CR2 0002000 #define CR3 0003000 #define TABDLY 0014000 #define TAB0 0000000 #define TAB1 0004000 #define TAB2 0010000 #define TAB3 0014000 #define XTABS 0014000 #define BSDLY 0020000 #define BS0 0000000 #define BS1 0020000 #define VTDLY 0040000 #define VT0 0000000 #define VT1 0040000 #define FFDLY 0100000 #define FF0 0000000 #define FF1 0100000 /* c_cflag bit meaning */ #define CBAUD 0010017 #define B0 0000000 /* hang up */ #define B50 0000001 #define B75 0000002 #define B110 0000003 #define B134 0000004 #define B150 0000005 #define B200 0000006 #define B300 0000007 #define B600 0000010 #define B1200 0000011 #define B1800 0000012 #define B2400 0000013 #define B4800 0000014 #define B9600 0000015 #define B19200 0000016 #define B38400 0000017 #define EXTA B19200 #define EXTB B38400 #define CSIZE 0000060 #define CS5 0000000 #define CS6 0000020 #define CS7 0000040 #define CS8 0000060 #define CSTOPB 0000100 #define CREAD 0000200 #define PARENB 0000400 #define PARODD 0001000 #define HUPCL 0002000 #define CLOCAL 0004000 #define CBAUDEX 0010000 #define B57600 0010001 #define B115200 0010002 #define B230400 0010003 #define CIBAUD 002003600000 /* input baud rate (not used) */ #define CRTSCTS 020000000000 /* flow control */ /* c_lflag bits */ #define ISIG 0000001 #define ICANON 0000002 #define XCASE 0000004 #define ECHO 0000010 #define ECHOE 0000020 #define ECHOK 0000040 #define ECHONL 0000100 #define NOFLSH 0000200 #define TOSTOP 0000400 #define ECHOCTL 0001000 #define ECHOPRT 0002000 #define ECHOKE 0004000 #define FLUSHO 0010000 #define PENDIN 0040000 #define IEXTEN 0100000 /* modem lines */ #define TIOCM_LE 0x001 #define TIOCM_DTR 0x002 #define TIOCM_RTS 0x004 #define TIOCM_ST 0x008 #define TIOCM_SR 0x010 #define TIOCM_CTS 0x020 #define TIOCM_CAR 0x040 #define TIOCM_RNG 0x080 #define TIOCM_DSR 0x100 #define TIOCM_CD TIOCM_CAR #define TIOCM_RI TIOCM_RNG /* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */ #define TIOCSER_TEMT 0x01 /* Transmitter physically empty */ /* tcflow() and TCXONC use these */ #define TCOOFF 0 #define TCOON 1 #define TCIOFF 2 #define TCION 3 /* tcflush() and TCFLSH use these */ #define TCIFLUSH 0 #define TCOFLUSH 1 #define TCIOFLUSH 2 /* tcsetattr uses these */ #define TCSANOW 0 #define TCSADRAIN 1 #define TCSAFLUSH 2 /* line disciplines */ #define N_TTY 0 #define N_SLIP 1 #define N_MOUSE 2 #define N_PPP 3 #define _POSIX_VDISABLE '\0' #endif /* __LINUXMT_TERMIOS_H */ dev86-0.16.21/libc/kinclude/linuxmt/types.h000066400000000000000000000006711231050321700203370ustar00rootroot00000000000000#ifndef __LINUXMT_TYPES_H #define __LINUXMT_TYPES_H #include typedef __u32 off_t; typedef __u16 pid_t; typedef __u16 uid_t; typedef __u16 gid_t; typedef __u32 time_t; typedef __u16 umode_t; typedef __u16 nlink_t; typedef __u16 mode_t; typedef __u32 loff_t; typedef __u32 speed_t; typedef __u16 size_t; typedef __u16 dev_t; typedef __uint ino_t; typedef __u32 tcflag_t; typedef __u8 cc_t; typedef int ptrdiff_t; #endif dev86-0.16.21/libc/malloc/000077500000000000000000000000001231050321700147675ustar00rootroot00000000000000dev86-0.16.21/libc/malloc/Config000066400000000000000000000000301231050321700161100ustar00rootroot00000000000000malloc: Malloc routines dev86-0.16.21/libc/malloc/Makefile000066400000000000000000000010161231050321700164250ustar00rootroot00000000000000# Copyright (C) 1995,1996 Robert de Bath # This file is part of the Linux-8086 C library and is distributed # under the GNU Library General Public License. ASRC=malloc.c AOBJ=malloc.o alloca.o free.o calloc.o realloc.o CFLAGS=$(ARCH) $(CCFLAGS) $(DEFS) all: $(LIBC)($(AOBJ)) @$(RM) $(OBJ) $(LIBC)($(AOBJ)): $(ASRC) $(CC) $(CFLAGS) -DL_$* $< -c -o $*.o $(AR) $(ARFLAGS) $@ $*.o clean: rm -f *.o libc.a ../include/malloc.h transfer: -@rm ../include/malloc.h cp -p malloc.h ../include/. dev86-0.16.21/libc/malloc/README000066400000000000000000000005631231050321700156530ustar00rootroot00000000000000Copyright (C) 1995,1996 Robert de Bath This file is part of the Linux-8086 C library and is distributed under the GNU Library General Public License. This is a combined alloca/malloc package. It uses a classic algorithm and so may be seen to be quite slow compared to more modern routines with 'nasty' distributions of allocation. -Robert dev86-0.16.21/libc/malloc/malloc.c000066400000000000000000000266171231050321700164160ustar00rootroot00000000000000/* Copyright (C) 1995,1996 Robert de Bath * This file is part of the Linux-8086 C library and is distributed * under the GNU Library General Public License. */ /* * This is a combined alloca/malloc package. It uses a classic algorithm * and so may be seen to be quite slow compared to more modern routines * with 'nasty' distributions. */ #include #include #define MCHUNK 2048 /* Allocation unit in 'mem' elements */ #define XLAZY_FREE /* If set frees can be infinitly defered */ #define XMINALLOC 32 /* Smallest chunk to alloc in 'mem's */ #define XVERBOSE /* Lots of noise, debuging ? */ #undef malloc #define MAX_INT ((int)(((unsigned)-1)>>1)) #ifdef VERBOSE #define noise __noise #else #define noise(y,x) #endif typedef union mem_cell { union mem_cell *next; /* A pointer to the next mem */ unsigned int size; /* An int >= sizeof pointer */ char *depth; /* For the alloca hack */ } mem; #define m_size(p) ((p) [0].size) /* For malloc */ #define m_next(p) ((p) [1].next) /* For malloc and alloca */ #define m_deep(p) ((p) [0].depth) /* For alloca */ extern void *__mini_malloc __P ((size_t)); extern void *(*__alloca_alloc) __P ((size_t)); extern mem *__freed_list; #ifdef L_free /* Start the alloca with just the dumb version of malloc */ void *(*__alloca_alloc) __P ((size_t)) = __mini_malloc; mem *__freed_list = 0; #ifdef VERBOSE /* NB: Careful here, stdio may use malloc - so we can't */ static phex(val) { static char hex[] = "0123456789ABCDEF"; int i; for (i = sizeof(int)*8-4; i >= 0; i -= 4) write(2, hex + ((val >> i) & 0xF), 1); } noise(y, x) char *y; mem *x; { write(2, "Malloc ", 7); phex(x); write(2, " sz ", 4); if(x) phex(m_size(x)); else phex(0); write(2, " nxt ", 5); if(x) phex(m_next(x)); else phex(0); write(2, " is ", 4); write(2, y, strlen(y)); write(2, "\n", 1); } #endif #endif #ifdef L_alloca /* This alloca is based on the same concept as the EMACS fallback alloca. * It should probably be considered Copyright the FSF under the GPL. */ static mem *alloca_stack = 0; void * alloca(size) size_t size; { auto char probe; /* Probes stack depth: */ register mem *hp; /* * Reclaim garbage, defined as all alloca'd storage that was allocated * from deeper in the stack than currently. */ for (hp = alloca_stack; hp != 0;) if (m_deep(hp) < &probe) { register mem *np = m_next(hp); free((void *) hp); /* Collect garbage. */ hp = np; /* -> next header. */ } else break; /* Rest are not deeper. */ alloca_stack = hp; /* -> last valid storage. */ if (size == 0) return 0; /* No allocation required. */ hp = (mem *) (*__alloca_alloc) (sizeof(mem)*2 + size); if (hp == 0) return hp; m_next(hp) = alloca_stack; m_deep(hp) = &probe; alloca_stack = hp; /* User storage begins just after header. */ return (void *) (hp + 2); } #endif /* L_alloca */ #ifdef L_free void free(ptr) void *ptr; { register mem *top; register mem *chk = (mem *) ptr; if (chk == 0) return; /* free(NULL) - be nice */ chk--; try_this:; top = (mem *) sbrk(0); if (chk + m_size(chk) == top) { noise("FREE brk", chk); brk(top-m_size(chk)); /* * Adding this code allow free to release blocks in any order; they * can still only be allocated from the top of the heap tho. */ #ifdef __MINI_MALLOC__ if (__alloca_alloc == __mini_malloc && __freed_list) { mem *prev, *curr; chk = __freed_list; __freed_list = m_next(__freed_list); goto try_this; } #endif } else { /* Nope, not sure where this goes, leave * it for malloc to deal with */ #ifdef __MINI_MALLOC__ if( __freed_list || chk > __freed_list ) { m_next(chk) = __freed_list; __freed_list = chk; } else { register mem *prev; prev=__freed_list; for(top=__freed_list; top && top > chk; prev=top, top=m_next(top)) ; m_next(chk) = top; m_next(prev) = chk; } #else m_next(chk) = __freed_list; __freed_list = chk; #endif noise("ADD LIST", chk); } } void * __mini_malloc(size) size_t size; { register mem *ptr; register unsigned int sz; /* First time round this _might_ be odd, But we won't do that! */ sz = (unsigned int) sbrk(0); if (sz & (sizeof(mem) - 1)) sbrk(4 - (sz & (sizeof(mem) - 1))); if (size <= 0) return 0; /* Minor oops here, sbrk has a signed argument */ if( size > (((unsigned)-1)>>1)-sizeof(mem)*3 ) { errno = ENOMEM; return 0; } size += sizeof(mem) * 2 - 1; /* Round up and leave space for size field */ size /= sizeof(mem); ptr = (mem *) sbrk(size * sizeof(mem)); if ((int) ptr == -1) return 0; m_size(ptr) = size; noise("CREATE", ptr); return ptr + 1; } #endif /* L_free */ #ifdef L_malloc /* * The chunk_list pointer is either NULL or points to a chunk in a * circular list of all the free blocks in memory */ #define Static static static mem *chunk_list = 0; Static void __insert_chunk(); Static mem *__search_chunk(); void * malloc(size) size_t size; { register mem *ptr = 0; register unsigned int sz; if (size == 0) return 0; /* ANSI STD */ sz = size + sizeof(mem) * 2 - 1; sz /= sizeof(mem); #ifdef MINALLOC if (sz < MINALLOC) sz = MINALLOC; #endif #ifdef VERBOSE { static mem arr[2]; m_size(arr) = sz; noise("WANTED", arr); } #endif __alloca_alloc = malloc; /* We'll be messing with the heap now TVM */ #ifdef LAZY_FREE ptr = __search_chunk(sz); if (ptr == 0) { #endif /* First deal with the freed list */ if (__freed_list) { while (__freed_list) { ptr = __freed_list; __freed_list = m_next(__freed_list); if (m_size(ptr) == sz) /* Oh! Well that's lucky ain't it * :-) */ { noise("LUCKY MALLOC", ptr); return ptr + 1; } __insert_chunk(ptr); } ptr = m_next(chunk_list); if (ptr + m_size(ptr) == (void *) sbrk(0)) { /* Time to free for real */ m_next(chunk_list) = m_next(ptr); if (ptr == m_next(ptr)) chunk_list = 0; free(ptr + 1); } #ifdef LAZY_FREE ptr = __search_chunk(sz); #endif } #ifndef LAZY_FREE ptr = __search_chunk(sz); #endif if (ptr == 0) { #ifdef MCHUNK unsigned int alloc; alloc = sizeof(mem) * (MCHUNK * ((sz + MCHUNK - 1) / MCHUNK) - 1); ptr = __mini_malloc(alloc); if (ptr) __insert_chunk(ptr - 1); else /* Oooo, near end of RAM */ { unsigned int needed = alloc; for(alloc/=2; alloc>256 && needed; ) { ptr = __mini_malloc(alloc); if (ptr) { if( alloc > needed ) needed = 0; else needed -= alloc; __insert_chunk(ptr - 1); } else alloc/=2; } } ptr = __search_chunk(sz); if (ptr == 0) #endif { #ifndef MCHUNK ptr = __mini_malloc(size); #endif #ifdef VERBOSE if( ptr == 0 ) noise("MALLOC FAIL", 0); else noise("MALLOC NOW", ptr - 1); #endif return ptr; } } #ifdef LAZY_FREE } #endif #ifdef VERBOSE ptr[1].size = 0x55555555; #endif noise("MALLOC RET", ptr); return ptr + 1; } /* * This function takes a pointer to a block of memory and inserts it into * the chain of memory chunks */ Static void __insert_chunk(mem_chunk) mem *mem_chunk; { register mem *p1, *p2; if (chunk_list == 0) /* Simple case first */ { m_next(mem_chunk) = chunk_list = mem_chunk; noise("FIRST CHUNK", mem_chunk); return; } p1 = mem_chunk; p2 = chunk_list; do { if (p1 > p2) { if (m_next(p2) <= p2) { /* We're at the top of the chain, p1 is * higher */ if (p2 + m_size(p2) == p1) { /* Good, stick 'em together */ noise("INSERT CHUNK", mem_chunk); m_size(p2) += m_size(p1); noise("JOIN 1", p2); } else { m_next(p1) = m_next(p2); m_next(p2) = p1; noise("INSERT CHUNK", mem_chunk); noise("FROM", p2); } return; } if (m_next(p2) > p1) { /* In chain, p1 between p2 and next */ m_next(p1) = m_next(p2); m_next(p2) = p1; noise("INSERT CHUNK", mem_chunk); noise("FROM", p2); /* Try to join above */ if (p1 + m_size(p1) == m_next(p1)) { m_size(p1) += m_size(m_next(p1)); m_next(p1) = m_next(m_next(p1)); noise("JOIN 2", p1); } /* Try to join below */ if (p2 + m_size(p2) == p1) { m_size(p2) += m_size(p1); m_next(p2) = m_next(p1); noise("JOIN 3", p2); } chunk_list = p2; /* Make sure it's valid */ return; } } else if (p1 < p2) { if (m_next(p2) <= p2 && p1 < m_next(p2)) { /* At top of chain, next is bottom of chain, p1 is below next */ m_next(p1) = m_next(p2); m_next(p2) = p1; noise("INSERT CHUNK", mem_chunk); noise("FROM", p2); chunk_list = p2; if (p1 + m_size(p1) == m_next(p1)) { if (p2 == m_next(p1)) chunk_list = p1; m_size(p1) += m_size(m_next(p1)); m_next(p1) = m_next(m_next(p1)); noise("JOIN 4", p1); } return; } } chunk_list = p2; /* Save for search */ p2 = m_next(p2); } while (p2 != chunk_list); /* If we get here we have a problem, ignore it, maybe it'll go away */ noise("DROPPED CHUNK", mem_chunk); } /* * This function will search for a chunk in memory of at least 'mem_size' * when found, if the chunk is too big it'll be split, and pointer to the * chunk returned. If none is found NULL is returned. */ Static mem * __search_chunk(mem_size) unsigned int mem_size; { register mem *p1, *p2; if (chunk_list == 0) /* Simple case first */ return 0; /* Search for a block >= the size we want */ p1 = m_next(chunk_list); p2 = chunk_list; do { noise("CHECKED", p1); if (m_size(p1) >= mem_size) break; p2 = p1; p1 = m_next(p1); } while (p2 != chunk_list); /* None found, exit */ if (m_size(p1) < mem_size) return 0; /* If it's exactly right remove it */ if (m_size(p1) < mem_size + 2) { noise("FOUND RIGHT", p1); chunk_list = m_next(p2) = m_next(p1); if (chunk_list == p1) chunk_list = 0; return p1; } noise("SPLIT", p1); /* Otherwise split it */ m_next(p2) = p1 + mem_size; chunk_list = p2; p2 = m_next(p2); m_size(p2) = m_size(p1) - mem_size; m_next(p2) = m_next(p1); m_size(p1) = mem_size; if (chunk_list == p1) chunk_list = p2; #ifdef VERBOSE p1[1].size = 0xAAAAAAAA; #endif noise("INSERT CHUNK", p2); noise("FOUND CHUNK", p1); noise("LIST IS", chunk_list); return p1; } #endif /* L_malloc */ #ifdef L_calloc void * calloc(elm, sz) unsigned int elm, sz; { register unsigned int v; register void *ptr; ptr = malloc(v = elm * sz); if (ptr) memset(ptr, 0, v); return ptr; } #endif /* L_calloc */ #ifdef L_realloc void * realloc(ptr, size) void *ptr; size_t size; { void *nptr; unsigned int osize; if (ptr == 0) return malloc(size); osize = (m_size(((mem *) ptr) - 1) - 1) * sizeof(mem); if (size <= osize) { return ptr; } nptr = malloc(size); if (nptr == 0) return 0; memcpy(nptr, ptr, osize); free(ptr); return nptr; } #endif /* L_realloc */ dev86-0.16.21/libc/malloc/malloc.h000066400000000000000000000012321231050321700164050ustar00rootroot00000000000000 #ifndef __MALLOC_H #define __MALLOC_H #include #include /* * Mini malloc allows you to use a less efficient but smaller malloc the * cost is about 100 bytes of code in free but malloc (700bytes) doesn't * have to be linked. Unfortunatly memory can only be reused if everything * above it has been freed * */ extern void free __P((void *)); extern void *malloc __P((size_t)); extern void *realloc __P((void *, size_t)); extern void *alloca __P((size_t)); extern void *(*__alloca_alloc) __P((size_t)); #ifdef __LIBC__ #define __MINI_MALLOC__ #endif #ifdef __MINI_MALLOC__ #define malloc(x) ((*__alloca_alloc)(x)) #endif #endif dev86-0.16.21/libc/misc/000077500000000000000000000000001231050321700144535ustar00rootroot00000000000000dev86-0.16.21/libc/misc/Config000066400000000000000000000000411231050321700155760ustar00rootroot00000000000000misc: Various unix lib functions dev86-0.16.21/libc/misc/Makefile000066400000000000000000000030411231050321700161110ustar00rootroot00000000000000# Copyright (C) 1995,1996 Robert de Bath # This file is part of the Linux-8086 C library and is distributed # under the GNU Library General Public License. MSRC=aliases.c MOBJ=labs.o abs.o raise.o bcopy.o bzero.o bcmp.o index.o rindex.o \ remove.o creat.o ESRC=atexit.c EOBJ=on_exit.o atexit.o __do_exit.o GOBJ=atoi.o atol.o ltoa.o ltostr.o \ ctype.o ctypefn.o qsort.o bsearch.o rand.o lsearch.o getopt.o \ itoa.o cputype.o strtol.o crypt.o UOBJ=getenv.o putenv.o popen.o system.o setenv.o getcwd.o tmpnam.o SSRC=syslib.c SOBJ=time.o abort.o wait.o wait3.o waitpid.o killpg.o setpgrp.o sleep.o \ usleep.o mkfifo.o ifeq ($(LIB_OS),ELKS) OBJ=$(MOBJ) $(EOBJ) $(GOBJ) $(UOBJ) $(SOBJ) else OBJ=$(MOBJ) $(EOBJ) $(GOBJ) endif # No ELKS strtod() until BCC does 16 bit FP... ifneq ($(LIB_CPU),i86) OBJ+=strtod.o atof.o endif CFLAGS=$(ARCH) $(CCFLAGS) $(DEFS) all: $(LIBC) @$(RM) $(OBJ) $(LIBC): $(LIBC)($(OBJ)) $(LIBC)($(MOBJ)): $(MSRC) $(CC) $(CFLAGS) -DL_$* $< -c -o $*.o $(AR) $(ARFLAGS) $@ $*.o $(LIBC)($(EOBJ)): $(ESRC) $(CC) $(CFLAGS) -DL_$* $< -c -o $*.o $(AR) $(ARFLAGS) $@ $*.o $(LIBC)($(SOBJ)): $(SSRC) $(CC) $(CFLAGS) -DL_$* $< -c -o $*.o $(AR) $(ARFLAGS) $@ $*.o clean: rm -f *.o libc.a $(LIBC)(strtol.o): strtol.c $(CC) -c -ansi $(ARCH) $(CCFLAGS) $(DEFS) $*.c $(AR) $(ARFLAGS) $@ $*.o $(LIBC)(strtod.o): strtod.c $(CC) -c -ansi $(ARCH) $(CCFLAGS) $(DEFS) $*.c $(AR) $(ARFLAGS) $@ $*.o $(LIBC)(crypt.o): crypt.c $(CC) -c -ansi $(ARCH) $(CCFLAGS) $(DEFS) $*.c $(AR) $(ARFLAGS) $@ $*.o dev86-0.16.21/libc/misc/aliases.c000066400000000000000000000027661231050321700162530ustar00rootroot00000000000000/* Copyright (C) 1995,1996 Robert de Bath * This file is part of the Linux-8086 C library and is distributed * under the GNU Library General Public License. */ #include #include #ifdef L_abs int abs(arg1) int arg1; { return arg1>0?arg1:-arg1; } #endif #ifdef L_labs long labs(arg1) long arg1; { return arg1>0?arg1:-arg1; } #endif #ifdef L_raise int raise(signo) int signo; { return kill(getpid(), signo); } #endif #ifdef L_bcopy #undef bcopy void bcopy(src, dest, len) __const void * src; void *dest; int len; { (void) memcpy(dest, src, len); } #endif #ifdef L_bzero #undef bzero void bzero(dest, len) void *dest; int len; { (void) memset(dest, '\0', len); } #endif #ifdef L_bcmp #undef bcmp int bcmp(dest, src, len) __const void * src, *dest; int len; { return memcmp(dest, src, len); } #endif #ifdef L_index #undef index char * index(src, chr) __const char *src; int chr; { return strchr(src, chr); } #endif #ifdef L_rindex #undef rindex char * rindex(src, chr) __const char *src; int chr; { return strrchr(src, chr); } #endif #ifdef L_remove #include int remove(src) __const char *src; { extern int errno; int er = errno; int rv = unlink(src); if( rv < 0 && errno == EISDIR ) rv = rmdir(src); if( rv >= 0 ) errno = er; return rv; } #endif #ifdef L_creat #include int creat(file, mode) __const char * file; mode_t mode; { return open(file, O_TRUNC|O_CREAT|O_WRONLY, mode); } #endif dev86-0.16.21/libc/misc/atexit.c000066400000000000000000000036111231050321700161160ustar00rootroot00000000000000/* Copyright (C) 1995,1996 Robert de Bath * This file is part of the Linux-8086 C library and is distributed * under the GNU Library General Public License. */ /* * This deals with both the atexit and on_exit function calls * * Note calls installed with atexit are called with the same args as on_exit * fuctions; the void* is given the NULL value. * */ #include /* ATEXIT.H */ #define MAXONEXIT 20 /* AIUI Posix requires 10 */ typedef void (*vfuncp) (); extern vfuncp __cleanup; extern void __do_exit(); extern struct exit_table { vfuncp called; void *argument; } __on_exit_table[MAXONEXIT]; extern int __on_exit_count; /* End ATEXIT.H */ #ifdef L_atexit int atexit(ptr) vfuncp ptr; { if( __on_exit_count < 0 || __on_exit_count >= MAXONEXIT) { errno = ENOMEM; return -1; } __cleanup = __do_exit; if( ptr ) { __on_exit_table[__on_exit_count].called = ptr; __on_exit_table[__on_exit_count].argument = 0; __on_exit_count++; } return 0; } #endif #ifdef L_on_exit int on_exit(ptr, arg) vfuncp ptr; void *arg; { if( __on_exit_count < 0 || __on_exit_count >= MAXONEXIT) { errno = ENOMEM; return -1; } __cleanup = __do_exit; if( ptr ) { __on_exit_table[__on_exit_count].called = ptr; __on_exit_table[__on_exit_count].argument = arg; __on_exit_count++; } return 0; } #endif #ifdef L___do_exit int __on_exit_count = 0; struct exit_table __on_exit_table[MAXONEXIT]; void __do_exit(rv) int rv; { register int count = __on_exit_count-1; register vfuncp ptr; __on_exit_count = -1; /* ensure no more will be added */ __cleanup = 0; /* Calling exit won't re-do this */ /* In reverse order */ for (; count >= 0; count--) { ptr = __on_exit_table[count].called; (*ptr) (rv, __on_exit_table[count].argument); } } #endif dev86-0.16.21/libc/misc/atof.c000066400000000000000000000004371231050321700155540ustar00rootroot00000000000000/* Copyright (C) Robert de Bath * This file is part of the Linux-8086 C library and is distributed * under the GNU Library General Public License. */ double #ifdef __STDC__ atof(const char *p) #else atof(p) char *p; #endif { return strtod(p, (char**)0); } dev86-0.16.21/libc/misc/atoi.c000066400000000000000000000010431231050321700155510ustar00rootroot00000000000000/* Copyright (C) 1995,1996 Robert de Bath * This file is part of the Linux-8086 C library and is distributed * under the GNU Library General Public License. */ int atoi(number) register char *number; { register int n = 0, neg = 0; while (*number <= ' ' && *number > 0) ++number; if (*number == '-') { neg = 1; ++number; } else if (*number == '+') ++number; while (*number>='0' && *number<='9') n = (n * 10) + ((*number++) - '0'); return (neg ? -n : n); } dev86-0.16.21/libc/misc/atol.c000066400000000000000000000010451231050321700155560ustar00rootroot00000000000000/* Copyright (C) 1995,1996 Robert de Bath * This file is part of the Linux-8086 C library and is distributed * under the GNU Library General Public License. */ long atol(number) register char *number; { register long n = 0, neg = 0; while (*number <= ' ' && *number > 0) ++number; if (*number == '-') { neg = 1; ++number; } else if (*number == '+') ++number; while (*number>='0' && *number<='9') n = (n * 10) + ((*number++) - '0'); return (neg ? -n : n); } dev86-0.16.21/libc/misc/bsearch.c000066400000000000000000000021151231050321700162250ustar00rootroot00000000000000 /* * This file lifted in toto from 'Dlibs' on the atari ST (RdeBath) * * * Dale Schumacher 399 Beacon Ave. * (alias: Dalnefre') St. Paul, MN 55104 * dal@syntel.UUCP United States of America * "It's not reality that's important, but how you perceive things." */ #include static int _bsearch; /* index of element found, or where to * insert */ char * bsearch(key, base, num, size, cmp) register char *key; /* item to search for */ register char *base; /* base address */ int num; /* number of elements */ register int size; /* element size in bytes */ register int (*cmp) (); /* comparison function */ { register int a, b, c, dir; a = 0; b = num - 1; while (a <= b) { c = (a + b) >> 1; /* == ((a + b) / 2) */ if (dir = (*cmp) ((base + (c * size)), key)) { if (dir > 0) b = c - 1; else /* (dir < 0) */ a = c + 1; } else { _bsearch = c; return (base + (c * size)); } } _bsearch = b; return (NULL); } dev86-0.16.21/libc/misc/cputype.c000066400000000000000000000144361231050321700163200ustar00rootroot00000000000000/* Copyright (C) 1989,1996 Robert de Bath * This file is part of the Linux-8086 C library and is distributed * under the terms of the GNU Library General Public License. ********************************************************************** * * This does a determination of the cpu type that is actually being used. * It can determine the CPU on anything upto and including a 386 accuratly * whatever mode the CPU is in (This is 16 bit code) * * For Post 386 interpretation the argument must be set to 1, if this is done * an attempt to determine the CPU type will be made using MSDOS calls and * potentially Illegal instructions. * * If STANDALONE is defined this will decode and print the output from cputype * * $ cputype # Call cputype(0) and interpret * $ cputype + # Call cputype(1) get a SIGILL (or perhaps interpret) * */ #ifdef STANDALONE #define cputype cpu #include #ifndef __MSDOS__ #include #endif char * name_808x[] = { "8088", "8086", "80C88", "80C86", "NEC V20", "NEC V30", "808x Clone" }; char * name_8018x[] = { "80188", "80186", "8018x Clone" }; void main(argc, argv) int argc; char **argv; { int c, major, flg, fpu; #ifdef SIGFPE signal(SIGFPE, SIG_IGN); #endif printf("Cpu identifier - (C) R de Bath \n"); c = cputype(argc!=1); fpu = (c<0); major = ((c>>8)&0x1F); c &= 0xFF; if( major == 0 ) { if( c > 6 ) c = 6; printf("Cpu is an %s\n", name_808x[c]); } else if( major == 1 ) { if( c > 3 ) c = 3; printf("Cpu is an %s\n", name_8018x[c]); } else { printf("Cpu is an 80%x86%s", major&0xF, major>15?"+":""); if(c&0x01) printf( " in protected mode"); printf(" MSW= "); if( c&0x10 ) printf("ET,"); else printf("--,"); if( c&0x08 ) printf("TS,"); else printf("--,"); if( c&0x04 ) printf("EM,"); else printf("--,"); if( c&0x02 ) printf("MP,"); else printf("--,"); if( c&0x01 ) printf("PE\n"); else printf("--\n"); if( !fpu && ( c&0x06) ) printf("An FPU appears to exist but it is unavailable\n"); else { if( c&0x02 ) printf("Math processor requires WAIT\n"); if( c&0x04 ) printf("Emulated math present\n"); if( c&0x08 ) printf("Math processor belongs to a different process\n"); /* if( c&0x10 ) printf("Humm\n"); */ } } if( fpu ) printf("FPU available for use\n"); exit(0); } #endif /* * The assembler for CPU determination. * * Improvements and additional CPUs are solicited. */ #ifdef __AS386_16__ #asm .text #ifdef STANDALONE export _cpu _cpu: #else export _cputype _cputype: #endif ; First save everything ... push bp mov bp,sp push ds push es push bx push cx push dx pushf #if __FIRST_ARG_IN_AX__ mov cx, ax ; Collect the flag #else mov cx, [bp+4] ; Collect the flag #endif ; Tiny mode code ... mov ax, cs mov es, ax mov ds, ax mov bx, #0 ; Init to 8086 ; First easy check is it a 286 or better ... push sp pop ax cmp ax, sp jz ge286 br pre286 ; Come here when we`re done (286+) cpu_prot: ; .286P smsw ax ; Fetch 5 LSB of MSW (PE,MP,EP,...) and al,#31 mov bl,al ; Check for FPU fninit xor ax,ax push ax mov bp,sp fnstcw word ptr [bp] pop ax cmp ah,#3 jne cpuend or bh,#$80 ; Another check for FPU *BUT* I think this only get`s 287+ ; finit ; fstsw ax ; or al,al ; jnz cpuend ; or bh,#$80 ; .8086 cpuend: mov ax, bx popf pop dx pop cx pop bx pop es pop ds pop bp ret ge286: ; .286P ; Does the caller want the exact CPU cmp cx,#0 jne try_486 ; Simple test for a 286 ... mov bh,#2 ; Major CPU type >= 80286 ; What`s the contents of the GDT pointer sub sp,#6 mov bp,sp sgdt [bp] add sp,#4 pop ax ; For 286, ah can only be 0xFF inc ah jz cpu_prot mov bh,#$13 ; Major CPU type >= 80386 #ifdef __MSDOS__ smsw ax ; If we`re in MSDOS and running in real mode ror ax,#1 ; we can do the int 6 detection. jnc try_486 #endif jmp cpu_prot ; Assume 486 test will NOT work in prot mode ; This is an alternate way of finding a 386 ... ; But it *can* be hidden by V86 mode. ; pushf ; mov ax,#$7000 ; push ax ; popf ; pushf ; pop ax ; popf ; and ax,#$7000 ; jz is_a_286 try_486: ; This trys to trap undefined instructions ; it may not work if the CPU is in protected mode ; Note: This code works for anything 286+ cli push bp mov bp, sp mov ax,#$3506 int #$21 ; WARNING - DOS DOS DOS DOS DOS !!!!! mov [vector+2], es mov [vector], bx mov ax,#$2506 lea dx, [int6] int #$21 mov bh,#2 ; 286 ; .486 test386: mov ebx,#$00040300 ; 386 or 486 test486: bswap ebx ; Byte twiddle now 486 mov ax,#1 do_cpuid: db $0F ; CPUID instruction db $A2 mov ax,#1 ; And again cause of Nasty EMM386s db $0F ; CPUID instruction db $A2 and ah,#15 ; Select family number mov bh,ah ; put it where we want it ; .286P fail386: mov ax, #$2506 mov dx, [vector] mov ds, [vector+2] int #$21 pop bp sti br cpu_prot ; Tests for processors before the 80286 ... ; .8086 pre286: ; Is it an 8018x ? These mask shifts to less that 32 bits mov cl,#32 mov ax, #$0100 shl ax,cl mov bx, ax jnz test8 ; Try for an NEC V20/30 mov ax, #$0208 db $D5 db 16 ; Only the 8088 actually checks the arg to AAD cmp al, #$28 ; as intel ran out of microcode space jz cmos mov bx,#4 ; NEC V20 jmp test8 ; The CMOS 8088/6 had the bug with rep lods repaired. cmos: push si sti mov cx, #$FFFF rep lodsb pop si or cx,cx jne test8 mov bx,#2 ; Intel 80C88 ; This tests the prefetch of the CPU, 8 bit ones have 4 bytes ; 16 bit cpus have a queue of 6 bytes. test8: push di push bx mov dx,#0 mov bx,#4 std mov al,#$90 retest: lea di,[_nop] cli mov cx,#3 rep stosb nop nop nop nop _inc: inc dx nop _nop: nop sti mov byte ptr [_inc], #$42 dec bx jnz retest pop bx cmp dx,#0 jz done8 inc bx done8: pop di cld br cpuend ; Function called by the illegal instruction trap int6: mov sp, bp jmp fail386 ; This was the old way, didn`t always work tho. ; push bp ; mov bp, sp ; push ax ; mov ax,cs ; cmp 4[bp],ax ; pop ax ; jnz pass ; cmp bh,#2 ; je move23 ; cmp bh,#3 ; je move34 ; add [bp+2], #(fail386 - do_cpuid) ; jmp return ;move34: add [bp+2], #(fail386 - test486) ; jmp return ;move23: add [bp+2], #(fail386 - test386) ;return: pop bp ; iret ; ;pass: pop bp ; jmp [vector] vector: dd 0 #endasm #endif dev86-0.16.21/libc/misc/crypt.c000066400000000000000000000041651231050321700157660ustar00rootroot00000000000000/* TEA based crypt(), version 0.0 * It looks like there are problems with key bits carrying through * to the encryted data, and I want to get rid of that libc call.. * This is just so rob could see it ;) */ /* * I've: * Compared the TEA implementation to a reference source - OK * Reduced the cycles count from 64 to 32 (the suggested value) * Changed the types of 'n' and 'i' for better code with bcc. * Removed a possible overrun of rkey by looping the values, it's now * possible to _choose_ every bit of the 128bit PW with a 32 character word. * Corrected the output transformation, it lost bits between words. * Cleaned out all trace of the uncrypted PW from rkey. * * RDB. */ #include char * crypt(const char * key, const char * salt) { /* n is the number of cycles (2 rounds/cycle), delta is a golden # derivative, k is the key, v is the data to be encrypted. */ unsigned long v[2], sum=0, delta=0x9e3779b9, k[4]; int n=32, i, j; static char rkey[16]; /* Our constant string will be a string of zeros .. */ v[0]=v[1]=k[0]=k[1]=k[2]=k[3]=0; for(i=0;i<16;i++) rkey[i]=0; rkey[0]=*salt; rkey[1]=salt[1]; for (j=2,i=0;key[i];i++,j=((j+1)&15)) rkey[j]=(rkey[j]<<4)+(rkey[j]>>4)+ key[i]; memcpy(k, rkey, 4*sizeof(long)); while (n-->0) { sum += delta; v[0] += (v[1]<<4)+k[0] ^ v[1]+sum ^ (v[1]>>5)+k[1]; v[1] += (v[0]<<4)+k[2] ^ v[0]+sum ^ (v[0]>>5)+k[3]; } /* Remove any trace of key */ for(i=0;i<16;i++) rkey[i]=0; *rkey=*salt; rkey[1]=salt[1]; /* Now we need to unpack the bits and map it to "A-Za-z0-9./" for printing in /etc/passwd */ sum=v[0]; for (i=2;i<13;i++) { /* This unpacks the 6 bit data, each cluster into its own byte */ rkey[i]=(sum&0x3F); sum>>=6; if(i==0+2) sum |= (v[1]<<26); if(i==5+2) sum |= (v[1]>>4); /* Now we map to the proper chars */ if (rkey[i]>=0 && rkey[i]<12) rkey[i]+=46; else if (rkey[i]>11 && rkey[i]<38) rkey[i]+=53; else if (rkey[i]>37 && rkey[i]<64) rkey[i]+=59; else return NULL; } rkey[13]='\0'; return rkey; } dev86-0.16.21/libc/misc/ctype.c000066400000000000000000000043011231050321700157410ustar00rootroot00000000000000/* Copyright (C) 1995,1996 Robert de Bath * This file is part of the Linux-8086 C library and is distributed * under the GNU Library General Public License. */ /* * CTYPE.C Character classification and conversion */ #include unsigned char __ctype[257] = { 0, /* -1 */ __CT_c, __CT_c, __CT_c, __CT_c, /* 0x00..0x03 */ __CT_c, __CT_c, __CT_c, __CT_c, /* 0x04..0x07 */ __CT_c, __CT_c|__CT_s, __CT_c|__CT_s, __CT_c|__CT_s, /* 0x08..0x0B */ __CT_c|__CT_s, __CT_c|__CT_s, __CT_c, __CT_c, /* 0x0C..0x0F */ __CT_c, __CT_c, __CT_c, __CT_c, /* 0x10..0x13 */ __CT_c, __CT_c, __CT_c, __CT_c, /* 0x14..0x17 */ __CT_c, __CT_c, __CT_c, __CT_c, /* 0x18..0x1B */ __CT_c, __CT_c, __CT_c, __CT_c, /* 0x1C..0x1F */ __CT_s, __CT_p, __CT_p, __CT_p, /* 0x20..0x23 */ __CT_p, __CT_p, __CT_p, __CT_p, /* 0x24..0x27 */ __CT_p, __CT_p, __CT_p, __CT_p, /* 0x28..0x2B */ __CT_p, __CT_p, __CT_p, __CT_p, /* 0x2C..0x2F */ __CT_d|__CT_x, __CT_d|__CT_x, __CT_d|__CT_x, __CT_d|__CT_x,/* 0x30..0x33 */ __CT_d|__CT_x, __CT_d|__CT_x, __CT_d|__CT_x, __CT_d|__CT_x,/* 0x34..0x37 */ __CT_d|__CT_x, __CT_d|__CT_x, __CT_p, __CT_p, /* 0x38..0x3B */ __CT_p, __CT_p, __CT_p, __CT_p, /* 0x3C..0x3F */ __CT_p, __CT_u|__CT_x, __CT_u|__CT_x, __CT_u|__CT_x, /* 0x40..0x43 */ __CT_u|__CT_x, __CT_u|__CT_x, __CT_u|__CT_x, __CT_u, /* 0x44..0x47 */ __CT_u, __CT_u, __CT_u, __CT_u, /* 0x48..0x4B */ __CT_u, __CT_u, __CT_u, __CT_u, /* 0x4C..0x4F */ __CT_u, __CT_u, __CT_u, __CT_u, /* 0x50..0x53 */ __CT_u, __CT_u, __CT_u, __CT_u, /* 0x54..0x57 */ __CT_u, __CT_u, __CT_u, __CT_p, /* 0x58..0x5B */ __CT_p, __CT_p, __CT_p, __CT_p, /* 0x5C..0x5F */ __CT_p, __CT_l|__CT_x, __CT_l|__CT_x, __CT_l|__CT_x, /* 0x60..0x63 */ __CT_l|__CT_x, __CT_l|__CT_x, __CT_l|__CT_x, __CT_l, /* 0x64..0x67 */ __CT_l, __CT_l, __CT_l, __CT_l, /* 0x68..0x6B */ __CT_l, __CT_l, __CT_l, __CT_l, /* 0x6C..0x6F */ __CT_l, __CT_l, __CT_l, __CT_l, /* 0x70..0x73 */ __CT_l, __CT_l, __CT_l, __CT_l, /* 0x74..0x77 */ __CT_l, __CT_l, __CT_l, __CT_p, /* 0x78..0x7B */ __CT_p, __CT_p, __CT_p, __CT_c /* 0x7C..0x7F */ }; dev86-0.16.21/libc/misc/ctypefn.c000066400000000000000000000006721231050321700162740ustar00rootroot00000000000000/* Copyright (C) 1995,1996 Robert de Bath * This file is part of the Linux-8086 C library and is distributed * under the GNU Library General Public License. */ /* * CTYPE.C Character classification and conversion */ #include #undef toupper #undef tolower int toupper(c) int c; { return(islower(c) ? (c ^ 0x20) : (c)); } int tolower(c) int c; { return(isupper(c) ? (c ^ 0x20) : (c)); } dev86-0.16.21/libc/misc/getcwd.c000066400000000000000000000043451231050321700161020ustar00rootroot00000000000000 #include #include #include #include /* * These functions find the absolute path to the current working directory. * * They don't use malloc or large amounts of stack space. */ static char * recurser(); /* Routine to go up tree */ static char * search_dir(); /* Routine to find the step back down */ static char * path_buf; static int path_size; static dev_t root_dev; static ino_t root_ino; static struct stat st; char * getcwd(buf, size) char * buf; int size; { path_buf = buf; path_size = size; if( size < 3 ) { errno = ERANGE; return 0; } strcpy(path_buf, "."); if( stat("/", &st) < 0 ) return 0; root_dev = st.st_dev; root_ino = st.st_ino; return recurser(); } static char * recurser() { dev_t this_dev; ino_t this_ino; if( stat(path_buf, &st) < 0 ) return 0; this_dev = st.st_dev; this_ino = st.st_ino; if( this_dev == root_dev && this_ino == root_ino ) { strcpy(path_buf, "/"); return path_buf; } if( strlen(path_buf) + 4 > path_size ) { errno = ERANGE; return 0; } strcat(path_buf, "/.."); if( recurser() == 0 ) return 0; return search_dir(this_dev, this_ino); } static char * search_dir(this_dev, this_ino) dev_t this_dev; ino_t this_ino; { DIR * dp; struct dirent * d; char * ptr; int slen; /* The test is for ELKS lib 0.0.9, this should be fixed in the real kernel*/ int slow_search = (sizeof(ino_t) != sizeof(d->d_ino)); if( stat(path_buf, &st) < 0 ) return 0; if( this_dev != st.st_dev ) slow_search = 1; slen = strlen(path_buf); ptr = path_buf + slen -1; if( *ptr != '/' ) { if( slen + 2 > path_size ) { errno = ERANGE; return 0; } strcpy(++ptr, "/"); slen++; } slen++; dp = opendir(path_buf); if( dp == 0 ) return 0; while( (d=readdir(dp)) != 0 ) { if( slow_search || this_ino == d->d_ino ) { if( slen + strlen(d->d_name) > path_size ) { errno = ERANGE; return 0; } strcpy(ptr+1, d->d_name); if( stat(path_buf, &st) < 0 ) continue; if( st.st_ino == this_ino && st.st_dev == this_dev ) { closedir(dp); return path_buf; } } } closedir(dp); errno = ENOENT; return 0; } dev86-0.16.21/libc/misc/getenv.c000066400000000000000000000010061231050321700161040ustar00rootroot00000000000000/* Copyright (C) 1995,1996 Robert de Bath * This file is part of the Linux-8086 C library and is distributed * under the GNU Library General Public License. */ extern char ** environ; char * getenv(name) char * name; { register int l; register char ** ep = environ; l = strlen(name); if( ep == 0 || l == 0 ) return 0; while(*ep) { if( **ep == *name && memcmp(name, *ep, l) == 0 && (*ep)[l] == '=' ) return *ep+l+1; ep++; } return 0; } dev86-0.16.21/libc/misc/getopt.c000066400000000000000000000060131231050321700161210ustar00rootroot00000000000000 /* * From: gwyn@brl-tgr.ARPA (Doug Gwyn ) Newsgroups: net.sources * Subject: getopt library routine Date: 30 Mar 85 04:45:33 GMT */ /* * getopt -- public domain version of standard System V routine * * Strictly enforces the System V Command Syntax Standard; provided by D A * Gwyn of BRL for generic ANSI C implementations * * #define STRICT to prevent acceptance of clustered options with arguments * and ommision of whitespace between option and arg. */ #include #include int opterr = 1; /* error => print message */ int optind = 1; /* next argv[] index */ char *optarg = NULL; /* option parameter if any */ static int Err(name, mess, c) /* returns '?' */ char *name; /* program name argv[0] */ char *mess; /* specific message */ int c; /* defective option letter */ { if (opterr) { (void) fprintf(stderr, "%s: %s -- %c\n", name, mess, c ); } return '?'; /* erroneous-option marker */ } int getopt(argc, argv, optstring) /* returns letter, '?', EOF */ int argc; /* argument count from main */ char *argv[]; /* argument vector from main */ char *optstring; /* allowed args, e.g. "ab:c" */ { static int sp = 1; /* position within argument */ register int osp; /* saved `sp' for param test */ #ifndef STRICT register int oind; /* saved `optind' for param test */ #endif register int c; /* option letter */ register char *cp; /* -> option in `optstring' */ optarg = NULL; if (sp == 1) /* fresh argument */ if (optind >= argc /* no more arguments */ || argv[optind][0] != '-' /* no more options */ || argv[optind][1] == '\0' /* not option; stdin */ ) return EOF; else if (strcmp(argv[optind], "--") == 0) { ++optind; /* skip over "--" */ return EOF; /* "--" marks end of options */ } c = argv[optind][sp]; /* option letter */ osp = sp++; /* get ready for next letter */ #ifndef STRICT oind = optind; /* save optind for param test */ #endif if (argv[optind][sp] == '\0')/* end of argument */ { ++optind; /* get ready for next try */ sp = 1; /* beginning of next argument */ } if (c == ':' || c == '?' /* optstring syntax conflict */ || (cp = strchr(optstring, c)) == NULL /* not found */ ) return Err(argv[0], "illegal option", c); if (cp[1] == ':') /* option takes parameter */ { #ifdef STRICT if (osp != 1) return Err(argv[0], "option must not be clustered", c ); if (sp != 1) /* reset by end of argument */ return Err(argv[0], "option must be followed by white space", c ); #else if (oind == optind) /* argument w/o whitespace */ { optarg = &argv[optind][sp]; sp = 1; /* beginning of next argument */ } else #endif if (optind >= argc) return Err(argv[0], "option requires an argument", c ); else /* argument w/ whitespace */ optarg = argv[optind]; ++optind; /* skip over parameter */ } return c; } dev86-0.16.21/libc/misc/itoa.c000066400000000000000000000005211231050321700155510ustar00rootroot00000000000000/* itoa.c */ #define __MAX_INT_CHARS 7 char * itoa(i) int i; { static char a[__MAX_INT_CHARS]; char *b = a + sizeof(a) - 1; int sign = (i < 0); if (sign) i = -i; *b = 0; do { *--b = '0' + (i % 10); i /= 10; } while (i); if (sign) *--b = '-'; return b; } dev86-0.16.21/libc/misc/lsearch.c000066400000000000000000000017321231050321700162430ustar00rootroot00000000000000/* * This file lifted in toto from 'Dlibs' on the atari ST (RdeBath) * * * Dale Schumacher 399 Beacon Ave. * (alias: Dalnefre') St. Paul, MN 55104 * dal@syntel.UUCP United States of America * "It's not reality that's important, but how you perceive things." */ #include char * lfind(key, base, num, size, cmp) register char *key, *base; unsigned int *num; register unsigned int size; register int (*cmp) (); { register int n = *num; while (n--) { if ((*cmp) (base, key) == 0) return (base); base += size; } return (NULL); } char * lsearch(key, base, num, size, cmp) char *key, *base; register unsigned int *num; register unsigned int size; int (*cmp) (); { register char *p; char *memcpy(); if ((p = lfind(key, base, num, size, cmp)) == NULL) { p = memcpy((base + (size * (*num))), key, size); ++(*num); } return (p); } dev86-0.16.21/libc/misc/ltoa.c000066400000000000000000000011001231050321700155460ustar00rootroot00000000000000/* Copyright (C) 1995,1996 Robert de Bath * This file is part of the Linux-8086 C library and is distributed * under the GNU Library General Public License. */ static char buf[12]; extern char * ultoa(); char * ltoa(val) long val; { char *p; int flg = 0; if( val < 0 ) { flg++; val= -val; } p = ultoa(val); if(flg) *--p = '-'; return p; } char * ultoa(val) unsigned long val; { char *p; p = buf+sizeof(buf); *--p = '\0'; do { *--p = '0' + val%10; val/=10; } while(val); return p; } dev86-0.16.21/libc/misc/ltostr.c000066400000000000000000000013631231050321700161510ustar00rootroot00000000000000/* Copyright (C) 1995,1996 Robert de Bath * This file is part of the Linux-8086 C library and is distributed * under the GNU Library General Public License. */ static char buf[34]; extern char * ultostr(); char * ltostr(val, radix) long val; int radix; { char *p; int flg = 0; if( val < 0 ) { flg++; val= -val; } p = ultostr(val, radix); if(p && flg) *--p = '-'; return p; } char * ultostr(val, radix) unsigned long val; int radix; { register char *p; register int c; if( radix > 36 || radix < 2 ) return 0; p = buf+sizeof(buf); *--p = '\0'; do { c = val%radix; val/=radix; if( c > 9 ) *--p = 'a'-10+c; else *--p = '0'+c; } while(val); return p; } dev86-0.16.21/libc/misc/popen.c000066400000000000000000000013401231050321700157360ustar00rootroot00000000000000 #include FILE * popen(command, rw) char * command; char * rw; { int pipe_fd[2]; int pid, reading; if( pipe(pipe_fd) < 0 ) return NULL; reading = (rw[0] == 'r'); pid = vfork(); if( pid < 0 ) { close(pipe_fd[0]); close(pipe_fd[1]); return NULL; } if( pid == 0 ) { close(pipe_fd[!reading]); close(reading); if( pipe_fd[reading] != reading ) { dup2(pipe_fd[reading], reading); close(pipe_fd[reading]); } execl("/bin/sh", "sh", "-c", command, (char*)0); _exit(255); } close(pipe_fd[reading]); return fdopen(pipe_fd[!reading], rw); } int pclose(fd) FILE *fd; { int waitstat; if( fclose(fd) != 0 ) return EOF; wait(&waitstat); } dev86-0.16.21/libc/misc/putenv.c000066400000000000000000000021361231050321700161420ustar00rootroot00000000000000/* Copyright (C) 1995,1996 Robert de Bath * This file is part of the Linux-8086 C library and is distributed * under the GNU Library General Public License. */ #include #include #include extern char ** environ; #define ADD_NUM 4 int putenv(var) char * var; { static char ** mall_env = 0; static int extras = 0; char **p, **d; char * r; int len; r = strchr(var, '='); if( r == 0 ) len = strlen(var); else len = r-var; for(p=environ; *p; p++) { if( memcmp(var, *p, len) == 0 && (*p)[len] == '=' ) { while( p[0] = p[1] ) p++; extras++; break; } } if( r == 0 ) return 0; if( extras <= 0 ) /* Need more space */ { d = malloc((p-environ+1+ADD_NUM)*sizeof(char*)); if( d == 0 ) return -1; memcpy((void*) d, (void*) environ, (p-environ+1)*sizeof(char*)); p = d + (p-environ); extras=ADD_NUM; if( mall_env ) free(mall_env); environ = d; mall_env = d; } *p++ = var; *p = '\0'; extras--; return 0; } dev86-0.16.21/libc/misc/qsort.c000066400000000000000000000065151231050321700157760ustar00rootroot00000000000000/* * This file lifted in toto from 'Dlibs' on the atari ST (RdeBath) * * * Dale Schumacher 399 Beacon Ave. * (alias: Dalnefre') St. Paul, MN 55104 * dal@syntel.UUCP United States of America * "It's not reality that's important, but how you perceive things." */ /* * Sun Feb 8 21:02:15 EST 1998 claudio@pos.inf.ufpr.br (Claudio Matsuoka) * Changed sort direction */ #include char *_qbuf = 0; /* pointer to storage for qsort() */ #define PIVOT ((i+j)>>1) #define moveitem(dst,src,size) if(dst != src) memcpy(dst, src, size) static _wqsort(base, lo, hi, cmp) register int *base; register int lo; register int hi; register int (*cmp) (); { int k; register int i, j, t; register int *p = &k; while (hi > lo) { i = lo; j = hi; t = PIVOT; *p = base[t]; base[t] = base[i]; base[i] = *p; while (i < j) { while (((*cmp) ((base + j), p)) <= 0) --j; base[i] = base[j]; while ((i < j) && (((*cmp) ((base + i), p)) > 0)) ++i; base[j] = base[i]; } base[i] = *p; if ((i - lo) < (hi - i)) { _wqsort(base, lo, (i - 1), cmp); lo = i + 1; } else { _wqsort(base, (i + 1), hi, cmp); hi = i - 1; } } } static _lqsort(base, lo, hi, cmp) register long *base; register int lo; register int hi; register int (*cmp) (); { long k; register int i, j, t; register long *p = &k; while (hi > lo) { i = lo; j = hi; t = PIVOT; *p = base[t]; base[t] = base[i]; base[i] = *p; while (i < j) { while (((*cmp) ((base + j), p)) <= 0) --j; base[i] = base[j]; while ((i < j) && (((*cmp) ((base + i), p)) > 0)) ++i; base[j] = base[i]; } base[i] = *p; if ((i - lo) < (hi - i)) { _lqsort(base, lo, (i - 1), cmp); lo = i + 1; } else { _lqsort(base, (i + 1), hi, cmp); hi = i - 1; } } } static _nqsort(base, lo, hi, size, cmp) register char *base; register int lo; register int hi; register int size; register int (*cmp) (); { register int i, j; register char *p = _qbuf; while (hi > lo) { i = lo; j = hi; p = (base + size * PIVOT); moveitem(_qbuf, p, size); moveitem(p, (base + size * i), size); moveitem((base + size * i), _qbuf, size); p = _qbuf; while (i < j) { while (((*cmp) ((base + size * j), p)) <= 0) --j; moveitem((base + size * i), (base + size * j), size); while ((i < j) && (((*cmp) ((base + size * i), p)) > 0)) ++i; moveitem((base + size * j), (base + size * i), size); } moveitem((base + size * i), p, size); if ((i - lo) < (hi - i)) { _nqsort(base, lo, (i - 1), size, cmp); lo = i + 1; } else { _nqsort(base, (i + 1), hi, size, cmp); hi = i - 1; } } } qsort(base, num, size, cmp) char *base; int num; int size; int (*cmp) (); { char _qtemp[128]; if (_qbuf == 0) { if (size > sizeof(_qtemp))/* records too large! */ return; _qbuf = _qtemp; } if (size == 2) _wqsort(base, 0, num - 1, cmp); else if (size == 4) _lqsort(base, 0, num - 1, cmp); else _nqsort(base, 0, num - 1, size, cmp); if (_qbuf == _qtemp) _qbuf = 0; } dev86-0.16.21/libc/misc/rand.c000066400000000000000000000020451231050321700155440ustar00rootroot00000000000000#ifdef ZX81_RNG /* * This is my favorite tiny RNG, If you had a ZX81 you may recognise it :-) * (RdeBath) */ #include #define MAXINT (((unsigned)-1)>>1) static unsigned int sseed = 0; int rand() { return ( sseed = (((sseed+1L)*75L)%65537L)-1 ) & MAXINT; } void srand(seed) unsigned int seed; { sseed=seed; } #else /* * This generator is a combination of three linear congruential generators * with periods or 2^15-405, 2^15-1041 and 2^15-1111. It has a period that * is the product of these three numbers. */ static int seed1 = 1; static int seed2 = 1; static int seed3 = 1; #define MAXINT (((unsigned)-1)>>1) #define CRANK(a,b,c,m,s) \ q = s/a; \ s = b*(s-a*q) - c*q; \ if(s<0) s+=m; int rand() { register int q, z; CRANK(206, 157, 31, 32363, seed1); CRANK(217, 146, 45, 31727, seed2); CRANK(222, 142, 133, 31657, seed3); return seed1^seed2^seed3; } void srand(seed) unsigned int seed; { seed &= MAXINT; seed1= seed%32362 + 1; seed2= seed%31726 + 1; seed3= seed%31656 + 1; } #endif dev86-0.16.21/libc/misc/setenv.c000066400000000000000000000040511231050321700161230ustar00rootroot00000000000000/* Copyright (C) 1992, 1995 Free Software Foundation, Inc. This file is part of the GNU C Library. */ #include #include #include #include extern char ** environ; int setenv(name, value, replace) __const char *name; __const char *value; int replace; { register char **ep; register size_t size; __const size_t namelen = strlen (name); __const size_t vallen = strlen (value); int result = 0; size = 0; for (ep = environ; *ep != NULL; ++ep) if (!memcmp (*ep, name, namelen) && (*ep)[namelen] == '=') break; else ++size; if (*ep == NULL) { static char **last_environ = NULL; char **new_environ = (char **) malloc((size + 2) * sizeof(char *)); if (new_environ == NULL) { result = -1; goto do_return; } (void) memcpy((void*) new_environ, (void*) environ, size * sizeof(char *)); new_environ[size] = malloc (namelen + 1 + vallen + 1); if (new_environ[size] == NULL) { free (new_environ); errno = ENOMEM; result = -1; goto do_return; } memcpy (new_environ[size], name, namelen); new_environ[size][namelen] = '='; memcpy (&new_environ[size][namelen + 1], value, vallen + 1); new_environ[size + 1] = NULL; if (last_environ != NULL) free ((void*) last_environ); last_environ = new_environ; environ = new_environ; } else if (replace) { size_t len = strlen (*ep); if (len < namelen + 1 + vallen) { char *new = malloc (namelen + 1 + vallen + 1); if (new == NULL) { result = -1; goto do_return; } *ep = new; } memcpy (*ep, name, namelen); (*ep)[namelen] = '='; memcpy (&(*ep)[namelen + 1], value, vallen + 1); } do_return: return result; } void unsetenv(name) __const char *name; { register char **ep; register char **dp; __const size_t namelen = strlen (name); for (dp = ep = environ; *ep != NULL; ++ep) if (memcmp (*ep, name, namelen) || (*ep)[namelen] != '=') { *dp = *ep; ++dp; } *dp = NULL; } dev86-0.16.21/libc/misc/strtod.c000066400000000000000000000037501231050321700161430ustar00rootroot00000000000000/* * strtod.c - This file is part of the libc-8086 package for ELKS, * Copyright (C) 1995, 1996 Nat Friedman . * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ #include #include double strtod(const char *nptr, char ** endptr) { unsigned short negative; double number; double fp_part; int exponent; unsigned short exp_negative; /* advance beyond any leading whitespace */ while (isspace(*nptr)) nptr++; /* check for optional '+' or '-' */ negative=0; if (*nptr=='-') { negative=1; nptr++; } else if (*nptr=='+') nptr++; number=0; while (isdigit(*nptr)) { number=number*10+(*nptr-'0'); nptr++; } if (*nptr=='.') { nptr++; fp_part=0; while (isdigit(*nptr)) { fp_part=fp_part/10.0 + (*nptr-'0')/10.0; nptr++; } number+=fp_part; } if (*nptr=='e' || *nptr=='E') { nptr++; exp_negative=0; if (*nptr=='-') { exp_negative=1; nptr++; } else if (*nptr=='+') nptr++; exponent=0; while (isdigit(*nptr)) { exponent=exponent*10+(*nptr-'0'); exponent++; } } while (exponent) { if (exp_negative) number/=10; else number*=10; exponent--; } return (negative ? -number:number); } dev86-0.16.21/libc/misc/strtol.c000066400000000000000000000051331231050321700161500ustar00rootroot00000000000000/* * strtol.c - This file is part of the libc-8086 package for ELKS, * Copyright (C) 1995, 1996 Nat Friedman . * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ /* TODO: This needs range clamping and setting errno when it's done. */ #include #include long int strtol(const char *nptr, char **endptr, int base) { const char * ptr; unsigned short negative; long int number; ptr=nptr; while (isspace(*ptr)) ptr++; negative=0; if (*ptr=='-') negative=1; number=(long int)strtoul(nptr, endptr, base); return (negative ? -number:number); } unsigned long int strtoul(const char *nptr, char **endptr, int base) { unsigned long int number; /* Sanity check the arguments */ if (base==1 || base>36 || base<0) base=0; /* advance beyond any leading whitespace */ while (isspace(*nptr)) nptr++; /* check for optional '+' or '-' */ if (*nptr=='-') nptr++; else if (*nptr=='+') nptr++; /* If base==0 and the string begins with "0x" then we're supposed to assume that it's hexadecimal (base 16). */ if (base==0 && *nptr=='0') { if (toupper(*(nptr+1))=='X') { base=16; nptr+=2; } /* If base==0 and the string begins with "0" but not "0x", then we're supposed to assume that it's octal (base 8). */ else { base=8; nptr++; } } /* If base is still 0 (it was 0 to begin with and the string didn't begin with "0"), then we are supposed to assume that it's base 10 */ if (base==0) base=10; number=0; while (isascii(*nptr) && isalnum(*nptr)) { int ch = *nptr; if (islower(ch)) ch = toupper(ch); ch -= (ch<='9' ? '0' : 'A'-10); if (ch>base) break; number= (number*base)+ch; nptr++; } /* Some code is simply _impossible_ to write with -Wcast-qual .. :-\ */ if (endptr!=NULL) *endptr=(char *)nptr; /* All done */ return number; } dev86-0.16.21/libc/misc/syslib.c000066400000000000000000000070401231050321700161250ustar00rootroot00000000000000/* Copyright (C) 1995,1996 Robert de Bath * This file is part of the Linux-8086 C library and is distributed * under the GNU Library General Public License. */ #include #include #include #include #include #include /* This only for the various unix version */ #ifdef __unix__ /********************** Function time ************************************/ #ifdef L_time time_t time(where) time_t *where; { struct timeval rv; if( gettimeofday(&rv, (void*)0) < 0 ) return -1; if(where) *where = rv.tv_sec; return rv.tv_sec; } #endif /********************** Function abort ************************************/ #ifdef L_abort int abort() { signal(SIGABRT, SIG_DFL); kill(SIGABRT, getpid()); /* Correct one */ pause(); /* System may just schedule */ signal(SIGKILL, SIG_DFL); kill(SIGKILL, getpid()); /* Can't trap this! */ __exit(255); /* WHAT!! */ } #endif /********************** Function wait ************************************/ #ifdef L_wait int wait(status) int * status; { return wait4(-1, status, 0, (void*)0); } #endif /********************** Function wait3 **************************************/ #ifdef L_wait3 int wait3(status, opts, usage) int * status; int opts; struct rusage * usage; { return wait4(-1, status, opts, usage); } #endif /********************** Function waitpid ************************************/ #ifdef L_waitpid int waitpid(pid, status, opts) int pid; int * status; int opts; { return wait4(pid, status, opts, (void*)0); } #endif /********************** Function killpg ************************************/ #ifdef L_killpg int killpg(pid, sig) int pid; int sig; { if(pid == 0) pid = getpgrp(); if(pid > 1) return kill(-pid, sig); errno = EINVAL; return -1; } #endif /********************** Function setpgrp ************************************/ #ifdef L_setpgrp int setpgrp() { return setpgid(0,0); } #endif /********************** Function sleep ************************************/ #ifdef L_sleep #ifdef __ELKS__ /* This uses SIGALRM, it does keep the previous alarm call but will lose * any alarms that go off during the sleep */ static void alrm() { } unsigned int sleep(seconds) unsigned int seconds; { void (*last_alarm)(); unsigned int prev_sec; prev_sec = alarm(0); if( prev_sec <= seconds ) prev_sec = 1; else prev_sec -= seconds; last_alarm = signal(SIGALRM, alrm); alarm(seconds); pause(); seconds = alarm(prev_sec); signal(SIGALRM, last_alarm); return seconds; } #else /* Is this a better way ? If we have select of course :-) */ unsigned int sleep(seconds) unsigned int seconds; { struct timeval timeout; time_t start = time((void*)0); timeout.tv_sec = seconds; timeout.tv_usec = 0; select(1, NULL, NULL, NULL, &timeout); return seconds - (time((void*)0) - start); } #endif #endif /********************** Function usleep ************************************/ #ifdef L_usleep void usleep(useconds) unsigned long useconds; { struct timeval timeout; timeout.tv_sec = useconds%1000000L; timeout.tv_usec = useconds/1000000L; select(1, NULL, NULL, NULL, &timeout); } #endif /********************** Function mkfifo ************************************/ #ifdef L_mkfifo int mkfifo(path, mode) char * path; int mode; { return mknod(path, mode | S_IFIFO, 0); } #endif /********************** THE END ********************************************/ #endif /* __unix__ */ dev86-0.16.21/libc/misc/system.c000066400000000000000000000016221231050321700161440ustar00rootroot00000000000000 #include #include int system(command) char * command; { int wait_val, wait_ret, pid; __sighandler_t save_quit; __sighandler_t save_int; if( command == 0 ) return 1; save_quit = signal(SIGQUIT, SIG_IGN); save_int = signal(SIGINT, SIG_IGN); if( (pid=vfork()) < 0 ) { signal(SIGQUIT, save_quit); signal(SIGINT, save_int); return -1; } if( pid == 0 ) { signal(SIGQUIT, SIG_DFL); signal(SIGINT, SIG_DFL); execl("/bin/sh", "sh", "-c", command, (char*)0); _exit(127); } /* Signals are not absolutly guarenteed with vfork */ signal(SIGQUIT, SIG_IGN); signal(SIGINT, SIG_IGN); do { if( (wait_ret = wait(&wait_val)) == -1 ) { wait_val = -1; break; } } while( wait_ret != pid ); signal(SIGQUIT, save_quit); signal(SIGINT, save_int); return wait_val; } dev86-0.16.21/libc/misc/tmpnam.c000066400000000000000000000016051231050321700161150ustar00rootroot00000000000000/* * (C) Shane Kerr under terms of LGPL */ #include #include #include #ifndef P_tmpdir #define P_tmpdir "/tmp" #endif #ifndef L_tmpnam #define L_tmpnam 20 #endif char *tmpnam(s) char *s; { static char ret_val[L_tmpnam]; static char c1 = 0; static char c2 = 0; static char c3 = 0; static char uniq_ch[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; struct stat stbuf; do { sprintf(ret_val, "%s/%05d%c%c%c", P_tmpdir, getpid(), uniq_ch[c1], uniq_ch[c2], uniq_ch[c3]); if (++c1 >= 62) { c1 = 0; if (++c2 >= 62) { c2 = 0; if (++c3 >= 62) { errno = EEXIST; return 0; } } } } while (stat(ret_val, &stbuf) == 0); if (s != 0) { strcpy(s, ret_val); return s; } else { return ret_val; } } dev86-0.16.21/libc/msdos/000077500000000000000000000000001231050321700146455ustar00rootroot00000000000000dev86-0.16.21/libc/msdos/Config000066400000000000000000000000321231050321700157700ustar00rootroot00000000000000msdos: Msdos system calls dev86-0.16.21/libc/msdos/Makefile000066400000000000000000000020451231050321700163060ustar00rootroot00000000000000# Copyright (C) 1995,1996 Robert de Bath # This file is part of the Linux-8086 C library and is distributed # under the GNU Library General Public License. ASRC=msdos.c AOBJ= \ dos_start.o __exterror.o __mkargv.o __mkenvp.o bdos.o \ dos__fconv.o dos_abort.o dos_close.o dos_getmod.o dos_getvect.o \ dos_isatty.o dos_lseek.o dos_open.o dos_read.o dos_segalloc.o \ dos_segfree.o dos_setvect.o dos_stat.o dos_unlink.o dos_write.o BSRC=i86.c BOBJ= __seg_regs.o __peek_es.o __poke_es.o __deek_es.o __doke_es.o \ __strnget_es.o __strchr_es.o __strlen_es.o int86.o int86x.o segread.o ifeq ($(LIB_CPU),i86) ifeq ($(LIB_OS),DOS) OBJ=$(AOBJ) $(BOBJ) time.o sound.o else OBJ=$(BOBJ) endif CFLAGS=$(ARCH) $(CCFLAGS) $(DEFS) all: $(LIBC) @$(RM) $(OBJ) $(LIBC): $(LIBC)($(OBJ)) $(LIBC)($(AOBJ)): $(ASRC) $(CC) $(CFLAGS) -DL_$* $< -c -o $*.o $(AR) $(ARFLAGS) $@ $*.o $(LIBC)($(BOBJ)): $(BSRC) $(CC) $(CFLAGS) -DL_$* $< -c -o $*.o $(AR) $(ARFLAGS) $@ $*.o else all: @: endif clean: rm -f *.o libc.a dev86-0.16.21/libc/msdos/Notes000066400000000000000000000005271231050321700156640ustar00rootroot00000000000000This is currently a very cutdown version of the syslib. This also currently does nothing about the difference between 'TEXT' and 'BINARY' modes but I think that this level of operation should be pure binary, the 'TEXT' mode is more suited to stdio where an "fopen(f, "rb")" is more reasonable and probably won't break on other OSs. -Robert. dev86-0.16.21/libc/msdos/TODO000066400000000000000000000001721231050321700153350ustar00rootroot00000000000000#define remove(x) unlink(x) opendir closedir readdir rewinddir See also the other files, many parts are incomplete. dev86-0.16.21/libc/msdos/dirent.c000066400000000000000000000000501231050321700162710ustar00rootroot00000000000000 opendir closedir readdir rewinddir dev86-0.16.21/libc/msdos/dosound.c000066400000000000000000000000521231050321700164610ustar00rootroot00000000000000 nosound() { } sound(freq) int freq { } dev86-0.16.21/libc/msdos/i86.c000066400000000000000000000131761231050321700154270ustar00rootroot00000000000000/* Copyright (C) 1995,1996 Robert de Bath * This file is part of the Linux-8086 C library and is distributed * under the GNU Library General Public License. */ /* * These functions will not normally be useful for Linux-8086. But they * can be used and may be useful in the kernel. */ #ifdef __AS386_16__ #ifdef L___seg_regs unsigned int __get_cs() { #asm mov ax,cs #endasm } unsigned int __get_ds() { #asm mov ax,ds #endasm } unsigned int __get_es() { #asm mov ax,es #endasm } void __set_es(seg) { #asm #if __FIRST_ARG_IN_AX__ mov es,ax #else mov bx,sp mov es,[bx+2] #endif #endasm } #endif #ifdef L___peek_es int __peek_es(off) unsigned int off; { #asm #if __FIRST_ARG_IN_AX__ mov bx,ax #else mov bx,sp mov bx,[bx+2] #endif seg es mov al,[bx] xor ah,ah #endasm } #endif #ifdef L___poke_es int __poke_es(off, value) unsigned int off; int value; { #asm #if __FIRST_ARG_IN_AX__ mov bx,sp mov bx,[bx+2] xchg ax,bx #else mov bx,sp mov ax,[bx+4] mov bx,[bx+2] #endif seg es mov [bx],al xor ah,ah #endasm } #endif #ifdef L___deek_es int __deek_es(off) unsigned int off; { #asm #if __FIRST_ARG_IN_AX__ mov bx,ax #else mov bx,sp mov bx,[bx+2] #endif seg es mov ax,[bx] #endasm } #endif #ifdef L___doke_es int __doke_es(off, value) unsigned int off; int value; { #asm #if __FIRST_ARG_IN_AX__ mov bx,sp mov bx,[bx+2] xchg ax,bx #else mov bx,sp mov ax,[bx+4] mov bx,[bx+2] #endif seg es mov [bx],ax #endasm } #endif #ifdef L___strchr_es char * __strchr_es(s, c) char * s; int c; { #asm mov bx,sp push si #if __FIRST_ARG_IN_AX__ mov bx,[bx+2] mov si,ax #else mov si,[bx+2] mov bx,[bx+4] #endif xor ax,ax #ifdef PARANOID cld #endif push ds push es pop ds in_loop: lodsb cmp al,bl jz got_it or al,al jnz in_loop pop ds pop si ret got_it: lea ax,[si-1] pop ds pop si #endasm } #endif #ifdef L___strnget_es char * __strnget_es(d, s, c) char *d; char *s; register int c; { register int i = __strlen_es(s); if(i < c) c = i+1; /* else s[--c] = 0; ?? */ /* else return -E2BIG; ?? */ __movedata(__get_es(), s, __get_ds(), d, c); } #endif #ifdef L___strlen_es int __strlen_es(str) char * str; { #asm #if !__FIRST_ARG_IN_AX__ mov bx,sp #endif push di cld #if __FIRST_ARG_IN_AX__ mov di,ax #else mov di,[bx+2] #endif mov cx,#-1 xor ax,ax repne scasb ! Scans [ES:DI] not cx dec cx mov ax,cx pop di #endasm } #endif #ifdef L_int86 int int86(intr, in_regs, out_regs) int intr; union REGS* in_regs; union REGS* out_regs; { #asm push bp mov bp,sp push ds ! save ds ! es too ? push bp ! same for new bp pushf ! iret flags mov ax,[bp-6] ! flags for simulated int push cs ! iret address segment mov bx,#ret_addr ! iret address offset push bx and ah,#$0C ! simulate interrupt flags push ax ! flags are pushed first xor bx,bx mov es,bx ! interrupt vectors in seg 0 mov bl,[bp+4] shl bx,#1 shl bx,#1 ! intr*4 => interrupt vector address seg es push [bx+2] ! fetch interrupt segment seg es push [bx] ! fetch interrupt offset mov bx,[bp+6] ! input union REGS* mov ax,[bx] mov cx,[bx+4] mov dx,[bx+6] mov si,[bx+8] mov di,[bx+10] mov bx,[bx+2] ! Ignore cflag/flags ? iret ! simulate interrupt. ! But won't be nice for protected mode ... ret_addr: ! Int $25/6 would need resetting sp:ss too ... should I ? pop bp ! unzapped versions pop ds ! paranoia pushf ! save interrupt flags push bx ! save pointer register mov bx,[bp+8] ! output union REGS* mov [bx],ax pop [bx+2] mov [bx+4],cx mov [bx+6],dx mov [bx+8],si mov [bx+10],di mov word [bx+12],#0 ! cflag jnc no_carry mov byte [bx+12],#1 no_carry: pop [bx+14] ! flags pop bp #endasm } #endif #ifdef L_int86x int int86x(intr, in_regs, out_regs, segr) int intr; union REGS* in_regs; union REGS* out_regs; struct SREGS * segr; { #asm push bp mov bp,sp push ds ! save ds ! es too ? push bp ! same for new bp pushf ! iret flags mov ax,[bp-6] ! flags for simulated int push cs ! iret address segment mov bx,#ret_addr ! iret address offset push bx and ah,#$0C ! simulate interrupt flags push ax ! flags are pushed first xor bx,bx mov es,bx ! interrupt vectors in seg 0 mov bl,[bp+4] shl bx,1 shl bx,1 ! intr*4 => interrupt vector address seg es push word [bx+2] ! fetch interrupt segment seg es push word [bx] ! fetch interrupt offset mov bx,[bp+10] ! struct SREGS* mov es,[bx] push [bx+6] ! ds mov bx,[bp+6] ! input union REGS* mov ax,[bx] mov cx,[bx+4] mov dx,[bx+6] mov si,[bx+8] mov di,[bx+10] mov bx,[bx+2] ! Ignore cflag/flags ? pop ds iret ! simulate interrupt ! But won't be nice for protected mode ... ret_addr: ! Int $25/6 would need resetting sp:ss too ... should I ? pop bp ! in case it was zapped pushf ! save interrupt flags push cx ! save work register mov cx,ds push bx ! save pointer register mov ds,word [bp-2] ! restore original ds mov bx,[bp+10] ! struct SREGS* mov [bx],es mov [bx+6],cx mov bx,[bp+8] ! output union REGS* mov [bx],ax pop [bx+2] ! bx pop [bx+4] ! cx mov [bx+6],dx mov [bx+8],si mov [bx+10],di mov word [bx+12],#0 ! cflag jnc no_carry mov byte [bx+12],#1 no_carry: pop [bx+14] ! flags pop ds pop bp #endasm } #endif #ifdef L_segread segread(segp) struct SREGS * segp; { #asm #if __FIRST_ARG_IN_AX__ mov bx,ax #else mov bx,sp mov bx,[bx+2] #endif mov [bx],es mov [bx+2],cs mov [bx+4],ss mov [bx+6],ds #endasm } #endif #endif /* __AS386_16__ */ dev86-0.16.21/libc/msdos/intr.c000066400000000000000000000020121231050321700157600ustar00rootroot00000000000000 struct REGPACK { unsigned r_ax, r_bx, r_cx, r_dx; unsigned r_bp, r_si, r_di, r_ds, r_es, r_flags; }; /* DANGER DANGER -- Self modifying code! */ #asm .text save_sp: dw 0 #endasm intr(intr, regs) int intr; struct REGPACK * regs; { #asm mov bx,sp push bp push si push di push es push ds mov ax,[bx+2] seg cs mov [intr_inst+1],al seg cs mov [save_sp],sp mov bx,[bx+4] mov ah,[bx+18] ! Flags low byte sahf mov ax,[bx] push [bx+2] mov cx,[bx+4] mov dx,[bx+6] mov bp,[bx+8] mov si,[bx+10] mov di,[bx+12] mov es,[bx+16] mov ds,[bx+14] pop bx intr_inst: int $FF ! Must be a real int .. consider protected mode. seg cs ! Could be SS as DS==SS mov sp,[save_sp] seg cs mov [save_sp],ds pop ds push [save_sp] push bx mov bx,sp mov bx,[bx+12] mov [bx],ax pop [bx+2] mov [bx+4],cx mov [bx+6],dx mov [bx+8],bp mov [bx+10],si mov [bx+12],di pop [bx+14] mov [bx+16],es pushf pop [bx+18] pop es pop di pop si pop bp #endasm } dev86-0.16.21/libc/msdos/msdos.c000066400000000000000000000312331231050321700161400ustar00rootroot00000000000000/* Copyright (C) 1995,1996 Robert de Bath * This file is part of the Linux-8086 C library and is distributed * under the GNU Library General Public License. */ #if !__FIRST_ARG_IN_AX__ #ifdef __AS386_16__ #ifdef __MSDOS__ #include #include #include int errno; unsigned _doserrno; #ifdef L_dos_start static char * defarg[2] = { "C" }; static char ** def_environ =defarg+1; void (*__cleanup)() = 0; #asm .data export ___envseg ___envseg: .word 0 export ___psp ___psp: .word 0 .text export _exit export __exit _exit: ! exit(rv) function mov bx,sp push [bx+2] ! Copy the `rv` for the exit fuctions. mov bx,[___cleanup] ! Call exit, normally this is `__do_exit` test bx,bx je no_clean ! But it`s default is null call bx no_clean: inc sp inc sp __exit: ! _exit(rv) mov bx,sp mov ax,[bx+2] mov ah,#$4c int #$21 dos_1_exit: int #$20 .text export ___cstartup ! Crt0 startup ___cstartup: mov ax,#$3000 ! Get DOS version int $21 cmp al,#2 ! DOS 2+ is Ok jb dos_1_exit mov dx,cs ! Current CS add dx,#__segoff ! This var generated by the linker mov ds,dx ! Correct DS mov [___psp],es ! PSP segment seg es mov ax,[$2c] mov [___envseg],ax ! Enviroment Segment ! Now need to free some RAM seg es mov bx,[2] ! Top of Ram mov ax,ds add ax,#4096 ! Top of 64k data seg jc use_tor ! Oops, wrapped cmp ax,bx jnc use_tor ! Bigger than tor mov bx,ax use_tor: mov ax,cs ! Work out how big the memseg is needed sub bx,ax mov ah,#$4A ! Set it int $21 jnc set_stack ! Good. ! Ooops, problem.. ! BX is now how big it can be so set that. ! FIXME should check for BSS v Stack overlap mov ah,#$4A int $21 set_stack: ! Now set SS to the same as DS sub bx,#__segoff ! And SP to the top of available memory. mov cl,#4 shl bx,cl sub bx,#2 mov ss,dx mov sp,bx zap_bss: ! Clear the BSS mov es,dx ! ES now data seg mov di,#__edata mov cx,#__end sub cx,di xor ax,ax cld rep stosb push [_def_environ] ! Defaults for when nothing is used. mov ax,#_defarg push ax mov ax,#1 push ax mov si,#auto_start ! Pointer to first autostart function auto_run: mov bx,[si] test bx,bx jz no_entry call bx ! Call the function no_entry: inc si ! SI at next inc si jmp auto_run ! And round for the next. call_exit: ! Last item called by above. pop bx ! Be tidy. push ax ! At the end the last called was main() push it`s call _exit ! return val and call exit(); bad_exit: jmp bad_exit ! Exit returned !! loc 2 .word _main ! Segment 2 is the trailing pointers, main and the .word call_exit ! routine to call exit. data_start: .text #endasm __E_nosys() { #asm .text export sys_call5 export sys_call4 export sys_call3 export sys_call2 export sys_call1 export sys_call0 sys_call5: ! Trap the unemulated Linux86 syscalls sys_call4: sys_call3: sys_call2: sys_call1: sys_call0: #endasm errno = ENOSYS; return -1; } #endif #ifdef L___mkargv #ifdef __AS386_16__ #asm loc 1 ! Make sure the pointer is in the correct segment auto_func: ! Label for bcc -M to work. .word ___mkargv ! Pointer to the autorun function .text ! So the function after is also in the correct seg. #endasm #endif __mkargv(__argc, __argv) int __argc; char ** __argv; { int length, i, argc=1, s=0; unsigned char *ptr, *p; __set_es(__psp); /* Pointer to the args */ length = __peek_es(0x80); /* Length of cmd line */ if( length > 0 ) { ptr = (char*) sbrk(length+1); /* Allocate some space */ for(i=0; i ' ' && s == 0 ) { argc++; s=1; } if( ptr[i] <= ' ' && s == 1 ) s=0; } ptr[length]=0; p= __argv[0]; __argv = (char**) sbrk((argc+1)*sizeof(char*)); __argv[0] = p; /* TODO: The real command can be found */ __argc=argc; /* * TODO: This needs to understand quoting and wildcards */ argc=1; s=0; for(i=0; i ' ' && s == 0 ) { __argv[argc++] = ptr+i; s=1; } if( ptr[i] <= ' ' && s == 1 ) { ptr[i] = '\0'; s=0; } } __argv[argc] = 0; } } #endif #ifdef L___mkenvp #ifdef __AS386_16__ #asm loc 1 ! Make sure the pointer is in the correct segment auto_func: ! Label for bcc -M to work. .word ___mkenvp ! Pointer to the autorun function .text ! So the function after is also in the correct seg. #endasm #endif char ** environ = 0; __mkenvp(__argc, __argv, __envp) int __argc; char ** __argv; char ** __envp; { /* FIXME !!! * * Note must write to __envp argument but not touch __argv or __argc */ } #endif #ifdef L_dos__fconv /* This function converts filenames from unix like to DOS. */ char * __fconv(fname) char * fname; { static char buf1[66], buf2[66], *str = 0; register char *p, ch; int dot = 0; if( strcmp("/dev/tty", fname) == 0 ) return "CON:"; if( str == buf1 ) str = buf2; else str = buf1; p = str; if( strncmp("/mnt/", fname, 5) == 0 ) { strcpy(p, "A:"); p+=2; fname+=4; } /* * POSS: * open("/name/*", ...); looks for an environ var PATH_name=c:\x\y\z */ while((ch = *fname++) && p < str+65) { if( ( ch >= 'a' && ch <= 'z' ) || ( ch >= '0' && ch <= '9' ) || ch == ':' || ch == '%' || ch == '-' || ch == '$' ) ; else if( ch >= 'A' && ch <= 'Z' ) ch = ch-'A'+'a'; else if( ch == '.' && dot == 0 ) dot = 1; else if( ch == '/' || ch == '\\' ) { dot = 0; ch = '\\'; } else ch = '_'; *p++ = ch; } *p++ = '\0'; return str; } #endif #ifdef L___exterror static char errno_xlate[] = { 0, EINVAL, ENOENT, ENOENT, EMFILE, EACCES, EBADF, EFAULT, ENOMEM, EFAULT, ENOMEM, EINVAL, EINVAL, EINVAL, EINVAL, ENODEV, EPERM, EXDEV, ENFILE, EROFS, ENODEV, ENXIO, EINVAL, EIO, EINVAL, ESPIPE, EIO, EIO, EAGAIN, EIO, EIO, EIO, EBUSY, EBUSY, ENODEV, EFAULT, ENOLCK, EFAULT, EFAULT, ENOSPC }; __exterror() { #asm export exterror exterror: push ds push es push di push si push bp xor bx,bx mov ah,#$59 int $21 pop bp pop si pop di pop es pop ds mov __doserrno,ax #endasm { int nerrno; extern unsigned _doserrno; if( _doserrno == 0 ) /* No error? No change. */; else if( _doserrno >= sizeof(errno_xlate) || errno_xlate[_doserrno] == EFAULT ) errno = 16384+_doserrno; else errno = errno_xlate[_doserrno]; } return -1; } #endif #ifdef L_dos_read int read(fd, ptr, len) int fd; char *ptr; unsigned len; { #asm mov bx,sp mov cx,[bx+6] mov dx,[bx+4] mov bx,[bx+2] mov ah,#$3f int #$21 jnc readok br exterror readok: #endasm } #endif #ifdef L_dos_write int write(fd, ptr, len) int fd; char *ptr; unsigned len; { #asm mov bx,sp mov cx,[bx+6] mov dx,[bx+4] mov bx,[bx+2] mov ah,#$40 int #$21 jnc writeok br exterror writeok: #endasm } #endif #ifdef L_dos_open int open(fname, type, cmode) char * fname; int type; int cmode; { register char * nname = __fconv(fname); int creat_mode = 0; int rv; static int xlate_mode[] = { #ifdef OPEN_LIKE_UNIX O_RDONLY|O_DENYNONE, O_WRONLY|O_DENYNONE, O_RDWR|O_DENYNONE, #else O_RDONLY|O_DENYNONE, O_WRONLY|O_DENYWRITE, O_RDWR|O_DENYALL, #endif 3 }; if( (cmode & 0222) == 0 ) creat_mode = 1; /* BzzzT. Ignore O_EXCL */ if( type & O_TRUNC ) /* Assume TRUNC always means CREAT too */ rv = __dos_creat(nname, creat_mode); else { int sv = errno; /* If we would open in compatibility mode make it a little more unixy */ if( type & O_DENYMODE ) rv = __dos_open(nname, type&(O_ACCMODE|O_DENYMODE|O_SETFD)); else rv = __dos_open(nname, xlate_mode[type&O_ACCMODE]); if (rv == -1 && errno == ENOENT && (type & O_CREAT)) { errno = sv; rv = __dos_creat(nname, creat_mode); } } return rv; } __dos_open(fname, mode) { #asm mov bx,sp mov dx,[bx+2] ;ds:dx points to source string mov al,[bx+4] ;access code mov ah,#$3d ;ask for a open int #$21 jnc openok ;return handle if no error br exterror openok: #endasm } __dos_creat(fname) char * fname; { #asm mov bx,sp mov dx,[bx+2] ;ds:dx points to source string xor cx,cx ;normal attributes mov ah,#$3c ;ask for a create int #$21 jnc creok ;return handle if no error br exterror creok: #endasm } #endif #ifdef L_dos_close close(fd) { #asm mov bx,sp mov bx,[bx+2] ;file handle mov ah,#$3e ;ask for a close int #$21 mov ax,0 ;return 0 if no error jnc closeok br exterror closeok: #endasm } #endif #ifdef L_dos_unlink unlink(fname) char * fname; { #asm mov bx,sp push [bx+2] call ___fconv inc sp inc sp mov dx,ax ;ds:dx points to source string mov ah,#$41 ;ask for a unlink int #$21 mov ax,0 ;assume no errors jnc unlok br exterror unlok: #endasm } #endif #ifdef L_dos_lseek long lseek(fd, offset, mode) int fd, mode; long offset; { #asm mov bx,sp mov al,[bx+8] ;mode of seek (0 to 2) mov dx,[bx+4] ;cx:dx is long offset mov cx,[bx+6] mov bx,[bx+2] ;file handle mov ah,#$42 int #$21 ;do the lseek jnc seekok call exterror mov dx,ax seekok: #endasm } #endif #ifdef L_dos_segalloc unsigned int __segalloc(paracount) unsigned int paracount; { #asm mov bx,sp mov bx,[bx+2] mov ah,#$48 int $21 jnc ok mov ax,#0 ok: #endasm } #endif #ifdef L_dos_segfree unsigned int __segfree(segno) unsigned int segno; { #asm push es mov bx,sp mov es,[bx+4] mov ah,#$49 int $21 jc err mov ax,#0 err: pop es #endasm } #endif #ifdef L_dos_setvect void __setvect(i,j) int i; long j; { #asm mov bx,sp mov ax,[bx+2] mov dx,[bx+4] mov bx,[bx+6] push ds test bx,bx jnz got_seg mov bx,cs got_seg: mov ds,bx mov ah,#$25 int $21 pop ds #endasm } #endif #ifdef L_dos_getvect long __getvect(vecno) int vecno; { #asm mov bx,sp mov ax,[bx+2] mov ah,#$35 push es int #$21 mov dx,es mov ax,bx pop es #endasm } #endif #ifdef L_dos_getmod int __dos_getmod(fname) { #asm #if __FIRST_ARG_IN_AX__ mov dx,ax #else mov bx,sp mov dx,[bx+2] #endif mov ax,#$4300 int #$21 jnc statok br exterror statok: mov ax,cx #endasm } #endif #ifdef L_dos_stat int __dos_stat(fname, dtaptr) { #asm mov bx,sp #if __FIRST_ARG_IN_AX__ mov cx,ax mov dx,[bx+2] #else mov dx,[bx+4] #endif mov ah,#$1A ; Set DTA to requested int #$21 #if __FIRST_ARG_IN_AX__ mov ax,cx #else mov dx,[bx+2] #endif mov ax,#$4300 ; Locate the file int #$21 jc nonesuch mov ax,#$4e00 ; Get all the available information. int #$21 jc nonesuch xor ax,ax ret nonesuch: mov ax,#2 mov _errno,ax mov ax,#-1 #endasm } #endif #ifdef L_dos_isatty isatty(fd) int fd; { #asm mov bx,sp mov bx,[bx+2] mov ah,#$44 mov al,#0 int #$21 xor ax,ax test dx,#$80 jz not_tty inc ax not_tty: #endasm } #endif #ifdef L_dos_abort abort() { write(2, "Abnormal program termination\r\n", 30); _exit(3); } #endif #ifdef L_bdos bdos(dosfn, dosdx, dosal) int dosfn; unsigned dosdx, dosal; { #asm _bdosptr = _bdos mov bx,sp push si push di mov dx,_bdos.dosdx[bx] mov cx,_bdos.dosfn[bx] mov ax,_bdos.dosal[bx] mov ah,cl int $21 pop di pop si #endasm } #endif #endif /* __MSDOS__ */ #endif /* __AS386_16__ */ #endif /* !__FIRST_ARG_IN_AX__ */ /* # Name No Args Flag, comment CHDIR 12 1 TIME 13 1 * No long return val, arg _must_ exist. MKNOD 14 3 CHMOD 15 2 CHOWN 16 3 BRK 17 1 * This is only to tell the system STAT 18 2 GETPID 20 1 * This gets both pid & ppid MOUNT 21 3 * Need more args & no ELKS UMOUNT 22 1 . No ELKS SETUID 23 1 GETUID 24 1 * This gets both uid and euid STIME 25 2 . No ELKS should be 1 LONG arg PTRACE 26 X + ALARM 27 2 ? No unused return. FSTAT 28 2 PAUSE 29 0 UTIME 30 2 STTY 31 2 . ELKS ain't got this and it'll probably change GTTY 32 2 . ELKS ain't got this and it'll probably change ACCESS 33 2 NICE 34 1 FTIME 35 1 . ELKS ain't got this. SYNC 36 0 KILL 37 2 RENAME 38 2 MKDIR 39 2 RMDIR 40 1 DUP 41 X - Using nasty fcntl function PIPE 42 1 TIMES 43 1 PROF 44 X + SETGID 46 1 GETGID 47 1 * This gets both gid and egid SIGNAL 48 2 + ACCT 51 X + PLOCK 53 X + IOCTL 54 3 FCNTL 55 3 EXEC 59 2 ? UMASK 60 1 CHROOT 61 1 SIGACTION 71 X SIGSUSPEND 72 X SIGPENDING 73 X SIGPROCMASK 74 X SIGRETURN 75 X REBOOT 76 3 . No ELKS and the magic number will be diff. */ dev86-0.16.21/libc/msdos/mslib.c000066400000000000000000000072371231050321700161300ustar00rootroot00000000000000/* Copyright (C) 1998 Robert de Bath * This file is part of the Linux-8086 C library and is distributed * under the GNU Library General Public License. */ #if !__FIRST_ARG_IN_AX__ #ifdef __AS386_16__ #ifdef __MSDOS__ #include #include #include int errno; #ifdef L_dos_chdir chdir(path) char * path; { #asm mov bx,sp mov bx,_chdir.path[bx] cmp [bx+1],': jnz do_chdir mov dl,[bx] and dl,#$3F dec dl mov ah,#$0E int $21 do_chdir: mov ah,#$3B mov dx,bx do_dxop: int $21 jnc op_ok br exterror op_ok: xor ax,ax #endasm } #endif #ifdef L_mkdir mkdir(path) char * path; { #asm mov bx,sp mov dx,_mkdir.path[bx] mov ah,#$39 j do_dxop #endasm } #endif #ifdef L_rmdir rmdir(path) char * path; { #asm mov bx,sp mov dx,_rmdir.path[bx] mov ah,#$3A j do_dxop #endasm } #endif #ifdef L_unlink unlink(path) char * path; { #asm mov bx,sp mov dx,_unlink.path[bx] mov ah,#$41 xor cx,cx ! Attrib 0 for servers. j do_dxop #endasm } #endif /************************************************************************* TO TEST ... */ #ifdef L_sleep sleep(secs) unsigned secs; { int counter = 0; int es = __get_es(); __set_es(0x40); while(secs>0) { int c = __peek_es(0x6C); while( c == __peek_es(0x6C) ) ; counter += 549; if( counter > 10000 ) { secs--; counter -= 10000; } /* Interrupt on ctrl-break */ if( __peek_es(0x71) & 0x80 ) break; } __set_es(es); return secs; } #endif /************************************************************************* TODO ... */ #ifdef L_dos_access access(filename, amode) char * filename; int amode; { XXX; } #endif #ifdef L__dos_allocmem _dos_allocmem(size ...) { } #endif #ifdef L__chmod _chmod(path, func, attrib) char * path; int func, attrib; { XXX; } #endif #ifdef L_chmod chmod(path, mode) char * path; int mode; { XXX; } #endif #ifdef L_clock clock_t clock() { XXX; } #endif #ifdef L_ctrlbrk ctrlbrk(func) int (*func)(); { XXX; } #endif #ifdef L_delay delay(millis) unsigned millis; { XXX; } #endif #ifdef L_dosexterr dosexterr(ptr) struct DOSERROR * ptr; { XXX; } #endif /* #ifdef __dos_getdiskfree */ #ifdef L_dup dup(fd) int fd; { XXX; } #endif #ifdef L_dup2 dup2(ofd, nfd) int ofd, nfd; { XXX; } #endif #ifdef L_filelength long filelength(fd) int fd; { XXX; } #endif #ifdef L_findfirst findfirst(path, fcb, attrib) char * path; void * fcb; int attrib; { XXX; } #endif #ifdef L_findnext findnext(fcb) void * fcb; { XXX; } #endif #ifdef L_stat stat(path, st) char * path; struct stat * st; { XXX; } #endif #ifdef L_fstat fstat(fd, st) int fd; struct stat * st; { XXX; } #endif #ifdef L_getcbrk getcbrk() { XXX int 0x21/33; } #endif #ifdef L_setcbrk setcbrk(mode) int mode; { XXX int 0x21/33; } #endif #ifdef L_getcwd getcwd(buf, buflen) char * buf; int buflen; { XXX; } #endif #ifdef L__getdrive _getdrive() { XXX; } #endif #ifdef L_getenv char * getenv(varname) char * varname; { XXX; } #endif #ifdef L_putenv putenv(varname) char * varname; { XXX; } #endif #ifdef L_getpid getpid() { XXX; } #endif #ifdef L_rename rename(oldname, newpath) char *oldpath, *newpath; { XXX; } #endif #ifdef L_setmode setmode(fd, amode) int fd, amode; { XXX; } #endif #ifdef L_system system(cmd) char * cmd; { XXX; } #endif #ifdef L_umask umask(mode) int mode; { XXX; /* * save umask value for open() use it for read-only bit. */ } #endif #ifdef L_utime utime(path, times) char * path; stuct utimbuf * times; { XXX; } #endif #endif /* __MSDOS__ */ #endif /* __AS386_16__ */ #endif /* !__FIRST_ARG_IN_AX__ */ dev86-0.16.21/libc/msdos/new86.c000066400000000000000000000007551231050321700157670ustar00rootroot00000000000000 #define disable() _disable() #define enable() _enable() _enable() { #asm sti #endasm } _disable() { #asm cli #endasm } geninterrupt(intr) int intr; { } inp(portno) int portno; { } inpw(portno) int portno; { } outp(...) { } outpw(...) { } peek(segment, offset) unsigned segment, offset; { } peekb(segment, offset) unsigned segment, offset; { } poke(segment, offset, value) unsigned segment, offset, value; { } pokeb(segment, offset, value) unsigned segment, offset, value; { } dev86-0.16.21/libc/msdos/sound.c000066400000000000000000000006041231050321700161410ustar00rootroot00000000000000 #include static int port_val = -1; sound(freq) unsigned freq; /* freq is in hertz */ { if(port_val == -1 ) port_val = inp(0x61); freq = 1193180L / freq; outp(0x61, port_val|3); outp(0x43, 0xb6); outp(0x42, freq&0xFF); outp(0x42, (freq>>8)&0xFF); } nosound() { if( port_val ) outp(0x61, port_val); else outp(0x61, inp(0x61)&~3); } dev86-0.16.21/libc/msdos/time.c000066400000000000000000000026101231050321700157460ustar00rootroot00000000000000 #include static int mdays[13] = { 0,31,31+28,31+28+31,31+28+31+30, 31+28+31+30+31,31+28+31+30+31+30,31+28+31+30+31+30+31, 31+28+31+30+31+30+31+31,31+28+31+30+31+30+31+31+30, 31+28+31+30+31+30+31+31+30+31,31+28+31+30+31+30+31+31+30+31+30, 365 }; #define SECSPERHOUR (60*60) #define SECSPERDAY (SECSPERHOUR*24L) /**************************************** * Return the number of seconds that have elapsed since the start * of 1970. * Input: * timer pointer to where to store result (or NULL) * Output: * *timer = result (unless timer == NULL) * Returns: * time */ static long get_time(ah) { #asm #if !__FIRST_ARG_IN_AX__ mov bx,sp mov ax,[bx+2] #endif mov ah,al int $21 mov ax,dx mov dx,cx #endasm } time_t time(timer) time_t *timer; { unsigned day,month,year; long rv; time_t t; rv = get_time(0x2C); rv >>= 8; t = (rv & 0xFF); rv >>= 8; t += (rv & 0xFF)*60; rv >>= 8; t += (rv & 0xFF)*3600; rv = get_time(0x2A); day = (rv & 0xFF); rv >>= 8; month = (rv & 0xFF) -1; rv >>= 8; year = (rv & 0xFFFF) - 1970; if (month <= 1 || year & 3) /* if before Feb or not a leap year */ day--; /* don't add day for this leap year */ day += mdays[month]; /* day in year */ day += (year + 3) >> 2; /* add a day for each leap year, but */ /* don't worry about 2100 */ t += ((year * 365L) + day) * SECSPERDAY; if (timer) *timer = t; return t; } dev86-0.16.21/libc/regexp/000077500000000000000000000000001231050321700150125ustar00rootroot00000000000000dev86-0.16.21/libc/regexp/Config000066400000000000000000000000371231050321700161420ustar00rootroot00000000000000regexp: Regular expression lib dev86-0.16.21/libc/regexp/Makefile000066400000000000000000000011251231050321700164510ustar00rootroot00000000000000 OBJ=regexp.o regsub.o LSRC=regexp.c regsub.c regerror.c CFLAGS=$(ARCH) $(CCFLAGS) $(DEFS) all: $(LIBC) @$(RM) $(OBJ) $(LIBC): $(LIBC)($(OBJ)) transfer: -@rm -f ../include/regexp.h ../include/regmagic.h cp -p regexp.h regmagic.h ../include/. $(LIBC)(regexp.o): regexp.c regexp.h regmagic.h $(CC) $(CFLAGS) -DL_$* $< -c -o $*.o $(AR) $(ARFLAGS) $@ $*.o $(LIBC)(regsub.o): regsub.c regexp.h regmagic.h $(CC) $(CFLAGS) -DL_$* $< -c -o $*.o $(AR) $(ARFLAGS) $@ $*.o clean: rm -f libc.a *.o core mon.out timer.t.h dMakefile dtr try timer rm -f ../include/regexp.h ../include/regmagic.h dev86-0.16.21/libc/regexp/Makefile.org000066400000000000000000000033631231050321700172450ustar00rootroot00000000000000# Things you might want to put in ENV and LENV: # -Dvoid=int compilers that don't do void # -DCHARBITS=0377 compilers that don't do unsigned char # -DSTATIC=extern compilers that don't like "static foo();" as forward decl # -DSTRCSPN library does not have strcspn() # -Dstrchr=index library does not have strchr() # -DERRAVAIL have utzoo-compatible error() function and friends # ENV=-DCHARBITS=0377 # LENV=-DCHARBITS=0377 # Things you might want to put in TEST: # -DDEBUG debugging hooks # -I. regexp.h from current directory, not /usr/include TEST=-I. # Things you might want to put in PROF: # -Dstatic='/* */' make everything global so profiler can see it. # -p profiler PROF= CFLAGS=-O $(ENV) $(TEST) $(PROF) LINTFLAGS=$(LENV) $(TEST) -ha LDFLAGS=-i OBJ=regexp.o regsub.o LSRC=regexp.c regsub.c regerror.c DTR=README dMakefile regexp.3 regexp.h regexp.c regsub.c regerror.c \ regmagic.h try.c timer.c tests try: try.o $(OBJ) cc $(LDFLAGS) try.o $(OBJ) -o try # Making timer will probably require putting stuff in $(PROF) and then # recompiling everything; the following is just the final stage. timer: timer.o $(OBJ) cc $(LDFLAGS) $(PROF) timer.o $(OBJ) -o timer timer.o: timer.c timer.t.h timer.t.h: tests sed 's/ /","/g;s/\\/&&/g;s/.*/{"&"},/' tests >timer.t.h # Regression test. r: try tests @echo 'No news is good news...' try dtr dMakefile: Makefile sed '/^L*ENV=/s/ *-DERRAVAIL//' Makefile >dMakefile dev86-0.16.21/libc/regexp/README000066400000000000000000000103761231050321700157010ustar00rootroot00000000000000This is a nearly-public-domain reimplementation of the V8 regexp(3) package. It gives C programs the ability to use egrep-style regular expressions, and does it in a much cleaner fashion than the analogous routines in SysV. Copyright (c) 1986 by University of Toronto. Written by Henry Spencer. Not derived from licensed software. Permission is granted to anyone to use this software for any purpose on any computer system, and to redistribute it freely, subject to the following restrictions: 1. The author is not responsible for the consequences of use of this software, no matter how awful, even if they arise from defects in it. 2. The origin of this software must not be misrepresented, either by explicit claim or by omission. 3. Altered versions must be plainly marked as such, and must not be misrepresented as being the original software. Barring a couple of small items in the BUGS list, this implementation is believed 100% compatible with V8. It should even be binary-compatible, sort of, since the only fields in a "struct regexp" that other people have any business touching are declared in exactly the same way at the same location in the struct (the beginning). This implementation is *NOT* AT&T/Bell code, and is not derived from licensed software. Even though U of T is a V8 licensee. This software is based on a V8 manual page sent to me by Dennis Ritchie (the manual page enclosed here is a complete rewrite and hence is not covered by AT&T copyright). The software was nearly complete at the time of arrival of our V8 tape. I haven't even looked at V8 yet, although a friend elsewhere at U of T has been kind enough to run a few test programs using the V8 regexp(3) to resolve a few fine points. I admit to some familiarity with regular-expression implementations of the past, but the only one that this code traces any ancestry to is the one published in Kernighan & Plauger (from which this one draws ideas but not code). Simplistically: put this stuff into a source directory, copy regexp.h into /usr/include, inspect Makefile for compilation options that need changing to suit your local environment, and then do "make r". This compiles the regexp(3) functions, compiles a test program, and runs a large set of regression tests. If there are no complaints, then put regexp.o, regsub.o, and regerror.o into your C library, and regexp.3 into your manual-pages directory. Note that if you don't put regexp.h into /usr/include *before* compiling, you'll have to add "-I." to CFLAGS before compiling. The files are: Makefile instructions to make everything regexp.3 manual page regexp.h header file, for /usr/include regexp.c source for regcomp() and regexec() regsub.c source for regsub() regerror.c source for default regerror() regmagic.h internal header file try.c source for test program timer.c source for timing program tests test list for try and timer This implementation uses nondeterministic automata rather than the deterministic ones found in some other implementations, which makes it simpler, smaller, and faster at compiling regular expressions, but slower at executing them. In theory, anyway. This implementation does employ some special-case optimizations to make the simpler cases (which do make up the bulk of regular expressions actually used) run quickly. In general, if you want blazing speed you're in the wrong place. Replacing the insides of egrep with this stuff is probably a mistake; if you want your own egrep you're going to have to do a lot more work. But if you want to use regular expressions a little bit in something else, you're in luck. Note that many existing text editors use nondeterministic regular-expression implementations, so you're in good company. This stuff should be pretty portable, given appropriate option settings. If your chars have less than 8 bits, you're going to have to change the internal representation of the automaton, although knowledge of the details of this is fairly localized. There are no "reserved" char values except for NUL, and no special significance is attached to the top bit of chars. The string(3) functions are used a fair bit, on the grounds that they are probably faster than coding the operations in line. Some attempts at code tuning have been made, but this is invariably a bit machine-specific. dev86-0.16.21/libc/regexp/README.rdb000066400000000000000000000003251231050321700164400ustar00rootroot00000000000000 I've applied the four bugfix patches I've found and made a couple of very small changes (added malloc.h) and put in a new Makefile. Otherwise this is as it was posted on by Henry Spencer to mod.sources. -Robert dev86-0.16.21/libc/regexp/patch.1000066400000000000000000000017101231050321700161720ustar00rootroot00000000000000Subject: bug in regexp(3), and fix Newsgroups: mod.sources Approved: jpn@panda.UUCP Mod.sources: Volume 3, Issue 105 Submitted by: genrad!decvax!utzoo!henry Drat! Chris Siebenmann at CSRI just found a bug in my regexp(3) routines. The problem is that the code for character classes does not check properly for the possibility that it might be looking at the end of the string. By simple bad luck none of my test cases hit this. To fix it, make the following two changes to regexp.c: 848c848 < if (strchr(OPERAND(scan), *reginput) == NULL) --- > if (*reginput == '\0' || strchr(OPERAND(scan), *reginput) == NULL) 853c853 < if (strchr(OPERAND(scan), *reginput) != NULL) --- > if (*reginput == '\0' || strchr(OPERAND(scan), *reginput) != NULL) and recompile. Also, add the following line to the "tests" file: [k] ab n - - My thanks to Chris for finding this. Henry Spencer @ U of Toronto Zoology {allegra,ihnp4,linus,decvax}!utzoo!henry dev86-0.16.21/libc/regexp/patch.2000066400000000000000000000014451231050321700162000ustar00rootroot00000000000000Subject: 2nd bug fix for regexp(3), in regsub() Newsgroups: mod.sources Approved: jpn@panda.UUCP Mod.sources: Volume 4, Issue 33 Submitted by: genrad!decvax!utzoo!henry I cringe with embarrassment! Another bug in regexp! In regsub.c, the following line (line 72 in the original distribution): if (*(dst-1) == '\0') { /* strncpy hit NUL. */ should read if (len != 0 && *(dst-1) == '\0') { /* strncpy hit NUL. */ This shows up as an occasional spurious complaint from regsub about "damaged match string"... *if* the program invoking it, and the compiler compiling it, happen to interact just right. It didn't show in any of my tests because mine don't. My thanks to H}vard Eidnes for finding this. Henry Spencer @ U of Toronto Zoology {allegra,ihnp4,linus,decvax}!utzoo!henry dev86-0.16.21/libc/regexp/patch.3000066400000000000000000000030021231050321700161700ustar00rootroot00000000000000Subject: regexp(3) improvement Newsgroups: mod.sources Approved: jpn@panda.UUCP Mod.sources: Volume 4, Issue 49 Submitted by: utzoo!henry (Henry Spencer) One flaw of my regexp(3) as distributed is that there is no way to get a literal `&' or '\n' (n a digit) past regsub(). The V8 manual page made no mention of an escape convention. It turns out that this is a deficiency in the documentation rather than the software. Accordingly, the following update should be applied to my regexp(3) to preserve full compatibility and to add this useful facility. In regsub.c, change the following (line numbers approximate only): 67,69c67,71 < if (no < 0) /* Ordinary character. */ < *dst++ = c; < else if (prog->startp[no] != NULL && prog->endp[no] != NULL) { --- > if (no < 0) { /* Ordinary character. */ > if (c == '\\' && (*src == '\\' || *src == '&')) > c = *src++; > *dst++ = c; > } else if (prog->startp[no] != NULL && prog->endp[no] != NULL) { In regexp.3, add the following sentence to the end of the paragraph describing regsub: To get a literal `&' or `\e\fIn\fR' into \fIdest\fR, prefix it with `\e'; to get a literal `\e' preceding `&' or `\e\fIn\fR', prefix it with another `\e'. And add the following two lines to the "tests" file: abcd abcd y &-\&-\\& abcd-&-\abcd a(bc)d abcd y \1-\\1-\\\1 bc-\1-\bc My thanks to Mike Lutz at Rochester Institute of Technology for noticing this issue and alerting me to it. Henry Spencer @ U of Toronto Zoology {allegra,ihnp4,decvax,pyramid}!utzoo!henry dev86-0.16.21/libc/regexp/patch.4000066400000000000000000000044521231050321700162030ustar00rootroot00000000000000Path: uunet!rs From: rs@uunet.UU.NET (Rich Salz) Newsgroups: comp.sources.unix Subject: v10i097: Bug-fix for regexp() library Message-ID: <789@uunet.UU.NET> Date: 7 Aug 87 11:20:15 GMT Organization: UUNET Communications Services, Arlington, VA Lines: 46 Approved: rs@uunet.UU.NET Submitted-by: seismo!ai.toronto.edu!utzoo!henry Posting-number: Volume 10, Issue 97 Archive-name: regexp.pch FURTHER NOTE by Rich $alz on Tue Apr 26 20:02:59 EDT 1988: This is a patch for Henry's regexp posting that appeared in volume 3 (first patch was volume3/regexp2; the naming convention used by my predecessor). There is another regexp library in volume 7 -- they're unreleated. The "fastgrep" posting appeards in volume 9. It also includes Henry's volume3 posting and both sets of patches. [ Regexp was published by itself in volume 6, and also as part of the "fastest grep around" earlier in this volume. --r$ ] Jeff Mc Carrell at Berkeley has found (gasp! choke! the horror! the horror!) another bug in my regexp functions. One thing my test set did not include was very large regular expressions. The bug is in the NEXT macro, which digs out the offset to the next node of the regexp: a parenthesization botch makes trouble if the offset is ever larger than 255. How humiliating. Here is the fix to regexp.c: 116c116 < #define NEXT(p) (((*((p)+1)&0377)<<8) + *((p)+2)&0377) --- > #define NEXT(p) (((*((p)+1)&0377)<<8) + (*((p)+2)&0377)) and here are some more lines for the "tests" file: [ -~]* abc y & abc [ -~ -~]* abc y & abc [ -~ -~ -~]* abc y & abc [ -~ -~ -~ -~]* abc y & abc [ -~ -~ -~ -~ -~]* abc y & abc [ -~ -~ -~ -~ -~ -~]* abc y & abc [ -~ -~ -~ -~ -~ -~ -~]* abc y & abc Just to let people know: there is some prospect of me coming out with a second edition of my regexp stuff, including a number of improvements that various people have suggested/contributed. However, it will not be soon, because I'm very busy right now. I can't spare the time to sort it all out, decide what belongs and what doesn't, write the missing bits of code, and integrate it all. Sometime later this year, maybe. Henry Spencer @ U of Toronto Zoology {allegra,ihnp4,decvax,pyramid}!utzoo!henry -- Rich $alz "Anger is an energy" Cronus Project, BBN Labs rsalz@bbn.com Moderator, comp.sources.unix sources@uunet.uu.net dev86-0.16.21/libc/regexp/regerror.c000066400000000000000000000002521231050321700170040ustar00rootroot00000000000000#include void regerror(s) char *s; { #ifdef ERRAVAIL error("regexp: %s", s); #else fprintf(stderr, "regexp(3): %s", s); exit(1); #endif /* NOTREACHED */ } dev86-0.16.21/libc/regexp/regexp.3000066400000000000000000000146151231050321700163770ustar00rootroot00000000000000.TH REGEXP 3 local .DA 30 Nov 1985 .SH NAME regcomp, regexec, regsub, regerror \- regular expression handler .SH SYNOPSIS .ft B .nf #include regexp *regcomp(exp) char *exp; int regexec(prog, string) regexp *prog; char *string; regsub(prog, source, dest) regexp *prog; char *source; char *dest; regerror(msg) char *msg; .SH DESCRIPTION These functions implement .IR egrep (1)-style regular expressions and supporting facilities. .PP .I Regcomp compiles a regular expression into a structure of type .IR regexp , and returns a pointer to it. The space has been allocated using .IR malloc (3) and may be released by .IR free . .PP .I Regexec matches a NUL-terminated \fIstring\fR against the compiled regular expression in \fIprog\fR. It returns 1 for success and 0 for failure, and adjusts the contents of \fIprog\fR's \fIstartp\fR and \fIendp\fR (see below) accordingly. .PP The members of a .I regexp structure include at least the following (not necessarily in order): .PP .RS char *startp[NSUBEXP]; .br char *endp[NSUBEXP]; .RE .PP where .I NSUBEXP is defined (as 10) in the header file. Once a successful \fIregexec\fR has been done using the \fIregexp\fR, each \fIstartp\fR-\fIendp\fR pair describes one substring within the \fIstring\fR, with the \fIstartp\fR pointing to the first character of the substring and the \fIendp\fR pointing to the first character following the substring. The 0th substring is the substring of \fIstring\fR that matched the whole regular expression. The others are those substrings that matched parenthesized expressions within the regular expression, with parenthesized expressions numbered in left-to-right order of their opening parentheses. .PP .I Regsub copies \fIsource\fR to \fIdest\fR, making substitutions according to the most recent \fIregexec\fR performed using \fIprog\fR. Each instance of `&' in \fIsource\fR is replaced by the substring indicated by \fIstartp\fR[\fI0\fR] and \fIendp\fR[\fI0\fR]. Each instance of `\e\fIn\fR', where \fIn\fR is a digit, is replaced by the substring indicated by \fIstartp\fR[\fIn\fR] and \fIendp\fR[\fIn\fR]. .PP .I Regerror is called whenever an error is detected in \fIregcomp\fR, \fIregexec\fR, or \fIregsub\fR. The default \fIregerror\fR writes the string \fImsg\fR, with a suitable indicator of origin, on the standard error output and invokes \fIexit\fR(2). .I Regerror can be replaced by the user if other actions are desirable. .SH "REGULAR EXPRESSION SYNTAX" A regular expression is zero or more \fIbranches\fR, separated by `|'. It matches anything that matches one of the branches. .PP A branch is zero or more \fIpieces\fR, concatenated. It matches a match for the first, followed by a match for the second, etc. .PP A piece is an \fIatom\fR possibly followed by `*', `+', or `?'. An atom followed by `*' matches a sequence of 0 or more matches of the atom. An atom followed by `+' matches a sequence of 1 or more matches of the atom. An atom followed by `?' matches a match of the atom, or the null string. .PP An atom is a regular expression in parentheses (matching a match for the regular expression), a \fIrange\fR (see below), `.' (matching any single character), `^' (matching the null string at the beginning of the input string), `$' (matching the null string at the end of the input string), a `\e' followed by a single character (matching that character), or a single character with no other significance (matching that character). .PP A \fIrange\fR is a sequence of characters enclosed in `[]'. It normally matches any single character from the sequence. If the sequence begins with `^', it matches any single character \fInot\fR from the rest of the sequence. If two characters in the sequence are separated by `\-', this is shorthand for the full list of ASCII characters between them (e.g. `[0-9]' matches any decimal digit). To include a literal `]' in the sequence, make it the first character (following a possible `^'). To include a literal `\-', make it the first or last character. .SH AMBIGUITY If a regular expression could match two different parts of the input string, it will match the one which begins earliest. If both begin in the same place but match different lengths, or match the same length in different ways, life gets messier, as follows. .PP In general, the possibilities in a list of branches are considered in left-to-right order, the possibilities for `*', `+', and `?' are considered longest-first, nested constructs are considered from the outermost in, and concatenated constructs are considered leftmost-first. The match that will be chosen is the one that uses the earliest possibility in the first choice that has to be made. If there is more than one choice, the next will be made in the same manner (earliest possibility) subject to the decision on the first choice. And so forth. .PP For example, `(ab|a)b*c' could match `abc' in one of two ways. The first choice is between `ab' and `a'; since `ab' is earlier, and does lead to a successful overall match, it is chosen. Since the `b' is already spoken for, the `b*' must match its last possibility\(emthe empty string\(emsince it must respect the earlier choice. .PP In the particular case where no `|'s are present and there is only one `*', `+', or `?', the net effect is that the longest possible match will be chosen. So `ab*', presented with `xabbbby', will match `abbbb'. Note that if `ab*' is tried against `xabyabbbz', it will match `ab' just after `x', due to the begins-earliest rule. (In effect, the decision on where to start the match is the first choice to be made, hence subsequent choices must respect it even if this leads them to less-preferred alternatives.) .SH SEE ALSO egrep(1), expr(1) .SH DIAGNOSTICS \fIRegcomp\fR returns NULL for a failure (\fIregerror\fR permitting), where failures are syntax errors, exceeding implementation limits, or applying `+' or `*' to a possibly-null operand. .SH HISTORY Both code and manual page were written at U of T. They are intended to be compatible with the Bell V8 \fIregexp\fR(3), but are not derived from Bell code. .SH BUGS Empty branches and empty regular expressions are not portable to V8. .PP The restriction against applying `*' or `+' to a possibly-null operand is an artifact of the simplistic implementation. .PP Does not support \fIegrep\fR's newline-separated branches; neither does the V8 \fIregexp\fR(3), though. .PP Due to emphasis on compactness and simplicity, it's not strikingly fast. It does give special attention to handling simple cases quickly. dev86-0.16.21/libc/regexp/regexp.c000066400000000000000000000657301231050321700164630ustar00rootroot00000000000000/* * regcomp and regexec -- regsub and regerror are elsewhere * * Copyright (c) 1986 by University of Toronto. * Written by Henry Spencer. Not derived from licensed software. * * Permission is granted to anyone to use this software for any * purpose on any computer system, and to redistribute it freely, * subject to the following restrictions: * * 1. The author is not responsible for the consequences of use of * this software, no matter how awful, even if they arise * from defects in it. * * 2. The origin of this software must not be misrepresented, either * by explicit claim or by omission. * * 3. Altered versions must be plainly marked as such, and must not * be misrepresented as being the original software. * * Beware that some of this code is subtly aware of the way operator * precedence is structured in regular expressions. Serious changes in * regular-expression syntax might require a total rethink. */ #include #include #include #include #include "regmagic.h" /* * The "internal use only" fields in regexp.h are present to pass info from * compile to execute that permits the execute phase to run lots faster on * simple cases. They are: * * regstart char that must begin a match; '\0' if none obvious * reganch is the match anchored (at beginning-of-line only)? * regmust string (pointer into program) that match must include, or NULL * regmlen length of regmust string * * Regstart and reganch permit very fast decisions on suitable starting points * for a match, cutting down the work a lot. Regmust permits fast rejection * of lines that cannot possibly match. The regmust tests are costly enough * that regcomp() supplies a regmust only if the r.e. contains something * potentially expensive (at present, the only such thing detected is * or + * at the start of the r.e., which can involve a lot of backup). Regmlen is * supplied because the test in regexec() needs it and regcomp() is computing * it anyway. */ /* * Structure for regexp "program". This is essentially a linear encoding * of a nondeterministic finite-state machine (aka syntax charts or * "railroad normal form" in parsing technology). Each node is an opcode * plus a "next" pointer, possibly plus an operand. "Next" pointers of * all nodes except BRANCH implement concatenation; a "next" pointer with * a BRANCH on both ends of it is connecting two alternatives. (Here we * have one of the subtle syntax dependencies: an individual BRANCH (as * opposed to a collection of them) is never concatenated with anything * because of operator precedence.) The operand of some types of node is * a literal string; for others, it is a node leading into a sub-FSM. In * particular, the operand of a BRANCH node is the first node of the branch. * (NB this is *not* a tree structure: the tail of the branch connects * to the thing following the set of BRANCHes.) The opcodes are: */ /* definition number opnd? meaning */ #define END 0 /* no End of program. */ #define BOL 1 /* no Match "" at beginning of line. */ #define EOL 2 /* no Match "" at end of line. */ #define ANY 3 /* no Match any one character. */ #define ANYOF 4 /* str Match any character in this string. */ #define ANYBUT 5 /* str Match any character not in this string. */ #define BRANCH 6 /* node Match this alternative, or the next... */ #define BACK 7 /* no Match "", "next" ptr points backward. */ #define EXACTLY 8 /* str Match this string. */ #define NOTHING 9 /* no Match empty string. */ #define STAR 10 /* node Match this (simple) thing 0 or more times. */ #define PLUS 11 /* node Match this (simple) thing 1 or more times. */ #define OPEN 20 /* no Mark this point in input as start of #n. */ /* OPEN+1 is number 1, etc. */ #define CLOSE 30 /* no Analogous to OPEN. */ /* * Opcode notes: * * BRANCH The set of branches constituting a single choice are hooked * together with their "next" pointers, since precedence prevents * anything being concatenated to any individual branch. The * "next" pointer of the last BRANCH in a choice points to the * thing following the whole choice. This is also where the * final "next" pointer of each individual branch points; each * branch starts with the operand node of a BRANCH node. * * BACK Normal "next" pointers all implicitly point forward; BACK * exists to make loop structures possible. * * STAR,PLUS '?', and complex '*' and '+', are implemented as circular * BRANCH structures using BACK. Simple cases (one character * per match) are implemented with STAR and PLUS for speed * and to minimize recursive plunges. * * OPEN,CLOSE ...are numbered at compile time. */ /* * A node is one char of opcode followed by two chars of "next" pointer. * "Next" pointers are stored as two 8-bit pieces, high order first. The * value is a positive offset from the opcode of the node containing it. * An operand, if any, simply follows the node. (Note that much of the * code generation knows about this implicit relationship.) * * Using two bytes for the "next" pointer is vast overkill for most things, * but allows patterns to get big without disasters. */ #define OP(p) (*(p)) #define NEXT(p) (((*((p)+1)&0377)<<8) + (*((p)+2)&0377)) #define OPERAND(p) ((p) + 3) /* * See regmagic.h for one further detail of program structure. */ /* * Utility definitions. */ #ifndef CHARBITS #define UCHARAT(p) ((int)*(unsigned char *)(p)) #else #define UCHARAT(p) ((int)*(p)&CHARBITS) #endif #define FAIL(m) { regerror(m); return(NULL); } #define ISMULT(c) ((c) == '*' || (c) == '+' || (c) == '?') #define META "^$.[()|?+*\\" /* * Flags to be passed up and down. */ #define HASWIDTH 01 /* Known never to match null string. */ #define SIMPLE 02 /* Simple enough to be STAR/PLUS operand. */ #define SPSTART 04 /* Starts with * or +. */ #define WORST 0 /* Worst case. */ /* * Global work variables for regcomp(). */ static char *regparse; /* Input-scan pointer. */ static int regnpar; /* () count. */ static char regdummy; static char *regcode; /* Code-emit pointer; ®dummy = don't. */ static long regsize; /* Code size. */ /* * Forward declarations for regcomp()'s friends. */ #ifndef STATIC #define STATIC static #endif STATIC char *reg(); STATIC char *regbranch(); STATIC char *regpiece(); STATIC char *regatom(); STATIC char *regnode(); STATIC char *regnext(); STATIC void regc(); STATIC void reginsert(); STATIC void regtail(); STATIC void regoptail(); #ifdef STRCSPN STATIC int strcspn(); #endif /* - regcomp - compile a regular expression into internal code * * We can't allocate space until we know how big the compiled form will be, * but we can't compile it (and thus know how big it is) until we've got a * place to put the code. So we cheat: we compile it twice, once with code * generation turned off and size counting turned on, and once "for real". * This also means that we don't allocate space until we are sure that the * thing really will compile successfully, and we never have to move the * code and thus invalidate pointers into it. (Note that it has to be in * one piece because free() must be able to free it all.) * * Beware that the optimization-preparation code in here knows about some * of the structure of the compiled regexp. */ regexp * regcomp(exp) char *exp; { register regexp *r; register char *scan; register char *longest; register int len; int flags; if (exp == NULL) FAIL("NULL argument"); /* First pass: determine size, legality. */ regparse = exp; regnpar = 1; regsize = 0L; regcode = ®dummy; regc(MAGIC); if (reg(0, &flags) == NULL) return(NULL); /* Small enough for pointer-storage convention? */ if (regsize >= 32767L) /* Probably could be 65535L. */ FAIL("regexp too big"); /* Allocate space. */ r = (regexp *)malloc(sizeof(regexp) + (unsigned)regsize); if (r == NULL) FAIL("out of space"); /* Second pass: emit code. */ regparse = exp; regnpar = 1; regcode = r->program; regc(MAGIC); if (reg(0, &flags) == NULL) return(NULL); /* Dig out information for optimizations. */ r->regstart = '\0'; /* Worst-case defaults. */ r->reganch = 0; r->regmust = NULL; r->regmlen = 0; scan = r->program+1; /* First BRANCH. */ if (OP(regnext(scan)) == END) { /* Only one top-level choice. */ scan = OPERAND(scan); /* Starting-point info. */ if (OP(scan) == EXACTLY) r->regstart = *OPERAND(scan); else if (OP(scan) == BOL) r->reganch++; /* * If there's something expensive in the r.e., find the * longest literal string that must appear and make it the * regmust. Resolve ties in favor of later strings, since * the regstart check works with the beginning of the r.e. * and avoiding duplication strengthens checking. Not a * strong reason, but sufficient in the absence of others. */ if (flags&SPSTART) { longest = NULL; len = 0; for (; scan != NULL; scan = regnext(scan)) if (OP(scan) == EXACTLY && strlen(OPERAND(scan)) >= len) { longest = OPERAND(scan); len = strlen(OPERAND(scan)); } r->regmust = longest; r->regmlen = len; } } return(r); } /* - reg - regular expression, i.e. main body or parenthesized thing * * Caller must absorb opening parenthesis. * * Combining parenthesis handling with the base level of regular expression * is a trifle forced, but the need to tie the tails of the branches to what * follows makes it hard to avoid. */ static char * reg(paren, flagp) int paren; /* Parenthesized? */ int *flagp; { register char *ret; register char *br; register char *ender; register int parno; int flags; *flagp = HASWIDTH; /* Tentatively. */ /* Make an OPEN node, if parenthesized. */ if (paren) { if (regnpar >= NSUBEXP) FAIL("too many ()"); parno = regnpar; regnpar++; ret = regnode(OPEN+parno); } else ret = NULL; /* Pick up the branches, linking them together. */ br = regbranch(&flags); if (br == NULL) return(NULL); if (ret != NULL) regtail(ret, br); /* OPEN -> first. */ else ret = br; if (!(flags&HASWIDTH)) *flagp &= ~HASWIDTH; *flagp |= flags&SPSTART; while (*regparse == '|') { regparse++; br = regbranch(&flags); if (br == NULL) return(NULL); regtail(ret, br); /* BRANCH -> BRANCH. */ if (!(flags&HASWIDTH)) *flagp &= ~HASWIDTH; *flagp |= flags&SPSTART; } /* Make a closing node, and hook it on the end. */ ender = regnode((paren) ? CLOSE+parno : END); regtail(ret, ender); /* Hook the tails of the branches to the closing node. */ for (br = ret; br != NULL; br = regnext(br)) regoptail(br, ender); /* Check for proper termination. */ if (paren && *regparse++ != ')') { FAIL("unmatched ()"); } else if (!paren && *regparse != '\0') { if (*regparse == ')') { FAIL("unmatched ()"); } else FAIL("junk on end"); /* "Can't happen". */ /* NOTREACHED */ } return(ret); } /* - regbranch - one alternative of an | operator * * Implements the concatenation operator. */ static char * regbranch(flagp) int *flagp; { register char *ret; register char *chain; register char *latest; int flags; *flagp = WORST; /* Tentatively. */ ret = regnode(BRANCH); chain = NULL; while (*regparse != '\0' && *regparse != '|' && *regparse != ')') { latest = regpiece(&flags); if (latest == NULL) return(NULL); *flagp |= flags&HASWIDTH; if (chain == NULL) /* First piece. */ *flagp |= flags&SPSTART; else regtail(chain, latest); chain = latest; } if (chain == NULL) /* Loop ran zero times. */ (void) regnode(NOTHING); return(ret); } /* - regpiece - something followed by possible [*+?] * * Note that the branching code sequences used for ? and the general cases * of * and + are somewhat optimized: they use the same NOTHING node as * both the endmarker for their branch list and the body of the last branch. * It might seem that this node could be dispensed with entirely, but the * endmarker role is not redundant. */ static char * regpiece(flagp) int *flagp; { register char *ret; register char op; register char *next; int flags; ret = regatom(&flags); if (ret == NULL) return(NULL); op = *regparse; if (!ISMULT(op)) { *flagp = flags; return(ret); } if (!(flags&HASWIDTH) && op != '?') FAIL("*+ operand could be empty"); *flagp = (op != '+') ? (WORST|SPSTART) : (WORST|HASWIDTH); if (op == '*' && (flags&SIMPLE)) reginsert(STAR, ret); else if (op == '*') { /* Emit x* as (x&|), where & means "self". */ reginsert(BRANCH, ret); /* Either x */ regoptail(ret, regnode(BACK)); /* and loop */ regoptail(ret, ret); /* back */ regtail(ret, regnode(BRANCH)); /* or */ regtail(ret, regnode(NOTHING)); /* null. */ } else if (op == '+' && (flags&SIMPLE)) reginsert(PLUS, ret); else if (op == '+') { /* Emit x+ as x(&|), where & means "self". */ next = regnode(BRANCH); /* Either */ regtail(ret, next); regtail(regnode(BACK), ret); /* loop back */ regtail(next, regnode(BRANCH)); /* or */ regtail(ret, regnode(NOTHING)); /* null. */ } else if (op == '?') { /* Emit x? as (x|) */ reginsert(BRANCH, ret); /* Either x */ regtail(ret, regnode(BRANCH)); /* or */ next = regnode(NOTHING); /* null. */ regtail(ret, next); regoptail(ret, next); } regparse++; if (ISMULT(*regparse)) FAIL("nested *?+"); return(ret); } /* - regatom - the lowest level * * Optimization: gobbles an entire sequence of ordinary characters so that * it can turn them into a single node, which is smaller to store and * faster to run. Backslashed characters are exceptions, each becoming a * separate node; the code is simpler that way and it's not worth fixing. */ static char * regatom(flagp) int *flagp; { register char *ret; int flags; *flagp = WORST; /* Tentatively. */ switch (*regparse++) { case '^': ret = regnode(BOL); break; case '$': ret = regnode(EOL); break; case '.': ret = regnode(ANY); *flagp |= HASWIDTH|SIMPLE; break; case '[': { register int class; register int classend; if (*regparse == '^') { /* Complement of range. */ ret = regnode(ANYBUT); regparse++; } else ret = regnode(ANYOF); if (*regparse == ']' || *regparse == '-') regc(*regparse++); while (*regparse != '\0' && *regparse != ']') { if (*regparse == '-') { regparse++; if (*regparse == ']' || *regparse == '\0') regc('-'); else { class = UCHARAT(regparse-2)+1; classend = UCHARAT(regparse); if (class > classend+1) FAIL("invalid [] range"); for (; class <= classend; class++) regc(class); regparse++; } } else regc(*regparse++); } regc('\0'); if (*regparse != ']') FAIL("unmatched []"); regparse++; *flagp |= HASWIDTH|SIMPLE; } break; case '(': ret = reg(1, &flags); if (ret == NULL) return(NULL); *flagp |= flags&(HASWIDTH|SPSTART); break; case '\0': case '|': case ')': FAIL("internal urp"); /* Supposed to be caught earlier. */ break; case '?': case '+': case '*': FAIL("?+* follows nothing"); break; case '\\': if (*regparse == '\0') FAIL("trailing \\"); ret = regnode(EXACTLY); regc(*regparse++); regc('\0'); *flagp |= HASWIDTH|SIMPLE; break; default: { register int len; register char ender; regparse--; len = strcspn(regparse, META); if (len <= 0) FAIL("internal disaster"); ender = *(regparse+len); if (len > 1 && ISMULT(ender)) len--; /* Back off clear of ?+* operand. */ *flagp |= HASWIDTH; if (len == 1) *flagp |= SIMPLE; ret = regnode(EXACTLY); while (len > 0) { regc(*regparse++); len--; } regc('\0'); } break; } return(ret); } /* - regnode - emit a node */ static char * /* Location. */ regnode(op) char op; { register char *ret; register char *ptr; ret = regcode; if (ret == ®dummy) { regsize += 3; return(ret); } ptr = ret; *ptr++ = op; *ptr++ = '\0'; /* Null "next" pointer. */ *ptr++ = '\0'; regcode = ptr; return(ret); } /* - regc - emit (if appropriate) a byte of code */ static void regc(b) char b; { if (regcode != ®dummy) *regcode++ = b; else regsize++; } /* - reginsert - insert an operator in front of already-emitted operand * * Means relocating the operand. */ static void reginsert(op, opnd) char op; char *opnd; { register char *src; register char *dst; register char *place; if (regcode == ®dummy) { regsize += 3; return; } src = regcode; regcode += 3; dst = regcode; while (src > opnd) *--dst = *--src; place = opnd; /* Op node, where operand used to be. */ *place++ = op; *place++ = '\0'; *place++ = '\0'; } /* - regtail - set the next-pointer at the end of a node chain */ static void regtail(p, val) char *p; char *val; { register char *scan; register char *temp; register int offset; if (p == ®dummy) return; /* Find last node. */ scan = p; for (;;) { temp = regnext(scan); if (temp == NULL) break; scan = temp; } if (OP(scan) == BACK) offset = scan - val; else offset = val - scan; *(scan+1) = (offset>>8)&0377; *(scan+2) = offset&0377; } /* - regoptail - regtail on operand of first argument; nop if operandless */ static void regoptail(p, val) char *p; char *val; { /* "Operandless" and "op != BRANCH" are synonymous in practice. */ if (p == NULL || p == ®dummy || OP(p) != BRANCH) return; regtail(OPERAND(p), val); } /* * regexec and friends */ /* * Global work variables for regexec(). */ static char *reginput; /* String-input pointer. */ static char *regbol; /* Beginning of input, for ^ check. */ static char **regstartp; /* Pointer to startp array. */ static char **regendp; /* Ditto for endp. */ /* * Forwards. */ STATIC int regtry(); STATIC int regmatch(); STATIC int regrepeat(); #ifdef DEBUG int regnarrate = 0; void regdump(); STATIC char *regprop(); #endif /* - regexec - match a regexp against a string */ int regexec(prog, string) register regexp *prog; register char *string; { register char *s; /* Be paranoid... */ if (prog == NULL || string == NULL) { regerror("NULL parameter"); return(0); } /* Check validity of program. */ if (UCHARAT(prog->program) != MAGIC) { regerror("corrupted program"); return(0); } /* If there is a "must appear" string, look for it. */ if (prog->regmust != NULL) { s = string; while ((s = strchr(s, prog->regmust[0])) != NULL) { if (strncmp(s, prog->regmust, prog->regmlen) == 0) break; /* Found it. */ s++; } if (s == NULL) /* Not present. */ return(0); } /* Mark beginning of line for ^ . */ regbol = string; /* Simplest case: anchored match need be tried only once. */ if (prog->reganch) return(regtry(prog, string)); /* Messy cases: unanchored match. */ s = string; if (prog->regstart != '\0') /* We know what char it must start with. */ while ((s = strchr(s, prog->regstart)) != NULL) { if (regtry(prog, s)) return(1); s++; } else /* We don't -- general case. */ do { if (regtry(prog, s)) return(1); } while (*s++ != '\0'); /* Failure. */ return(0); } /* - regtry - try match at specific point */ static int /* 0 failure, 1 success */ regtry(prog, string) regexp *prog; char *string; { register int i; register char **sp; register char **ep; reginput = string; regstartp = prog->startp; regendp = prog->endp; sp = prog->startp; ep = prog->endp; for (i = NSUBEXP; i > 0; i--) { *sp++ = NULL; *ep++ = NULL; } if (regmatch(prog->program + 1)) { prog->startp[0] = string; prog->endp[0] = reginput; return(1); } else return(0); } /* - regmatch - main matching routine * * Conceptually the strategy is simple: check to see whether the current * node matches, call self recursively to see whether the rest matches, * and then act accordingly. In practice we make some effort to avoid * recursion, in particular by going through "ordinary" nodes (that don't * need to know whether the rest of the match failed) by a loop instead of * by recursion. */ static int /* 0 failure, 1 success */ regmatch(prog) char *prog; { register char *scan; /* Current node. */ char *next; /* Next node. */ extern char *strchr(); scan = prog; #ifdef DEBUG if (scan != NULL && regnarrate) fprintf(stderr, "%s(\n", regprop(scan)); #endif while (scan != NULL) { #ifdef DEBUG if (regnarrate) fprintf(stderr, "%s...\n", regprop(scan)); #endif next = regnext(scan); switch (OP(scan)) { case BOL: if (reginput != regbol) return(0); break; case EOL: if (*reginput != '\0') return(0); break; case ANY: if (*reginput == '\0') return(0); reginput++; break; case EXACTLY: { register int len; register char *opnd; opnd = OPERAND(scan); /* Inline the first character, for speed. */ if (*opnd != *reginput) return(0); len = strlen(opnd); if (len > 1 && strncmp(opnd, reginput, len) != 0) return(0); reginput += len; } break; case ANYOF: if (*reginput == '\0' || strchr(OPERAND(scan), *reginput) == NULL) return(0); reginput++; break; case ANYBUT: if (*reginput == '\0' || strchr(OPERAND(scan), *reginput) != NULL) return(0); reginput++; break; case NOTHING: break; case BACK: break; case OPEN+1: case OPEN+2: case OPEN+3: case OPEN+4: case OPEN+5: case OPEN+6: case OPEN+7: case OPEN+8: case OPEN+9: { register int no; register char *save; no = OP(scan) - OPEN; save = reginput; if (regmatch(next)) { /* * Don't set startp if some later * invocation of the same parentheses * already has. */ if (regstartp[no] == NULL) regstartp[no] = save; return(1); } else return(0); } break; case CLOSE+1: case CLOSE+2: case CLOSE+3: case CLOSE+4: case CLOSE+5: case CLOSE+6: case CLOSE+7: case CLOSE+8: case CLOSE+9: { register int no; register char *save; no = OP(scan) - CLOSE; save = reginput; if (regmatch(next)) { /* * Don't set endp if some later * invocation of the same parentheses * already has. */ if (regendp[no] == NULL) regendp[no] = save; return(1); } else return(0); } break; case BRANCH: { register char *save; if (OP(next) != BRANCH) /* No choice. */ next = OPERAND(scan); /* Avoid recursion. */ else { do { save = reginput; if (regmatch(OPERAND(scan))) return(1); reginput = save; scan = regnext(scan); } while (scan != NULL && OP(scan) == BRANCH); return(0); /* NOTREACHED */ } } break; case STAR: case PLUS: { register char nextch; register int no; register char *save; register int min; /* * Lookahead to avoid useless match attempts * when we know what character comes next. */ nextch = '\0'; if (OP(next) == EXACTLY) nextch = *OPERAND(next); min = (OP(scan) == STAR) ? 0 : 1; save = reginput; no = regrepeat(OPERAND(scan)); while (no >= min) { /* If it could work, try it. */ if (nextch == '\0' || *reginput == nextch) if (regmatch(next)) return(1); /* Couldn't or didn't -- back up. */ no--; reginput = save + no; } return(0); } break; case END: return(1); /* Success! */ break; default: regerror("memory corruption"); return(0); break; } scan = next; } /* * We get here only if there's trouble -- normally "case END" is * the terminating point. */ regerror("corrupted pointers"); return(0); } /* - regrepeat - repeatedly match something simple, report how many */ static int regrepeat(p) char *p; { register int count = 0; register char *scan; register char *opnd; scan = reginput; opnd = OPERAND(p); switch (OP(p)) { case ANY: count = strlen(scan); scan += count; break; case EXACTLY: while (*opnd == *scan) { count++; scan++; } break; case ANYOF: while (*scan != '\0' && strchr(opnd, *scan) != NULL) { count++; scan++; } break; case ANYBUT: while (*scan != '\0' && strchr(opnd, *scan) == NULL) { count++; scan++; } break; default: /* Oh dear. Called inappropriately. */ regerror("internal foulup"); count = 0; /* Best compromise. */ break; } reginput = scan; return(count); } /* - regnext - dig the "next" pointer out of a node */ static char * regnext(p) register char *p; { register int offset; if (p == ®dummy) return(NULL); offset = NEXT(p); if (offset == 0) return(NULL); if (OP(p) == BACK) return(p-offset); else return(p+offset); } #ifdef DEBUG STATIC char *regprop(); /* - regdump - dump a regexp onto stdout in vaguely comprehensible form */ void regdump(r) regexp *r; { register char *s; register char op = EXACTLY; /* Arbitrary non-END op. */ register char *next; extern char *strchr(); s = r->program + 1; while (op != END) { /* While that wasn't END last time... */ op = OP(s); printf("%2d%s", s-r->program, regprop(s)); /* Where, what. */ next = regnext(s); if (next == NULL) /* Next ptr. */ printf("(0)"); else printf("(%d)", (s-r->program)+(next-s)); s += 3; if (op == ANYOF || op == ANYBUT || op == EXACTLY) { /* Literal string, where present. */ while (*s != '\0') { putchar(*s); s++; } s++; } putchar('\n'); } /* Header fields of interest. */ if (r->regstart != '\0') printf("start `%c' ", r->regstart); if (r->reganch) printf("anchored "); if (r->regmust != NULL) printf("must have \"%s\"", r->regmust); printf("\n"); } /* - regprop - printable representation of opcode */ static char * regprop(op) char *op; { register char *p; static char buf[50]; (void) strcpy(buf, ":"); switch (OP(op)) { case BOL: p = "BOL"; break; case EOL: p = "EOL"; break; case ANY: p = "ANY"; break; case ANYOF: p = "ANYOF"; break; case ANYBUT: p = "ANYBUT"; break; case BRANCH: p = "BRANCH"; break; case EXACTLY: p = "EXACTLY"; break; case NOTHING: p = "NOTHING"; break; case BACK: p = "BACK"; break; case END: p = "END"; break; case OPEN+1: case OPEN+2: case OPEN+3: case OPEN+4: case OPEN+5: case OPEN+6: case OPEN+7: case OPEN+8: case OPEN+9: sprintf(buf+strlen(buf), "OPEN%d", OP(op)-OPEN); p = NULL; break; case CLOSE+1: case CLOSE+2: case CLOSE+3: case CLOSE+4: case CLOSE+5: case CLOSE+6: case CLOSE+7: case CLOSE+8: case CLOSE+9: sprintf(buf+strlen(buf), "CLOSE%d", OP(op)-CLOSE); p = NULL; break; case STAR: p = "STAR"; break; case PLUS: p = "PLUS"; break; default: regerror("corrupted opcode"); break; } if (p != NULL) (void) strcat(buf, p); return(buf); } #endif /* * The following is provided for those people who do not have strcspn() in * their C libraries. They should get off their butts and do something * about it; at least one public-domain implementation of those (highly * useful) string routines has been published on Usenet. */ #ifdef STRCSPN /* * strcspn - find length of initial segment of s1 consisting entirely * of characters not from s2 */ static int strcspn(s1, s2) char *s1; char *s2; { register char *scan1; register char *scan2; register int count; count = 0; for (scan1 = s1; *scan1 != '\0'; scan1++) { for (scan2 = s2; *scan2 != '\0';) /* ++ moved down. */ if (*scan1 == *scan2++) return(count); count++; } return(count); } #endif dev86-0.16.21/libc/regexp/regexp.h000066400000000000000000000010761231050321700164610ustar00rootroot00000000000000/* * Definitions etc. for regexp(3) routines. * * Caveat: this is V8 regexp(3) [actually, a reimplementation thereof], * not the System V one. */ #define NSUBEXP 10 typedef struct regexp { char *startp[NSUBEXP]; char *endp[NSUBEXP]; char regstart; /* Internal use only. */ char reganch; /* Internal use only. */ char *regmust; /* Internal use only. */ int regmlen; /* Internal use only. */ char program[1]; /* Unwarranted chumminess with compiler. */ } regexp; extern regexp *regcomp(); extern int regexec(); extern void regsub(); extern void regerror(); dev86-0.16.21/libc/regexp/regmagic.h000066400000000000000000000002311231050321700167350ustar00rootroot00000000000000/* * The first byte of the regexp internal "program" is actually this magic * number; the start node begins in the second byte. */ #define MAGIC 0234 dev86-0.16.21/libc/regexp/regsub.c000066400000000000000000000036551231050321700164560ustar00rootroot00000000000000/* * regsub * * Copyright (c) 1986 by University of Toronto. * Written by Henry Spencer. Not derived from licensed software. * * Permission is granted to anyone to use this software for any * purpose on any computer system, and to redistribute it freely, * subject to the following restrictions: * * 1. The author is not responsible for the consequences of use of * this software, no matter how awful, even if they arise * from defects in it. * * 2. The origin of this software must not be misrepresented, either * by explicit claim or by omission. * * 3. Altered versions must be plainly marked as such, and must not * be misrepresented as being the original software. */ #include #include #include "regmagic.h" #ifndef CHARBITS #define UCHARAT(p) ((int)*(unsigned char *)(p)) #else #define UCHARAT(p) ((int)*(p)&CHARBITS) #endif /* - regsub - perform substitutions after a regexp match */ void regsub(prog, source, dest) regexp *prog; char *source; char *dest; { register char *src; register char *dst; register char c; register int no; register int len; extern char *strncpy(); if (prog == NULL || source == NULL || dest == NULL) { regerror("NULL parm to regsub"); return; } if (UCHARAT(prog->program) != MAGIC) { regerror("damaged regexp fed to regsub"); return; } src = source; dst = dest; while ((c = *src++) != '\0') { if (c == '&') no = 0; else if (c == '\\' && '0' <= *src && *src <= '9') no = *src++ - '0'; else no = -1; if (no < 0) { /* Ordinary character. */ if (c == '\\' && (*src == '\\' || *src == '&')) c = *src++; *dst++ = c; } else if (prog->startp[no] != NULL && prog->endp[no] != NULL) { len = prog->endp[no] - prog->startp[no]; (void) strncpy(dst, prog->startp[no], len); dst += len; if (len != 0 && *(dst-1) == '\0') { /* strncpy hit NUL. */ regerror("damaged match string"); return; } } } *dst++ = '\0'; } dev86-0.16.21/libc/regexp/tests000066400000000000000000000053521231050321700161040ustar00rootroot00000000000000abc abc y & abc abc xbc n - - abc axc n - - abc abx n - - abc xabcy y & abc abc ababc y & abc ab*c abc y & abc ab*bc abc y & abc ab*bc abbc y & abbc ab*bc abbbbc y & abbbbc ab+bc abbc y & abbc ab+bc abc n - - ab+bc abq n - - ab+bc abbbbc y & abbbbc ab?bc abbc y & abbc ab?bc abc y & abc ab?bc abbbbc n - - ab?c abc y & abc ^abc$ abc y & abc ^abc$ abcc n - - ^abc abcc y & abc ^abc$ aabc n - - abc$ aabc y & abc ^ abc y & $ abc y & a.c abc y & abc a.c axc y & axc a.*c axyzc y & axyzc a.*c axyzd n - - a[bc]d abc n - - a[bc]d abd y & abd a[b-d]e abd n - - a[b-d]e ace y & ace a[b-d] aac y & ac a[-b] a- y & a- a[b-] a- y & a- a[b-a] - c - - a[]b - c - - a[ - c - - a] a] y & a] a[]]b a]b y & a]b a[^bc]d aed y & aed a[^bc]d abd n - - a[^-b]c adc y & adc a[^-b]c a-c n - - a[^]b]c a]c n - - a[^]b]c adc y & adc ab|cd abc y & ab ab|cd abcd y & ab ()ef def y &-\1 ef- ()* - c - - *a - c - - ^* - c - - $* - c - - (*)b - c - - $b b n - - a\ - c - - a\(b a(b y &-\1 a(b- a\(*b ab y & ab a\(*b a((b y & a((b a\\b a\b y & a\b abc) - c - - (abc - c - - ((a)) abc y &-\1-\2 a-a-a (a)b(c) abc y &-\1-\2 abc-a-c a+b+c aabbabc y & abc a** - c - - a*? - c - - (a*)* - c - - (a*)+ - c - - (a|)* - c - - (a*|b)* - c - - (a+|b)* ab y &-\1 ab-b (a+|b)+ ab y &-\1 ab-b (a+|b)? ab y &-\1 a-a [^ab]* cde y & cde (^)* - c - - (ab|)* - c - - )( - c - - abc y & abc n - - a* y & ([abc])*d abbbcd y &-\1 abbbcd-c ([abc])*bcd abcd y &-\1 abcd-a a|b|c|d|e e y & e (a|b|c|d|e)f ef y &-\1 ef-e ((a*|b))* - c - - abcd*efg abcdefg y & abcdefg ab* xabyabbbz y & ab ab* xayabbbz y & a (ab|cd)e abcde y &-\1 cde-cd [abhgefdc]ij hij y & hij ^(ab|cd)e abcde n x\1y xy (abc|)ef abcdef y &-\1 ef- (a|b)c*d abcd y &-\1 bcd-b (ab|ab*)bc abc y &-\1 abc-a a([bc]*)c* abc y &-\1 abc-bc a([bc]*)(c*d) abcd y &-\1-\2 abcd-bc-d a([bc]+)(c*d) abcd y &-\1-\2 abcd-bc-d a([bc]*)(c+d) abcd y &-\1-\2 abcd-b-cd a[bcd]*dcdcde adcdcde y & adcdcde a[bcd]+dcdcde adcdcde n - - (ab|a)b*c abc y &-\1 abc-ab ((a)(b)c)(d) abcd y \1-\2-\3-\4 abc-a-b-d [a-zA-Z_][a-zA-Z0-9_]* alpha y & alpha ^a(bc+|b[eh])g|.h$ abh y &-\1 bh- (bc+d$|ef*g.|h?i(j|k)) effgz y &-\1-\2 effgz-effgz- (bc+d$|ef*g.|h?i(j|k)) ij y &-\1-\2 ij-ij-j (bc+d$|ef*g.|h?i(j|k)) effg n - - (bc+d$|ef*g.|h?i(j|k)) bcdd n - - (bc+d$|ef*g.|h?i(j|k)) reffgz y &-\1-\2 effgz-effgz- ((((((((((a)))))))))) - c - - (((((((((a))))))))) a y & a multiple words of text uh-uh n - - multiple words multiple words, yeah y & multiple words (.*)c(.*) abcde y &-\1-\2 abcde-ab-de \((.*), (.*)\) (a, b) y (\2, \1) (b, a) [k] ab n - - abcd abcd y &-\&-\\& abcd-&-\abcd a(bc)d abcd y \1-\\1-\\\1 bc-\1-\bc [ -~]* abc y & abc [ -~ -~]* abc y & abc [ -~ -~ -~]* abc y & abc [ -~ -~ -~ -~]* abc y & abc [ -~ -~ -~ -~ -~]* abc y & abc [ -~ -~ -~ -~ -~ -~]* abc y & abc [ -~ -~ -~ -~ -~ -~ -~]* abc y & abc dev86-0.16.21/libc/regexp/timer.c000066400000000000000000000072131231050321700163010ustar00rootroot00000000000000/* * Simple timing program for regcomp(). * * Copyright (c) 1986 by University of Toronto. * Written by Henry Spencer. Not derived from licensed software. * * Permission is granted to anyone to use this software for any * purpose on any computer system, and to redistribute it freely, * subject to the following restrictions: * * 1. The author is not responsible for the consequences of use of * this software, no matter how awful, even if they arise * from defects in it. * * 2. The origin of this software must not be misrepresented, either * by explicit claim or by omission. * * 3. Altered versions must be plainly marked as such, and must not * be misrepresented as being the original software. * * Usage: timer ncomp nexec nsub * or * timer ncomp nexec nsub regexp string [ answer [ sub ] ] * * The second form is for timing repetitions of a single test case. * The first form's test data is a compiled-in copy of the "tests" file. * Ncomp, nexec, nsub are how many times to do each regcomp, regexec, * and regsub. The way to time an operation individually is to do something * like "timer 1 50 1". */ #include struct try { char *re, *str, *ans, *src, *dst; } tests[] = { #include "timer.t.h" { NULL, NULL, NULL, NULL, NULL } }; #include int errreport = 0; /* Report errors via errseen? */ char *errseen = NULL; /* Error message. */ char *progname; /* ARGSUSED */ main(argc, argv) int argc; char *argv[]; { int ncomp, nexec, nsub; struct try one; char dummy[512]; if (argc < 4) { ncomp = 1; nexec = 1; nsub = 1; } else { ncomp = atoi(argv[1]); nexec = atoi(argv[2]); nsub = atoi(argv[3]); } progname = argv[0]; if (argc > 5) { one.re = argv[4]; one.str = argv[5]; if (argc > 6) one.ans = argv[6]; else one.ans = "y"; if (argc > 7) { one.src = argv[7]; one.dst = "xxx"; } else { one.src = "x"; one.dst = "x"; } errreport = 1; try(one, ncomp, nexec, nsub); } else multiple(ncomp, nexec, nsub); exit(0); } void regerror(s) char *s; { if (errreport) errseen = s; else error(s, ""); } #ifndef ERRAVAIL error(s1, s2) char *s1; char *s2; { fprintf(stderr, "regexp: "); fprintf(stderr, s1, s2); fprintf(stderr, "\n"); exit(1); } #endif int lineno = 0; multiple(ncomp, nexec, nsub) int ncomp, nexec, nsub; { register int i; extern char *strchr(); errreport = 1; for (i = 0; tests[i].re != NULL; i++) { lineno++; try(tests[i], ncomp, nexec, nsub); } } try(fields, ncomp, nexec, nsub) struct try fields; int ncomp, nexec, nsub; { regexp *r; char dbuf[BUFSIZ]; register int i; errseen = NULL; r = regcomp(fields.re); if (r == NULL) { if (*fields.ans != 'c') complain("regcomp failure in `%s'", fields.re); return; } if (*fields.ans == 'c') { complain("unexpected regcomp success in `%s'", fields.re); free((char *)r); return; } for (i = ncomp-1; i > 0; i--) { free((char *)r); r = regcomp(fields.re); } if (!regexec(r, fields.str)) { if (*fields.ans != 'n') complain("regexec failure in `%s'", ""); free((char *)r); return; } if (*fields.ans == 'n') { complain("unexpected regexec success", ""); free((char *)r); return; } for (i = nexec-1; i > 0; i--) (void) regexec(r, fields.str); errseen = NULL; for (i = nsub; i > 0; i--) regsub(r, fields.src, dbuf); if (errseen != NULL) { complain("regsub complaint", ""); free((char *)r); return; } if (strcmp(dbuf, fields.dst) != 0) complain("regsub result `%s' wrong", dbuf); free((char *)r); } complain(s1, s2) char *s1; char *s2; { fprintf(stderr, "try: %d: ", lineno); fprintf(stderr, s1, s2); fprintf(stderr, " (%s)\n", (errseen != NULL) ? errseen : ""); } dev86-0.16.21/libc/regexp/try.c000066400000000000000000000123551231050321700160020ustar00rootroot00000000000000/* * Simple test program for regexp(3) stuff. Knows about debugging hooks. * * Copyright (c) 1986 by University of Toronto. * Written by Henry Spencer. Not derived from licensed software. * * Permission is granted to anyone to use this software for any * purpose on any computer system, and to redistribute it freely, * subject to the following restrictions: * * 1. The author is not responsible for the consequences of use of * this software, no matter how awful, even if they arise * from defects in it. * * 2. The origin of this software must not be misrepresented, either * by explicit claim or by omission. * * 3. Altered versions must be plainly marked as such, and must not * be misrepresented as being the original software. * * Usage: try re [string [output [-]]] * The re is compiled and dumped, regexeced against the string, the result * is applied to output using regsub(). The - triggers a running narrative * from regexec(). Dumping and narrative don't happen unless DEBUG. * * If there are no arguments, stdin is assumed to be a stream of lines with * five fields: a r.e., a string to match it against, a result code, a * source string for regsub, and the proper result. Result codes are 'c' * for compile failure, 'y' for match success, 'n' for match failure. * Field separator is tab. */ #include #include #ifdef ERRAVAIL char *progname; extern char *mkprogname(); #endif #ifdef DEBUG extern int regnarrate; #endif char buf[BUFSIZ]; int errreport = 0; /* Report errors via errseen? */ char *errseen = NULL; /* Error message. */ int status = 0; /* Exit status. */ /* ARGSUSED */ main(argc, argv) int argc; char *argv[]; { regexp *r; int i; #ifdef ERRAVAIL progname = mkprogname(argv[0]); #endif if (argc == 1) { multiple(); exit(status); } r = regcomp(argv[1]); if (r == NULL) error("regcomp failure", ""); #ifdef DEBUG regdump(r); if (argc > 4) regnarrate++; #endif if (argc > 2) { i = regexec(r, argv[2]); printf("%d", i); for (i = 1; i < NSUBEXP; i++) if (r->startp[i] != NULL && r->endp[i] != NULL) printf(" \\%d", i); printf("\n"); } if (argc > 3) { regsub(r, argv[3], buf); printf("%s\n", buf); } exit(status); } void regerror(s) char *s; { if (errreport) errseen = s; else error(s, ""); } #ifndef ERRAVAIL error(s1, s2) char *s1; char *s2; { fprintf(stderr, "regexp: "); fprintf(stderr, s1, s2); fprintf(stderr, "\n"); exit(1); } #endif int lineno; regexp badregexp; /* Implicit init to 0. */ multiple() { char rbuf[BUFSIZ]; char *field[5]; char *scan; int i; regexp *r; extern char *strchr(); errreport = 1; lineno = 0; while (fgets(rbuf, sizeof(rbuf), stdin) != NULL) { rbuf[strlen(rbuf)-1] = '\0'; /* Dispense with \n. */ lineno++; scan = rbuf; for (i = 0; i < 5; i++) { field[i] = scan; if (field[i] == NULL) { complain("bad testfile format", ""); exit(1); } scan = strchr(scan, '\t'); if (scan != NULL) *scan++ = '\0'; } try(field); } /* And finish up with some internal testing... */ lineno = 9990; errseen = NULL; if (regcomp((char *)NULL) != NULL || errseen == NULL) complain("regcomp(NULL) doesn't complain", ""); lineno = 9991; errseen = NULL; if (regexec((regexp *)NULL, "foo") || errseen == NULL) complain("regexec(NULL, ...) doesn't complain", ""); lineno = 9992; r = regcomp("foo"); if (r == NULL) { complain("regcomp(\"foo\") fails", ""); return; } lineno = 9993; errseen = NULL; if (regexec(r, (char *)NULL) || errseen == NULL) complain("regexec(..., NULL) doesn't complain", ""); lineno = 9994; errseen = NULL; regsub((regexp *)NULL, "foo", rbuf); if (errseen == NULL) complain("regsub(NULL, ..., ...) doesn't complain", ""); lineno = 9995; errseen = NULL; regsub(r, (char *)NULL, rbuf); if (errseen == NULL) complain("regsub(..., NULL, ...) doesn't complain", ""); lineno = 9996; errseen = NULL; regsub(r, "foo", (char *)NULL); if (errseen == NULL) complain("regsub(..., ..., NULL) doesn't complain", ""); lineno = 9997; errseen = NULL; if (regexec(&badregexp, "foo") || errseen == NULL) complain("regexec(nonsense, ...) doesn't complain", ""); lineno = 9998; errseen = NULL; regsub(&badregexp, "foo", rbuf); if (errseen == NULL) complain("regsub(nonsense, ..., ...) doesn't complain", ""); } try(fields) char **fields; { regexp *r; char dbuf[BUFSIZ]; errseen = NULL; r = regcomp(fields[0]); if (r == NULL) { if (*fields[2] != 'c') complain("regcomp failure in `%s'", fields[0]); return; } if (*fields[2] == 'c') { complain("unexpected regcomp success in `%s'", fields[0]); free((char *)r); return; } if (!regexec(r, fields[1])) { if (*fields[2] != 'n') complain("regexec failure in `%s'", ""); free((char *)r); return; } if (*fields[2] == 'n') { complain("unexpected regexec success", ""); free((char *)r); return; } errseen = NULL; regsub(r, fields[3], dbuf); if (errseen != NULL) { complain("regsub complaint", ""); free((char *)r); return; } if (strcmp(dbuf, fields[4]) != 0) complain("regsub result `%s' wrong", dbuf); free((char *)r); } complain(s1, s2) char *s1; char *s2; { fprintf(stderr, "try: %d: ", lineno); fprintf(stderr, s1, s2); fprintf(stderr, " (%s)\n", (errseen != NULL) ? errseen : ""); status = 1; } dev86-0.16.21/libc/stdio/000077500000000000000000000000001231050321700146425ustar00rootroot00000000000000dev86-0.16.21/libc/stdio/Config000066400000000000000000000000321231050321700157650ustar00rootroot00000000000000# stdio: Stdio package dev86-0.16.21/libc/stdio/Makefile000066400000000000000000000022271231050321700163050ustar00rootroot00000000000000# Copyright (C) 1995,1996 Robert de Bath # This file is part of the Linux-8086 C library and is distributed # under the GNU Library General Public License. ifneq ($(LIB_CPU),i86) CFLAGS=$(CCFLAGS) $(LIBDEFS) -DFLOATS endif ASRC=stdio.c AOBJ=_stdio_init.o fputc.o fgetc.o fflush.o fgets.o gets.o fputs.o \ puts.o fread.o fwrite.o fopen.o fdopen.o freopen.o __fopen.o \ fclose.o fseek.o rewind.o ftell.o setbuffer.o setvbuf.o ungetc.o PSRC=printf.c POBJ=printf.o sprintf.o fprintf.o vprintf.o vsprintf.o vfprintf.o fp_print.o SSRC=scanf.c SOBJ=scanf.o sscanf.o fscanf.o vscanf.o vsscanf.o vfscanf.o OBJ= $(AOBJ) $(POBJ) $(SOBJ) CFLAGS=$(ARCH) $(CCFLAGS) $(DEFS) all: $(LIBC) @$(RM) $(OBJ) $(LIBC): $(LIBC)($(OBJ)) $(LIBC)($(AOBJ)): $(ASRC) $(CC) $(CFLAGS) -DL_$* $< -c -o $*.o $(AR) $(ARFLAGS) $@ $*.o $(LIBC)($(POBJ)): $(PSRC) $(CC) $(CFLAGS) -DL_$* $< -c -o $*.o $(AR) $(ARFLAGS) $@ $*.o $(LIBC)($(SOBJ)): $(SSRC) $(CC) $(CFLAGS) -DL_$* $< -c -o $*.o $(AR) $(ARFLAGS) $@ $*.o transfer: -@rm -f ../include/stdio.h cp -p stdio.h ../include/. clean: rm -f *.o libc.a ../include/stdio.h $(LIBC)($(OBJ)): stdio.h dev86-0.16.21/libc/stdio/printf.c000066400000000000000000000212671231050321700163200ustar00rootroot00000000000000/* * This file based on printf.c from 'Dlibs' on the atari ST (RdeBath) * * 19-OCT-88: Dale Schumacher * > John Stanley has again been a great help in debugging, particularly * > with the printf/scanf functions which are his creation. * * Dale Schumacher 399 Beacon Ave. * (alias: Dalnefre') St. Paul, MN 55104 * dal@syntel.UUCP United States of America * "It's not reality that's important, but how you perceive things." * */ /* Altered to use stdarg, made the core function vfprintf. * Hooked into the stdio package using 'inside information' * Altered sizeof() assumptions, now assumes all integers except chars * will be either * sizeof(xxx) == sizeof(long) or sizeof(xxx) == sizeof(short) * * -RDB */ #include #include #if defined(__STDC__) && !defined(__FIRST_ARG_IN_AX__) #include #define va_strt va_start #else #include #define va_strt(p,i) va_start(p) #endif #include "stdio.h" #ifdef L_printf #if defined(__STDC__) && !defined(__FIRST_ARG_IN_AX__) int printf(const char * fmt, ...) #else int printf(fmt, va_alist) __const char *fmt; va_dcl #endif { va_list ptr; int rv; va_strt(ptr, fmt); rv = vfprintf(stdout,fmt,ptr); va_end(ptr); return rv; } #endif #ifdef L_sprintf #if defined(__STDC__) && !defined(__FIRST_ARG_IN_AX__) int sprintf(char * sp, const char * fmt, ...) #else int sprintf(sp, fmt, va_alist) char * sp; __const char *fmt; va_dcl #endif { static FILE string[1] = { {0, 0, (char*)(unsigned) -1, 0, (char*) (unsigned) -1, -1, _IOFBF | __MODE_WRITE} }; va_list ptr; int rv; va_strt(ptr, fmt); string->bufpos = sp; rv = vfprintf(string,fmt,ptr); va_end(ptr); *(string->bufpos) = 0; return rv; } #endif #ifdef L_fprintf #if defined(__STDC__) && !defined(__FIRST_ARG_IN_AX__) int fprintf(FILE * fp, const char * fmt, ...) #else int fprintf(fp, fmt, va_alist) FILE * fp; __const char *fmt; va_dcl #endif { va_list ptr; int rv; va_strt(ptr, fmt); rv = vfprintf(fp,fmt,ptr); va_end(ptr); return rv; } #endif #ifdef L_vprintf int vprintf(fmt, ap) __const char *fmt; va_list ap; { return vfprintf(stdout,fmt,ap); } #endif #ifdef L_vsprintf int vsprintf(sp, fmt, ap) char * sp; __const char *fmt; va_list ap; { static FILE string[1] = { {0, 0, (char*)(unsigned) -1, 0, (char*) (unsigned) -1, -1, _IOFBF | __MODE_WRITE} }; int rv; string->bufpos = sp; rv = vfprintf(string,fmt,ap); *(string->bufpos) = 0; return rv; } #endif #ifdef L_vfprintf #ifndef __HAS_NO_FLOATS__ int (*__fp_print)() = 0; #endif static int prtfld(op, buf, ljustf, sign, pad, width, preci, buffer_mode) register FILE *op; register unsigned char *buf; int ljustf; register char sign; char pad; register int width; int preci; int buffer_mode; /* * Output the given field in the manner specified by the arguments. Return * the number of characters output. */ { register int cnt = 0, len; register unsigned char ch; len = strlen(buf); if (*buf == '-') sign = *buf++; else if (sign) len++; if ((preci != -1) && (len > preci)) /* limit max data width */ len = preci; if (width < len) /* flexible field width or width overflow */ width = len; /* * at this point: width = total field width len = actual data width * (including possible sign character) */ cnt = width; width -= len; while (width || len) { if (!ljustf && width) /* left padding */ { if (len && sign && (pad == '0')) goto showsign; ch = pad; --width; } else if (len) { if (sign) { showsign:ch = sign; /* sign */ sign = '\0'; } else ch = *buf++; /* main field */ --len; } else { ch = pad; /* right padding */ --width; } putc(ch, op); if( ch == '\n' && buffer_mode == _IOLBF ) fflush(op); } return (cnt); } int vfprintf(op, fmt, ap) FILE *op; register __const char *fmt; register va_list ap; { register int i, cnt = 0, ljustf, lval; int preci, dpoint, width; char pad, sign, radix, hash; register char *ptmp; char tmp[64], *ltostr(), *ultostr(); int buffer_mode; /* This speeds things up a bit for unbuffered */ buffer_mode = (op->mode&__MODE_BUF); op->mode &= (~__MODE_BUF); while (*fmt) { if (*fmt == '%') { if( buffer_mode == _IONBF ) fflush(op); ljustf = 0; /* left justify flag */ sign = '\0'; /* sign char & status */ pad = ' '; /* justification padding char */ width = -1; /* min field width */ dpoint = 0; /* found decimal point */ preci = -1; /* max data width */ radix = 10; /* number base */ ptmp = tmp; /* pointer to area to print */ hash = 0; lval = (sizeof(int)==sizeof(long)); /* long value flaged */ fmtnxt: i = 0; for(;;) { ++fmt; if(*fmt < '0' || *fmt > '9' ) break; i = (i * 10) + (*fmt - '0'); if (dpoint) preci = i; else if (!i && (pad == ' ')) { pad = '0'; goto fmtnxt; } else width = i; } switch (*fmt) { case '\0': /* early EOS */ --fmt; goto charout; case '-': /* left justification */ ljustf = 1; goto fmtnxt; case ' ': case '+': /* leading sign flag */ sign = *fmt; goto fmtnxt; case '*': /* parameter width value */ i = va_arg(ap, int); if (dpoint) preci = i; else width = i; goto fmtnxt; case '.': /* secondary width field */ dpoint = 1; goto fmtnxt; case 'l': /* long data */ lval = 1; goto fmtnxt; case 'h': /* short data */ lval = 0; goto fmtnxt; case 'd': /* Signed decimal */ case 'i': ptmp = ltostr((long) ((lval) ? va_arg(ap, long) : va_arg(ap, short)), 10); goto printit; case 'b': /* Unsigned binary */ radix = 2; goto usproc; case 'o': /* Unsigned octal */ radix = 8; goto usproc; case 'p': /* Pointer */ lval = (sizeof(char*) == sizeof(long)); pad = '0'; width = 6; preci = 8; /* fall thru */ case 'x': /* Unsigned hexadecimal */ case 'X': radix = 16; /* fall thru */ case 'u': /* Unsigned decimal */ usproc: ptmp = ultostr((unsigned long) ((lval) ? va_arg(ap, unsigned long) : va_arg(ap, unsigned short)), radix); if( hash && radix == 8 ) { width = strlen(ptmp)+1; pad='0'; } goto printit; case '#': hash=1; goto fmtnxt; case 'c': /* Character */ ptmp[0] = va_arg(ap, int); ptmp[1] = '\0'; goto nopad; case 's': /* String */ ptmp = va_arg(ap, char*); nopad: sign = '\0'; pad = ' '; printit: cnt += prtfld(op, ptmp, ljustf, sign, pad, width, preci, buffer_mode); break; #ifndef __HAS_NO_FLOATS__ case 'e': /* float */ case 'f': case 'g': case 'E': case 'G': if ( __fp_print ) { (*__fp_print)(&va_arg(ap, double), *fmt, preci, ptmp); preci = -1; goto printit; } /* FALLTHROUGH if no floating printf available */ #endif default: /* unknown character */ goto charout; } } else { charout: putc(*fmt, op); /* normal char out */ ++cnt; if( *fmt == '\n' && buffer_mode == _IOLBF ) fflush(op); } ++fmt; } op->mode |= buffer_mode; if( buffer_mode == _IONBF ) fflush(op); if( buffer_mode == _IOLBF ) op->bufwrite = op->bufstart; return (cnt); } #endif #ifdef L_fp_print #ifndef __HAS_NO_FLOATS__ #ifdef __AS386_16__ #asm loc 1 ! Make sure the pointer is in the correct segment auto_func: ! Label for bcc -M to work. .word ___xfpcvt ! Pointer to the autorun function .text ! So the function after is also in the correct seg. #endasm #endif #ifdef __AS386_32__ #asm loc 1 ! Make sure the pointer is in the correct segment auto_func: ! Label for bcc -M to work. .long ___xfpcvt ! Pointer to the autorun function .text ! So the function after is also in the correct seg. #endasm #endif void __fp_print_func(pval, style, preci, ptmp) double * pval; int style; int preci; char * ptmp; { int decpt, negative; char * cvt; double val = *pval; if (preci < 0) preci = 6; cvt = fcvt(val, preci, &decpt, &negative); if(negative) *ptmp++ = '-'; if (decpt<0) { *ptmp++ = '0'; *ptmp++ = '.'; while(decpt<0) { *ptmp++ = '0'; decpt++; } } while(*cvt) { *ptmp++ = *cvt++; if (decpt == 1) *ptmp++ = '.'; decpt--; } while(decpt > 0) { *ptmp++ = '0'; decpt--; } } void __xfpcvt() { extern int (*__fp_print)(); __fp_print = __fp_print_func; } #endif #endif dev86-0.16.21/libc/stdio/scanf.c000066400000000000000000000232021231050321700160770ustar00rootroot00000000000000/* * This file based on scanf.c from 'Dlibs' on the atari ST (RdeBath) * * 19-OCT-88: Dale Schumacher * > John Stanley has again been a great help in debugging, particularly * > with the printf/scanf functions which are his creation. * * Dale Schumacher 399 Beacon Ave. * (alias: Dalnefre') St. Paul, MN 55104 * dal@syntel.UUCP United States of America * "It's not reality that's important, but how you perceive things." * */ #include #include #include #if defined(__STDC__) && !defined(__FIRST_ARG_IN_AX__) #include #define va_strt va_start #else #include #define va_strt(p,i) va_start(p) #endif #ifdef L_scanf #if defined(__STDC__) && !defined(__FIRST_ARG_IN_AX__) int scanf(const char * fmt, ...) #else int scanf(fmt, va_alist) __const char *fmt; va_dcl #endif { va_list ptr; int rv; va_strt(ptr, fmt); rv = vfscanf(stdin,fmt,ptr); va_end(ptr); return rv; } #endif #ifdef L_sscanf #if defined(__STDC__) && !defined(__FIRST_ARG_IN_AX__) int sscanf(char * sp, const char * fmt, ...) #else int sscanf(sp, fmt, va_alist) char * sp; __const char *fmt; va_dcl #endif { static FILE string[1] = { {0, (char*)(unsigned) -1, 0, 0, (char*) (unsigned) -1, -1, _IOFBF | __MODE_READ} }; va_list ptr; int rv; va_strt(ptr, fmt); string->bufpos = sp; rv = vfscanf(string,fmt,ptr); va_end(ptr); return rv; } #endif #ifdef L_fscanf #if defined(__STDC__) && !defined(__FIRST_ARG_IN_AX__) int fscanf(FILE * fp, const char * fmt, ...) #else int fscanf(fp, fmt, va_alist) FILE * fp; __const char *fmt; va_dcl #endif { va_list ptr; int rv; va_strt(ptr, fmt); rv = vfscanf(fp,fmt,ptr); va_end(ptr); return rv; } #endif #ifdef L_vscanf int vscanf(fmt, ap) __const char *fmt; va_list ap; { return vfscanf(stdin,fmt,ap); } #endif #ifdef L_vsscanf int vsscanf(sp, fmt, ap) char * sp; __const char *fmt; { static FILE string[1] = { {0, (char*)(unsigned) -1, 0, 0, (char*) (unsigned) -1, -1, _IOFBF | __MODE_READ} }; string->bufpos = sp; return vfscanf(string,fmt,ap); } #endif #ifdef L_vfscanf /* #define skip() do{c=getc(fp); if (c<1) goto done;}while(isspace(c))*/ #define skip() while(isspace(c)) { if ((c=getc(fp))<1) goto done; } #if FLOATS /* fp scan actions */ #define F_NADA 0 /* just change state */ #define F_SIGN 1 /* set sign */ #define F_ESIGN 2 /* set exponent's sign */ #define F_INT 3 /* adjust integer part */ #define F_FRAC 4 /* adjust fraction part */ #define F_EXP 5 /* adjust exponent part */ #define F_QUIT 6 #define NSTATE 8 #define FS_INIT 0 /* initial state */ #define FS_SIGNED 1 /* saw sign */ #define FS_DIGS 2 /* saw digits, no . */ #define FS_DOT 3 /* saw ., no digits */ #define FS_DD 4 /* saw digits and . */ #define FS_E 5 /* saw 'e' */ #define FS_ESIGN 6 /* saw exp's sign */ #define FS_EDIGS 7 /* saw exp's digits */ #define FC_DIG 0 #define FC_DOT 1 #define FC_E 2 #define FC_SIGN 3 /* given transition,state do what action? */ int fp_do[][NSTATE] = { {F_INT,F_INT,F_INT, F_FRAC,F_FRAC, F_EXP,F_EXP,F_EXP}, /* see digit */ {F_NADA,F_NADA,F_NADA, F_QUIT,F_QUIT,F_QUIT,F_QUIT,F_QUIT}, /* see '.' */ {F_QUIT,F_QUIT, F_NADA,F_QUIT,F_NADA, F_QUIT,F_QUIT,F_QUIT}, /* see e/E */ {F_SIGN,F_QUIT,F_QUIT,F_QUIT,F_QUIT, F_ESIGN,F_QUIT,F_QUIT}, /* see sign */ }; /* given transition,state what is new state? */ int fp_ns[][NSTATE] = { {FS_DIGS,FS_DIGS,FS_DIGS, FS_DD,FS_DD, FS_EDIGS,FS_EDIGS,FS_EDIGS}, /* see digit */ {FS_DOT,FS_DOT,FS_DD, }, /* see '.' */ {0,0, FS_E,0,FS_E, }, /* see e/E */ {FS_SIGNED,0,0,0,0, FS_ESIGN,0,0}, /* see sign */ }; /* which states are valid terminators? */ int fp_sval[NSTATE] = { 0,0,1,0,1,0,0,1 }; #endif vfscanf(fp, fmt, ap) register FILE *fp; register char *fmt; va_list ap; { register long n; register int c, width, lval, cnt = 0; int store, neg, base, wide1, endnull, rngflag, c2; register unsigned char *p; unsigned char delim[128], digits[17], *q; #if FLOATS long frac, expo; int eneg, fraclen, fstate, trans; double fx, fp_scan(); #endif if (!*fmt) return (0); c = getc(fp); while (c > 0) { store = 0; if (*fmt == '%') { n = 0; width = -1; wide1 = 1; base = 10; lval = (sizeof(long) == sizeof(int)); store = 1; endnull = 1; neg = -1; strcpy(delim, "\011\012\013\014\015 "); strcpy(digits, "0123456789ABCDEF"); if (fmt[1] == '*') { endnull = store = 0; ++fmt; } while (isdigit(*++fmt))/* width digit(s) */ { if (width == -1) width = 0; wide1 = width = (width * 10) + (*fmt - '0'); } --fmt; fmtnxt: ++fmt; switch (tolower(*fmt)) /* tolower() is a MACRO! */ { case '*': endnull = store = 0; goto fmtnxt; case 'l': /* long data */ lval = 1; goto fmtnxt; case 'h': /* short data */ lval = 0; goto fmtnxt; case 'i': /* any-base numeric */ base = 0; goto numfmt; case 'b': /* unsigned binary */ base = 2; goto numfmt; case 'o': /* unsigned octal */ base = 8; goto numfmt; case 'x': /* unsigned hexadecimal */ base = 16; goto numfmt; case 'd': /* SIGNED decimal */ neg = 0; /* FALL-THRU */ case 'u': /* unsigned decimal */ numfmt:skip(); if (isupper(*fmt)) lval = 1; if (!base) { base = 10; neg = 0; if (c == '%') { base = 2; goto skip1; } else if (c == '0') { c = getc(fp); if (c < 1) goto savnum; if ((c != 'x') && (c != 'X')) { base = 8; digits[8] = '\0'; goto zeroin; } base = 16; goto skip1; } } if ((neg == 0) && (base == 10) && ((neg = (c == '-')) || (c == '+'))) { skip1: c = getc(fp); if (c < 1) goto done; } digits[base] = '\0'; p = ((unsigned char *) strchr(digits, toupper(c))); if ((!c || !p) && width) goto done; while (p && width-- && c) { n = (n * base) + (p - digits); c = getc(fp); zeroin: p = ((unsigned char *) strchr(digits, toupper(c))); } savnum: if (store) { if (neg == 1) n = -n; if (lval) *va_arg(ap, long*) = n; else *va_arg(ap, short*) = n; ++cnt; } break; #if FLOATS case 'e': /* float */ case 'f': case 'g': skip(); if (isupper(*fmt)) lval = 1; fstate = FS_INIT; neg = 0; eneg = 0; n = 0; frac = 0; expo = 0; fraclen = 0; while (c && width--) { if (c >= '0' && c <= '9') trans = FC_DIG; else if (c == '.') trans = FC_DOT; else if (c == '+' || c == '-') trans = FC_SIGN; else if (tolower(c) == 'e') trans = FC_E; else goto fdone; switch (fp_do[trans][fstate]) { case F_SIGN: neg = (c == '-'); break; case F_ESIGN: eneg = (c == '-'); break; case F_INT: n = 10 * n + (c - '0'); break; case F_FRAC: frac = 10 * frac + (c - '0'); fraclen++; break; case F_EXP: expo = 10 * expo + (c - '0'); break; case F_QUIT: goto fdone; } fstate = fp_ns[trans][fstate]; c = getc(fp); } fdone: if (!fp_sval[fstate]) goto done; if (store) { fx = fp_scan(neg, eneg, n, frac, expo, fraclen); if (lval) *va_arg(ap, double *) = fx; else *va_arg(ap, float *) = fx; ++cnt; } break; #endif case 'c': /* character data */ width = wide1; lval = endnull = 0; delim[0] = '\0'; goto strproc; case '[': /* string w/ delimiter set */ /* get delimiters */ p = delim; if (*++fmt == '^') { fmt++; lval = 0; } else lval = 1; rngflag = 2; if ((*fmt == ']') || (*fmt == '-')) { *p++ = *fmt++; rngflag = 0; } while (*fmt != ']') { if (*fmt == '\0') goto done; switch (rngflag) { case 1: c2 = *(p - 2); if (c2 <= *fmt) { p -= 2; while (c2 < *fmt) *p++ = c2++; rngflag = 2; break; } /* fall thru intentional */ case 0: rngflag = (*fmt == '-'); break; case 2: rngflag = 0; } *p++ = *fmt++; } *p = '\0'; goto strproc; case 's': /* string data */ lval = 0; skip(); strproc: /* process string */ p = va_arg(ap, unsigned char *); /* if the 1st char fails, match fails */ if (width) { q = ((unsigned char *) strchr(delim, c)); if ((c < 1) || lval == (q==0)) { if (endnull) *p = '\0'; goto done; } } for (;;) /* FOREVER */ { if (store) *p++ = c; if (((c = getc(fp)) < 1) || (--width == 0)) break; q = ((unsigned char *) strchr(delim, c)); if (lval == (q==0)) break; } if (store) { if (endnull) *p = '\0'; ++cnt; } break; case '\0': /* early EOS */ --fmt; /* FALL THRU */ default: goto cmatch; } } else if (isspace(*fmt)) /* skip whitespace */ { skip(); } else { /* normal match char */ cmatch: if (c != *fmt) break; c = getc(fp); } if (!*++fmt) break; } done: /* end of scan */ if ((c == EOF) && (cnt == 0)) return (EOF); if( c != EOF ) ungetc(c, fp); return (cnt); } #endif dev86-0.16.21/libc/stdio/stdio.c000066400000000000000000000425251231050321700161400ustar00rootroot00000000000000/* Copyright (C) 1996 Robert de Bath * This file is part of the Linux-8086 C library and is distributed * under the GNU Library General Public License. */ /* This is an implementation of the C standard IO package. */ #include #include #include #include #include #ifndef O_BINARY #define O_BINARY 0 #endif extern FILE *__IO_list; /* For fflush at exit */ #ifdef __AS386_16__ #define Inline_init #endif #ifdef __AS386_32__ #define Inline_init #endif #ifndef Inline_init #define Inline_init __io_init_vars() #endif #ifdef L__stdio_init #define buferr (stderr->unbuf) /* Stderr is unbuffered */ FILE *__IO_list = 0; /* For fflush at exit */ static char bufin[BUFSIZ]; static char bufout[BUFSIZ]; #ifndef buferr static char buferr[BUFSIZ]; #endif FILE stdin[1] = { {bufin, bufin, bufin, bufin, bufin + sizeof(bufin), 0, _IOFBF | __MODE_READ | __MODE_IOTRAN} }; FILE stdout[1] = { {bufout, bufout, bufout, bufout, bufout + sizeof(bufout), 1, _IOFBF | __MODE_WRITE | __MODE_IOTRAN} }; FILE stderr[1] = { {buferr, buferr, buferr, buferr, buferr + sizeof(buferr), 2, _IONBF | __MODE_WRITE | __MODE_IOTRAN} }; /* Call the stdio initiliser; it's main job it to call atexit */ #ifdef __AS386_16__ #define STATIC static #asm loc 1 ! Make sure the pointer is in the correct segment auto_func: ! Label for bcc -M to work. .word ___io_init_vars ! Pointer to the autorun function .text ! So the function after is also in the correct seg. #endasm #endif #ifdef __AS386_32__ #define STATIC static #asm loc 1 ! Make sure the pointer is in the correct segment auto_func: ! Label for bcc -M to work. .long ___io_init_vars ! Pointer to the autorun function .text ! So the function after is also in the correct seg. #endasm #endif #ifndef STATIC #define STATIC #endif STATIC int __stdio_close_all() { FILE *fp; fflush(stdout); fflush(stderr); for (fp = __IO_list; fp; fp = fp->next) { fflush(fp); close(fp->fd); /* Note we're not de-allocating the memory */ /* There doesn't seem to be much point :-) */ fp->fd = -1; } } STATIC void __io_init_vars() { #ifndef __AS386_16__ #ifndef __AS386_32__ static int first_time = 1; if( !first_time ) return ; first_time = 0; #endif #endif if (isatty(1)) stdout->mode |= _IOLBF; atexit(__stdio_close_all); } #endif #ifdef L_fputc int fputc(ch, fp) int ch; FILE *fp; { register int v; Inline_init; /* If last op was a read ... note fflush may change fp->mode and ret OK */ if ((fp->mode & __MODE_READING) && fflush(fp)) return EOF; v = fp->mode; /* Can't write if there's been an EOF or error then return EOF */ if ((v & (__MODE_WRITE | __MODE_EOF | __MODE_ERR)) != __MODE_WRITE) return EOF; /* In MSDOS translation mode */ #if __MODE_IOTRAN && !O_BINARY if (ch == '\n' && (v & __MODE_IOTRAN) && fputc('\r', fp) == EOF) return EOF; #endif /* Buffer is full */ if (fp->bufpos >= fp->bufend && fflush(fp)) return EOF; /* Right! Do it! */ *(fp->bufpos++) = ch; fp->mode |= __MODE_WRITING; /* Unbuffered or Line buffered and end of line */ if (((ch == '\n' && (v & _IOLBF)) || (v & _IONBF)) && fflush(fp)) return EOF; /* Can the macro handle this by itself ? */ if (v & (__MODE_IOTRAN | _IOLBF | _IONBF)) fp->bufwrite = fp->bufstart; /* Nope */ else fp->bufwrite = fp->bufend; /* Yup */ /* Correct return val */ return (unsigned char) ch; } #endif #ifdef L_fgetc int fgetc(fp) FILE *fp; { int ch; if (fp->mode & __MODE_WRITING) fflush(fp); try_again: /* Can't read or there's been an EOF or error then return EOF */ if ((fp->mode & (__MODE_READ | __MODE_EOF | __MODE_ERR)) != __MODE_READ) return EOF; /* Nothing in the buffer - fill it up */ if (fp->bufpos >= fp->bufread) { /* Bind stdin to stdout if it's open and line buffered */ if( fp == stdin && stdout->fd >= 0 && (stdout->mode & _IOLBF )) fflush(stdout); fp->bufpos = fp->bufread = fp->bufstart; ch = fread(fp->bufpos, 1, fp->bufend - fp->bufstart, fp); if (ch == 0) return EOF; fp->bufread += ch; fp->mode |= __MODE_READING; fp->mode &= ~__MODE_UNGOT; } ch = *(fp->bufpos++); #if __MODE_IOTRAN && !O_BINARY /* In MSDOS translation mode; WARN: Doesn't work with UNIX macro */ if (ch == '\r' && (fp->mode & __MODE_IOTRAN)) goto try_again; #endif return ch; } #endif #ifdef L_fflush int fflush(fp) FILE *fp; { int len, cc, rv=0; char * bstart; if (fp == NULL) /* On NULL flush the lot. */ { if (fflush(stdin)) return EOF; if (fflush(stdout)) return EOF; if (fflush(stderr)) return EOF; for (fp = __IO_list; fp; fp = fp->next) if (fflush(fp)) return EOF; return 0; } /* If there's output data pending */ if (fp->mode & __MODE_WRITING) { len = fp->bufpos - fp->bufstart; if (len) { bstart = fp->bufstart; /* * The loop is so we don't get upset by signals or partial writes. */ do { cc = write(fp->fd, bstart, len); if( cc > 0 ) { bstart+=cc; len-=cc; } } while ( len>0 && (cc>0 || (cc == -1 && errno == EINTR))); /* * If we get here with len!=0 there was an error, exactly what to * do about it is another matter ... * * I'll just clear the buffer. */ if (len) { fp->mode |= __MODE_ERR; rv = EOF; } } } /* If there's data in the buffer sychronise the file positions */ else if (fp->mode & __MODE_READING) { /* Humm, I think this means sync the file like fpurge() ... */ /* Anyway the user isn't supposed to call this function when reading */ len = fp->bufread - fp->bufpos; /* Bytes buffered but unread */ /* If it's a file, make it good */ if (len > 0 && lseek(fp->fd, (long)-len, 1) < 0) { /* Hummm - Not certain here, I don't think this is reported */ /* * fp->mode |= __MODE_ERR; return EOF; */ } } /* All done, no problem */ fp->mode &= (~(__MODE_READING|__MODE_WRITING|__MODE_EOF|__MODE_UNGOT)); fp->bufread = fp->bufwrite = fp->bufpos = fp->bufstart; return rv; } #endif #ifdef L_fgets /* Nothing special here ... */ char * fgets(s, count, f) char *s; size_t count; FILE *f; { char *ret; register size_t i; register int ch; ret = s; for (i = count-1; i > 0; i--) { ch = getc(f); if (ch == EOF) { if (s == ret) return 0; break; } *s++ = (char) ch; if (ch == '\n') break; } *s = 0; if (ferror(f)) return 0; return ret; } #endif #ifdef L_gets char * gets(str) /* BAD function; DON'T use it! */ char *str; { /* Auwlright it will work but of course _your_ program will crash */ /* if it's given a too long line */ register char *p = str; register int c; while (((c = getc(stdin)) != EOF) && (c != '\n')) *p++ = c; *p = '\0'; return (((c == EOF) && (p == str)) ? NULL : str); /* NULL == EOF */ } #endif #ifdef L_fputs int fputs(str, fp) char *str; FILE *fp; { register int n = 0; while (*str) { if (putc(*str++, fp) == EOF) return (EOF); ++n; } return (n); } #endif #ifdef L_puts int puts(str) char *str; { register int n; if (((n = fputs(str, stdout)) == EOF) || (putc('\n', stdout) == EOF)) return (EOF); return (++n); } #endif #ifdef L_fread /* * fread will often be used to read in large chunks of data calling read() * directly can be a big win in this case. Beware also fgetc calls this * function to fill the buffer. * * This ignores __MODE__IOTRAN; probably exactly what you want. (It _is_ what * fgetc wants) */ int fread(buf, size, nelm, fp) char *buf; int size; int nelm; FILE *fp; { int len, v; unsigned bytes, got = 0; Inline_init; v = fp->mode; /* Want to do this to bring the file pointer up to date */ if (v & __MODE_WRITING) fflush(fp); /* Can't read or there's been an EOF or error then return zero */ if ((v & (__MODE_READ | __MODE_EOF | __MODE_ERR)) != __MODE_READ) return 0; /* This could be long, doesn't seem much point tho */ bytes = size * nelm; len = fp->bufread - fp->bufpos; if (len >= bytes) /* Enough buffered */ { memcpy(buf, fp->bufpos, (unsigned) bytes); fp->bufpos += bytes; return nelm; } else if (len > 0) /* Some buffered */ { memcpy(buf, fp->bufpos, len); fp->bufpos += len; got = len; } /* Need more; do it with a direct read */ len = read(fp->fd, buf + got, (unsigned) (bytes - got)); /* Possibly for now _or_ later */ if (len < 0) { fp->mode |= __MODE_ERR; len = 0; } else if (len == 0) fp->mode |= __MODE_EOF; return (got + len) / size; } #endif #ifdef L_fwrite /* * Like fread, fwrite will often be used to write out large chunks of * data; calling write() directly can be a big win in this case. * * But first we check to see if there's space in the buffer. * * Again this ignores __MODE__IOTRAN. */ int fwrite(buf, size, nelm, fp) char *buf; int size; int nelm; FILE *fp; { register int v; int len; unsigned bytes, put; /* If last op was a read ... note fflush may change fp->mode and ret OK */ if ((fp->mode & __MODE_READING) && fflush(fp)) return 0; v = fp->mode; /* Can't write or there's been an EOF or error then return 0 */ if ((v & (__MODE_WRITE | __MODE_EOF | __MODE_ERR)) != __MODE_WRITE) return 0; /* This could be long, doesn't seem much point tho */ bytes = size * nelm; len = fp->bufend - fp->bufpos; /* Flush the buffer if not enough room */ if (bytes > len) if (fflush(fp)) return 0; len = fp->bufend - fp->bufpos; if (bytes <= len) /* It'll fit in the buffer ? */ { register int do_flush=0; fp->mode |= __MODE_WRITING; memcpy(fp->bufpos, buf, bytes); if (v & _IOLBF) { if(memchr(fp->bufpos, '\n', bytes)) do_flush=1; } fp->bufpos += bytes; /* If we're unbuffered or line buffered and have seen nl */ if (do_flush || (v & _IONBF) != 0) fflush(fp); return nelm; } else /* Too big for the buffer */ { put = bytes; do { len = write(fp->fd, buf, bytes); if( len > 0 ) { buf+=len; bytes-=len; } } while (len > 0 || (len == -1 && errno == EINTR)); if (len < 0) fp->mode |= __MODE_ERR; put -= bytes; } return put / size; } #endif #ifdef L_rewind void rewind(fp) FILE * fp; { fseek(fp, (long)0, 0); clearerr(fp); } #endif #ifdef L_fseek int fseek(fp, offset, ref) FILE *fp; long offset; int ref; { #if 1 /* if __MODE_READING and no ungetc ever done can just move pointer */ if ( (fp->mode &(__MODE_READING | __MODE_UNGOT)) == __MODE_READING && ( ref == SEEK_SET || ref == SEEK_CUR )) { long fpos = lseek(fp->fd, 0L, SEEK_CUR); if( fpos == -1 ) return EOF; if( ref == SEEK_CUR ) { ref = SEEK_SET; offset = fpos + offset + fp->bufpos - fp->bufread; } if( ref == SEEK_SET ) { if ( offset < fpos && offset >= fpos + fp->bufstart - fp->bufread ) { fp->bufpos = offset - fpos + fp->bufread; return 0; } } } #endif /* Use fflush to sync the pointers */ if (fflush(fp) == EOF) return EOF; if (lseek(fp->fd, offset, ref) < 0) return EOF; return 0; } #endif #ifdef L_ftell long ftell(fp) FILE * fp; { long rv; if (fflush(fp) == EOF) return EOF; return lseek(fp->fd, 0L, SEEK_CUR); } #endif #ifdef L_fopen FILE * fopen(file, mode) char * file; char * mode; { return __fopen(file, -1, (FILE*)0, mode); } #endif #ifdef L_freopen FILE * freopen(file, mode, fp) char * file; char * mode; FILE * fp; { return __fopen(file, -1, fp, mode); } #endif #ifdef L_fdopen FILE * fdopen(file, mode) int file; char * mode; { return __fopen((char*)0, file, (FILE*)0, mode); } #endif #ifdef L___fopen /* * This is the common code for all three of fopen, fdopen and freopen. */ FILE * __fopen(fname, fd, fp, mode) char *fname; int fd; FILE *fp; char *mode; { int open_mode = 0; #if __MODE_IOTRAN && !O_BINARY int do_iosense = 1; #endif int fopen_mode = 0; FILE *nfp = 0; /* If we've got an fp close the old one (freopen) */ if (fp) { /* Careful, don't de-allocate it */ fopen_mode |= (fp->mode & (__MODE_BUF | __MODE_FREEFIL | __MODE_FREEBUF)); fp->mode &= ~(__MODE_FREEFIL | __MODE_FREEBUF); fclose(fp); } /* decode the new open mode */ while (*mode) switch (*mode++) { case 'r': fopen_mode |= __MODE_READ; break; case 'w': fopen_mode |= __MODE_WRITE; open_mode = (O_CREAT | O_TRUNC); break; case 'a': fopen_mode |= __MODE_WRITE; open_mode = (O_CREAT | O_APPEND); break; case '+': fopen_mode |= __MODE_RDWR; break; #if __MODE_IOTRAN || O_BINARY case 'b': /* Binary */ fopen_mode &= ~__MODE_IOTRAN; open_mode |= O_BINARY; #if __MODE_IOTRAN && !O_BINARY do_iosense=0; #endif break; case 't': /* Text */ fopen_mode |= __MODE_IOTRAN; #if __MODE_IOTRAN && !O_BINARY do_iosense=0; #endif break; #endif } /* Add in the read/write options to mode for open() */ switch (fopen_mode & (__MODE_READ | __MODE_WRITE)) { case 0: return 0; case __MODE_READ: open_mode |= O_RDONLY; break; case __MODE_WRITE: open_mode |= O_WRONLY; break; default: open_mode |= O_RDWR; break; } /* Allocate the (FILE) before we do anything irreversable */ if (fp == 0) { nfp = malloc(sizeof(FILE)); if (nfp == 0) return 0; } /* Open the file itself */ if (fname) fd = open(fname, open_mode, 0666); if (fd < 0) /* Grrrr */ { if (nfp) free(nfp); if (fp) { fp->mode |= fopen_mode; fclose(fp); /* Deallocate if required */ } return 0; } /* If this isn't freopen create a (FILE) and buffer for it */ if (fp == 0) { fp = nfp; fp->next = __IO_list; __IO_list = fp; fp->mode = __MODE_FREEFIL; if( isatty(fd) ) { fp->mode |= _IOLBF; #if __MODE_IOTRAN && !O_BINARY if( do_iosense ) fopen_mode |= __MODE_IOTRAN; #endif } else fp->mode |= _IOFBF; fp->bufstart = malloc(BUFSIZ); if (fp->bufstart == 0) /* Oops, no mem */ { /* Humm, full buffering with a two(!) byte * buffer. */ fp->bufstart = fp->unbuf; fp->bufend = fp->unbuf + sizeof(fp->unbuf); } else { fp->bufend = fp->bufstart + BUFSIZ; fp->mode |= __MODE_FREEBUF; } } /* Ok, file's ready clear the buffer and save important bits */ fp->bufpos = fp->bufread = fp->bufwrite = fp->bufstart; fp->mode |= fopen_mode; fp->fd = fd; return fp; } #endif #ifdef L_fclose int fclose(fp) FILE *fp; { int rv = 0; if (fp == 0) { errno = EINVAL; return EOF; } if (fp->fd != -1) { if (fflush(fp)) return EOF; if (close(fp->fd)) rv = EOF; fp->fd = -1; } if (fp->mode & __MODE_FREEBUF) { free(fp->bufstart); fp->mode &= ~__MODE_FREEBUF; fp->bufstart = fp->bufend = 0; } if (fp->mode & __MODE_FREEFIL) { FILE *prev = 0, *ptr; fp->mode = 0; for (ptr = __IO_list; ptr && ptr != fp; ptr = ptr->next) ; if (ptr == fp) { if (prev == 0) __IO_list = fp->next; else prev->next = fp->next; } free(fp); } else fp->mode = 0; return rv; } #endif #ifdef L_setbuffer void setbuffer(fp, buf, size) FILE * fp; char * buf; int size; { fflush(fp); if( fp->mode & __MODE_FREEBUF ) free(fp->bufstart); fp->mode &= ~(__MODE_FREEBUF|__MODE_BUF); if( buf == 0 ) { fp->bufstart = fp->unbuf; fp->bufend = fp->unbuf + sizeof(fp->unbuf); fp->mode |= _IONBF; } else { fp->bufstart = buf; fp->bufend = buf+size; fp->mode |= _IOFBF; } fp->bufpos = fp->bufread = fp->bufwrite = fp->bufstart; } #endif #ifdef L_setvbuf int setvbuf(fp, buf, mode, size) FILE * fp; char * buf; int mode; size_t size; { int rv = 0; fflush(fp); if( fp->mode & __MODE_FREEBUF ) free(fp->bufstart); fp->mode &= ~(__MODE_FREEBUF|__MODE_BUF); fp->bufstart = fp->unbuf; fp->bufend = fp->unbuf + sizeof(fp->unbuf); fp->mode |= _IONBF; if( mode == _IOFBF || mode == _IOLBF ) { if( size <= 0 ) size = BUFSIZ; if( buf == 0 ) { if( (buf = malloc(size)) != 0 ) fp->mode |= __MODE_FREEBUF; else rv = EOF; } if( buf ) { fp->bufstart = buf; fp->bufend = buf+size; fp->mode &= ~__MODE_BUF; fp->mode |= mode; } } fp->bufpos = fp->bufread = fp->bufwrite = fp->bufstart; return rv; } #endif #ifdef L_ungetc int ungetc(c, fp) int c; FILE *fp; { if (fp->mode & __MODE_WRITING) fflush(fp); /* Can't read or there's been an error then return EOF */ if ((fp->mode & (__MODE_READ | __MODE_ERR)) != __MODE_READ) return EOF; /* Can't do fast fseeks */ fp->mode |= __MODE_UNGOT; if( fp->bufpos > fp->bufstart ) return *--fp->bufpos = (unsigned char) c; else if( fp->bufread == fp->bufstart ) return *fp->bufread++ = (unsigned char) c; else return EOF; } #endif dev86-0.16.21/libc/stdio/stdio.h000066400000000000000000000073271231050321700161460ustar00rootroot00000000000000 #ifndef __STDIO_H #define __STDIO_H #include #include #ifndef SEEK_SET #define SEEK_SET 0 #define SEEK_CUR 1 #define SEEK_END 2 #endif #define _IOFBF 0x00 /* full buffering */ #define _IOLBF 0x01 /* line buffering */ #define _IONBF 0x02 /* no buffering */ #define __MODE_BUF 0x03 /* Modal buffering dependent on isatty */ #define __MODE_FREEBUF 0x04 /* Buffer allocated with malloc, can free */ #define __MODE_FREEFIL 0x08 /* FILE allocated with malloc, can free */ #define __MODE_READ 0x10 /* Opened in read only */ #define __MODE_WRITE 0x20 /* Opened in write only */ #define __MODE_RDWR 0x30 /* Opened in read/write */ #define __MODE_READING 0x40 /* Buffer has pending read data */ #define __MODE_WRITING 0x80 /* Buffer has pending write data */ #define __MODE_EOF 0x100 /* EOF status */ #define __MODE_ERR 0x200 /* Error status */ #define __MODE_UNGOT 0x400 /* Buffer has been polluted by ungetc */ #ifdef __MSDOS__ #define __MODE_IOTRAN 0x1000 /* MSDOS nl <-> cr,nl translation */ #else #define __MODE_IOTRAN 0 #endif /* when you add or change fields here, be sure to change the initialization * in stdio_init and fopen */ struct __stdio_file { unsigned char *bufpos; /* the next byte to write to or read from */ unsigned char *bufread; /* the end of data returned by last read() */ unsigned char *bufwrite; /* highest address writable by macro */ unsigned char *bufstart; /* the start of the buffer */ unsigned char *bufend; /* the end of the buffer; ie the byte after the last malloc()ed byte */ int fd; /* the file descriptor associated with the stream */ int mode; char unbuf[8]; /* The buffer for 'unbuffered' streams */ struct __stdio_file * next; }; #define EOF (-1) #ifndef NULL #define NULL ((void*)0) #endif typedef struct __stdio_file FILE; #ifdef __AS386_16__ #define BUFSIZ (256) #else #define BUFSIZ (2048) #endif extern FILE stdin[1]; extern FILE stdout[1]; extern FILE stderr[1]; #ifdef __MSDOS__ #define putc(c, fp) fputc(c, fp) #define getc(fp) fgetc(fp) #else #define putc(c, stream) \ (((stream)->bufpos >= (stream)->bufwrite) ? fputc((c), (stream)) \ : (unsigned char) (*(stream)->bufpos++ = (c)) ) #define getc(stream) \ (((stream)->bufpos >= (stream)->bufread) ? fgetc(stream): \ (*(stream)->bufpos++)) #endif #define putchar(c) putc((c), stdout) #define getchar() getc(stdin) #define ferror(fp) (((fp)->mode&__MODE_ERR) != 0) #define feof(fp) (((fp)->mode&__MODE_EOF) != 0) #define clearerr(fp) ((fp)->mode &= ~(__MODE_EOF|__MODE_ERR),0) #define fileno(fp) ((fp)->fd) /* declare functions; not like it makes much difference without ANSI */ /* RDB: The return values _are_ important, especially if we ever use 8086 'large' model */ /* These two call malloc */ #define setlinebuf(__fp) setvbuf((__fp), (char*)0, _IOLBF, 0) extern int setvbuf __P((FILE*, char*, int, size_t)); /* These don't */ #define setbuf(__fp, __buf) setbuffer((__fp), (__buf), BUFSIZ) extern void setbuffer __P((FILE*, char*, int)); extern int fgetc __P((FILE*)); extern int fputc __P((int, FILE*)); extern int fclose __P((FILE*)); extern int fflush __P((FILE*)); extern char *fgets __P((char*, size_t, FILE*)); extern FILE *fopen __P((char*, char*)); extern FILE *fdopen __P((int, char*)); extern FILE *freopen __P((char*, char*, FILE*)); #ifdef __LIBC__ extern FILE *__fopen __P((char*, int, FILE*, char*)); #endif extern int fputs __P((char*, FILE*)); extern int puts __P((char*)); extern int printf __P ((__const char*, ...)); extern int fprintf __P ((FILE*, __const char*, ...)); extern int sprintf __P ((char*, __const char*, ...)); #define stdio_pending(fp) ((fp)->bufread>(fp)->bufpos) #endif /* __STDIO_H */ dev86-0.16.21/libc/string/000077500000000000000000000000001231050321700150265ustar00rootroot00000000000000dev86-0.16.21/libc/string/Config000066400000000000000000000000471231050321700161570ustar00rootroot00000000000000string: String and memory manipulation dev86-0.16.21/libc/string/Makefile000066400000000000000000000014021231050321700164630ustar00rootroot00000000000000# Copyright (C) 1995,1996 Robert de Bath # This file is part of the Linux-8086 C library and is distributed # under the GNU Library General Public License. SSRC=string.c SOBJ=strlen.o strcat.o strcpy.o strcmp.o strncat.o strncpy.o strncmp.o \ strchr.o strrchr.o strdup.o memcpy.o memccpy.o memchr.o memset.o \ memcmp.o memmove.o movedata.o OBJ=$(SOBJ) strpbrk.o strsep.o strstr.o strtok.o strcspn.o \ strspn.o strcasecmp.o strncasecmp.o CFLAGS=$(ARCH) $(CCFLAGS) $(DEFS) all: $(LIBC) @$(RM) $(OBJ) $(LIBC): $(LIBC)($(OBJ)) $(LIBC)($(SOBJ)): $(SSRC) $(CC) $(CFLAGS) -DL_$* $< -c -o $*.o $(AR) $(ARFLAGS) $@ $*.o transfer: -@rm -f ../include/string.h cp -p string.h ../include/. clean: rm -f *.o ../include/string.h dev86-0.16.21/libc/string/strcasecmp.c000066400000000000000000000007101231050321700173340ustar00rootroot00000000000000/* Copyright (C) 1995,1996 Robert de Bath * This file is part of the Linux-8086 C library and is distributed * under the GNU Library General Public License. */ #include #include int strcasecmp(s, d) char *s; char *d; { for(;;) { if( *s != *d ) { if( tolower(*s) != tolower(*d) ) return *s - *d; } else if( *s == '\0' ) break; s++; d++; } return 0; } dev86-0.16.21/libc/string/strcspn.c000066400000000000000000000011771231050321700166740ustar00rootroot00000000000000/* strcspn.c */ /* from Schumacher's Atari library, improved */ #include size_t strcspn(string, set) register char *string; char *set; /* * Return the length of the sub-string of that consists * entirely of characters not found in . The terminating '\0' * in is not considered part of the match set. If the first * character if is in , 0 is returned. */ { register char *setptr; char *start; start = string; while (*string) { setptr = set; do if (*setptr == *string) goto break2; while (*setptr++); ++string; } break2: return string - start; } dev86-0.16.21/libc/string/string.c000066400000000000000000000265621231050321700165130ustar00rootroot00000000000000/* Copyright (C) 1995,1996 Robert de Bath * This file is part of the Linux-8086 C library and is distributed * under the GNU Library General Public License. */ #include #include #ifdef __AS386_16__ #if __FIRST_ARG_IN_AX__ #define BCC_AX_ASM /* BCC Assembler that can cope with arg in AX */ #else #define BCC_AX_ASM #define BCC_ASM /* Use 16 bit BCC assembler */ #endif #define PARANOID /* Include extra code for cld and ES register */ #endif /* This is a basic string package; it includes the most used functions strlen strcat strcpy strcmp strncat strncpy strncmp strchr strrchr strdup memcpy memccpy memchr memset memcmp memmove These functions are in seperate files. strpbrk.o strsep.o strstr.o strtok.o strcspn.o strspn.o strcasecmp.o strncasecmp.o */ /********************** Function strlen ************************************/ #ifdef L_strlen size_t strlen(str) const char * str; { #ifdef BCC_AX_ASM #asm #if !__FIRST_ARG_IN_AX__ mov bx,sp #endif push di #ifdef PARANOID push es push ds ! Im not sure if this is needed, so just in case. pop es cld #endif ! This is almost the same as memchr, but it can ! stay as a special. #if __FIRST_ARG_IN_AX__ mov di,ax #else mov di,[bx+2] #endif mov cx,#-1 xor ax,ax repne scasb not cx dec cx mov ax,cx #ifdef PARANOID pop es #endif pop di #endasm #else register char * p =(char *) str; while(*p) p++; return p-str; #endif /* ifdef BCC_AX_ASM */ } #endif /********************** Function strcat ************************************/ #ifdef L_strcat char * strcat(d, s) char *d; const char * s; { (void) strcpy(d+strlen(d), s); return d; } #endif /********************** Function strcpy ************************************/ #ifdef L_strcpy char * strcpy(d, s) char *d; const char * s; { /* This is probably the quickest on an 8086 but a CPU with a cache will * prefer to do this in one pass */ return memcpy(d, s, strlen(s)+1); } #endif /********************** Function strcmp ************************************/ #ifdef L_strcmp int strcmp(d, s) const char *d; const char * s; { /* There are a number of ways to do this and it really does depend on the types of strings given as to which is better, nevertheless the Glib method is quite reasonable so we'll take that */ #ifdef BCC_AX_ASM #asm mov bx,sp push di push si #ifdef PARANOID push es push ds ; Im not sure if this is needed, so just in case. pop es cld #endif #if __FIRST_ARG_IN_AX__ mov di,ax ; dest mov si,[bx+2] ; source #else mov di,[bx+2] ; dest mov si,[bx+4] ; source #endif sc_1: lodsb scasb jne sc_2 ; If bytes are diff skip out. testb al,al jne sc_1 ; If this byte in str1 is nul the strings are equal xor ax,ax ; so return zero jmp sc_3 sc_2: cmc sbb ax,ax ; Collect correct val (-1,1). orb al,#1 sc_3: #ifdef PARANOID pop es #endif pop si pop di #endasm #else /* ifdef BCC_AX_ASM */ register char *s1=(char *)d, *s2=(char *)s, c1,c2; while((c1= *s1++) == (c2= *s2++) && c1 ); return c1 - c2; #endif /* ifdef BCC_AX_ASM */ } #endif /********************** Function strncat ************************************/ #ifdef L_strncat char * strncat(d, s, l) char *d, *s; size_t l; { register char *s1=d+strlen(d), *s2; s2 = memchr(s, l, 0); if( s2 ) memcpy(s1, s, s2-s+1); else { memcpy(s1, s, l); s1[l] = '\0'; } return d; } #endif /********************** Function strncpy ************************************/ #ifdef L_strncpy char * strncpy(d, s, l) /* FIXME need the fast version of this */ char *d, *s; size_t l; { register char *s1=d, *s2=s; while(l > 0) { l--; if( (*s1++ = *s2++) == '\0') break; } /* This _is_ correct strncpy is supposed to zap */ for(; l>0; l--) *s1++ = '\0'; return d; } #endif /********************** Function strncmp ************************************/ #ifdef L_strncmp int strncmp(d, s, l) const char *d, *s; size_t l; { #ifdef BCC_AX_ASM #asm mov bx,sp push si push di #ifdef PARANOID push es push ds ! Im not sure if this is needed, so just in case. pop es cld #endif #if __FIRST_ARG_IN_AX__ mov si,ax mov di,[bx+2] mov cx,[bx+4] #else mov si,[bx+2] ! Fetch mov di,[bx+4] mov cx,[bx+6] #endif inc cx lp1: dec cx je lp2 lodsb scasb jne lp3 testb al,al jne lp1 lp2: xor ax,ax jmp lp4 lp3: sbb ax,ax or al,#1 lp4: #ifdef PARANOID pop es #endif pop di pop si #endasm #else register char c1=0, c2=0; while(l-- >0) if( (c1= *d++) != (c2= *s++) || c1 == '\0' ) break; return c1-c2; #endif } #endif /********************** Function strchr ************************************/ #ifdef L_strchr char * strchr(s, c) char * s; int c; { #ifdef BCC_AX_ASM #asm mov bx,sp push si #if __FIRST_ARG_IN_AX__ mov bx,[bx+2] mov si,ax #else mov si,[bx+2] mov bx,[bx+4] #endif xor ax,ax #ifdef PARANOID cld #endif in_loop: lodsb cmp al,bl jz got_it or al,al jnz in_loop pop si ret got_it: lea ax,[si-1] pop si #endasm #else /* ifdef BCC_AX_ASM */ register char ch; for(;;) { if( (ch= *s) == c ) return s; if( ch == 0 ) return 0; s++; } #endif /* ifdef BCC_AX_ASM */ } #endif /********************** Function strrchr ************************************/ #ifdef L_strrchr char * strrchr(s, c) char * s; int c; { register char * prev = 0; register char * p = s; /* For null it's just like strlen */ if( c == '\0' ) return p+strlen(p); /* everything else just step along the string. */ while( (p=strchr(p, c)) != 0 ) { prev = p; p++; } return prev; } #endif /********************** Function strdup ************************************/ #ifdef L_strdup char * strdup(s) char * s; { register size_t len; register char * p; len = strlen(s)+1; p = (char *) malloc(len); if(p) memcpy(p, s, len); /* Faster than strcpy */ return p; } #endif /********************** Function memcpy ************************************/ #ifdef L_memcpy void * memcpy(d, s, l) void *d; const void *s; size_t l; { #ifdef BCC_AX_ASM #asm mov bx,sp push di push si #ifdef PARANOID push es push ds ; Im not sure if this is needed, so just in case. pop es cld #endif #if __FIRST_ARG_IN_AX__ mov di,ax ; dest mov si,[bx+2] ; source mov cx,[bx+4] ; count #else mov di,[bx+2] ; dest mov si,[bx+4] ; source mov cx,[bx+6] ; count mov ax,di #endif ; If di is odd we could mov 1 byte before doing word move ; as this would speed the copy slightly but its probably ; too rare to be worthwhile. ; NB 8086 has no problem with mis-aligned access. shr cx,#1 ; Do this faster by doing a mov word rep movsw adc cx,cx ; Retrieve the leftover 1 bit from cflag. rep movsb #ifdef PARANOID pop es #endif pop si pop di #endasm #else /* ifdef BCC_AX_ASM */ register char *s1=d, *s2=(char *)s; for( ; l>0; l--) *((unsigned char*)s1++) = *((unsigned char*)s2++); return d; #endif /* ifdef BCC_AX_ASM */ } #endif /********************** Function memccpy ************************************/ #ifdef L_memccpy void * memccpy(d, s, c, l) /* Do we need a fast one ? */ void *s, *d; int c; size_t l; { register char *s1=d, *s2=s; while(l-- > 0) if((*s1++ = *s2++) == c ) return s1; return 0; } #endif /********************** Function memchr ************************************/ #ifdef L_memchr void * memchr(str, c, l) const void * str; int c; size_t l; { #ifdef BCC_ASM #asm mov bx,sp push di #ifdef PARANOID push es push ds ; Im not sure if this is needed, so just in case. pop es cld #endif mov di,[bx+2] mov ax,[bx+4] mov cx,[bx+6] test cx,cx je is_z ! Zero length, do not find. repne ! Scan scasb jne is_z ! Not found, ret zero dec di ! Adjust ptr mov ax,di ! return jmp xit is_z: xor ax,ax xit: #ifdef PARANOID pop es #endif pop di #endasm #else /* ifdef BCC_ASM */ register char *p=(char *)str; while(l-- > 0) { if(*p == c) return p; p++; } return 0; #endif /* ifdef BCC_ASM */ } #endif /********************** Function memset ************************************/ #ifdef L_memset void * memset(str, c, l) void * str; int c; size_t l; { #ifdef BCC_AX_ASM #asm mov bx,sp push di #ifdef PARANOID push es push ds ; Im not sure if this is needed, so just in case. pop es cld #endif #if __FIRST_ARG_IN_AX__ mov di,ax ; Fetch mov ax,[bx+2] mov cx,[bx+4] #else mov di,[bx+2] ; Fetch mov ax,[bx+4] mov cx,[bx+6] #endif ; How much difference does this alignment make ? ; I don`t think it`s significant cause most will already be aligned. ; test cx,cx ; Zero size - skip ; je xit ; ; test di,#1 ; Line it up ; je s_1 ; stosb ; dec cx ;s_1: mov ah,al ; Replicate byte shr cx,#1 ; Do this faster by doing a sto word rep ; Bzzzzz ... stosw adc cx,cx ; Retrieve the leftover 1 bit from cflag. rep ; ... z stosb xit: mov ax,[bx+2] #ifdef PARANOID pop es #endif pop di #endasm #else /* ifdef BCC_AX_ASM */ register char *s1=str; while(l-->0) *s1++ = c; return str; #endif /* ifdef BCC_AX_ASM */ } #endif /********************** Function memcmp ************************************/ #ifdef L_memcmp int memcmp(s, d, l) const void *s, *d; size_t l; { #ifdef BCC_ASM #asm mov bx,sp push di push si #ifdef PARANOID push es push ds ! Im not sure if this is needed, so just in case. pop es cld #endif mov si,[bx+2] ! Fetch mov di,[bx+4] mov cx,[bx+6] xor ax,ax rep ! Bzzzzz cmpsb je xit ! All the same! sbb ax,ax sbb ax,#-1 ! choose +/-1 xit: #ifdef PARANOID pop es #endif pop si pop di #endasm #else /* ifdef BCC_ASM */ register const char *s1=d, *s2=s; register char c1=0, c2=0; while(l-- > 0) if( (c1= *s1++) != (c2= *s2++) ) break; return c1-c2; #endif /* ifdef BCC_ASM */ } #endif /********************** Function memmove ************************************/ #ifdef L_memmove void * memmove(d, s, l) void *d, *s; size_t l; { register char *s1=d, *s2=s; /* This bit of sneakyness c/o Glibc, it assumes the test is unsigned */ if( s1-s2 >= l ) return memcpy(d,s,l); /* This reverse copy only used if we absolutly have to */ s1+=l; s2+=l; while(l-- >0) *(--s1) = *(--s2); return d; } #endif /********************** Function movedata ***********************************/ #ifdef L_movedata /* NB There isn't any C version of this function ... */ #ifdef BCC_AX_ASM void __movedata(srcseg, srcoff, destseg, destoff, len) unsigned int srcseg, srcoff, destseg, destoff, len; { #asm push bp mov bp,sp push si push di push ds #ifdef PARANOID push es cld #endif ! sti ! Are we _really_ paranoid ? #if !__FIRST_ARG_IN_AX__ mov ds,[bp+4] ! Careful, [bp+xx] is SS based. mov si,[bp+6] mov es,[bp+8] mov di,[bp+10] mov cx,[bp+12] #else mov ds,ax mov si,[bp+4] mov es,[bp+6] mov di,[bp+8] mov cx,[bp+10] #endif ; Would it me a good idea to normalise the pointers ? ; How about allowing for overlapping moves ? shr cx,#1 ; Do this faster by doing a mov word rep movsw adc cx,cx ; Retrieve the leftover 1 bit from cflag. rep movsb ! cli ! Are we _really_ paranoid ? #ifdef PARANOID pop es #endif pop ds pop di pop si pop bp #endasm } #endif #endif /********************** THE END ********************************************/ dev86-0.16.21/libc/string/string.h000066400000000000000000000030421231050321700165040ustar00rootroot00000000000000 #ifndef __STRING_H #define __STRING_H #include #include #include /* Basic string functions */ extern size_t strlen __P ((__const char* __str)); extern char * strcat __P ((char*, __const char*)); extern char * strcpy __P ((char*, __const char*)); extern int strcmp __P ((__const char*, __const char*)); extern char * strncat __P ((char*, char*, size_t)); extern char * strncpy __P ((char*, char*, size_t)); extern int strncmp __P ((__const char*, __const char*, size_t)); extern char * strchr __P ((char*, int)); extern char * strrchr __P ((char*, int)); extern char * strdup __P ((char*)); /* Basic mem functions */ extern void * memcpy __P ((void*, __const void*, size_t)); extern void * memccpy __P ((void*, void*, int, size_t)); extern void * memchr __P ((__const void*, __const int, size_t)); extern void * memset __P ((void*, int, size_t)); extern int memcmp __P ((__const void*, __const void*, size_t)); extern void * memmove __P ((void*, void*, size_t)); /* Minimal (very!) locale support */ #define strcoll strcmp #define strxfrm strncpy /* BSDisms */ #define index strchr #define rindex strrchr /* Other common BSD functions */ extern int strcasecmp __P ((char*, char*)); extern int strncasecmp __P ((char*, char*, size_t)); char *strpbrk __P ((char *, char *)); char *strsep __P ((char **, char *)); char *strstr __P ((char *, char *)); char *strtok __P ((char *, char *)); size_t strcspn __P ((char *, char *)); size_t strspn __P ((char *, char *)); /* Linux silly hour */ char *strfry __P ((char *)); #endif dev86-0.16.21/libc/string/strncasecmp.c000066400000000000000000000007431231050321700175200ustar00rootroot00000000000000/* Copyright (C) 1995,1996 Robert de Bath * This file is part of the Linux-8086 C library and is distributed * under the GNU Library General Public License. */ #include #include int strncasecmp(s, d, l) char *s; char *d; size_t l; { while(l>0) { if( *s != *d ) { if( tolower(*s) != tolower(*d) ) return *s - *d; } else if( *s == '\0' ) return 0; s++; d++; l--; } return 0; } dev86-0.16.21/libc/string/strpbrk.c000066400000000000000000000006761231050321700166720ustar00rootroot00000000000000/* Copyright (C) 1995,1996 Robert de Bath * This file is part of the Linux-8086 C library and is distributed * under the GNU Library General Public License. */ #include /* This uses strchr, strchr should be in assembler */ char *strpbrk(str, set) register char *str; char *set; { while (*str != '\0') if (strchr(set, *str) == 0) ++str; else return (char *) str; return 0; } dev86-0.16.21/libc/string/strsep.c000066400000000000000000000020471231050321700165150ustar00rootroot00000000000000/* Copyright (C) 1992, 1993 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the GNU C Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include char * strsep(pp, delim) char **pp; char *delim; { char *p, *q; if (!(p = *pp)) return 0; if (q = strpbrk (p, delim)) { *pp = q + 1; *q = '\0'; } else *pp = 0; return p; } dev86-0.16.21/libc/string/strspn.c000066400000000000000000000023571231050321700165320ustar00rootroot00000000000000/* Copyright (C) 1992, 1993 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the GNU C Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include /* Return the length of the maximum initial segment of S which contains only characters in ACCEPT. */ size_t strspn(s, accept) char *s; char *accept; { register char *p; register char *a; register size_t count = 0; for (p = s; *p != '\0'; ++p) { for (a = accept; *a != '\0'; ++a) if (*p == *a) break; if (*a == '\0') return count; else ++count; } return count; } dev86-0.16.21/libc/string/strstr.c000066400000000000000000000020251231050321700165320ustar00rootroot00000000000000/* Copyright (C) 1995,1996 Robert de Bath * This file is part of the Linux-8086 C library and is distributed * under the GNU Library General Public License. */ #include #if 1 /* We've now got a nice fast strchr and memcmp use them */ char * strstr(s1, s2) char *s1; char *s2; { register int l = strlen(s2); register char * p = s1; if( l==0 ) return p; while (p = strchr(p, *s2)) { if( memcmp(p, s2, l) == 0 ) return p; p++; } return (char *) 0; } #else /* This is a nice simple self contained strstr, now go and work out why the GNU one is faster :-) */ char *strstr(str1, str2) char *str1, *str2; { register char *Sptr, *Tptr; int len = strlen(str1) -strlen(str2) + 1; if (*str2) for (; len > 0; len--, str1++){ if (*str1 != *str2) continue; for (Sptr = str1, Tptr = str2; *Tptr != '\0'; Sptr++, Tptr++) if (*Sptr != *Tptr) break; if (*Tptr == '\0') return (char*) str1; } return (char*)0; } #endif dev86-0.16.21/libc/string/strtok.c000066400000000000000000000033301231050321700165170ustar00rootroot00000000000000/* Copyright (C) 1991 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the GNU C Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include static char *olds = 0; /* Parse S into tokens separated by characters in DELIM. If S is NULL, the last string strtok() was called with is used. For example: char s[] = "-abc=-def"; x = strtok(s, "-"); // x = "abc" x = strtok(NULL, "=-"); // x = "def" x = strtok(NULL, "="); // x = NULL // s = "abc\0-def\0" */ char * strtok(s, delim) register char *s; register char *delim; { char *token; if (s == 0) { if (olds == 0) { return 0; } else s = olds; } /* Scan leading delimiters. */ s += strspn(s, delim); if (*s == '\0') { olds = 0; return 0; } /* Find the end of the token. */ token = s; s = strpbrk(token, delim); if (s == 0) /* This token finishes the string. */ olds = 0; else { /* Terminate the token and make OLDS point past it. */ *s = '\0'; olds = s + 1; } return token; } dev86-0.16.21/libc/syscall/000077500000000000000000000000001231050321700151725ustar00rootroot00000000000000dev86-0.16.21/libc/syscall/Config000066400000000000000000000000511231050321700163160ustar00rootroot00000000000000syscall: Linux-8086 system call routines dev86-0.16.21/libc/syscall/Makefile000066400000000000000000000023071231050321700166340ustar00rootroot00000000000000# Copyright (C) 1995,1996 Robert de Bath # This file is part of the Linux-8086 C library and is distributed # under the GNU Library General Public License. LSRC=syslib0.c LOBJ=__cstartup.o lseek.o getpid.o getppid.o getuid.o geteuid.o getgid.o \ getegid.o dup2.o getpgrp.o times.o ESRC=exec.c EOBJ=execve.o execl.o execv.o execle.o execlp.o execvp.o DSRC=dirent.c DOBJ=opendir.o closedir.o readdir.o ifeq ($(LIB_CPU)-$(LIB_OS),i86-ELKS) OBJ=$(LOBJ) $(DOBJ) $(EOBJ) signal.o setjmp.o SYSCALLS=call_i86 endif ifeq ($(SYSCALLS),) OBJ=setjmp.o endif CFLAGS=$(ARCH) $(CCFLAGS) $(DEFS) all: $(SYSCALLS) $(LIBC) @$(RM) $(OBJ) call_i86: syscall.mak $(MAKE) -f syscall.mak LIBC="$(LIBC)" CFLAGS="$(CFLAGS)" syscall.mak: mksyscall syscall.dat sh mksyscall syscall.dat: @touch syscall.dat $(LIBC): $(LIBC)($(OBJ)) $(LIBC)($(LOBJ)): $(LSRC) $(CC) $(CFLAGS) -DL_$* $< -c -o $*.o $(AR) $(ARFLAGS) $@ $*.o $(LIBC)($(DOBJ)): $(DSRC) $(CC) $(CFLAGS) -DL_$* $< -c -o $*.o $(AR) $(ARFLAGS) $@ $*.o $(LIBC)($(EOBJ)): $(ESRC) $(CC) $(CFLAGS) -DL_$* $< -c -o $*.o $(AR) $(ARFLAGS) $@ $*.o clean: rm -f *.o libc.a rm -f syscall.c syscall.mak syscall.dat rm -f call_tab.v defn_tab.v dev86-0.16.21/libc/syscall/TODO000066400000000000000000000120621231050321700156630ustar00rootroot00000000000000SYSV IPC, there's and __ipc syscall and the hardware can manage messages and semaphores. Idea, for RPC syscall, seperate all the FD related calls from the system ones IIRC all the single FD related ones have the FD in arg0 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- Subject: 8086 Shared Libs and local RPC. True shared libs are impossible with the 8086 in small model. BUT we can use RPC type links to provide a similar system. This is very machine specific. Client side ----------- shl_open("socket", 0x81); Open the shared lib called '/lib/socket.shl' on irq 0x81 The kernel starts the server daemon from /lib and binds it to the interrupt. If the server is already loaded and has flag 'Multi_access' it will not be reloaded; note the daemon can be loaded by init or similar. The binding may be global or process specific depending on if we are running in real mode or protected and the options the server starts with. If the interrupt is busy or the program cannot be run an error is returned. Note also the server has the option to reject the connection even if the kernel is happy. If the server does a shl_open() on itself it is registering a request to be known on the given interrupt by any process without prior registration. int The must be the interrupt previously accepted by the kernel. The registers AX,BX,CX,DX,DI,SI are passed to the server in the structure for shl_accept in the vars: rtype, arg1, ... arg5. Also the DS register is saved for access by the server. If the server has died or doesn't respond after a (long) timeout an error should be returned. Note: A server that is not present may be respawned if it's stateless. Note this is _very_ similar to the system call interrupt and it's possible the system call server can be a model for a multi-threaded server. Server side ----------- shl_register("socket", flags); Flags: Multi_access: Server can accept accesses from multiple clients. Stateless: If server dies it can be restarted in some manner without the clients being aware. Non-block: Calls to shl_accept do not block, return error. Another possibility is to register to a device (major/minor pair) when a client attempts to access this device messages the open syscall is passed to the server like the syscalls for fds opened by shl_popen(). The server can then do a shl_popen to allow the client access to a channel. This has the advantage that the client doesn't need to know anything special about the server. shl_accept(struct shl_message *); A client has just made an INT call. If pid == 0 this is a shl_open request passed via the kernel, arg1 is pid, arg2 is euid and arg3 is the egid. The reply will be the return from the shl_open syscall. struct shl_message { int pid; int rtype; /* AX register */ int arg1, arg2, arg3, arg4, arg5; /* BX,CX,DX,DI,SI registers */ int dseg; /* DS register */ } buffer; Structure for 'accept' and 'reply' calls. shl_reply(struct shl_message *); The rtype, arg1..3 values are copied back to the registers in the calling program. shl_notify(int flag); Allow asychronus notification of the arrival of shl_accept requests. Perhaps a signal, SIGURG ? The flag could be a ms time between signals while there are pending items. (0=none, -1=1 per item, >0=time) (If this used fds this could be done via select but as we ain't got it ...) shl_popen(int pid); Open a file descriptor on the given process, return the FD number. THIS WILL ONLY WORK IF THE PROCESS IS CURRENTLY WAITING FOR A REPLY. This FD when accessed will send messages to the server process, These messages will be identical in form to the normal messages except that the value 0x8000 will be ored with the syscall number in AX. Beware also the semantics of fork and exec which can give a server FD to a process that either knows nothing about the server or will later register with the server in it's own right. (This will probably need a 'dup3(fd, oldpid, newpid)' style call) shl_force(struct shl_message *); This forces the remote process to execute a syscall THIS WILL ONLY WORK IF THE PROCESS IS CURRENTLY WAITING FOR A REPLY. This would be useful for: shl_open("minix", 0x20); or if an error causes a forced closure of an FD. shl_copy(int io, char * localbuf, int pid, char * remotebuf); Copies data between the address space of the client process and the server. (Could be shl_read and shl_write) THIS WILL ONLY WORK IF THE PROCESS IS CURRENTLY WAITING FOR A REPLY. On Linux-8086 this will just be a far memcpy, in protected mode the segment descriptor will have to be setup, either specially or previously. This will be complicated slightly by the problem that a multi-threaded server may have many clients waiting at the same time. Also the kernel is able to change the segment that a given program resides. dev86-0.16.21/libc/syscall/dirent.c000066400000000000000000000020751231050321700166270ustar00rootroot00000000000000 #include #include #include #include #include #include #ifdef L_opendir DIR * opendir(dname) const char *dname; { struct stat st; int fd; DIR *p; if (stat(dname, &st) < 0) return 0; if (!S_ISDIR(st.st_mode)) { errno = ENOTDIR; return 0; } if ((fd = open(dname, O_RDONLY)) < 0) return 0; p = malloc(sizeof(DIR)); if (p == 0) { close(fd); return 0; } p->dd_buf = malloc(sizeof(struct dirent)); if (p->dd_buf == 0) { free(p); close(fd); return 0; } p->dd_fd = fd; p->dd_loc = p->dd_size = 0; return p; } #endif #ifdef L_closedir int closedir(dirp) DIR *dirp; { int fd; fd = dirp->dd_fd; free(dirp->dd_buf); free(dirp); return close(fd); } #endif #ifdef L_readdir struct dirent * readdir(dirp) DIR *dirp; { int cc; cc = __readdir(dirp->dd_fd, dirp->dd_buf, 1); if (cc <= 0) return 0; if (cc>1) dirp->dd_buf->d_name[cc] = 0; return dirp->dd_buf; } #endif dev86-0.16.21/libc/syscall/exec.c000066400000000000000000000125201231050321700162620ustar00rootroot00000000000000 #include #include extern char ** environ; #ifdef L_execl int execl(fname, arg0) char * fname, *arg0; { return execve(fname, &arg0, environ); } #endif #ifdef L_execv int execv(fname, argv) char * fname, **argv; { return execve(fname, argv, environ); } #endif #ifdef L_execle int execle(fname, arg0) char *fname, *arg0; { char ** envp = &arg0; while(*envp) envp++; return execve(fname, &arg0, envp+1); } #endif #ifdef L_execve int execve(fname, argv, envp) char * fname; char ** argv; char ** envp; { char **p; int argv_len=0, argv_count=0; int envp_len=0, envp_count=0; int stack_bytes; unsigned short * pip; char * pcp, * stk_ptr, *baseoff; int rv; /* How much space for argv */ for(p=argv; p && *p && argv_len >= 0; p++) { argv_count++; argv_len += strlen(*p)+1; } /* How much space for envp */ for(p=envp; p && *p && envp_len >= 0; p++) { envp_count++; envp_len += strlen(*p)+1; } /* tot it all up */ stack_bytes = 2 /* argc */ + argv_count * 2 + 2 /* argv */ + argv_len + envp_count * 2 + 2 /* envp */ + envp_len; /* Allocate it */ if( argv_len < 0 || envp_len < 0 || stack_bytes <= 0 || (int)(stk_ptr = (char*)sbrk(stack_bytes)) == -1) { errno = ENOMEM; return -1; } /* Sanity check printf("Argv = (%d,%d), Envp=(%d,%d), stack=%d\n", argv_count, argv_len, envp_count, envp_len, stack_bytes); */ /* Now copy in the strings */ pip=(unsigned short *) stk_ptr; pcp=stk_ptr+2*(1+argv_count+1+envp_count+1); /* baseoff = stk_ptr + stack_bytes; */ baseoff = stk_ptr; *pip++ = argv_count; for(p=argv; p && *p; p++) { int l; *pip++ = pcp-baseoff; l = strlen(*p)+1; memcpy(pcp, *p, l); pcp += l; } *pip++ = 0; for(p=envp; p && *p; p++) { int l; *pip++ = pcp-baseoff; l = strlen(*p)+1; memcpy(pcp, *p, l); pcp += l; } *pip++ = 0; rv = __execve(fname, stk_ptr, stack_bytes); /* FIXME: This will probably have to interpret '#!' style exe's */ sbrk(-stack_bytes); return rv; } #endif #ifdef L_execlp int execlp(fname, arg0) char * fname, *arg0; { return execvp(fname, &arg0); } #endif #ifdef L_execvp int execvp(fname, argv) char * fname, **argv; { char *pname = fname, *path; int besterr = ENOENT; int flen, plen; char * bp = sbrk(0); if( *fname != '/' && (path = getenv("PATH")) != 0 ) { flen = strlen(fname)+2; for(;path;) { if( *path == ':' || *path == '\0' ) { tryrun(fname, argv); if( errno == EACCES ) besterr = EACCES; if( *path ) path++; else break; } else { char * p = strchr(path, ':'); if(p) *p = '\0'; plen = strlen(path); pname = sbrk(plen+flen); strcpy(pname, path); strcat(pname, "/"); strcat(pname, fname); tryrun(pname, argv); if( errno == EACCES ) besterr = EACCES; brk(pname); pname = fname; if(p) *p++ = ':'; path=p; } } } tryrun(pname, argv); brk(bp); if( errno == ENOENT || errno == 0 ) errno = besterr; return -1; } static int tryrun(pname, argv) char * pname; char ** argv; { static char *shprog[] = {"/bin/sh", "", 0}; struct stat st; if( stat(pname, &st) < 0 ) return; if( !S_ISREG(st.st_mode) ) return; #ifdef __AS386_16__ __execvve(pname, (void*)0, argv, environ); if( errno == ENOEXEC ) { shprog[1] = pname; __execvve(shprog[0], shprog, argv, environ); } #else execve(pname, argv, environ); /* FIXME - running /bin/sh in 386 mode */ #endif } #ifdef __AS386_16__ static int __execvve(fname, interp, argv, envp) char * fname; char ** interp; char ** argv; char ** envp; { char **p; int argv_len=0, argv_count=0; int envp_len=0, envp_count=0; int stack_bytes; unsigned short * pip; char * pcp, * stk_ptr, *baseoff; int rv; /* How much space for argv */ for(p=interp; p && *p && argv_len >= 0; p++) { argv_count++; argv_len += strlen(*p)+1; } for(p=argv; p && *p && argv_len >= 0; p++) { argv_count++; argv_len += strlen(*p)+1; } /* How much space for envp */ for(p=envp; p && *p && envp_len >= 0; p++) { envp_count++; envp_len += strlen(*p)+1; } /* tot it all up */ stack_bytes = 2 /* argc */ + argv_count * 2 + 2 /* argv */ + argv_len + envp_count * 2 + 2 /* envp */ + envp_len; /* Allocate it */ if( argv_len < 0 || envp_len < 0 || stack_bytes <= 0 || (int)(stk_ptr = (char*)sbrk(stack_bytes)) == -1) { errno = ENOMEM; return -1; } /* Sanity check printf("Argv = (%d,%d), Envp=(%d,%d), stack=%d\n", argv_count, argv_len, envp_count, envp_len, stack_bytes); */ /* Now copy in the strings */ pip=(unsigned short *) stk_ptr; pcp=stk_ptr+2*(1+argv_count+1+envp_count+1); /* baseoff = stk_ptr + stack_bytes; */ baseoff = stk_ptr; *pip++ = argv_count; for(p=interp; p && *p; p++) { int l; *pip++ = pcp-baseoff; l = strlen(*p)+1; memcpy(pcp, *p, l); pcp += l; } for(p=argv; p && *p; p++) { int l; *pip++ = pcp-baseoff; l = strlen(*p)+1; memcpy(pcp, *p, l); pcp += l; } *pip++ = 0; for(p=envp; p && *p; p++) { int l; *pip++ = pcp-baseoff; l = strlen(*p)+1; memcpy(pcp, *p, l); pcp += l; } *pip++ = 0; rv = __execve(fname, stk_ptr, stack_bytes); /* FIXME: This will probably have to interpret '#!' style exe's */ sbrk(-stack_bytes); return rv; } #endif #endif dev86-0.16.21/libc/syscall/mkentry.sh000066400000000000000000000031251231050321700172200ustar00rootroot00000000000000#!/bin/sh - # # This program generates entry.c from syscall.dat cat << \Trailer /* Switched to V7 system call layout... Chad - 1/5/96 */ #asm * * The call table - autogenerated from syscall.dat * .data sys_call_table: Trailer tr '[A-Z]' '[a-z]' < syscall.dat | \ awk '/^#/{next;} /^[ ]$/{next;} { callno = 0+$2; if( $4 != "-" ) assigned_to[callno] = $1; if( $3 == "x" || $3 == "" ) next; else if( $4 == "@" || $4 == "-" ) next; # Not implemented yet if( substr($2, 1, 1) != "+" ) next; if( maxno < callno ) maxno = callno; str = "\t.word _sys_" $1; line[callno] = sprintf("%-25s ! %d", str, callno); } END{ for(callno=0; callno<=maxno; callno++) { if( assigned_to[callno] == "fork" ) gsub("_sys_fork", "_do_fork ", line[callno]); if( callno in line ) print line[callno]; else { if( assigned_to[callno] == "" ) assigned_to[callno] = "unassigned"; if( assigned_to[callno] == "vfork" ) { str = "\t.word _do_fork"; } else str = "\t.word _no_syscall"; printf "%-25s ! %d - %s\n", str, callno, assigned_to[callno]; } } } ' cat <<\Trailer sys_call_table_end: * * Despatch a syscall (called from syscall_int) * Entry: ax=function code, stack contains parameters * .text .globl _syscall _syscall: cmp ax,#((sys_call_table_end - sys_call_table)/2) ja _no_syscall ! look up address and jump to function mov bx,ax shl bx,#1 ! multiply by 2 add bx,#sys_call_table j [bx] * * Unimplemented calls * _no_syscall: mov ax,#-38 ret #endasm Trailer dev86-0.16.21/libc/syscall/mksyscall000066400000000000000000000211161231050321700171200ustar00rootroot00000000000000# Copyright (C) 1995,1996 Robert de Bath # This file is part of the Linux-8086 C library and is distributed # under the GNU Library General Public License. # # This script generates the 'simple' system calls. # # Each call is put into it's own object file, if the semantics of the # call are not correct UNIX then the 4th field in the dat file has a # marker and the function is generated with a __ prefix. # # # Different levels of squeeze # 0 = each is complete # 1 = Short codes calling common function COMPACT=1 rm -f syscall.c syscall.mak call_tab.v defn_tab.v syscall.dat if [ -r ${ELKSSRC}/arch/i86/kernel/syscall.dat \ -a ! -r ${TOPDIR}/libc/kinclude/Used ] then echo Using syscalls from ${ELKSSRC} cp -p ${ELKSSRC}/arch/i86/kernel/syscall.dat syscall.dat else echo Using syscalls from syscall.dev86 cp -p syscall.dev86 syscall.dat fi tr '[A-Z]' '[a-z]' < syscall.dat | \ awk -v COMPACT=$COMPACT 'BEGIN{ print "# Copyright (C) 1995,1996 Robert de Bath " > "syscall.mak"; print "# This file is part of the Linux-8086 C library and is distributed" > "syscall.mak"; print "# under the GNU Library General Public License." > "syscall.mak"; print "# " > "syscall.mak"; print "# This file is automatically generated\n" > "syscall.mak" print "/* Copyright (C) 1995,1996 Robert de Bath "; print " * This file is part of the Linux-8086 C library and is distributed"; print " * under the GNU Library General Public License."; print " * "; print " * This file is automatically generated */\n" obj="OBJ="; print "/* Standard start */\n\n" printf("#ifndef __MSDOS__\n"); printf("#ifdef __AS386_16__\n"); printf("#asm\n"); printf(" .text\n"); printf(" .even\n"); printf("#endasm\n\n"); { obj=obj "__syscall.o __syscall4.o "; print "/* Shared system call code */\n" printf("#ifdef L___syscall\n", funcname); printf("#asm\n"); printf("#if __FIRST_ARG_IN_AX__\n"); printf("export sys_call3\nsys_call3:\n"); printf(" mov bx,sp\n"); printf(" mov cx,[bx+2]\n"); printf(" mov bx,[bx+4]\n"); # ax=arg1 bx=arg3 cx=arg2 dx=arg0 printf(" xchg ax,bx\n"); # ax=arg3 bx=arg1 cx=arg2 dx=arg0 printf(" xchg ax,dx\n"); # ax=arg0 bx=arg1 cx=arg2 dx=arg3 printf(" jmp sys_call0\n\n"); printf("export sys_call2\nsys_call2:\n"); printf(" mov bx,sp\n"); printf(" mov cx,[bx+2]\n"); printf(" mov bx,ax\n"); printf(" mov ax,dx\n"); printf(" jmp sys_call0\n\n"); printf("export sys_call1\nsys_call1:\n"); printf(" mov bx,ax\n"); printf(" mov ax,dx\n"); printf("#else\n"); printf("export sys_call3\nsys_call3:\n"); printf(" mov bx,sp\n"); printf(" mov dx,[bx+6]\n"); printf(" mov cx,[bx+4]\n"); printf(" mov bx,[bx+2]\n"); printf(" jmp sys_call0\n\n"); printf("export sys_call2\nsys_call2:\n"); printf(" mov bx,sp\n"); printf(" mov cx,[bx+4]\n"); printf(" mov bx,[bx+2]\n"); printf(" jmp sys_call0\n\n"); printf("export sys_call1\nsys_call1:\n"); printf(" mov bx,sp\n"); printf(" mov bx,[bx+2]\n"); printf("#endif\n\n"); printf("export sys_call0\nsys_call0:\n"); printf(" int $80\n"); printf(" test ax,ax\n"); printf(" jge syscall_ok\n"); printf(" neg ax\n"); printf(" mov [_errno],ax\n"); printf(" mov ax,#-1\n"); printf("syscall_ok:\n"); printf(" ret\n"); printf("#endasm\n"); printf("#endif\n\n"); print "/* Shared system call code, syscalls with 4/5 args */\n" printf("#ifdef L___syscall4\n", funcname); printf("#asm\n"); printf("#if __FIRST_ARG_IN_AX__\n"); printf("export sys_call4\nsys_call4:\n"); printf("export sys_call5\nsys_call5:\n"); printf(" mov bx,sp\n"); printf(" push si\n"); printf(" mov si,[bx+8]\n"); printf(" push di\n"); printf(" mov di,[bx+6]\n"); printf(" mov cx,[bx+2]\n"); printf(" mov bx,[bx+4]\n"); # ax=arg1 bx=arg3 cx=arg2 dx=arg0 printf(" xchg ax,bx\n"); # ax=arg3 bx=arg1 cx=arg2 dx=arg0 printf(" xchg ax,dx\n"); # ax=arg0 bx=arg1 cx=arg2 dx=arg3 printf("#else\n"); printf("export sys_call4\nsys_call4:\n"); printf("export sys_call5\nsys_call5:\n"); printf(" mov bx,sp\n"); printf(" push si\n"); printf(" mov si,[bx+10]\n"); printf(" push di\n"); printf(" mov di,[bx+8]\n"); printf(" mov dx,[bx+6]\n"); printf(" mov cx,[bx+4]\n"); printf(" mov bx,[bx+2]\n"); printf("#endif\n\n"); printf(" int $80\n"); printf(" pop di\n"); printf(" pop si\n"); printf(" test ax,ax\n"); printf(" jge syscall_ok\n"); printf(" neg ax\n"); printf(" mov [_errno],ax\n"); printf(" mov ax,#-1\n"); printf("syscall_ok:\n"); printf(" ret\n"); printf("#endasm\n"); printf("#endif\n\n"); } } /^[ ]*#/ { next; } /^[ ]*$/ { next; } { callno = 0+$2; if( !(callno in calltab) ) callwas[callno] = " /* " $1 " */"; if( $3 == "x" || $3 == "" ) next; else if( $4 == "@" || $4 == "-" ) next; else if( $4 == "*" ) funcname="__" $1; else funcname=$1; if( callno > max_call ) max_call = callno; calltab[callno] = $1; if( length(obj) > 60 ) { printf("%s\t\\\n", obj) > "syscall.mak"; obj=" "; } obj=obj funcname ".o "; printf "/* CALL %s */\n\n", $0; printf("#ifdef L_%s\n", funcname); printf("#asm\n", funcname); printf("export _%s\n", funcname); printf("_%s:\n", funcname); # Inline assembler max to 5 args (10 bytes) if( $3 != 4 && $3 != 5 && ( COMPACT || $3 > 5 )) { if( $3 == 0 ) { printf(" mov ax,#%d\n", callno); } else { printf("#if __FIRST_ARG_IN_AX__\n"); printf(" mov dx,#%d\n", callno); printf("#else\n"); printf(" mov ax,#%d\n", callno); printf("#endif\n"); } printf(" br sys_call%d\n", $3); } else { if( $3 >= 1 ) printf("#if __FIRST_ARG_IN_AX__\n"); if( $3 >= 2 ) printf(" mov bx,sp\n"); if( $3 >= 5 ) printf(" push si\n"); if( $3 >= 5 ) printf(" mov si,[bx+8]\n"); if( $3 >= 4 ) printf(" push di\n"); if( $3 >= 4 ) printf(" mov di,[bx+6]\n"); if( $3 >= 3 ) printf(" mov dx,[bx+4]\n"); if( $3 >= 2 ) printf(" mov cx,[bx+2]\n"); if( $3 >= 1 ) printf(" mov bx,ax\n"); if( $3 >= 1 ) printf("#else\n"); if( $3 >= 1 ) printf(" mov bx,sp\n"); if( $3 >= 5 ) printf(" push si\n"); if( $3 >= 5 ) printf(" mov si,[bx+10]\n"); if( $3 >= 4 ) printf(" push di\n"); if( $3 >= 4 ) printf(" mov di,[bx+8]\n"); if( $3 >= 3 ) printf(" mov dx,[bx+6]\n"); if( $3 >= 2 ) printf(" mov cx,[bx+4]\n"); if( $3 >= 1 ) printf(" mov bx,[bx+2]\n"); if( $3 >= 1 ) printf("#endif\n"); printf(" mov ax,#%d\n", callno); printf(" int $80\n"); if( $3 >= 4 ) printf(" pop di\n"); if( $3 >= 5 ) printf(" pop si\n"); printf(" test ax,ax\n"); printf(" jl syscall_err\n"); printf(" ret\n"); printf("syscall_err:\n"); printf(" neg ax\n"); printf(" mov [_errno],ax\n"); printf(" mov ax,#-1\n"); printf(" ret\n"); } printf("#endasm\n"); printf("#endif\n\n"); } END{ for(i=0; i<=max_call; i++) if( i in calltab ) { printf("#ifndef sys_%s\n", calltab[i]) > "defn_tab.v"; printf("#define sys_%s sys_enosys\n", calltab[i]) > "defn_tab.v"; printf("#endif\n\n") > "defn_tab.v"; } for(i=0; i<=max_call; i++) if( i in calltab ) printf("/* %3d */ sys_%s,\n", i, calltab[i]) > "call_tab.v"; else printf("/* %3d */ sys_enosys,%s\n", i, callwas[i]) > "call_tab.v"; printf("#endif /* __AS386_16__ */\n\n"); printf("#endif /* __MSDOS__ */\n\n"); printf("%s\n", obj) > "syscall.mak"; printf "\n" > "syscall.mak"; }' > syscall.c cat >> syscall.mak <<\! all: $(LIBC)($(OBJ)) @$(RM) $(OBJ) $(LIBC)($(OBJ)): syscall.dat $(CC) $(CFLAGS) -DL_$* syscall.c -c -o $*.o $(AR) $(ARFLAGS) $@ $*.o ! exit $? dev86-0.16.21/libc/syscall/setjmp.c000066400000000000000000000013051231050321700166370ustar00rootroot00000000000000 #include #if __AS386_16__ int setjmp(env) jmp_buf env; { #asm export __setjmp __setjmp: pop cx ! PC #if __FIRST_ARG_IN_AX__ mov bx,ax #else mov bx,sp mov bx,[bx] ! TOS is prt -> env #endif mov [bx+0],cx ! PC mov [bx+2],sp ! This registers are all that may be constant. mov [bx+4],bp mov [bx+6],si ! Is saving these the "right thing" ? mov [bx+8],di xor ax,ax jmp cx #endasm } void longjmp(env, rv) jmp_buf env; int rv; { #asm export __longjmp __longjmp: pop cx ! pc #if __FIRST_ARG_IN_AX__ mov bx,ax ! env-> #else pop bx ! env-> #endif pop ax ! rv mov cx,[bx+0] ! PC mov sp,[bx+2] mov bp,[bx+4] mov si,[bx+6] mov di,[bx+8] jmp cx #endasm } #endif dev86-0.16.21/libc/syscall/signal.c000066400000000000000000000042501231050321700166140ustar00rootroot00000000000000 #ifndef __MSDOS__ #ifdef __AS386_16__ #include #include typedef __sighandler_t Sig; extern int __signal __P((int, __sighandler_t)); static Sig system_signal(); Sig __sigtable[_NSIG-1]; /* * Signal handler. * */ /* * KERNEL INTERFACE: * It is assumed the kernel will never give us a signal we haven't * _explicitly_ asked for! * * The Kernel need only save space for _one_ function pointer * (to system_signal) and must deal with SIG_DFL and SIG_IGN * in kernel space. * * When a signal is required the kernel must set all the registers as if * returning from a interrupt normally then push the number of the signal * to be generated, push the current pc value, then set the pc to the * address of the 'system_signal' function. */ Sig signal(number, pointer) int number; Sig pointer; { Sig old_sig; int rv; if( number < 1 || number >= _NSIG ) { errno=EINVAL; return SIG_ERR; } if( pointer == SIG_DFL || pointer == SIG_IGN ) rv = __signal(number, pointer); else rv = __signal(number, (__sighandler_t) system_signal); if( rv < 0 ) return SIG_ERR; old_sig = __sigtable[number-1]; __sigtable[number-1] = pointer; switch(rv) { case 0: return SIG_DFL; case 1: return SIG_IGN; return old_sig; } } #asm .text _system_signal: ! When this is called by the kernel the stack contains pushf ! in order: push ax ! push bx ! The signal number, (NOS) push cx ! The program counter, (TOS) push dx ! push si ! It does NOT contain the CS register or the flags. push di ! This means it cannot be unraveled by an iret. push bp push es ! Note also only ES segment register is saved. mov bx,sp ! Unlike minix the rv from a system call is in AX. mov bx,[bx+20] #if __FIRST_ARG_IN_AX__ mov ax,bx #else push bx ! NB this is _unchecked_, do we want to ? #endif add bx,bx mov bx,[bx+___sigtable-2] ! Offset by 2 cause no entry for signal 0 call bx ! Do we want to check BX for 0 or 1 ? inc sp inc sp pop es pop bp pop di pop si pop dx pop cx pop bx pop ax popf ret #2 ! Get rid of the signum too. #endasm #endif /* __AS386_16__ */ #endif /* __MSDOS__ */ dev86-0.16.21/libc/syscall/syscall.dev86000066400000000000000000000125771231050321700175360ustar00rootroot00000000000000# # WARNING! # This file is used to generate the system call lists for Dev86(elks) # ELKSemu and elks itself. Changes to this may require changes in # all three of those packages. # # '.' = Ok, with comment # '*' = Needs libc code (Prefix __) # '-' = Obsolete/not required # '@' = May be required later # '=' = Depends on stated config variable # # An initial plus on the call number specifies that this call is # implemented in the kernel. # # # Name No Args Flag, comment # exit +1 1 * c exit does stdio, _exit in crt0 fork +2 0 read +3 3 write +4 3 open +5 3 close +6 1 wait4 +7 4 creat 8 0 - Not needed alias for open link +9 2 unlink +10 1 execve +11 3 * execve minix style chdir +12 1 time 13 1 - Use settimeofday mknod +14 3 chmod +15 2 chown +16 3 brk +17 1 * This is only to tell the system stat +18 2 lseek +19 3 * nb 2nd arg is an io ptr to long not a long. getpid +20 1 * this gets both pid & ppid mount +21 5 umount +22 1 setuid +23 1 getuid +24 1 * this gets both uid and euid stime 25 2 - this must not exist - even as a libc. ptrace 26 4 @ adb/sdb/dbx need this. alarm 27 2 fstat +28 2 pause 29 0 utime +30 2 chroot +31 1 vfork +32 0 access +33 2 nice 34 1 sleep 35 1 sync +36 0 kill +37 2 rename +38 2 mkdir +39 2 rmdir +40 1 dup +41 1 . There is a fcntl lib function too. pipe +42 1 times 43 2 * 2nd arg is pointer for long ret val. profil 44 4 @ dup2 +45 2 setgid +46 1 getgid 47 1 * this gets both gid and egid signal +48 2 * have put the despatch table in user space. getinfo 49 1 @ possible? gets pid,ppid,uid,euid etc fcntl +50 3 acct 51 1 @ Accounting to named file (off if null) phys 52 3 - Replaced by mmap() lock 53 1 @ Prevent swapping for this proc if flg!=0 ioctl +54 3 . make this and fcntl the same ? reboot +55 3 . the magic number is 0xfee1,0xdead,... mpx 56 2 - Replaced by fifos and select. lstat +57 2 symlink +58 2 readlink +59 3 umask +60 1 settimeofday +61 2 gettimeofday +62 2 select +63 5 . 5 paramaters is possible readdir +64 3 * insmod 65 1 - Removed support for modules fchown +66 3 dlload +67 2 setsid +68 0 socket +69 3 bind +70 3 listen +71 2 accept +72 3 connect +73 3 knlvsn +74 1 = CONFIG_SYS_VERSION # # Name No Args Flag&comment # # ( awk '{$2=NR+500;OFS="\t";print ;}'| expand -24,32,40 | unexpand ) < * This file is part of the Linux-8086 C library and is distributed * under the GNU Library General Public License. */ #include #include #include #include /* MSDOS has it's own versions */ #ifndef __MSDOS__ #ifdef __AS386_16__ /********************** Function __cstartup *******************************/ #ifdef L___cstartup void (*__cleanup)() = 0; char ** environ; #asm loc 2 call_main: .word run_main ! Segment 2 is the trailing pointers, main and the .word call_exit ! routine to call exit. #if __FIRST_ARG_IN_AX__ .data saved_arg1: .word 0 #endif .data loop_safe: .word 0 .text export ___cstartup ___cstartup: ! Crt0 startup pop cx ! Argc mov bx,sp ! Calculate ptrs to argv and envp mov ax,cx inc ax shl ax,#1 add ax,bx export ___mkargv ___mkargv: ! BCC tells the linker to init argc,argv with this. push ax ! Push Envp mov [_environ],ax ! And save push bx ! Push argv #if __FIRST_ARG_IN_AX__ mov [saved_arg1],cx #else push cx ! Push argc #endif mov bx,#auto_start ! Pointer to first autostart function auto_run: #if __FIRST_ARG_IN_AX__ mov ax,[saved_arg1] #endif mov [loop_safe],bx mov bx,[bx] test bx,bx jz no_entry call bx ! Call the function no_entry: mov bx,[loop_safe] inc bx ! next inc bx jmp auto_run ! And round for the next. run_main: br _main call_exit: ! Last item called by above. pop bx ! Be tidy. #if !__FIRST_ARG_IN_AX__ push ax ! At the end the last called was main() push it`s #endif call _exit ! return val and call exit(); bad_exit: jmp bad_exit ! Exit returned !! export _exit export __exit _exit: ! exit(rv) function #if __FIRST_ARG_IN_AX__ mov [saved_arg1],ax #else mov bx,sp push [bx+2] ! Copy the `rv` for the exit fuctions. #endif mov bx,[___cleanup] ! Call exit, normally this is `__do_exit` test bx,bx je no_clean ! But it`s default is null call bx no_clean: #if __FIRST_ARG_IN_AX__ mov ax,[saved_arg1] #else inc sp inc sp #endif __exit: ! _exit(rv) br ___exit ! This is just an alias for __exit(); #endasm #endif /********************** Function lseek ************************************/ #ifdef L_lseek off_t lseek(fd, posn, where) int fd; off_t posn; int where; { if( __lseek(fd, &posn, where) < 0 ) return -1; else return posn; } #endif /********************** Function getpid ************************************/ #ifdef L_getpid int getpid() { int ppid; return __getpid(&ppid); } #endif /********************** Function getppid ************************************/ #ifdef L_getppid int getppid() { int ppid; __getpid(&ppid); return ppid; } #endif /********************** Function getuid ************************************/ #ifdef L_getuid int getuid() { int euid; return __getuid(&euid); } #endif /********************** Function geteuid ************************************/ #ifdef L_geteuid int geteuid() { int euid; __getuid(&euid); return euid; } #endif /********************** Function getgid ************************************/ #ifdef L_getgid int getgid() { int egid; return __getgid(&egid); } #endif /********************** Function getegid ************************************/ #ifdef L_getegid int getegid() { int egid; __getgid(&egid); return egid; } #endif /********************** Function dup2 ************************************/ #ifdef L_dup2 #include int dup2(ifd, ofd) int ifd; { return fcntl(ifd, F_DUPFD, ofd); } #endif /********************** Function dup ************************************/ #ifdef L_dup #include #include #include /* This is horribly complicated, there _must_ be a better way! */ int dup(fd) int fd; { int nfd; extern int errno; int oerr = errno; errno = 0; for(nfd=0; nfd # This file is part of the Linux-8086 C library and is distributed # under the GNU Library General Public License. TSRC=termios.c TOBJ=tcsetattr.o tcgetattr.o tcdrain.o tcflow.o tcflush.o tcsendbreak.o \ tcsetpgrp.o tcgetpgrp.o isatty.o \ cfgetospeed.o cfgetispeed.o cfsetospeed.o cfsetispeed.o cfmakeraw.o ifeq ($(LIB_OS),ELKS) OBJ=$(TOBJ) ttyname.o CFLAGS=$(ARCH) $(CCFLAGS) $(DEFS) all: $(LIBC) @$(RM) $(OBJ) $(LIBC): $(LIBC)($(OBJ)) $(LIBC)($(TOBJ)): $(TSRC) $(CC) $(CFLAGS) -DL_$* $< -c -o $*.o $(AR) $(ARFLAGS) $@ $*.o else all: @: endif clean: rm -f *.o libc.a dev86-0.16.21/libc/termios/README000066400000000000000000000003541231050321700160640ustar00rootroot00000000000000Copyright (C) 1996 Robert de Bath This file is part of the Linux-8086 C library and is distributed under the GNU Library General Public License. There's currently nothing special about termios. -Robert dev86-0.16.21/libc/termios/termios.c000066400000000000000000000106101231050321700170260ustar00rootroot00000000000000/* Copyright (C) 1996 Robert de Bath This * file is part of the Linux-8086 C library and is distributed under the * GNU Library General Public License. */ /* Note: This is based loosely on the Glib termios routines. */ #ifndef __MSDOS__ #include #include #include #include #ifdef L_isatty isatty(fd) int fd; { struct termios term; int rv, err = errno; rv= (ioctl(fd, TCGETS, &term)==0); if( rv==0 && errno == ENOSYS ) rv = (fd<3); errno = err; return rv; } #endif #ifdef L_tcgetattr int tcgetattr(fd, term) int fd; struct termios *term; { return ioctl(fd, TCGETS, term); } #endif #ifdef L_tcsetattr int tcsetattr(fildes, optional_actions, termios_p) int fildes; int optional_actions; struct termios *termios_p; { switch (optional_actions) { case TCSANOW: return ioctl(fildes, TCSETS, termios_p); case TCSADRAIN: return ioctl(fildes, TCSETSW, termios_p); case TCSAFLUSH: return ioctl(fildes, TCSETSF, termios_p); default: errno = EINVAL; return -1; } } #endif #ifdef L_tcdrain /* Wait for pending output to be written on FD. */ int tcdrain(fd) int fd; { /* With an argument of 1, TCSBRK just waits for output to drain. */ return ioctl(fd, TCSBRK, 1); } #endif #ifdef L_tcflow int tcflow(fd, action) int fd; int action; { return ioctl(fd, TCXONC, action); } #endif #ifdef L_tcflush /* Flush pending data on FD. */ int tcflush(fd, queue_selector) int fd; int queue_selector; { return ioctl(fd, TCFLSH, queue_selector); } #endif #ifdef L_tcsendbreak /* Send zero bits on FD. */ int tcsendbreak(fd, duration) int fd; int duration; { /* * The break lasts 0.25 to 0.5 seconds if DURATION is zero, and an * implementation-defined period if DURATION is nonzero. We define a * positive DURATION to be number of milliseconds to break. */ if (duration <= 0) return ioctl(fd, TCSBRK, 0); /* * ioctl can't send a break of any other duration for us. This could be * changed to use trickery (e.g. lower speed and send a '\0') to send * the break, but for now just return an error. */ errno = EINVAL; return -1; } #endif #ifdef L_tcsetpgrp /* Set the foreground process group ID of FD set PGRP_ID. */ int tcsetpgrp(fd, pgrp_id) int fd; pid_t pgrp_id; { return ioctl(fd, TIOCSPGRP, &pgrp_id); } #endif #ifdef L_tcgetpgrp /* Return the foreground process group ID of FD. */ pid_t tcgetpgrp(fd) int fd; { int pgrp; if (ioctl(fd, TIOCGPGRP, &pgrp) < 0) return (pid_t) - 1; return (pid_t) pgrp; } #endif #ifdef L_cfgetospeed speed_t cfgetospeed(tp) struct termios *tp; { return (tp->c_cflag & CBAUD); } #endif #ifdef L_cfgetispeed speed_t cfgetispeed(tp) struct termios *tp; { return (tp->c_cflag & CBAUD); } #endif #ifdef L_cfsetospeed int cfsetospeed(tp, speed) struct termios *tp; speed_t speed; { #ifdef CBAUDEX if ((speed & ~CBAUD) || ((speed & CBAUDEX) && (speed < B57600 || speed > B115200))) return 0; #else if (speed & ~CBAUD) return 0; #endif tp->c_cflag &= ~CBAUD; tp->c_cflag |= speed; return 0; } #endif #ifdef L_cfsetispeed int cfsetispeed(tp, speed) struct termios *tp; speed_t speed; { return cfsetospeed(tp, speed); } #endif /* From linux libc-4.6.27 again */ #ifdef L_cfmakeraw /* Copyright (C) 1992 Free Software Foundation, Inc. This file is part of the GNU C Library.*/ void cfmakeraw(t) struct termios *t; { /* I changed it to the current form according to the suggestions * from Bruce Evans. Thanks Bruce. Please report the problems to * H.J. Lu (hlu@eecs.wsu.edu). */ /* * I took out the bits commented out by #if 1...#else - RHP */ /* VMIN = 0 means non-blocking for Linux */ t->c_cc[VMIN] = 1; t->c_cc[VTIME] = 1; /* clear some bits with &= ~(bits), set others with |= */ t->c_cflag &= ~(CSIZE|PARENB|CSTOPB); t->c_cflag |= (CS8|HUPCL|CREAD); t->c_iflag &= ~(IGNBRK|BRKINT|PARMRK|INPCK|ISTRIP); t->c_iflag &= ~(INLCR|IGNCR|ICRNL|IXON|IXOFF); t->c_iflag |= (BRKINT|IGNPAR); t->c_oflag &= ~(OPOST|OLCUC|OCRNL|ONOCR|ONLRET|OFILL|OFDEL); t->c_oflag &= ~(NLDLY|CRDLY|TABDLY|BSDLY|VTDLY|FFDLY); t->c_oflag |= (ONLCR|NL0|CR0|TAB3|BS0|VT0|FF0); t->c_lflag &= ~(ISIG|ICANON|IEXTEN|ECHO|ECHOE|ECHOK|ECHONL); t->c_lflag &= ~(NOFLSH|XCASE); t->c_lflag &= ~(ECHOPRT|ECHOCTL|ECHOKE); } #endif #endif dev86-0.16.21/libc/termios/ttyname.c000066400000000000000000000015441231050321700170330ustar00rootroot00000000000000 #include #include #include char * ttyname(fd) int fd; { static char dev[] = "/dev"; struct stat st, dst; DIR *fp; struct dirent *d; static char name[16]; /* should be MAXNAMLEN but that's overkill */ int noerr = errno; if (fstat(fd, &st) < 0) return 0; if (!isatty(fd)) { errno = ENOTTY; return 0; } fp = opendir(dev); if (fp == 0) return 0; strcpy(name, dev); strcat(name, "/"); while ((d = readdir(fp)) != 0) { if( strlen(d->d_name) > sizeof(name) - sizeof(dev) - 1) continue; strcpy(name + sizeof(dev), d->d_name); if (stat(name, &dst) == 0 && st.st_dev == dst.st_dev && st.st_ino == dst.st_ino) { closedir(fp); errno = noerr; return name; } } closedir(fp); errno = noerr; return 0; } dev86-0.16.21/libc/time/000077500000000000000000000000001231050321700144565ustar00rootroot00000000000000dev86-0.16.21/libc/time/Config000066400000000000000000000000501231050321700156010ustar00rootroot00000000000000time: Unix time manipulation functions. dev86-0.16.21/libc/time/Makefile000066400000000000000000000005541231050321700161220ustar00rootroot00000000000000# Copyright (C) 1996 Robert de Bath # This file is part of the Linux-8086 C library and is distributed # under the GNU Library General Public License. OBJ=localtime.o gmtime.o asctime.o ctime.o asc_conv.o tm_conv.o CFLAGS=$(ARCH) $(CCFLAGS) $(DEFS) all: $(LIBC) @$(RM) $(OBJ) $(LIBC): $(LIBC)($(OBJ)) clean: rm -f *.o libc.a dev86-0.16.21/libc/time/README000066400000000000000000000004331231050321700153360ustar00rootroot00000000000000Copyright (C) 1996 Robert de Bath This file is part of the Linux-8086 C library and is distributed under the GNU Library General Public License. There are two ways of converting the time_t to a struct tm, I'm not quite sure which is better. -Robert dev86-0.16.21/libc/time/asc_conv.c000066400000000000000000000021411231050321700164130ustar00rootroot00000000000000 #include #include /* * Internal ascii conversion routine, avoid use of printf, it's a bit big! */ static void hit(buf, val) char * buf; int val; { *buf = '0' + val%10; } void __asctime(buffer, ptm) register char * buffer; struct tm * ptm; { static char days[] = "SunMonTueWedThuFriSat"; static char mons[] = "JanFebMarAprMayJunJulAugSepOctNovDec"; int year; /* 012345678901234567890123456 */ strcpy(buffer, "Err Err .. ..:..:.. ....\n"); if( (ptm->tm_wday >= 0) && (ptm->tm_wday <= 6) ) memcpy(buffer, days+3*(ptm->tm_wday), 3); if( (ptm->tm_mon >= 0) && (ptm->tm_mon <= 11) ) memcpy(buffer+4, mons+3*(ptm->tm_mon), 3); hit(buffer+ 8, ptm->tm_mday/10); hit(buffer+ 9, ptm->tm_mday ); hit(buffer+11, ptm->tm_hour/10); hit(buffer+12, ptm->tm_hour ); hit(buffer+14, ptm->tm_min/10); hit(buffer+15, ptm->tm_min ); hit(buffer+17, ptm->tm_sec/10); hit(buffer+18, ptm->tm_sec ); year = ptm->tm_year + 1900; hit(buffer+20, year/1000); hit(buffer+21, year/100); hit(buffer+22, year/10); hit(buffer+23, year); } dev86-0.16.21/libc/time/asctime.c000066400000000000000000000003241231050321700162460ustar00rootroot00000000000000 #include extern void __asctime(); char * asctime(timeptr) __const struct tm * timeptr; { static char timebuf[26]; if( timeptr == 0 ) return 0; __asctime(timebuf, timeptr); return timebuf; } dev86-0.16.21/libc/time/ctime.c000066400000000000000000000005651231050321700157310ustar00rootroot00000000000000 #include extern void __tm_conv(); extern void __asctime(); char * ctime(timep) __const time_t * timep; { static char cbuf[26]; struct tm tmb; struct timezone tz; time_t offt; gettimeofday((void*)0, &tz); offt = -tz.tz_minuteswest*60L; /* tmb.tm_isdst = ? */ __tm_conv(&tmb, timep, offt); __asctime(cbuf, &tmb); return cbuf; } dev86-0.16.21/libc/time/gmtime.c000066400000000000000000000002561231050321700161070ustar00rootroot00000000000000 #include extern void __tm_conv(); struct tm * gmtime(timep) __const time_t * timep; { static struct tm tmb; __tm_conv(&tmb, timep, 0L); return &tmb; } dev86-0.16.21/libc/time/localtime.c000066400000000000000000000004701231050321700165740ustar00rootroot00000000000000 #include extern void __tm_conv(); struct tm * localtime(timep) __const time_t * timep; { static struct tm tmb; struct timezone tz; time_t offt; gettimeofday((void*)0, &tz); offt = -tz.tz_minuteswest*60L; /* tmb.tm_isdst = ? */ __tm_conv(&tmb, timep, offt); return &tmb; } dev86-0.16.21/libc/time/tm_conv.c000066400000000000000000000053531231050321700162750ustar00rootroot00000000000000 #if 0 #include /* This is a translation from ALGOL in Collected Algorithms of CACM. */ /* Copied from Algorithm 199, Author: Robert G. Tantzen */ void __tm_conv(tmbuf, timep, offset) struct tm *tmbuf; time_t *timep; time_t offset; { static int moffset[] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}; long s; long j, d, m, y; offset += *timep; tmbuf->tm_isdst = 0; /* Someone else can set this */ j = offset / 86400L + 719469; s = offset % 86400L; if( s < 0 ) { s += 86400L; j--; } tmbuf->tm_sec = s % 60; tmbuf->tm_min = (s / 60) % 60; tmbuf->tm_hour = s / 3600; tmbuf->tm_wday = (j+2) % 7; /* * Julian date converter. Takes a julian date (the number of days since * some distant epoch or other), and fills tmbuf. */ y = (4L * j - 1L) / 146097L; j = 4L * j - 1L - 146097L * y; d = j / 4L; j = (4L * d + 3L) / 1461L; d = 4L * d + 3L - 1461L * j; d = (d + 4L) / 4L; m = (5L * d - 3L) / 153L; d = 5L * d - 3 - 153L * m; d = (d + 5L) / 5L; y = 100L * y + j; if (m < 10) m += 2; else { m -= 10; ++y; } tmbuf->tm_year = y - 1900; tmbuf->tm_mon = m; tmbuf->tm_mday = d; tmbuf->tm_yday = d + moffset[m]; if (m > 1 && ((y) % 4 == 0 && ((y) % 100 != 0 || (y) % 400 == 0))) tmbuf->tm_yday++; } #else /* This is adapted from glibc */ /* Copyright (C) 1991, 1993 Free Software Foundation, Inc */ #define SECS_PER_HOUR 3600L #define SECS_PER_DAY 86400L #include static const unsigned short int __mon_lengths[2][12] = { /* Normal years. */ { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, /* Leap years. */ { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } }; void __tm_conv(tmbuf, t, offset) struct tm *tmbuf; time_t *t; time_t offset; { long days, rem; register int y; register unsigned short int *ip; days = *t / SECS_PER_DAY; rem = *t % SECS_PER_DAY; rem += offset; while (rem < 0) { rem += SECS_PER_DAY; --days; } while (rem >= SECS_PER_DAY) { rem -= SECS_PER_DAY; ++days; } tmbuf->tm_hour = rem / SECS_PER_HOUR; rem %= SECS_PER_HOUR; tmbuf->tm_min = rem / 60; tmbuf->tm_sec = rem % 60; /* January 1, 1970 was a Thursday. */ tmbuf->tm_wday = (4 + days) % 7; if (tmbuf->tm_wday < 0) tmbuf->tm_wday += 7; y = 1970; while (days >= (rem = __isleap(y) ? 366 : 365)) { ++y; days -= rem; } while (days < 0) { --y; days += __isleap(y) ? 366 : 365; } tmbuf->tm_year = y - 1900; tmbuf->tm_yday = days; ip = __mon_lengths[__isleap(y)]; for (y = 0; days >= ip[y]; ++y) days -= ip[y]; tmbuf->tm_mon = y; tmbuf->tm_mday = days + 1; tmbuf->tm_isdst = -1; } #endif dev86-0.16.21/libcompat000066400000000000000000000006321231050321700145050ustar00rootroot00000000000000#!/bin/sh - FILES="$*" [ "$FILES" = "" ] && FILES="lib/*.a" for i in $FILES do ID="`dd bs=8 count=1 < $i 2>/dev/null | cat -v`" [ "$ID" != "!" ] && { make ld86r || exit $? echo Translating archive $i rm -rf libconv.d mkdir libconv.d cd libconv.d ar x ../$i cd .. bin/ld86r -o $i libconv.d/* || exit $? rm -rf libconv.d } done exit 0 dev86-0.16.21/makefile.in000066400000000000000000000233351231050321700147220ustar00rootroot00000000000000#ifdef COMMENT ############################################################################## # # This Makefile has been completely re-vamped. Two reasons, first to allow # for a full compile before installation, hence allowing us to make a binary # distribution without installing and second to allow proper dependancy trees # for the different versions of the library. # # As an aside, it would be useful if I could avoid GNU-make constucts. # ############################################################################## #endif # Defaults, generic C ARFLAGS =r CC =%CC% CFLAGS =%CFLAGS% LDFLAGS = MAKEARG =CC='$(CC)' CFLAGS='$(CFLAGS)' LDFLAGS='$(LDFLAGS)' \ PREFIX=$(PREFIX) LIBDIR='$(LIBDIR)' \ BINDIR='$(BINDIR)' ANSI='$(ANSI)' MAKEC=$(MAKE) -C MAKEX= # This is only allowed on Linux because make needs to know how to look # inside an archive to get the last modified times of the component .o # files. This should be fine for Linux, but it won't be for AIX etc. # Unfortunatly it's even _required_ for linux because some versions # have a broken standard ar command. Ie they barf if given something # they think is not an a.out. #ifdef __linux__ AR=ar86 #endif #ifdef __GNUC__ CC =%CC% #ifdef GCCDB WALL =-Wall -Wtraditional -Wshadow -Wpointer-arith \ -Wcast-qual -Wcast-align -Wconversion -Waggregate-return \ -Wstrict-prototypes -Wmissing-prototypes -Wredundant-decls \ -Wnested-externs -Winline CFLAGS =$(GCCFLAG) $(WALL) -O2 -g #else WALL =-Wall -Wstrict-prototypes CFLAGS =$(GCCFLAG) -O2 -fno-strict-aliasing #endif #endif #ifndef GNUMAKE MAKEC=sh makec MAKEX=makec #endif #ifdef __minix # Minix make doesn't understand -C, cc runs out of memory with the headers. MAKEC=ash makec MAKEX=makec CFLAGS=-O -m -w -DPOSIX_HEADERS_MISSING -DVERY_SMALL_MEMORY #endif #ifdef __BCC__ ANSI =-ansi #ifdef __AS386_32__ CFLAGS =-Ml LDFLAGS =-Ml -s #else CFLAGS =-O LDFLAGS =-s -H10000 BCCARCH = #endif #endif # Apple cpp-precomp 6.14 (devkit-213/devkit_tools-214) cannot # handle the QUOT macro in bcc. It puts a space in /usr so that # it becomes / usr #ifdef __APPLE__ CFLAGS += -no-cpp-precomp #endif # Install files with the userid of the currently running process. INDAT=-m 644 INEXE=-m 755 -s INSCR=-m 755 #ifdef __CYGWIN__ EXE=.exe #else EXE= #endif #ifdef GNUMAKE all: check_config bcc86 cpp unproto copt as86 ar86 ld86 objdump86 \ library lib-bsd alt-libs elksemu install: check_config install-bcc install-man \ install-lib install-emu install-all: install install-other #else all: check_config bcc86 cpp unproto copt as86 ar86 ld86 objdump86 @echo @echo 'NOTE: To build the libraries you need GNU-Make.' @echo ' They are available precompiled in the Dev86clb-X.X.X.zip file.' install install-all: check_config install-bcc install-man @echo @echo 'NOTE: To build the libraries you need GNU-Make.' @echo ' They are available precompiled in the Dev86clb-X.X.X.zip file.' #endif ############################################################################## LIBARGS= CC=ncc "CCFLAGS=-O" AR=$(AR) ARFLAGS=$(ARFLAGS) LIB3ARGS= CC=ncc AR=$(AR) ARFLAGS=$(ARFLAGS) # Season in the top makefile ELKSSRC= %ELKSSRC% PREFIX= %PREFIX% BINDIR= %BINDIR% LIBDIR= %LIBDIR% INCLDIR= %INCLDIR% ASLDDIR= %ASLDDIR% MANDIR= %MANDIR% #ifdef GNUMAKE export ELKSSRC #endif DISTBIN= $(DIST)$(BINDIR) DISTLIB= $(DIST)$(LIBDIR) DISTASLD=$(DIST)$(ASLDDIR) DISTINCL=$(DIST)$(INCLDIR) # Others to install OTHERS= tests dis88 doselks bootblocks CLEANLIST= bcc as ar ld cpp unproto copt libc elksemu libbsd $(OTHERS) ############################################################################## bindir: $(MAKEX) @mkdir -p bin lib lib/i386 @rm -f include @ln -s libc/include include 2>/dev/null || true #ifndef GNUMAKE @rm -f include/linuxmt include/arch || true @ln -s ../kinclude/linuxmt include/linuxmt 2>/dev/null || true @ln -s ../kinclude/arch include/arch 2>/dev/null || true #endif bcc86: bindir versions $(MAKEC) bcc $(MAKEARG) BCCARCH='$(BCCARCH)' bcc ncc bcc-cc1 cp -p bcc/bcc$(EXE) bin/Bcc$(EXE) cp -p bcc/ncc$(EXE) bin/ncc$(EXE) cp -p bcc/bcc-cc1$(EXE) lib/bcc-cc1$(EXE) cpp: bindir $(MAKEC) cpp $(MAKEARG) bcc-cpp cp -p cpp/bcc-cpp$(EXE) lib/bcc-cpp$(EXE) unproto: bindir $(MAKEC) unproto $(MAKEARG) unproto cp -p unproto/unproto$(EXE) lib/unproto$(EXE) copt: bindir $(MAKEC) copt $(MAKEARG) copt cp -p copt/copt$(EXE) lib/copt$(EXE) cp -p copt/rules.* lib/. cp -p copt/rules.start lib/i386/. cp -p copt/rules.386 lib/i386/. cp -p copt/rules.end lib/i386/. as86: bindir versions $(MAKEC) as $(MAKEARG) all cp -p as/as86$(EXE) bin/as86$(EXE) cp -p as/as86_encap bin/as86_encap ar86: bindir $(MAKEC) ar $(MAKEARG) all cp -p ar/ar86$(EXE) bin/ar86$(EXE) ld86: bindir versions $(MAKEC) ld $(MAKEARG) ld86 cp -p ld/ld86$(EXE) bin/ld86$(EXE) ld86r: bindir $(MAKEC) ld $(MAKEARG) ld86r cp -p ld/ld86r$(EXE) bin/ld86r$(EXE) objdump86: bindir $(MAKEC) ld $(MAKEARG) objdump86 cp -p ld/objdump86$(EXE) bin/objdump86$(EXE) #ifndef __AS386_16__ #ifdef __elksemu_works__ elksemu: bindir $(MAKEC) elksemu elksemu cp -p elksemu/elksemu bin/elksemu #else try_elksemu: bindir $(MAKEC) elksemu CC='ncc' elksemu cp -p elksemu/elksemu bin/elksemu #endif #endif install-bcc: bcc86 cpp unproto copt as86 ar86 ld86 objdump86 install -d $(DISTBIN) $(DISTLIB) install $(INEXE) bin/Bcc$(EXE) $(DISTBIN)/bcc$(EXE) install $(INEXE) bin/as86$(EXE) $(DISTASLD)/as86$(EXE) install $(INEXE) bin/ld86$(EXE) $(DISTASLD)/ld86$(EXE) install $(INEXE) bin/ar86$(EXE) $(DISTBIN)/ar86$(EXE) install $(INEXE) bin/objdump86$(EXE) $(DISTBIN)/objdump86$(EXE) install $(INEXE) bin/objdump86$(EXE) $(DISTBIN)/nm86$(EXE) install $(INEXE) bin/objdump86$(EXE) $(DISTBIN)/size86$(EXE) install $(INSCR) bin/as86_encap $(DISTLIB)/as86_encap install $(INEXE) lib/bcc-cc1$(EXE) $(DISTLIB)/bcc-cc1$(EXE) install $(INEXE) lib/bcc-cpp$(EXE) $(DISTLIB)/bcc-cpp$(EXE) install $(INEXE) lib/unproto$(EXE) $(DISTLIB)/unproto$(EXE) install $(INEXE) lib/copt$(EXE) $(DISTLIB)/copt$(EXE) install $(INDAT) lib/rules.* $(DISTLIB) install -d $(DISTLIB)/i386 install $(INDAT) lib/i386/rules.* $(DISTLIB)/i386 # NB: This doesn't install as a suid root, that's ok though. install-emu: elksemu #ifdef __elksemu_works__ install -d $(DISTBIN) install $(INEXE) bin/elksemu $(DISTBIN)/elksemu #endif install-man: -$(MAKEC) man MANDIR=$(DIST)$(MANDIR) install install-lib: lib/lib0-done lib/lib2-done lib/lib1-done $(MAKEC) libc $(LIBARGS) DISTINCL=$(DISTINCL) install_incl install $(INDAT) lib/crt0.o $(DISTLIB)/crt0.o install $(INDAT) lib/libc.a $(DISTLIB)/libc.a install $(INDAT) lib/libc_f.a $(DISTLIB)/libc_f.a install $(INDAT) lib/libc_s.a $(DISTLIB)/libc_s.a install $(INDAT) lib/libbsd.a $(DISTLIB)/libbsd.a install $(INDAT) lib/libdos.a $(DISTLIB)/libdos.a install $(INDAT) lib/libbcc.a $(DISTLIB)/libbcc.a #ifndef __AS386_16__ install -d $(DISTLIB)/i386 install $(INDAT) lib/i386/crt0.o $(DISTLIB)/i386/crt0.o install $(INDAT) lib/i386/libc.a $(DISTLIB)/i386/libc.a #endif lib/lib0-done: $(MAKE) -f make.fil library lib/lib1-done: $(MAKE) -f make.fil alt-libs lib/lib2-done: $(MAKE) -f make.fil lib-bsd all-libs: library lib-bsd alt-libs @: library: bindir test -f bin/ncc $(MAKEC) libc $(LIBARGS) PLATFORM=i86-ELKS cp -p libc/crt0.o libc/libc.a libc/libbcc.a lib/. sh libcompat lib/libc.a @touch lib/lib0-done lib-bsd: bindir test -f bin/ncc $(MAKEC) libbsd $(LIBARGS) cp -p libbsd/libbsd.a lib/libbsd.a sh libcompat lib/libbsd.a @touch lib/lib2-done #ifdef __AS386_16__ alt-libs: lib-stand lib-dos lib-fast @touch lib/lib1-done #else alt-libs: lib-stand lib-dos lib-386 lib-fast @touch lib/lib1-done #endif lib-fast: bindir test -f bin/ncc $(MAKEC) libc $(LIBARGS) PLATFORM=i86-FAST cp -p libc/libc_f.a lib/libc_f.a sh libcompat lib/libc_f.a lib-stand: bindir test -f bin/ncc $(MAKEC) libc $(LIBARGS) PLATFORM=i86-BIOS cp -p libc/libc_s.a lib/libc_s.a sh libcompat lib/libc_s.a lib-dos: bindir test -f bin/ncc $(MAKEC) libc $(LIBARGS) PLATFORM=i86-DOS cp -p libc/libdos.a lib/libdos.a sh libcompat lib/libdos.a lib-386: bindir test -f bin/ncc $(MAKEC) libc $(LIB3ARGS) PLATFORM=i386-BCC cp -p libc/crt3.o lib/i386/crt0.o cp -p libc/libc3.a lib/i386/libc.a sh libcompat lib/i386/libc.a ############################################################################## #ifdef GNUMAKE check_config: $(MAKEX) $(MAKEC) libc .config.dir config: $(MAKEX) $(MAKEC) libc config #else check_config: ; config: ; #endif makec: echo 'cd $$1 ; shift ; make "$$@"' > makec chmod +x makec versions: bcc/version.h bcc/version.h: Makefile echo '#define VERSION "'"$(VERSION)"'"' > bcc/version.h echo '#define VERSION "'"$(VERSION)"'"' > as/version.h echo '#define VERSION "'"$(VERSION)"'"' > bootblocks/version.h echo '#define VERSION "'"$(VERSION)"'"' > ld/version.h VER=$(VERSION) ; \ echo "#define VER_MAJ $${VER%%.*}" >> bcc/version.h ; \ VER="$${VER#*.}" ; \ echo "#define VER_MIN $${VER%.*}" >> bcc/version.h ; \ echo "#define VER_PAT $${VER#*.}" >> bcc/version.h ############################################################################## install-other: other @for i in $(OTHERS) ; do \ $(MAKEC) $$i BCC=ncc DIST=$(DIST) PREFIX=$(PREFIX) install || exit 1 ; \ done other: versions @for i in $(OTHERS) ; do \ $(MAKEC) $$i BCC=ncc DIST=$(DIST) PREFIX=$(PREFIX) || exit 1; \ done ############################################################################## clean: -@for i in $(CLEANLIST) ; do $(MAKEC) $$i $@ ; true ; done realclean: -@for i in $(CLEANLIST) ; do $(MAKEC) $$i $@ ; true ; done rm -rf bin lib rm -f include rm -f makec rm -f `find $(CLEANLIST) -type l -print` rm -f bcc/version.h rm -f as/version.h rm -f ld/version.h rm -f bootblocks/version.h ############################################################################## dev86-0.16.21/man/000077500000000000000000000000001231050321700133625ustar00rootroot00000000000000dev86-0.16.21/man/Makefile000066400000000000000000000002621231050321700150220ustar00rootroot00000000000000 MANDIR=/usr/man MAN1PG=as86.1 bcc.1 elks.1 elksemu.1 ld86.1 MAN1DIR=$(MANDIR)/man1 all: install: install -m 755 -d $(MAN1DIR) install -m 644 $(MAN1PG) $(MAN1DIR) clean: dev86-0.16.21/man/as86.1000066400000000000000000000275471231050321700142440ustar00rootroot00000000000000.TH as86 1 "Mar, 1999" .BY Bruce Evans, Robert de Bath .nh .SH NAME as86 \- Assembler for 8086..80386 processors .SH SYNOPSIS .B as86 .RB [ -0123agjuw ] .RB [ -lm [ list ]] .RB [ -n\ name ] .RB [ -o\ obj ] .RB [ -b [ bin ]] .RB [ -s\ sym ] .RB [ -t\ textseg ] .B src .B as86_encap\ prog.s\ prog.v .RB [ prefix_ ] .RB [ as86_options ] .SH DESCRIPTION .B as86 is an assembler for the 8086..80386 processors, it's syntax is closer to the intel/microsoft form rather than the more normal generic form of the unix system assembler. The .B src file can be '-' to assemble the standard input. This assembler can be compiled to support the 6809 cpu and may even work. .B as86_encap is a shell script to call as86 and convert the created binary into a C file .B prog.v to be included in or linked with programs like boot block installers. The .B prefix_ argument is a prefix to be added to all variables defined by the source, it defaults to the name of the source file. The variables defined include .B prefix_start .B prefix_size and .B prefix_data to define and contain the code, plus integers containing the values of all exported labels. Either or both the .B prog.s and .B prog.v arguments can be '-' for standard in/out. .\" The 'src' file can be '-' for stdin but ONLY on 'big' machines. .SH OPTIONS .\"defaults (off or none except for these; no output is produced without a flag): .\"-03 native .\"list stdout (beware of clobbering next arg) .\"name basename of the source name .TP .B -0 start with 16-bit code segment, warn for all instructions > 8086 .TP .B -1 start with 16-bit code segment, warn for all instructions > 80186 .TP .B -2 start with 16-bit code segment, warn for all instructions > 80286 .TP .B -3 start with 32-bit code segment, don't warn for any instructions. (not even 486 or 586) .TP .B -a enable partial compatibility with Minix asld. This swaps the interpretation of round brackets and square brackets as well as making alterations to the code generation and syntax for 16bit jumps and calls. ("jmp @(bx)" is then a valid instruction) .TP .B -g only put global symbols in object or symbol file .TP .B -j replace all short jumps with similar 16 or 32 bit jumps, the 16 bit conditional branches are encoded as a short conditional and a long unconditional branch. .TP .B -O this causes the assembler to add extra passes to try to use forward references to reduce the bytes needed for some instructions. If the labels move on the last pass the assembler will keep adding passes until the labels all stabilise (to a maximum of 30 passes) It's probably not a good idea to use this with hand written assembler use the explicit .B br\ bmi\ bcc style opcodes for 8086 code or the .B jmp\ near style for conditional i386 instructions and make sure all variables are defined before they are used. .TP .B -l produce list file, filename may follow .TP .B -m print macro expansions in listing .TP .B -n name of module follows (goes in object instead of source name) .TP .B -o produce object file, filename follows .TP .B -b produce a raw binary file, filename may follow. This is a 'raw' binary file with no header, if there's no .B -s option the file starts at location 0. .TP .B -s produce an ASCII symbol file, filename follows. The format of this table is designed to be easy to parse for encapsulation and related activities in relation to binary files created with the .B -b option. If a binary file doesn't start at location zero the first two items in the table are the start and end addresses of the binary file. .TP .B -u assume undefined symbols are imported-with-unspecified segment. .TP .B -w- allow the assembler to print warning messages. .TP .B -t n move all text segment data in segment n+3. .P .SH AS86 SOURCE Special characters .TP .B * Address of the start of the current line. .TP .B ; ! Either of these marks the start of a comment. In addition any 'unexpected' character at the start of a line is assumed to be a comment (but it's also displayed to the terminal). .TP .B $ Prefix for hexadecimal numbers, the 'C' syntax, eg\ 0x1234, is also accepted. .TP .B % Prefix for binary numbers. .TP .B # Prefix for immediate operands. .TP .B [ ] Specifies an indirect operand. .br Unlike MASM the assembler has no type information on labels just a segment and offset. This means that the way this operator and the immediate prefix work are like traditional assemblers. .sp Examples: .br mov ax,bx .br jmp bx .br Direct register addressing, the jump copies BX into PC. .sp .nf mov ax,[bx] jmp [bx] .fi Simple indirect register addressing, the jump moves the contents of the location specified by BX into the PC. .sp mov ax,#1234 .br Immediate value, ax becomes 1234. .sp .nf mov ax,1234 mov ax,_hello mov ax,[_hello] .fi Absolute addressing, ax is set to contents of location 1234. Note the third option is not strictly consistant but is in place mainly for asld compatibility. .sp .nf mov ax,_table[bx] mov ax,_table[bx+si] mov eax,_table[ebx*4] mov ax,[bx+_table] mov ax,[bx+si+_table] mov eax,[ebx*4+_table] .fi Indexed addressing, both formats are ok, I think the first is more correct but I tend to used the second. :-) .br .P Conditionals .TP .B IF, ELSE, ELSEIF, ENDIF Numeric condition .TP .B IFC, ELSEIFC String compare (str1,str2) .TP .B FAIL .FAIL Generate user error. .P Segment related .TP .B .TEXT .ROM .DATA .BSS Set current segment. These can be preceded by the keyword .B .SECT .TP .B LOC Set numeric segment 0=TEXT, 3=DATA,ROM,BSS, 14=MAX. The segment order set by the linker is now 0,4,5,6,7,8,9,A,B,C,D,E,1,2,3. Segment 0 and all segments above 3 are assumed to be text segment. Note the 64k size restrictions are not imposed for segments 3-14. .P Label type definition .TP .B EXPORT PUBLIC .DEFINE Export label defined in this object .TP .B ENTRY Force linker to include the specified label in a.out .TP .B .GLOBL .GLOBAL Define label as external and force import even if it isn't used. .TP .B EXTRN EXTERN IMPORT .EXTERN Import list of externally defined labels .br NB: It doesn't make sense to use imports for raw binary files. .TP .B .ENTER Mark entry for old binary file (obs) .P Data definition .TP .B DB .DATA1 .BYTE FCB List of 1 byte objects. .TP .B DW .DATA2 .SHORT FDB .WORD List of 2 byte objects. .TP .B DD .DATA4 .LONG List of 4 byte objects. .TP .B .ASCII FCC Ascii string copied to output. .TP .B .ASCIZ Ascii string copied to output with trailing .B nul byte. .P Space definition .TP .B .BLKB RMB .SPACE Space is counted in bytes. .TP .B .BLKW .ZEROW Space is counted in words. (2 bytes each) .TP .B COMM .COMM LCOMM .LCOMM Common area data definition .P Other useful pseudo operations. .TP .B .ALIGN .EVEN Alignment .TP .B EQU Define label .TP .B SET Define re-definable label .TP .B ORG .ORG Set assemble location .TP .B BLOCK Set assemble location and stack old one .TP .B ENDB Return to stacked assemble location .TP .B GET INCLUDE Insert new file (no quotes on name) .TP .BR USE16\ [ cpu ] Define default operand size as 16 bit, argument is cpu type the code is expected to run on (86, 186, 286, 386, 486, 586) instructions for cpus later than specified give a warning. .TP .BR USE32\ [ cpu ] Define default operand size as 32 bit, argument is cpu type the code is expected to run on (86, 186, 286, 386, 486, 586) instructions for cpus later than specified give a warning. If the cpu is not mentioned the assembler ensures it is >= 80386. .TP .B END End of compilation for this file. .TP .B .WARN Switch warnings .TP .B .LIST Listings on/off (1,-1) .TP .B .MACLIST Macro listings on/off (1,-1) .P Macros, now working, the general form is like this. MACRO sax mov ax,#?1 MEND sax(1) .TP Unimplemented/unused. .TP IDENT Define object identity string. .TP SETDP Set DP value on 6809 .TP MAP Set binary symbol table map number. .TP Registers .br BP BX DI SI .br EAX EBP EBX ECX EDI EDX ESI ESP .br AX CX DX SP .br AH AL BH BL CH CL DH DL .br CS DS ES FS GS SS .br CR0 CR2 CR3 DR0 DR1 DR2 DR3 DR6 DR7 .br TR3 TR4 TR5 TR6 TR7 ST .TP Operand type specifiers BYTE DWORD FWORD FAR PTR PWORD QWORD TBYTE WORD NEAR .sp The 'near and 'far' do not allow multi-segment programming, all 'far' operations are specified explicitly through the use of the instructions: jmpi, jmpf, callf, retf, etc. The 'Near' operator can be used to force the use of 80386 16bit conditional branches. The 'Dword' and 'word' operators can control the size of operands on far jumps and calls. .TP General instructions. These are in general the same as the instructions found in any 8086 assembler, the main exceptions being a few 'Bcc' (BCC, BNE, BGE, etc) instructions which are shorthands for a short branch plus a long jump and 'BR' which is the longest unconditional jump (16 or 32 bit). .TP Long branches BCC BCS BEQ BGE BGT BHI BHIS BLE BLO BLOS BLT BMI BNE BPC BPL BPS BVC BVS BR .TP Intersegment CALLI CALLF JMPI JMPF .TP Segment modifier instructions ESEG FSEG GSEG SSEG .TP Byte operation instructions ADCB ADDB ANDB CMPB DECB DIVB IDIVB IMULB INB INCB MOVB MULB NEGB NOTB ORB OUTB RCLB RCRB ROLB RORB SALB SARB SHLB SHRB SBBB SUBB TESTB XCHGB XORB .TP Standard instructions AAA AAD AAM AAS ADC ADD AND ARPL BOUND BSF BSR BSWAP BT BTC BTR BTS CALL CBW CDQ CLC CLD CLI CLTS CMC CMP CMPS CMPSB CMPSD CMPSW CMPW CMPXCHG CSEG CWD CWDE DAA DAS DEC DIV DSEG ENTER HLT IDIV IMUL IN INC INS INSB INSD INSW INT INTO INVD INVLPG INW IRET IRETD J JA JAE JB JBE JC JCXE JCXZ JE JECXE JECXZ JG JGE JL JLE JMP JNA JNAE JNB JNBE JNC JNE JNG JNGE JNL JNLE JNO JNP JNS JNZ JO JP JPE JPO JS JZ LAHF LAR LDS LEA LEAVE LES LFS LGDT LGS LIDT LLDT LMSW LOCK LODB LODS LODSB LODSD LODSW LODW LOOP LOOPE LOOPNE LOOPNZ LOOPZ LSL LSS LTR MOV MOVS MOVSB MOVSD MOVSW MOVSX MOVW MOVZX MUL NEG NOP NOT OR OUT OUTS OUTSB OUTSD OUTSW OUTW POP POPA POPAD POPF POPFD PUSH PUSHA PUSHAD PUSHF PUSHFD RCL RCR RDMSR REP REPE REPNE REPNZ REPZ RET RETF RETI ROL ROR SAHF SAL SAR SBB SCAB SCAS SCASB SCASD SCASW SCAW SEG SETA SETAE SETB SETBE SETC SETE SETG SETGE SETL SETLE SETNA SETNAE SETNB SETNBE SETNC SETNE SETNG SETNGE SETNL SETNLE SETNO SETNP SETNS SETNZ SETO SETP SETPE SETPO SETS SETZ SGDT SHL SHLD SHR SHRD SIDT SLDT SMSW STC STD STI STOB STOS STOSB STOSD STOSW STOW STR SUB TEST VERR VERW WAIT WBINVD WRMSR XADD XCHG XLAT XLATB XOR .TP Floating point F2XM1 FABS FADD FADDP FBLD FBSTP FCHS FCLEX FCOM FCOMP FCOMPP FCOS FDECSTP FDISI FDIV FDIVP FDIVR FDIVRP FENI FFREE FIADD FICOM FICOMP FIDIV FIDIVR FILD FIMUL FINCSTP FINIT FIST FISTP FISUB FISUBR FLD FLD1 FLDL2E FLDL2T FLDCW FLDENV FLDLG2 FLDLN2 FLDPI FLDZ FMUL FMULP FNCLEX FNDISI FNENI FNINIT FNOP FNSAVE FNSTCW FNSTENV FNSTSW FPATAN FPREM FPREM1 FPTAN FRNDINT FRSTOR FSAVE FSCALE FSETPM FSIN FSINCOS FSQRT FST FSTCW FSTENV FSTP FSTSW FSUB FSUBP FSUBR FSUBRP FTST FUCOM FUCOMP FUCOMPP FWAIT FXAM FXCH FXTRACT FYL2X FYL2XP1 .P .SH Using GASP The Gnu assembler preprocessor provides some reasonable implementations of user biased pseudo opcodes. It can be invoked in a form similar to: .TP .B gasp .RB [ -a... ] .B file.s .RB [ file2.s ] .B | .br .B as86 .RB [ ... ] .B - .RB [ -o\ obj ]\ [ -b\ bin ] .P Be aware though that Gasp generates an error for .B .org commands, if you're not using alternate syntax you can use .B org instead, otherwise use .BR block and .BR endb . The directive .B export is translated into .BR .global , which forces an import, if you are making a file using .B -b use .B public or .B .define instead. The GASP list options have no support in as86. .SH SEE ALSO as(1), ld86(1), bcc(1) .SH BUGS The 6809 version does not support -0, -3, -a or -j. If this assembler is compiled with BCC this is classed as a 'small' compiler, so there is a maximum input line length of 256 characters and the instruction to cpu checking is not included. The checking for instructions that work on specific cpus is probably not complete, the distinction between 80186 and 80286 is especially problematic. The .B .text and .B .data pseudo operators are not useful for raw binary files. When using the .B org directive the assembler can generate object files that may break ld86(1). dev86-0.16.21/man/bcc.1000066400000000000000000000214431231050321700141770ustar00rootroot00000000000000.TH bcc 1 "Nov, 1997" .BY Bruce Evans .nh .SH NAME bcc \- Bruce's C compiler .SH SYNOPSIS .B bcc .RB [ -03EGNOPSVcegvwxW ] .RB [ -Aas_option ] .RB [ -Bexecutable_prefix ] .RB [ -Ddefine ] .RB [ -Uundef ] .RB [ -Mc_mode ] .RB [ -o\ outfile ] .RB [ -ansi ] .RB [ -Ccc1_option ] .RB [ -Pcpp_option ] .RB [ -Iinclude_dir ] .RB [ -Lld_option ] .RB [ -Ttmpdir ] .RB [ -Qc386_option ] .RB [ -ttext_segno ] .RB [ ld_options ] .RB [ infiles ] .SH DESCRIPTION .B Bcc is a simple C compiler that produces 8086 assembler, in addition compiler compile time options allow 80386 or 6809 versions. The compiler understands traditional K&R C with just the restriction that bit fields are mapped to one of the other integer types. The default operation is to produce an 8086 executable called .B a.out from the source file. .SH OPTIONS .TP .B -ansi Pass the C source through .B unprotoize after preprocessing and before code generation. This will allow .I some ansi C to be compiled but it is definitly .B NOT a true ansi-C compiler. .TP .B -0 8086 target (works on 80386 host, but not 6809) .TP .B -3 80386 target (may work on 8086 host, but not 6809) .TP .B -A pass remainder of option to assembler (e.g. -A-l -Alistfile for a listing) .TP .B -B prefix for executable search path (as usual; the search order is all paths specified using .BR -B , in order, then the path given in the environment variable .B BCC_EXEC_PREFIX if that is set, then the compiled-in defaults (something like /usr/lib/bcc/ followed by /usr/bin/) .TP .B -C pass remainder of option to bcc-cc1, see code generation options. .TP .B -D preprocessor define .TP .B -E produce preprocessor output to standard out. .TP .B -G produce GCC objects (Same as -Mg) .TP .B -Ixyz include search 'xyz' path .TP .B -I don't add default include to search list .TP .B -Lxyz add directory name 'xyz' to the head of the list of library directories searched .TP .B -L don't add default library to search list .TP .B -Md alters the arguments for all passes to produce MSDOS executable COM files. These are small model executables, use .B -i to get tiny model. .TP .B -Mf sets bcc to pass the .B -c and .B -f arguments to the code generator for smaller faster code. Note this code is not compatible with the standard calling conventions so a different version of the C library is linked too. .TP .B -Mc sets bcc to pass the .B -c argument to the code generator for smaller faster code. Note the standard libc is normally transparent to this, but there are exceptions. .TP .B -Ms alters the arguments for all passes and selects C-library to produce standalone Linux-86 executables .TP .B -Ml switches to i386-Linux code generator and library. This configuration accepts the .B -z flag to generate QMAGIC a.out files instead of the normal OMAGIC. .TP .B -Mg switches to i386-Linux code generator and generates OMAGIC object files that can be linked with some versions of gcc; unfortunatly the most recent versions use 'collect2' to link and this crashes. .TP .B -N makes the linker produce a native a.out file (Linux OMAGIC) if combined with -3 the executable will run under Linux-i386. .TP .B -O optimize, call .BR copt ( 1 ) to optimize 8086 code. Specifiers to choose which rules .B copt should use can be appended to the .B -O and the option can be repeated. .TP .B -P produce preprocessor output with no line numbers to standard output. .TP .B -Q pass full option to c386 (Only for c386 version) .TP .B -S produce assembler file .TP .B -T temporary directory (overrides previous value and default; default is from the environment variable TMPDIR if that is set, otherwise /tmp) .TP .B -U preprocessor undefine .TP .B -V print names of files being compiled .TP .B -X pass remainder of option to linker (e.g. -X-Ofile is passed to the linker as -Ofile) .TP .B -c produce object file .TP .B -f turn on floating point support, no effect with i386, changes libc library with 8086 code. .TP .B -g produce debugging info (ignored.) .TP .B -o output file name follows (assembler, object or executable) (as usual) .TP .B -p produce profiling info (ignored.) .TP .B -t1 pass to the assembler to renumber the text segment for multi-segment programs. .TP .B -v print names and args of subprocesses being run. Two or more -v's print names of files being unlinked. Three or more -v's print names of paths being searched. .TP .B -w Supress any warning diagnostics. .TP .B -W Turn .B on assembler warning messages. .TP .B -x don't include crt0.o in the link. .TP .B -i don't pass .B -i to the linker so that it will create an impure executable. .TP .B -7 Turn on ancient C mode (see CODE GENERATOR OPTIONS below). Among other things, this disables valuable error checks and even parses certain constructs incompatibly (e.g. .I =- is postdecrement instead of an assignment of a negative number) to later C standards, so this option should only be used with ancient code. To generate executables for a V7 variant you should tell linker to generate old a.out header with .B -X-7 option. .P Other options are passed to the linker, in particular -lx, -M, -m, -s, -H. .SH CODE GENERATOR OPTIONS These are all options that the code generator pass .B bcc-cc1 understands, only some will be useful for the .B -C option of bcc. .TP .B -0 8086 target (works even on 80386 host, not on 6809) .TP .B -3 80386 target (may work even on 8086 host, not on 6809) .TP .B -D define (as usual) .TP .B -E produce preprocessor output (as usual) .TP .B -I include search path (as usual) .TP .B -P produce preprocessor output with no line numbers (as usual) .TP .B -c produce code with caller saving regs before function calls .TP .B -d print debugging information in assembly output .TP .B -f produce code with 1st argument passed in a register (AX, EAX or X) .TP .B -l produce code for 2 3 1 0 long byte order (only works in 16-bit code), a special library of compiler helper functions is needed for this mode. .TP .B -o assembler output file name follows .TP .B -p produce (almost) position-independent code (only for the 6809) .TP .B -t print source code in assembly output .TP .B -w print what cc1 thinks is the location counter in assembly output .TP .B -7 Accept various obsolete construct for ancient C compilers, including Ritchie's Sixth Edition UNIX C compiler and Seventh Edition UNIX Portable C compiler. Enough of these compilers is emulated to compile all of Seventh Edition userspace and kernel. .P All the options except -D, -I and -o may be turned off by following the option letter by a '-'. Options are processed left to right so the last setting has precedence. .SH PREPROCESSOR DEFINES The preprocessor has a number of manifest constants. .TP .B __BCC__ 1 The compiler identifier, normally used to avoid compiler limitations. .TP .B __FILE__ stringized name of current input file .TP .B __LINE__ current line number .TP .B __MSDOS__ 1 compiler is configured for generating MSDOS executable COM files. .TP .B __STANDALONE__ 1 compiler is configured for generating standalone executables. .TP .B __AS386_16__ 1 compiler is generating 16 bit 8086 assembler and the .B #asm keyword is available for including 8086 code. .TP .B __AS386_32__ 1 compiler is generating 32 bit 80386 assembler and the .B #asm keyword is available for including 80386 code. .TP .B __CALLER_SAVES__ 1 compiler calling conventions are altered so the calling function must save the .I SI and .I DI registers if they are in use (ESI and EDI on the 80386) .TP .B __FIRST_ARG_IN_AX__ 1 compiler calling conventions are altered so the calling function is passing the first argument to the function in the .I AX (or .I EAX ) register. .TP .B __LONG_BIG_ENDIAN__ 1 alters the word order of code generated by the 8086 compiler. .P These defines only occur in the 6809 version of the compiler. .TP .B __AS09__ 1 compiler is generating 6809 code .TP .B __FIRST_ARG_IN_X__ 1 the first argument to functions is passed in the .I X register. .TP .B __POS_INDEPENDENT__ 1 the code generated is (almost) position independent. .P .SH ENVIRONMENT .TP .B BCC_EXEC_PREFIX default directory to seach for compiler passes .TP .B TMPDIR directory to place temporary files (default /tmp) .P .SH DIRECTORIES All the include, library and compiler components are stored under the .I /usr/bcc directory under Linux-i386, this is laid out the same as a .I /usr filesystem and if bcc is to be the primary compiler on a system it should be moved there. The configuration for this is in the .B bcc.c source file only, all other executables are independent of location. The library installation also creates the file .BR /usr/lib/liberror.txt , this path is hardcoded into the C library. The .B bcc executable itself, .B as86 and .B ld86 are in /usr/bin. .SH SEE ALSO as86(1), ld86(1), elksemu(1) .SH BUGS The bcc.c compiler driver source is very untidy. The linker, ld86, produces a broken a.out object file if given one input and the .B -r option this is so it is compatible with pre-dev86 versions. dev86-0.16.21/man/elks.1000066400000000000000000000000231231050321700143750ustar00rootroot00000000000000.so man1/elksemu.1 dev86-0.16.21/man/elksemu.1000066400000000000000000000023541231050321700151150ustar00rootroot00000000000000.TH elksemu 1 "Jan, 1997" .BY Me! .nh .SH NAME elksemu \- Embedded Linux Kernel Subset emulator .SH SYNOPSIS .B /lib/elksemu .B program .RB [ arguments ] .SH DESCRIPTION .B Elksemu is a program that allows 8086 .B ELKS programs to be run under Linux-i386. These programs can be compiled using the .B bcc(1) C compiler. Yom may use the .I binfmt-misc module under Linux 2.1.43 or greater as described in the elksemu README which will cause the kernel to run .I elksemu with the correct arguments whenever the user tries to execute an ELKS executable directly. .SH OPTIONS There are no flag options to elksemu, the first argument is the name of the program to run the rest are arguments that are passed to the Elks program. .SH SECURITY The .B elksemu program may be installed suid-root and in this event it is able to run execute only (chmod 111) elks executables and act correctly on the suid permission bits on any executable. This should be considered a security hazard so elksemu does .I not have to be installed suid-root. If you consider using this facility you should also be aware that it will override the 'nosuid' mount(8) option. .SH SEE ALSO bcc(1), as86(1), ld86(1) .SH BUGS Elksemu is incomplete. The program may still have security bugs! dev86-0.16.21/man/ld86.1000066400000000000000000000100511231050321700142160ustar00rootroot00000000000000.TH ld86 1 "Apr, 1997" .BY Bruce Evans .nh .SH NAME ld86 \- Linker for as86(1) .SH SYNOPSIS .BR ld86 .RB [ -03MNdimrstyz [-]] .RB [ -llib_extension ] .RB [ -o\ outfile ] .RB [ -Ccrtfile ] .RB [ -Llibdir ] .RB [ -Olibfile ] .RB [ -Ttextaddr ] .RB [ -Hheapsize ] .RB [ -Ddataaddr ] .B infile... .SH DESCRIPTION This linker understands only the object files produced by the as86 assembler, it can link them into either an impure or a separate I&D executable. The linking defaults are everything off or none except for .B -0 and the output file is .BR a.out . There is .I not a standard library location defined in the linker. .SH OPTIONS .TP .B -0 produce header with 16-bit magic .\"and use library subdir i86 for -lx .TP .B -3 produce header with 32-bit magic .\"and use library subdir i386 for -lx .TP .B -7 produce Seventh Edition UNIX a.out header. .TP .B -d delete the header from the output file, used for MSDOS COM files. As a side effect this also includes -s as there's nowhere to put a symbol table. .TP .B -Cx add file libdir-from-search/crtx.o to list of files linked .TP .B -D data base address follows (in format suitable for strtoul) .TP .B -H the top of heap (initial stack) address (in format suitable for strtoul) .TP .B -Lx add dir name x to the head of the list of library dirs searched .TP .B -M print symbols linked on stdout .TP .B -N Create a native Linux OMAGIC output file. If the contents are i386 code the binary can be either linked by GCC or executed by linux. If the .B -z option is also included the linker can generate a QMAGIC executable. .TP .B -Ox add library or object file libdir-from-search/x to list of files linked .TP .B -T text base address follows (in format suitable for strtoul) .TP .B -i separate I&D output .TP .B -lx add library libdir-from-search/libx.a to list of files linked .TP .B -m print modules linked on stdout .TP .B -o output file name follows .TP .B -s strip symbols .TP .B -r Generate a relocatable object from one source object, if the linker is given the -N option also the output format will be the hosts native format if possible. .TP .B -t trace modules being looked at on stdout .TP .B -y Alter the symbol tables to add label 'extensions' so that labels with more than 8 characters can be stored in elks executables. .TP .B -z produce "unmapped zero page" or "QMAGIC" executables .P All the options not taking an argument may be turned off by following the option letter by a '-', as for cc1. .SH PREDEFINED LABELS The linker predefines several labels that can be imported into user programs. .TP .B __etext Standard C variable for the end of the text segment. .TP .B __edata Standard C variable for the end of the initilised data. .TP .B __end Standard C variable for the end of the bss area. .TP .B __segoff The offset within the executable file between the start of the text segment and the start of the data segment in 16 byte 'paragraphs'. Note this is .B zero for impure (tiny model) executables and is adjusted for executables that don't start at offset 0 within the segment. .TP .B __segXDL The lowest address with data in segment 'X'. (eg __seg0DL is for segment zero or the text segment, __seg3DL is for the data segment) The value 'X' is a hex digit. .TP .B __segXDH The top of segment 'X's data area. .TP .B __segXCL The bottom of segment 'X's 'common data' or unitilised data area. Each segment has both an initilised and unitilised data area. .TP .B __segXCH The top of segment 'X's common area. .TP .B __segXSO This is the adjusted offset from segment 0 of the start of segment 'X' in 'paragraphs'. .SH HISTORY The 6809 version does not support -i. The previous versions of the linker could produce an 8086 executable with segments of a size >64k, now only i386 executables may have segments this large. .SH BUGS The linker cannot deal with reverse seeks caused by .B org instructions in the object file. Unlike previous versions the current one traps the error rather than trying to fill up the hard disk. The linker produces a broken a.out object file if given one input and the .B -r option this is so it is compatible with pre-dev86 versions. dev86-0.16.21/mkcompile000066400000000000000000000043361231050321700145200ustar00rootroot00000000000000#!/bin/sh SRC_BCC='bcc.c' SRC_CPP='main.c cpp.c hash.c token1.c token2.c' SRC_UPR='unproto.c error.c hash.c strsave.c symbol.c tok_clas.c tok_io.c tok_pool.c unproto.c vstring.c' SRC_CC1='bcc-cc1.c assign.c codefrag.c debug.c declare.c express.c exptree.c floatop.c function.c gencode.c genloads.c glogcode.c hardop.c input.c label.c loadexp.c longop.c output.c preproc.c preserve.c scan.c softop.c state.c table.c type.c' SRC_AS=' alloc.c as.c assemble.c errors.c express.c genbin.c genlist.c genobj.c gensym.c keywords.c macro.c mops.c pops.c readsrc.c scan.c table.c typeconv.c' SRC_LD=' ld.c dumps.c io.c linksyms.c readobj.c table.c typeconv.c writebin.c writex86.c' SRC_UP=' unproto.c tok_io.c tok_class.c tok_pool.c vstring.c symbol.c error.c hash.c strsave.c' main() { echo '@echo off' CFLAGS='-nologo -O' LDFLAGS='%LIB%\setargv.obj -link /NOE' ARCH=-Ms build bcc bcc bin $SRC_BCC CFLAGS='-nologo -O -DPOSIX_HEADERS_MISSING' LDFLAGS= ARCH=-Ml build cpp bcc-cpp lib $SRC_CPP build bcc bcc-cc1 lib $SRC_CC1 build as as86 bin $SRC_AS build ld ld86 bin $SRC_LD build unproto unproto lib $SRC_UPR echo "echo Compile complete." echo ":exit_now" } build() { DIR="$1" ; shift PRG="$1" ; shift BIN="$1" ; shift OBJ= BOBJ= COBJ= LOBJ= SRC="$*" for i in $SRC do j=`basename $i .c` echo "cl $ARCH $CFLAGS -c -Fo%TMP%\\$j.obj $DIR\\$i" if [ "$BOBJ" = "" ] then BOBJ="%TMP%\\$j.obj" else LOBJ="$LOBJ +%TMP%\\$j.obj" fi COBJ="$COBJ %TMP%\\$j.obj" OBJ="$OBJ $j.obj" echo "if errorlevel 1 goto exit_now" done echo if [ `echo $COBJ | wc -c` -lt 50 ] then echo "cl $ARCH -o $BIN\\$PRG.exe$COBJ $LDFLAGS" echo "if errorlevel 1 goto exit_now" else echo "if exist %TMP%\\doslib.lib del %TMP%\\doslib.lib" echo $LOBJ | fmt -62 | \ sed "s/\(.*\)/lib %TMP%\\\\doslib.lib \1; /" | sed 's/$/@if errorlevel 1 goto exit_now/' | tr '@' '\012' echo echo "cl $ARCH -o $BIN\\$PRG.exe $BOBJ %TMP%\\doslib.lib $LDFLAGS" echo "if errorlevel 1 goto exit_now" fi echo } main "$@" | sed 's/$/ /' > compile.bat dev86-0.16.21/tests/000077500000000000000000000000001231050321700137515ustar00rootroot00000000000000dev86-0.16.21/tests/Makefile000066400000000000000000000024541231050321700154160ustar00rootroot00000000000000# Copyright (C) 1996 Robert de Bath # This file is part of the Linux-8086 C library and is distributed # under the GNU Library General Public License. BCC=bcc CC=$(BCC) CFLAGS=-O SRC=env.c ft.c hd.c sync.c compr.c ucomp.c ouch.c lines.c \ wc.c line2.c rand.c grab.c OBJ= EXE=env ft hd sync compr ucomp ouch lines wc line2 rand grab bcc-x86 LINK_FILES=cat chgrp chmod chown cp install ln mkdir mkfifo mknod mv rm all: $(EXE) bcc-x86: $(CC) -O -o bcc-x86 \ ../bcc/assign.c ../bcc/bcc-cc1.c ../bcc/codefrag.c \ ../bcc/dbnode.c ../bcc/debug.c ../bcc/declare.c \ ../bcc/express.c ../bcc/exptree.c ../bcc/floatop.c \ ../bcc/function.c ../bcc/gencode.c ../bcc/genloads.c \ ../bcc/glogcode.c ../bcc/hardop.c ../bcc/hashcmd.c \ ../bcc/input.c ../bcc/label.c ../bcc/loadexp.c \ ../bcc/longop.c ../bcc/output.c ../bcc/preproc.c \ ../bcc/preserve.c ../bcc/scan.c ../bcc/softop.c \ ../bcc/state.c ../bcc/table.c ../bcc/type.c install: echo Use real-install if you actually want to install these real-install: install wc hd env ft $(DIST)$(PREFIX)/bin for i in $(LINK_FILES) ; do ln -s ft $(DIST)$(PREFIX)/bin/$$i ; done install_links: for i in $(LINK_FILES) ; do ln -s ft $$i ; done no_links: rm -f $(LINK_FILES) clean realclean: rm -f $(OBJ) $(EXE) $(LINK_FILES) dev86-0.16.21/tests/README000066400000000000000000000014651231050321700146370ustar00rootroot00000000000000Copyright (C) 1996 Robert de Bath This file is part of the Linux-8086 C library and is distributed under the GNU Library General Public License. These are user level tools, they're being used to test libc routines. env.c Prints the environment and arguments (Plus some junk) compr.c Mini compression program (rather slow but squeezes better than compress) ucomp.c Mini uncompression program (Very fast) ft.c Multiple simple file tools. hd.c Hex dump. line2.c Print lines from /etc/passwd (stdio) lines.c Print lines from /etc/passwd ouch.c Signal test size.c Size of Linux-i86 executables and object files. sync.c :-) wc.c Word,line and character counts. grab.c Grabs _all_ available memory (3GB+ on Linux-i386) then frees rand.c Generates random numbers and pipes them to 'hd' -Robert dev86-0.16.21/tests/a.out000077500000000000000000000303751231050321700147350ustar00rootroot00000000000000ELF`ƒ4!4 (!44€4€àà€€aadd˜d˜tt˜t˜ÈÈ((( Qåtd/lib/ld-linux.so.2GNU 5µPú.9<Ñb±Aˆ  _Jv_RegisterClasses__gmon_start__libc.so.6printfmallocexit_IO_stdin_used__libc_start_mainfreeGLIBC_2.0$ii gp™\™`™d™h™l™U‰åƒìè•èüè§ÉÃÿ5T™ÿ%X™ÿ%\™héàÿÿÿÿ%`™héÐÿÿÿÿ%d™héÀÿÿÿÿ%h™hé°ÿÿÿÿ%l™h é ÿÿÿ1í^‰áƒäðPTRh@‡hà†QVh$„è›ÿÿÿôU‰åSè[ÃÃP‹ƒ …ÀtÿЋ]üÉÃU‰åƒì€=t™u-¡l˜‹…Òt¶ƒÀ£l˜ÿÒ¡l˜‹…ÒuëÆt™ÉÉöU‰åƒì¡L™…Àt!¸…ÀtÇ$L™èì{û÷¶¿‰ì]ÃU‰åƒì8ƒäð¸)ÄÇEüÇEèÇEðÇEìƒ}ð~霋Eìƒè‰$è£þÿÿ‰Eø‹Eø‰D$‹Eø‰D$ ‹Eì‰D$‹Eð‰D$Ç$ ˆè˜þÿÿƒ}øuë[‹UìEèƒ}üu‹Eø‰Eô‰Eü‹EôÇë‹Uô‹Eø‰‹Eø‰Eô‹EôÇEðÿ‹Eì‹Eì%@ Ð%ÿÿÿ‰EìéYÿÿÿEìÑ8ƒ}ì鉋Eìƒè‰$è÷ýÿÿ‰Eøƒ}øuEìÑ8ë׋Eø‰D$‹Eø‰D$ ‹Eì‰D$‹Eð‰D$EðÿÇ$ ˆèÚýÿÿ‹UìEèƒ}üu‹Eø‰Eô‰Eü‹EôÇ눋Uô‹Eø‰‹Eø‰Eô‹EôÇélÿÿÿ‹EèÁè ‰D$Ç$@ˆè†ýÿÿƒ}üuë‹Eü‹‰Eô‹Eü‰$è‹ýÿÿ‹Eô‰EüëÝÇ$Èè7ýÿÿ‰Eø‹Eø‰D$‹Eø‰D$ ÇD$È‹Eð‰D$EðÿÇ$ ˆè&ýÿÿÇ$0uèúüÿÿ‰Eø‹Eø‰D$‹Eø‰D$ ÇD$0u‹Eð‰D$EðÿÇ$ ˆèéüÿÿÇ$ Nè½üÿÿ‰Eø‹Eø‰D$‹Eø‰D$ ÇD$ N‹Eð‰D$EðÿÇ$ ˆè¬üÿÿÇEì‹Eìƒè‰$èwüÿÿ‰Eø‹Eø‰D$‹Eø‰D$ ‹Eì‰D$‹Eð‰D$EðÿÇ$ ˆègüÿÿƒ}øtƒ}ðc~¶Ç$è_üÿÿU‰åWV1öSƒì è Ã`èéûÿÿ“ÿÿÿƒÿÿÿ)ÂÁú9Ös‰×´&¼'ÿ”³ÿÿÿF9þrôƒÄ [^_]ö¿U‰åƒì‰$èBÉt$ƒÿÿÿ“ÿÿÿ)ÐÁø…Àpÿuè[‹$‹t$‰ì]Ãÿ”³ÿÿÿ‰ðN…Àuòëà‹$ÃU‰åSƒì»<™¡<™ƒøÿtv¼'ƒëÿЋƒøÿuôX[]ÃU‰åSè[ÃwRèÊûÿÿ‹]üÉÃ%2d(%8u)..%08lx..%ld Free all - total was %ldK bytes H™$ ä‚ ЇH‚€ q P™(¼‚´‚þÿÿo”‚ÿÿÿoðÿÿo‚‚ÿÿÿÿÿÿÿÿt˜ƒ"ƒ2ƒBƒRƒGCC: (GNU) 3.3.5 (Debian 1:3.3.5-12)GCC: (GNU) 3.3.5 (Debian 1:3.3.5-12)GCC: (GNU) 3.3.5 (Debian 1:3.3.5-13)GCC: (GNU) 3.3.5 (Debian 1:3.3.5-13)GCC: (GNU) 3.3.5 (Debian 1:3.3.5-12)GCC: (GNU) 3.3.5 (Debian 1:3.3.5-13)GCC: (GNU) 3.3.5 (Debian 1:3.3.5-12)`ƒ",! Їä‚ „ƒ"$Ê æ‡ù‚!…œ„_IO_stdin_used`ƒ‚ƒ../sysdeps/i386/elf/start.S/home/drow/debian-glibc/glibc-2.3.2.ds1/build-tree/glibc-2.3.2/csuGNU AS 2.15€˜q„ƒ„ƒ.<UÃÕ0'¬"B¢3#T $0N%q"3(ƒ¤@)B¬* áC+Tí,½int™-0û2ÚóÔ3ìE;Úu<ìëˆì4‰0ÙŠ0ÿ‹q)Œìg0¢Ž0aøÚ+‘½•’Í’•#¥½¥'W’~»“a”q\•ìß–0 —a°˜0™a›½¬œa¤½á ½„£½¾¦aY«aK¬Ú‰¯qX°ì5³qJ´ì¶½£ºhp»© ó¼º À«¿½ïÂ0 3Ea Nb0 S Qé <R$À¥IT=N½#ÓSõ#ÍT$y zV#8I#)T©#z!h#8"I#z#„ ù&-®æ`¨g¶ 8;JH R½R7ºÀË×½½ X7µ<?Âu¦#×vç#½x½#Vzº# Ê{º#Ç}#~Ý#Ì#.€$# b„½#$ï…½#(ц½#,t‡½#0Žн#4†Œ…#8 =ºÅ$@“Ñ#ž”Ñ#–˜½#œ½# Ÿ ½#%¢¬#8£I#8§š# À ÆB Ñ B %Kè îéRB@N $½R€O/ 5ARtXL R…½R7…ÀºÀË×÷]’ ˜¼½…ÀÀÑÑ×aÇ Íç½çò× íÀ ø çµd  $½$ç …€e5 ;G…šBõjA#ák‡#l*#†m…# nš# Gd   Ié‚­Û®%#B¯R#†°é#ø=¥†± ².,4ú2²#†3=# M,5 ú/² ª4 Q5.ä7 8½—9T–:0–ˆ½¥5/home/drow/debian-glibc/glibc-2.3.2.ds1/build-tree/i386-libc/csu/crti.S/home/drow/debian-glibc/glibc-2.3.2.ds1/build-tree/glibc-2.3.2/csuGNU AS 2.15€¥(Ý/home/drow/debian-glibc/glibc-2.3.2.ds1/build-tree/i386-libc/csu/crtn.S/home/drow/debian-glibc/glibc-2.3.2.ds1/build-tree/glibc-2.3.2/csuGNU AS 2.15€%% : ; I$ > $ >  : ;  : ; I8 I!I/  I : ;I  : ; : ; I  : ; ( ' II : ; &I'  < !I4: ; I?  %%S/û ../sysdeps/i386/elfstart.S`ƒ.01:"VWYXû Àºû /usr/lib/gcc-lib/i486-linux/3.3.5/include../sysdeps/generic/bits../wcsmbs../sysdeps/gnu../iconvinit.cstddef.htypes.hwchar.h_G_config.hgconv.h¤[û /home/drow/debian-glibc/glibc-2.3.2.ds1/build-tree/i386-libc/csucrti.SЇ2,Wdä‚",:„ƒ ,Wdd,,-:‚[û /home/drow/debian-glibc/glibc-2.3.2.ds1/build-tree/i386-libc/csucrtn.Sæ‡:ù‚ _G_int32_t__time_t__GCONV_INCOMPLETE_INPUT__GCONV_OK__state__gconv_init_fct_G_iconv_t__rlim64_t__GCONV_ILLEGAL_DESCRIPTOR__gconv_infoshort unsigned intunsigned char__useconds_t__counter__fct__val__value__nsteps_G_int16_t__max_needed_from__gconv_btowc_fct__off_t__ssize_t__statepinit.c__fsfilcnt_t__steps__fsfilcnt64_t__blkcnt_t__gconv_loaded_object_G_fpos64_t__gconv_t__trans_end_fct__u_int__GCONV_ILLEGAL_INPUT__blksize_t__to_name__uint64_t__id_t__GCONV_EMPTY_INPUT__cd__ino_t__GCONV_NOCONV__invocation_counter__pid_t__u_short__count__quad_t__u_long__fsid_t__GCONV_FULL_OUTPUT__max_needed_to__timer_t__stateful__uint32_t__key_t__u_char__gconv_step__shlib_handle__min_needed_toshort int__dev_tlong long int__gconv_trans_data__outbuflong long unsigned int__uid_t__wchb__uint16_twint_tGNU C 3.3.5 (Debian 1:3.3.5-12)__u_quad_t__gconv_trans_end_fct__flags__outbufend__combined__gconv_trans_init_fct__init_fct__modname__trans_context_fct__trans_fct__rlim_t__wch__intptr_t__suseconds_t__ino64_twchar_t__GCONV_IS_LAST__blkcnt64_t__fsblkcnt64_t__mode_t__qaddr_t__pos__gconv_end_fct_IO_stdin_used__internal_use__GCONV_NODB__clock_t__gconv_step_data__gconv_trans_query_fct__socklen_t__int64_t__GCONV_NOMEM__off64_t__btowc_fct_G_fpos_t__int8_t/home/drow/debian-glibc/glibc-2.3.2.ds1/build-tree/glibc-2.3.2/csu__daddr_t__fsblkcnt_t_G_uint32_t__nlink_t__swblk_t__GCONV_INTERNAL_ERROR__mbstate_t__gid_t__clockid_t__int32_t__gconv_trans_context_fct__next__GCONV_IGNORE_ERRORS__end_fct__trans__uint8_t__gconv_fct__from_name__min_needed_from__gconv_trans_fct__data__caddr_t_G_uint16_t__loff_t__int16_t.symtab.strtab.shstrtab.interp.note.ABI-tag.hash.dynsym.dynstr.gnu.version.gnu.version_r.rel.dyn.rel.plt.init.text.fini.rodata.data.eh_frame.dynamic.ctors.dtors.jcr.got.bss.comment.debug_aranges.debug_pubnames.debug_info.debug_abbrev.debug_line.debug_str#(( 1HH87 €€?‚qGÿÿÿo‚‚‚Tþÿÿo”‚” c ´‚´l ¼‚¼( uä‚äpü‚ü`{`ƒ`pЇÐ‡ˆa d˜d •p˜pŸt˜tȨ<™< ¯D™D ¶L™L »P™P $Àt™t Åt ΀ xÝø %í s ù8Èc0+¶á(&à R -õ(H€‚‚‚”‚´‚¼‚ ä‚ ü‚ `ƒ Ї ˆd˜p˜t˜<™D™L™P™t™ ñÿñÿñÿVñÿañÿlñÿañÿñÿañÿñÿñÿñÿVñÿañÿ·ñÿ¾ñÿñÿNñÿ¾ñÿñÿñÿñÿVñÿ¾ñÿY„ƒ iñÿt<™‚D™L™l˜¡t™­°ƒ Ãðƒ iñÿÏ@™ÜH™ép˜÷L™ ‡ ñÿñÿNñÿñÿñÿñÿñÿVñÿñÿañÿht˜qˆxd˜ñÿ‰h˜–@‡P ¦ä‚ ¬µ¾`ƒ Åd˜ñÿØà†T èt™ñÿô$„¹ ùúd˜ñÿ'd˜ 29DЇ JÑZt™ñÿa‡ xP™Ž±žx™ñÿ£d˜ñÿ¶ˆÅd˜Ò æ /home/drow/debian-glibc/glibc-2.3.2.ds1/build-tree/i386-libc/config.habi-note.S/home/drow/debian-glibc/glibc-2.3.2.ds1/build-tree/i386-libc/csu/abi-tag.hinit.c/home/drow/debian-glibc/glibc-2.3.2.ds1/build-tree/i386-libc/csu/crti.S/home/drow/debian-glibc/glibc-2.3.2.ds1/build-tree/i386-libc/csu/defs.hinitfini.ccall_gmon_startcrtstuff.c__CTOR_LIST____DTOR_LIST____JCR_LIST__p.0completed.1__do_global_dtors_auxframe_dummy__CTOR_END____DTOR_END____FRAME_END____JCR_END____do_global_ctors_aux/home/drow/debian-glibc/glibc-2.3.2.ds1/build-tree/i386-libc/csu/crtn.Sgrab.c_DYNAMIC_fp_hw__fini_array_end__dso_handle__libc_csu_fini_initmalloc@@GLIBC_2.0_start__fini_array_start__libc_csu_init__bss_startmain__libc_start_main@@GLIBC_2.0__init_array_enddata_startprintf@@GLIBC_2.0_finiexit@@GLIBC_2.0_edata__i686.get_pc_thunk.bx_GLOBAL_OFFSET_TABLE_free@@GLIBC_2.0_end__init_array_start_IO_stdin_used__data_start_Jv_RegisterClasses__gmon_start__dev86-0.16.21/tests/compr.c000066400000000000000000000175121231050321700152430ustar00rootroot00000000000000 #include #include #include #include #include #define MAXNO 32767 #define MAXLEN 127 #define XXQSCAN /* Speed up scanning at the cost of not being optimal */ unsigned char *fptr; unsigned short *vptr; FILE * fd; #define ITBSIZE 4096 #define itbfunc() (ptr[mainscan]^(ptr[mainscan+1]<<4)^(ptr[mainscan+2]<<2)) /* #define ITBSIZE 4001 #define itbfunc() ((ptr[mainscan]+ptr[mainscan+1]*79+ptr[mainscan+2]*307)%4001) */ int * itb; int size; long cnt=0; #ifdef __GNUC__ int maxno= 16384; #else int maxno= 8000; #endif long icount = 0; long ocount = 0; unsigned char key; int fl; main(argc, argv) int argc; char ** argv; { if( argc < 2 ) { fprintf(stderr, "Usage; ... \n"); exit(1); } if( argc == 3 ) { maxno = atoi(argv[2]); if( maxno < 256 ) maxno = 256; if( maxno > MAXNO) maxno = MAXNO; } if( strcmp(argv[1], "-") == 0 ) fd = stdin; else fd = fopen(argv[1], "r" ); if( fd == 0 ) { perror("Open failed\n"); exit(1); } fptr = (unsigned char * ) malloc((unsigned)maxno*2); itb = (int * ) malloc(ITBSIZE*sizeof(int)); if( itb ) vptr = (unsigned short * ) malloc((unsigned)maxno * sizeof(short)*2 ); else vptr = 0; if( fptr == 0 ) { perror("Cannot allocate RAM"); exit(1); } if( vptr == 0 && itb ) free(itb); fl = 0; { if( (size = fread(fptr, 1, (int)maxno, fd )) < 0 ) { fprintf(stderr, "\nRead failed\n"); exit(1); } if( size ) { icount += size; if( fl == 0 ) { key = scan_min(); putchar(key); ocount++; fl = 1; } else fprintf(stderr, "\rBlock %d \r", fl++ ); if( vptr) compress(); else slo_compress(); } } fprintf(stderr, "\n"); exit(0); } scan_min() { long count[256]; long i; int j, n; for( j=0; j<256; j++ ) count[j] = 0; for( i=0; i> 1), j=0; j<256; j++ ) if( count[j] < i ) { i = count[j] ; n = j; } fprintf(stderr, "Most unused in 0x%lx to 0x%lx is 0x%02x at %ld\n", cnt, cnt+size, n, i ); cnt+= size; return n; } compress() { register long mainscan; register long secondscan; register unsigned char * ptr = (unsigned char * ) fptr; register int len; register int matchlen; long notepos; long emark; #ifdef QSCAN int count; #endif for( mainscan=0; mainscan = 0 && mainscan - secondscan < maxno; secondscan -= vptr[secondscan] ) { #ifdef DEBUG if( vptr[secondscan] == 0 ) { fprintf(stderr, "\nOh !!!!! mainsc %ld, sec-scan %ld\n", mainscan, secondscan); vptr[secondscan] = secondscan+1; } #endif for( len = 0; len < MAXLEN ; len++ ) if( mainscan+len >= size || ptr[mainscan+len] != ptr[secondscan+len] ) break; if( len > matchlen && (len != 4 || mainscan - secondscan < 256 ) ) { notepos = secondscan; matchlen = len; if( len == MAXLEN ) break; } #ifdef QSCAN if( matchlen > 20 && len > 3 && ++count > 5 ) break; #endif } if( notepos == -1 ) { if( ptr[mainscan] == key ) { ocount+=2; putchar(key); putchar(0); } else { ocount++; putchar(ptr[mainscan]); } matchlen = 1; } else { long x = mainscan - notepos; ocount+=3; putchar(key); if( x > 255 ) putchar(matchlen | 0x80); else putchar(matchlen); putchar((int)x); if( x > 255 ) { putchar((int)x>>8); ocount++; } } while( matchlen-- ) { len = itbfunc(); vptr[mainscan] = mainscan - itb[len]; #if 1 if( vptr[mainscan] == 0 ) { fprintf(stderr, "\nHumm.. ms=%ld, hash=%d, itb[hash]=%ld\n", mainscan, len, itb[len]); vptr[mainscan] = mainscan+1; } #endif itb[len] = mainscan; mainscan++; } } fprintf(stderr, "\rBlock %d ..In:%ld Out:%ld \r", fl-1, icount, ocount ); if( emark < size-4 ) { int cnt; long l ; if(mainscan > maxno ) { for(cnt=0; cnt= emark ) emark = size -4; goto loopback; } for( ; mainscan < size; ) { if( ptr[mainscan] == key ) { ocount+=2; putchar(key); putchar(0); } else { ocount++; putchar(fptr[mainscan]); } mainscan++; } fprintf(stderr, "\rBlock %d ..In:%ld Out:%ld \r", fl-1, icount, ocount ); /* end */ } slo_compress() { register long mainscan; register long secondscan; register unsigned char * ptr = (unsigned char * ) fptr; register int len; register int matchlen; long notepos; long emark; #ifdef QSCAN int count; #endif mainscan=0; emark = size - 130 ; loopback: for( ; mainscan < emark; ) { matchlen = 3; notepos = -1; #ifdef QSCAN count = 0; #endif for( secondscan=mainscan-1; secondscan >= 0 && mainscan - secondscan < maxno; secondscan-- ) { for( len = 0; len < MAXLEN ; len++ ) if( mainscan+len >= size || ptr[mainscan+len] != ptr[secondscan+len] ) break; if( len > matchlen && (len != 4 || mainscan - secondscan < 256 ) ) { notepos = secondscan; matchlen = len; if( len == MAXLEN ) break; } #ifdef QSCAN if( matchlen > 20 && len > 3 && ++count > 5 ) break; #endif } if( notepos == -1 ) { if( ptr[mainscan] == key ) { ocount+=2; putchar(key); putchar(0); } else { ocount++; putchar(ptr[mainscan]); } matchlen = 1; } else { long x = mainscan - notepos; ocount+=3; putchar(key); if( x > 255 ) putchar(matchlen | 0x80); else putchar(matchlen); putchar((int)x); if( x > 255 ) { putchar((int)x>>8); ocount++; } } mainscan += matchlen; } fprintf(stderr, "\rBlock %d ..In:%ld Out:%ld \r", fl-1, icount, ocount ); if( emark < size-4 ) { int cnt; long l ; if(mainscan > maxno ) { for(l=0; l= emark ) emark = size -4; goto loopback; } for( ; mainscan < size; ) { if( ptr[mainscan] == key ) { ocount+=2; putchar(key); putchar(0); } else { ocount++; putchar(fptr[mainscan]); } mainscan++; } fprintf(stderr, "\rBlock %d ..In:%ld Out:%ld \r", fl-1, icount, ocount ); /* end */ } dev86-0.16.21/tests/env.c000066400000000000000000000025311231050321700147060ustar00rootroot00000000000000 char hex[] = "0123456789ABCDEF"; char buf[20]; main(argc, argv, envp) int argc; char ** argv; char ** envp; { int i,j; char *p; char * str; int * arg = &argc; for(j=0; j<8; j++) { phex(arg); putstr(":"); for(i=0; i<8; i++) { putstr(" "); phex(*arg++); } putstr("\n"); } #if 0 str = alloca(sizeof(hex)+2); putstr("Alloca = "); phex(&str); putstr(","); phex(str); putstr("\n"); #endif p = (char*) &argc; putstr("ARGC="); phex(argc); putstr("\n"); putstr("ARGV="); phex(argv); putstr("\n"); putstr("ENVP="); phex(envp); putstr("\n"); for(i=0; i\n"); for(; *envp; envp++) { phex(envp); putstr(":"); phex(*envp); putstr(":"); putstr(*envp); putstr("\n"); } } phex(val) { int i; printf("%04x", val); } putstr(str) { printf("%s", str); } #if 0 int global_var_that_needs_init = 0x201; #asm loc 1 ! Make sure the pointer is in the correct segment auto_func: ! Label for bcc -M to work. .word _init_vars ! Pointer to the autorun function .text ! So the function after is also in the correct seg. #endasm static void init_vars() { global_var_that_needs_init = getuid(); } #endif dev86-0.16.21/tests/ft.c000066400000000000000000000666571231050321700145520ustar00rootroot00000000000000/* Copyright (C) 1995,1996 Robert de Bath * This program is distributed under the GNU General Public License. */ /* * File Tool, This program is a collection of basic file tools * it includes cat, cp, ln, mkdir, mknod, chmod, chown, mv, rm * * Links may be used to call it under any of these names. */ #include #ifdef __STDC__ #include #include #endif #include #include #include #include #include #include #include #include #include #include #if defined(S_IFSOCK) && !defined(__BCC__) #define __HAS_SOCKETS #endif #ifndef S_IFLNK #define lstat stat #endif #ifdef __HAS_SOCKETS #include #endif /* Ansi prototypes */ #ifdef __STDC__ #define PR(x) x #else #define PR(x) () #endif int main PR((int argc, char ** argv)); int select_command PR((char * argv)); void do_prep PR((void)); void do_post PR((void)); void execute PR((char * dname, char * fname)); int exec_for_subdir PR((char * dname)); void exec_for_item PR((int when, char * fname)); void parse_perms PR((char * prefix, char * ustring)); int edit_mode PR((int mode, char * mode_str)); int cmd_ft PR((char * fname)); int cmd_mkfifo PR((char * fname)); int cmd_mksock PR((char * fname)); int cmd_rm PR((char * fname)); void build_dest PR((char * dest, char * name, char * newpath)); int strisdigit PR((char * str)); int cmd_mv PR((char * fname)); int cmd_ln PR((char * fname)); int cmd_cp PR((char * fname)); int copy_modes PR((char * file)); int copy_file PR((char * source, char * dest)); void Usage PR((void)); int cmd_mkdir PR((char * dirname)); int cmd_mknod PR((void)); int warning PR((int enumber, char * estr, char * eobj)); int error PR((int enumber, char * estr, char * eobj)); #define DO_BDIR 0x0010 /* Do Dir before contents */ #define DO_ADIR 0x0020 /* Do Dir after contents */ #define DO_MCOPY 0x0040 /* Preserve modes flag forced */ #define OK_DIR 0x0080 /* Directorys OK even if no flg_recurse */ #define IGN_LNK 0x0100 /* Not interested in symlinks */ #define NO_SOURCE 0x0200 /* Named files created */ #define OK_NO_SOURCE 0x0400 /* Don't need the source */ #define CMD_FT (0+OK_DIR+DO_BDIR) #define CMD_CAT (1+IGN_LNK) #define CMD_CHGRP (2+OK_DIR+IGN_LNK+DO_ADIR) #define CMD_CHMOD (3+OK_DIR+IGN_LNK+DO_ADIR) #define CMD_CHOWN (4+OK_DIR+IGN_LNK+DO_ADIR) #define CMD_CP (5+IGN_LNK) #define CMD_EXTAR (6+DO_MCOPY+DO_BDIR) #define CMD_INSTALL (7+DO_MCOPY) #define CMD_LN (8+IGN_LNK+DO_BDIR) #define CMD_MKDIR (9+NO_SOURCE) #define CMD_MKFIFO (10+NO_SOURCE) #define CMD_MKSOCK (11+NO_SOURCE) #define CMD_MKNOD (12+NO_SOURCE) #define CMD_MV (13+DO_MCOPY+OK_DIR+DO_BDIR) #define CMD_RM (14+DO_ADIR) struct { char * name; int cmd; int argpat; char * opts; } command_list[] = { { "ft", CMD_FT, 0, "-Rv" }, { "cat", CMD_CAT, 0, "uR" }, { "chgrp", CMD_CHGRP, 1, "vfR" }, { "chmod", CMD_CHMOD, 1, "vfR" }, { "chown", CMD_CHOWN, 1, "vfR" }, { "cp", CMD_CP, -1, "vifRrpsda" }, { "extar", CMD_EXTAR, 1, "" }, { "install", CMD_INSTALL, -1, "cdso:g:m:" }, { "ln", CMD_LN, -1, "vifs" }, { "mkdir", CMD_MKDIR, 0, "m:" }, { "mkfifo", CMD_MKFIFO, 0, "m:" }, #ifdef __HAS_SOCKETS { "mksock", CMD_MKSOCK, 0, "m:" }, #endif { "mknod", CMD_MKNOD, 4, "m:" }, { "mv", CMD_MV, -1, "vif" }, { "rm", CMD_RM, 0, "vifr" }, { 0 } }; int cmd_arg = 0; int cmd_tok = CMD_FT; char * cmd_opt = "-"; char * cmd_string = 0; /* the first (or last) arg where special */ char * prog_name = ""; char ** flist = 0; int fcount = 0; int add_base=0; char * or_name = 0; int or_offset = 0; int flg_recurse = 0; int flg_verbose = 1; int flg_preserve= 0; int flg_mkpdir = 0; int flg_noderef = 0; int flg_symlink = 0; int flg_exestrip= 0; int flg_r, flg_force; char *str_o, *str_g, *str_m; /* Things to set on the new file */ int set_user = -1; int set_group = -1; int set_mode = -1; time_t set_time = -1; char mode_str[32] = ""; int u_mask = 0; /* 07777 altered by umask() */ struct stat cur_file_stat; struct stat dest_item; struct stat access_stat; int done_something = 0; int main(argc, argv) int argc; char ** argv; { int ar; (void) select_command(argv[0]); for(ar=1; argv[ar] && argv[ar][0] == '-' && argv[ar][1]; ar++) { char * p = argv[ar]+1; /* For symbolic changes of the form -rwx */ if( cmd_tok == CMD_CHMOD && strchr("rwx", *p) != 0 ) break; while(*p) { char * ap=0, *av=0; char ch; /* Is it a valid opt for this cmd */ if(*p == ':' || (ap=strchr(cmd_opt, *p)) == 0) Usage(); /* Got an argument ? */ if(ap[1] == ':') { if(!argv[ar+1]) Usage(); av = argv[++ar]; } if( (ch = *p) == '-' ) { if( (ch=select_command(p)) < 0 ) Usage(); } switch(ch) { case '\0': break; case 'r': case 'R': flg_recurse++; break; case 'v': flg_verbose++; break; case 'p': if(cmd_tok == CMD_MKDIR) flg_mkpdir++; else flg_preserve++; break; case 'd': if(cmd_tok == CMD_INSTALL) { flg_mkpdir++; cmd_arg=0; } /* Special mkdir */ else flg_noderef++; /* cmd_copy */ break; case 'f': flg_force++; flg_verbose=0; break; case 'o': str_o = av; break; case 'g': str_g = av; break; case 'm': str_m = av; break; case 's': flg_symlink++; if( cmd_tok == CMD_LN) cmd_tok |= OK_DIR+OK_NO_SOURCE; break; case 'a': flg_recurse++; flg_preserve++; flg_noderef++; break; } if(*p == '-') break; p++; } } switch(cmd_arg) { case 1: if( ar >= argc ) Usage(); cmd_string = argv[ar++]; fcount = argc-ar; flist = argv+ar; break; case 0: fcount = argc-ar; flist = argv+ar; break; case -1: if( ar >= argc ) Usage(); cmd_string = argv[argc-1]; fcount = argc-ar-1; flist = argv+ar; break; default: if( ar != argc-cmd_arg ) Usage(); fcount = argc-ar; flist = argv+ar; break; } do_prep(); for(ar=0; ar 1 ) { if( cmd_mkdir(cmd_string) < 0 ) exit(1); stat(cmd_string, &dest_item); add_base = 1; } } else { if( !S_ISDIR(dest_item.st_mode) ) { if( fcount > 1 ) { error(0, "Destination must be a directory:", cmd_string); exit(1); } } else add_base = 1; } } } void do_post() { /* Oh! It seems there's nothing to do, ah well. */ } void execute(dname, fname) char * dname; char * fname; { char * buf; if( strcmp(dname, "-") == 0 ) { exec_for_item(0, dname); return; } if( fname ) { buf = alloca(strlen(dname) + strlen(fname) + 4); if( buf == 0 ) { error(errno, "Can't allocate memory for path beyond ", dname); return ; } strcpy(buf, dname); if(strcmp(dname, "/")) strcat(buf, "/"); strcat(buf, fname); } else buf = dname; if( lstat(buf, &cur_file_stat) == -1 ) { if( cmd_tok&(NO_SOURCE|OK_NO_SOURCE) ) exec_for_item(0, buf); else warning(errno, "", buf); return; } if( !flg_force && ( cmd_tok&NO_SOURCE )) { error(EEXIST, "", buf); return; } if( S_ISDIR(cur_file_stat.st_mode)) { if( (cmd_tok&OK_DIR) || flg_recurse ) (void) exec_for_subdir(buf); else error(EISDIR, "", buf); return; } #ifdef S_IFLNK if( S_ISLNK(cur_file_stat.st_mode)) { /* Links are special */ if( cmd_tok&IGN_LNK ) { if( stat(buf, &cur_file_stat) == -1 ) { warning(errno, "", buf); return; } } } #endif exec_for_item(0, buf); } int exec_for_subdir(dname) char * dname; { DIR * dfd; struct dirent * ent; int old_mode = -1; if( cmd_tok&DO_BDIR ) exec_for_item(-1, dname); if( flg_recurse ) { dfd = opendir(dname); if( dfd == 0 && errno == EACCES && flg_force ) { old_mode = (cur_file_stat.st_mode & 07777); if( chmod(dname, (0700|old_mode)) ) return error(errno, "", dname); dfd = opendir(dname); } if( dfd == 0 ) return error(errno, "", dname); while((ent=readdir(dfd))) { if( strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0 ) continue; alloca(0); /* Free up if using fake version */ execute(dname, ent->d_name); } closedir(dfd); if( old_mode != -1 ) chmod(dname, old_mode); } if( cmd_tok&DO_ADIR ) { lstat(dname, &cur_file_stat); exec_for_item(1, dname); } return 0; } void exec_for_item(when, fname) int when; char * fname; { int rv = -1; switch(cmd_tok) { case CMD_FT: rv = cmd_ft(fname); break; case CMD_CAT: rv = copy_file(fname, "-"); break; case CMD_CHGRP: /* And fall */ case CMD_CHMOD: /* And fall */ case CMD_CHOWN: rv = copy_modes(fname); break; case CMD_CP: rv = cmd_cp(fname); break; case CMD_MV: rv = cmd_mv(fname); break; case CMD_RM: rv = cmd_rm(fname); break; case CMD_EXTAR: error(EINVAL, "", "No code."); exit(1); case CMD_LN+OK_DIR+OK_NO_SOURCE: case CMD_LN: rv = cmd_ln(fname); break; case CMD_INSTALL: error(EINVAL, "", ""); exit(1); case CMD_MKDIR: rv = cmd_mkdir(fname); break; case CMD_MKFIFO: rv = cmd_mkfifo(fname); break; #ifdef __HAS_SOCKETS case CMD_MKSOCK: rv = cmd_mksock(fname); break; #endif case CMD_MKNOD: break; } } void parse_perms(prefix, ustring) char * prefix; char * ustring; { char * userstr; char * groupstr; char * modestr; char * cp; struct passwd * pwd = 0; struct group * grp; userstr = alloca(strlen(prefix) + strlen(ustring) + 2); strcpy(userstr, prefix); strcat(userstr, ustring); /* Select User */ cp = strchr(userstr, ':'); if(!cp) cp = strchr(userstr, '.'); if(cp) *cp = '\0'; /* If there's a user */ if( *userstr != 0 ) { pwd = getpwnam(userstr); if(pwd == NULL) { if(!strisdigit(userstr) ) { error(EINVAL, "Unknown user ", userstr); exit(1); } set_user = atoi(userstr); } else set_user = pwd->pw_uid; endpwent(); } if(cp) { groupstr = cp+1; cp = strchr(groupstr, ':'); if(!cp) cp = strchr(groupstr, '.'); if(cp) *cp = '\0'; if( *groupstr != '\0' ) { grp = getgrnam(groupstr); if(grp == NULL) { if(!strisdigit(groupstr) ) { error(EINVAL, "Unknown group ", groupstr); exit(1); } set_group = atoi(groupstr); } else set_group = grp->gr_gid; endgrent(); } else if( pwd ) set_group = pwd->pw_gid; } if(cp) { modestr = cp+1; if(strisdigit(modestr)) set_mode = strtol(modestr, NULL, 8); else { strncpy(mode_str, modestr, sizeof(mode_str)-1); /* This is the time that the mode change will fail on syn error */ (void) edit_mode(u_mask, mode_str); } } if( set_user == -1 && set_group == -1 && set_mode < 0 && *mode_str == 0) { error(EINVAL, "", "Permission string has no changes"); exit(1); } } int edit_mode(mode, mode_str) int mode; char * mode_str; { char * str=mode_str; static mtab[] = {0, 0111, 0222, 0333, 0444, 0555, 0666, 0777 }; int done_change = 0; int isdir = S_ISDIR(mode); int change_op = 0; int change_mask = u_mask; int v=0, s=0, nm=0; for(; *mode_str; mode_str++) { switch(*mode_str) { case ',': change_op = 0; change_mask=u_mask; continue; case '=': change_op = 1; if(0) { case '+': change_op = 2; } if(0) { case '-': change_op = 3; } v=0; nm=0; if(strchr(",=+-", mode_str[1]) == 0 ) continue; break; case 'a': if(change_op) goto ch_error; nm |= 07777; if(0) { case 'u': nm |= 04700; s= 6; } if(0) { case 'g': nm |= 02070; s= 3; } if(0) { case 'o': nm |= 01007; s= 0; } if(change_op==0) { change_mask=nm; continue; } v |= mtab[(mode>>s)&7]; break; case 'r': v |= 0444; break; case 'w': v |= 0222; break; case 'x': v |= 0111; break; case 's': v |=06000; break; case 't': v |=01000; break; case 'X': v |= mtab[isdir]; break; default: goto ch_error; } switch(change_op) { case 0: goto ch_error; case 1: mode= ((mode&(~change_mask)) | (v&change_mask)); break; case 2: mode= ( mode | (v&change_mask)); break; case 3: mode= ( mode & ~(v&change_mask)); break; } done_change=1; } if(!done_change) { ch_error: error(EINVAL, "Invalid mode string ", str); exit(1); } return mode; } int cmd_ft(fname) char * fname; { static char oldpath[2048] = "~"; static int last_uid=-1, last_gid=-1, last_mode=-1; struct passwd * pptr; struct group * gptr; int major, minor; if( flg_verbose>1 ) { char *p = 0; if( fname[1] ) p = strrchr(fname, '/'); if( p ) { *p = '\0'; if( strcmp(fname, oldpath) != 0 ) { strcpy(oldpath, fname); printf("%s/\n", oldpath); } *p = '/'; } else if( *oldpath ) *oldpath = '\0'; if(p) printf("%s", p+1); else printf("%s", fname); #ifdef S_IFLNK if( S_ISLNK(cur_file_stat.st_mode)) { char linkbuf[1024]; int v; *linkbuf='\0'; v = readlink(fname, linkbuf, sizeof(linkbuf)); if(v>0) linkbuf[v] = '\0'; printf("\t+%s", linkbuf); } else #endif if( cur_file_stat.st_mode != last_mode || cur_file_stat.st_uid != last_uid || cur_file_stat.st_gid != last_gid) { printf("\t"); if( cur_file_stat.st_uid != last_uid ) { pptr = getpwuid(cur_file_stat.st_uid); if( pptr ) printf("%s", pptr->pw_name); else printf("%d", cur_file_stat.st_uid); } printf(":"); if( cur_file_stat.st_gid != last_gid ) { gptr = getgrgid(cur_file_stat.st_gid); if( gptr ) printf("%s", gptr->gr_name); else printf("%d", cur_file_stat.st_gid); } if( (cur_file_stat.st_mode&07777) != (last_mode&07777) ) printf(":%03o", cur_file_stat.st_mode & 07777); #ifdef __linux__ major = ((cur_file_stat.st_rdev >> 8) & 0xfff); if (sizeof(cur_file_stat.st_rdev) > 4) major |= ((cur_file_stat.st_rdev >> 32) & ~0xfff); minor = (cur_file_stat.st_rdev & 0xff) | ((cur_file_stat.st_rdev >> 12) & ~0xff); #else major = ((cur_file_stat.st_rdev >> 8) & 0xFF); minor = (cur_file_stat.st_rdev&0xFF); #endif switch(cur_file_stat.st_mode & S_IFMT) { case S_IFDIR: printf("\td"); break; case S_IFIFO: printf("\tp"); break; #ifdef __HAS_SOCKETS case S_IFSOCK: printf("\ts"); break; #endif case S_IFBLK: printf("\tb,%d,%d", major, minor); break; case S_IFCHR: printf("\tc,%d,%d", major, minor); break; } last_mode = ((cur_file_stat.st_mode&07777)|S_IFREG); if( (cur_file_stat.st_mode&07000) ) last_mode = -1; last_uid = cur_file_stat.st_uid; last_gid = cur_file_stat.st_gid; } printf("\n"); } else printf("%s\n", fname); return 0; } int cmd_mkfifo(fname) char * fname; { int rv; int mode=0666; if( set_mode >= 0 ) mode=set_mode; rv = mknod(fname, S_IFIFO|mode, 0); if(rv<0) warning(errno, "Cannot create fifo ", fname); return rv; } #ifdef __HAS_SOCKETS int cmd_mksock(fname) char * fname; { int rv, fd, len; struct sockaddr *adr; len = strlen(fname)+1 + sizeof(*adr) - sizeof(adr->sa_data); if( len < sizeof(*adr) ) len = sizeof(*adr); adr = alloca(len+2); adr->sa_family = AF_UNIX; strcpy(adr->sa_data, fname); rv = fd = socket(AF_UNIX, SOCK_STREAM, 0); if( fd>=0 ) rv = bind(fd, adr, len); if( fd>=0 ) close(fd); if(set_mode >= 0 && chmod(fname, set_mode&07777) < 0 ) warning(errno, "Chmod ", fname); if(rv<0) warning(errno, "Cannot create socket ", fname); return rv; } #endif int cmd_rm(fname) char * fname; { struct stat dirstat; int rv; char * buf, * p; if( S_ISDIR(cur_file_stat.st_mode) ) if( !flg_recurse ) return error(EISDIR, "", fname); if( S_ISDIR(cur_file_stat.st_mode) ) { if( rmdir(fname) >= 0 ) return 0; } else { if( unlink(fname) >= 0 ) return 0; } if( !flg_force ) return error(errno, "", fname); /* Try VERY hard */ buf = alloca(strlen(fname)+4); strcpy(buf, fname); p = strrchr(buf, '/'); if( p ) strcpy(p+1, "."); else strcpy(buf, "."); if( stat(buf, &dirstat) < 0 ) return -1; if( chmod(buf, dirstat.st_mode|0700) < 0 ) return -1; if( S_ISDIR(cur_file_stat.st_mode) ) rv = rmdir(fname); else rv = unlink(fname); chmod(buf, dirstat.st_mode); return rv; } void build_dest(dest, name, newpath) char * dest; char * name; char * newpath; { char * p; strcpy(dest, newpath); if( add_base ) { strcat(dest, "/"); p = strrchr(or_name, '/'); if(p==0) strcat(dest, or_name); else strcat(dest, p+1); } if(strlen(name) <= or_offset) return; strcat(dest, name+or_offset); } int strisdigit(str) char * str; { if( str==0 || *str == 0 ) return 0; for(;*str; str++) if(*str>'9'|| *str<'0') return 0; return 1; } int cmd_mv(fname) char * fname; { char * destfile; destfile = alloca(strlen(fname)+strlen(cmd_string)+4); build_dest(destfile, fname, cmd_string); if( !flg_force && lstat(destfile, &access_stat) == 0 ) return error(EEXIST, "", destfile); if( rename(fname, destfile) == 0 ) return 0; if( errno != EXDEV ) return error(errno, "", fname); if( S_ISDIR(cur_file_stat.st_mode) ) return error(EISDIR, "Can't rename across devices ", fname); if( copy_file(fname, destfile) != 0 ) return -1; copy_modes(destfile); return unlink(fname); } int cmd_ln(fname) char * fname; { char * destfile; destfile = alloca(strlen(fname)+strlen(cmd_string)+4); build_dest(destfile, fname, cmd_string); if( lstat(destfile, &access_stat) != -1 ) { if( !flg_force ) return error(EEXIST, "", destfile); cmd_rm(destfile); } #ifdef S_IFLNK if( flg_symlink ) { if( symlink(fname, destfile) == 0 ) return 0; } else { #endif if( link(fname, destfile) == 0 ) return 0; #ifdef S_IFLNK } #endif return error(errno, "", destfile); } int cmd_cp(fname) char * fname; { struct stat dest_stat; char * destfile; int no_dest = 0; destfile = alloca(strlen(fname)+strlen(cmd_string)+4); build_dest(destfile, fname, cmd_string); if( stat(destfile, &dest_stat) >= 0 ) { if( dest_stat.st_ino == cur_file_stat.st_ino && dest_stat.st_dev == cur_file_stat.st_dev ) { warning(EPERM, "Can't copy file to itself ", fname); return -1; } } else no_dest = 1; if( S_ISDIR(cur_file_stat.st_mode) ) { if( !no_dest ) { if( S_ISDIR(dest_stat.st_mode) ) return 0; if( unlink(destfile) < 0 ) return error(errno, "Can't delete ", destfile); } return cmd_mkdir(destfile); } else if( S_ISDIR(dest_stat.st_mode) ) return error(EPERM, "Can't copy non-directory to directory ", destfile); else if( S_ISREG(cur_file_stat.st_mode) ) { /* Copy_ok - do we want to force a real file */; if( flg_force && !no_dest && !S_ISREG(dest_stat.st_mode) ) cmd_rm(destfile); } else if( flg_recurse ) /* Don't copy other things while recursing */ { return error(EPERM, "Can't copy ", fname); } if( copy_file(fname, destfile) != 0 ) return -1; if( flg_preserve ) copy_modes(destfile); return 0; } int copy_modes(file) char * file; { int user, group, mode; /* chown turns off set[ug]id bits for non-root, so do the chmod last. */ /* Try to copy the old file's modtime and access time. */ if(set_time) { struct utimbuf tv; tv.actime = cur_file_stat.st_atime; tv.modtime = cur_file_stat.st_mtime; if( set_time != -1 ) tv.modtime = set_time; if (utime (file, &tv) && !flg_force) return error (errno, "", file); } /* Try to preserve ownership. For non-root it might fail, but that's ok. But root probably wants to know, e.g. if NFS disallows it. */ user = cur_file_stat.st_uid; if(set_user != -1) user = set_user; group = cur_file_stat.st_gid; if(set_group != -1) group = set_group; if (chown (file, user, group) && (errno != EPERM || geteuid() == 0 || (flg_preserve==0 && flg_force==0))) error (errno, "Can't change perms for ", file); mode = cur_file_stat.st_mode; if(set_mode>=0) mode=set_mode; else if(*mode_str) mode = edit_mode(mode, mode_str); if (chmod (file, mode & 07777)) return error (errno, "", file); return 0; } /* This copies from something to a file or stdout */ /* If the source has zero blocks (possibly holes) the destination * is built with holes (assuming it's a normal file) */ int copy_file(source, dest) char * source; char * dest; { char * buf; int sfd, dfd; struct stat st; int blksz = BUFSIZ; int cc; char * ptr; int hole_flag = 0; int retv = 0; int no_seek; int mmode = 0666; if(flg_verbose>1) printf("%s -> %s\n", source, dest); if( strcmp(source, "-") == 0 ) sfd = 0; else { sfd = open(source, O_RDONLY); if(sfd<0) return error(errno, "", source); mmode = (cur_file_stat.st_mode&0777); } if( strcmp(dest, "-") == 0 ) dfd = 1; else { dfd = open(dest, O_WRONLY|O_TRUNC|O_CREAT, mmode); if(dfd<0) { close(sfd); return error(errno, "Cannot create ", source); } } if( fstat(dfd, &st) ) { retv = error(errno, "", dest); no_seek = 1; } else { #ifndef __BCC__ blksz = st.st_blksize; #endif no_seek = !S_ISREG(st.st_mode); } buf = alloca(blksz + sizeof(int)); if( buf == 0 ) return error(0, "Out of memory", ""); for(;;) { cc = read(sfd, buf, blksz); if(cc<0) { retv = error(errno, "", source); goto exit_now; } if(cc==0) break; buf[cc] = 1; for(ptr=buf; *ptr==0 ; ptr++) ; if((hole_flag = (ptr == buf+cc))) { /* Make a hole */ if( lseek(dfd, (off_t) cc, SEEK_CUR) < 0 ) { retv = error(errno, "", dest); goto exit_now; } } else { if( cc != write(dfd, buf, cc)) { retv = error(errno, "", dest); goto exit_now; } } } if( hole_flag ) { if( lseek(dfd, (off_t) -1, SEEK_CUR) < 0 || write(dfd, "", 1) != 1 ) { retv = error(errno, "", dest); goto exit_now; } } exit_now: if(sfd>2) close(sfd); if(dfd>2) close(dfd); return retv; } void Usage() { int i; printf("FileTool Usage: %s%s", prog_name[0]=='-'?"ft -":"", prog_name); if( cmd_tok == CMD_FT ) { printf(" --[com_name] [-options] [files]\n"); printf("\nAvailable commands are:\n"); } for(i=1; command_list[i].name; i++) { if( cmd_tok == CMD_FT ) printf(" %s --%s", prog_name, command_list[i].name); else if( cmd_tok != command_list[i].cmd ) continue; if( *command_list[i].opts ) printf(" [-%s]", command_list[i].opts); switch(command_list[i].argpat) { case 1: printf(" [files]"); break; case -1: printf(" [files] [dest]"); break; case 0: printf(" [files]"); break; default: printf(" path [bcu] major minor"); break; } printf("\n"); } exit(99); } int cmd_mkdir(dirname) char * dirname; { int retv; int mode = 0777; if( set_mode >= 0 ) mode = set_mode; retv = mkdir(dirname, mode); if(retv<0) { if(flg_mkpdir && errno == ENOENT) { /* Create parents */ } } if( retv>=0 && cmd_tok == CMD_MKDIR ) { if( set_user != -1 || set_group != -1 ) { if( chown(dirname, set_user, set_group) < 0) warning(errno, "Cannot change directory owner ", dirname); else if( chmod (dirname, mode & 07777) ) warning(errno, "", dirname); } } if(retv<0) error(errno, "Cannot create directory ", dirname); return retv; } int cmd_mknod() { int device, major, minor; int rv = -1; int mode=0666; if( set_mode >= 0 ) mode=set_mode; major = atoi(flist[2]); minor = atoi(flist[3]); #ifdef __linux__ /* Linux 2.6+ uses an odd arrangment. */ device = (major<<8) + (minor & 0xFF) + ((minor & 0xFFF00) << 12); #else device = (major<<8) + (minor & 0xFF); #endif if(flist[1][0] == 'b') rv = mknod(flist[0], S_IFBLK|mode, device); else if(flist[1][0] == 'c' || flist[1][0] == 'u') rv = mknod(flist[0], S_IFCHR|mode, device); else Usage(); if(rv<0) { error(errno, "", flist[0]); exit(1); } return rv; } int warning(enumber, estr, eobj) int enumber; char * estr; char * eobj; { if(flg_verbose) return error(enumber, estr, eobj); return 0; } int error(enumber, estr, eobj) int enumber; char * estr; char * eobj; { fprintf(stderr, "%s%s: ", prog_name[0]=='-'?"ft":"", prog_name); fprintf(stderr, "%s%s: %s\n", estr, eobj, strerror(enumber)); return -1; } dev86-0.16.21/tests/grab.c000066400000000000000000000030441231050321700150310ustar00rootroot00000000000000 #include #include struct s { struct s * n; char v[1]; }; #define M ((unsigned)-1>>1) #define V (M^(M>>1)) main (argc,argv) int argc; char ** argv; { struct s * ptr1 = 0; struct s * ptr2; struct s * ptr3; int i,sz; unsigned long total = 0; for(i=0, sz=256 ; i<32; i++, sz = ((sz << 1) | (sz & V)) & M) { ptr2 = (struct s *) malloc(sz-sizeof(int)); printf("%2d(%8u)..%08lx..%ld\n",i,sz,(long)ptr2,(long)ptr2); if(ptr2==0) break; total+=sz; if(ptr1==0) { ptr1 = ptr3 = ptr2; ptr3->n = 0; } else { ptr3->n = ptr2; ptr3 = ptr2; ptr3->n = 0; } } for(sz>>=1; sz>3; ) { ptr2 = (struct s *) malloc(sz-sizeof(int)); if(ptr2==0) { sz >>=1; continue; } printf("%2d(%8u)..%08lx..%ld\n",i++,sz,(long)ptr2,(long)ptr2); total+=sz; if(ptr1==0) { ptr1 = ptr3 = ptr2; ptr3->n = 0; } else { ptr3->n = ptr2; ptr3 = ptr2; ptr3->n = 0; } } printf("Free all - total was %ldK bytes\n", total/1024); while( ptr1 ) { ptr3 = ptr1->n; free(ptr1); ptr1 = ptr3; } ptr2 = (struct s *) malloc(200); printf("%2d(%8u)..%08lx..%ld\n",i++,200,(long)ptr2,(long)ptr2); ptr2 = (struct s *) malloc(30000); printf("%2d(%8u)..%08lx..%ld\n",i++,30000,(long)ptr2,(long)ptr2); ptr2 = (struct s *) malloc(20000); printf("%2d(%8u)..%08lx..%ld\n",i++,20000,(long)ptr2,(long)ptr2); sz = (256< #include #include #ifndef MSDOS #ifndef __BCC__ #include #endif #endif int lastnum[16] = {-1}; long lastaddr = -1; long offset = 0; FILE *fd; FILE * ofd; char * outfile = 0; int reverse = 0; main(argc, argv) int argc; char **argv; { int done = 0; int ar; int aflag = 1; #ifndef MSDOS #ifndef __BCC__ setlocale(LC_CTYPE, ""); #endif #endif ofd = stdout; for (ar = 1; ar < argc; ar++) if (aflag && argv[ar][0] == '-') switch (argv[ar][1]) { case 'r': /* Reverse */ reverse = 1; break; case 's': /* Skip */ offset = strtol(argv[ar] + 2, (void *) 0, 0); break; case '-': aflag = 0; break; case 'o': /* Output */ if( argv[ar][2] ) outfile = argv[ar]+2; else { if( ++ar >= argc ) Usage(); outfile = argv[ar]; } break; default: Usage(); } else { if( outfile ) { if( ofd != stdout ) fclose(ofd); #ifdef MSDOS if( reverse ) ofd = fopen(outfile, "wb"); else #endif ofd = fopen(outfile, "w"); if( ofd == 0 ) { fprintf(stderr, "Cannot open file '%s'\n", outfile); exit(9); } } fd = fopen(argv[ar], "rb"); if (fd == 0) fprintf(stderr, "Cannot open file '%s'\n", argv[ar]); else { if( reverse ) do_rev_fd(); else do_fd(); fclose(fd); } done = 1; } if (!done) #ifdef MSDOS Usage(); #else { fd = stdin; if( reverse ) do_rev_fd(); else do_fd(); } #endif exit(0); } Usage() { fprintf(stderr, "Usage: hd [-o Outfile][-r]|[[-sSkip_bytes] file]\n"); exit(1); } do_fd() { int j, ch; char buf[20]; int num[16]; if (offset) fseek(fd, offset, 0); for (ch = 0; ch != EOF; offset += 16) { memset(buf, '\0', 16); for (j = 0; j < 16; j++) num[j] = -1; for (j = 0; j < 16; j++) { ch = fgetc(fd); if (ch == EOF) break; num[j] = ch; if (isprint(ch)) buf[j] = ch; else buf[j] = '.'; } printline(offset, num, buf, ch == EOF); } } printline(address, num, chr, eofflag) long address; int *num; char *chr; int eofflag; { int j; if (lastaddr >= 0) { for (j = 0; j < 16; j++) if (num[j] != lastnum[j]) break; if (j == 16 && !eofflag) { if (lastaddr + 16 == address) { fprintf(ofd, "*\n"); fflush(ofd); } return; } } lastaddr = address; fprintf(ofd, "%06lx:", address); for (j = 0; j < 16; j++) { if (j == 8) fputc(' ', ofd); if (num[j] >= 0) fprintf(ofd, " %02x", num[j]); else fprintf(ofd, " "); lastnum[j] = num[j]; num[j] = -1; } fprintf(ofd, " %.16s\n", chr); } /* * This function takes output from hd and converts it back into a binary * file */ do_rev_fd() { char str[160]; char * ptr; int c[16], i, nxtaddr, addr; int zap_last = 1; for (i = 0; i < 16; i++) c[i] = 0; nxtaddr = 0; for (nxtaddr = 0;;) { if (fgets(str, sizeof(str), fd) == NULL) break; str[57] = 0; ptr = str; if( *ptr == '*' ) zap_last = 0; if( *ptr != ':' ) { if( !isxdigit(*ptr) ) continue; addr = strtol(ptr, &ptr, 16); } else addr = nxtaddr; if( *ptr == ':' ) ptr++; if (nxtaddr == 0) nxtaddr = addr; if( zap_last ) memset(c, 0, sizeof(c)); else zap_last = 1; while (nxtaddr < addr) { for (i = 0; nxtaddr < addr && i < 16; i++, nxtaddr++) fputc(c[i], ofd); } for (i = 0; i < 16 && *ptr; i++) { char * ptr2; c[i] = strtol(ptr, &ptr2, 16); if( ptr == ptr2 ) break; fputc(c[i], ofd); ptr = ptr2; } nxtaddr += 16; } return 0; } dev86-0.16.21/tests/hello_world.s000066400000000000000000000002511231050321700164450ustar00rootroot00000000000000 .text entry start start: mov ax,#4 mov bx,#1 mov cx,#hello mov dx,#endhello-hello int $80 mov bx,#0 mov ax,#1 int $80 .data hello: .ascii "Hello world!\n" endhello: dev86-0.16.21/tests/line2.c000066400000000000000000000002651231050321700151310ustar00rootroot00000000000000 #include char buf[256]; main() { FILE * fd; fd = fopen("/etc/passwd", "r"); while(fgets(buf, sizeof(buf), fd) != NULL) { printf(">>%s", buf); } } dev86-0.16.21/tests/lines.c000066400000000000000000000010431231050321700152250ustar00rootroot00000000000000 #include #include char * readline(fd) { static char linebuf[256]; int cc; char * p; cc = read(fd, linebuf, sizeof(linebuf)-1); if( cc <= 0 ) return 0; p = strchr(linebuf, '\n'); if( p == 0 ) p = linebuf+sizeof(linebuf)-1; else { p++; lseek(fd, (long)(p-linebuf)-cc, 1); } *p = 0; return linebuf; } main() { int fd = open("/etc/passwd", O_RDONLY); char * p; if(fd<0) exit(1); while( p=readline(fd) ) { write(1, ">>", 2); write(1, p, strlen(p)); } } dev86-0.16.21/tests/ouch.c000066400000000000000000000006001231050321700150470ustar00rootroot00000000000000 #include #include #include void trap() { write(1, "Ouch!!\n", 7); } main() { char buf[2]; int cc; signal(SIGINT, trap); while( (cc=read(0, buf, 1)) > 0 || (cc == -1 && errno == EINTR) ) { if( cc < 0 ) fprintf(stderr, "INTR\n"); else fprintf(stderr, "%x\n", buf[0]); } write(1, "\nExit!\n", 7); } dev86-0.16.21/tests/rand.c000066400000000000000000000002751231050321700150450ustar00rootroot00000000000000#include FILE * popen(); main() { FILE * fd = popen("./hd", "w"); int ch; srand(time((void*)0)); for(ch=0; ch<256; ch++) putc(rand(), fd); pclose(fd); } dev86-0.16.21/tests/sync.c000066400000000000000000000000361231050321700150700ustar00rootroot00000000000000int main() { return sync(); } dev86-0.16.21/tests/ucomp.c000066400000000000000000000040671231050321700152470ustar00rootroot00000000000000 /* * Uncompress program this is very very fast * */ #include #include #include #include #include #define MAXLEN 255 #define maxno 61000U #define USE_BSS #ifdef USE_BSS unsigned char fptr[maxno]; #else unsigned char *fptr; #endif FILE * fd; int key; main(argc, argv) int argc; char ** argv; { #ifndef USE_BSS fptr = (unsigned char * ) malloc(maxno); if( fptr == 0 ) { perror("Cannot allocate memory"); exit(1); } #endif if( argc < 2 ) { fd = stdin; key = getc(fd); uncompress(); } else { fd = fopen(argv[1], "r" ); if( fd == 0 ) { perror("Open failed"); exit(1); } key = getc(fd); uncompress(); } } /* Uncompression routine -- v.v.fast */ uncompress() { register unsigned char * mainscan; register unsigned char * secondscan; register unsigned char * ptr = (unsigned char * ) fptr; register unsigned char * eptr = ptr+maxno; register unsigned int len; register int ch; mainscan = ptr; for(;;) { ch = getc(fd); if(ch == EOF) break; ch &= 0xFF; if(ch == key) { ch = getc(fd); if( ch == 0 ) *mainscan++ = key; else { len = (unsigned char) getc(fd); if( ch & 0x80 ) len += ((unsigned char) getc(fd)) << 8; secondscan = mainscan - len; if(len > mainscan - ptr) secondscan += maxno; len = (unsigned char) ch & 0x7F; for( ; len>0; len-- ) { *mainscan++ = *secondscan++; if( secondscan == eptr ) secondscan = ptr; if( mainscan == eptr ) { write(1, ptr, (int)(mainscan-ptr)); mainscan = ptr; } } } } else *mainscan++ = ch; if( mainscan == eptr ) { write(1, ptr, (int)(mainscan-ptr)); mainscan = ptr; } } if( mainscan != ptr ) { write(1, ptr, (int)(mainscan-ptr)); mainscan = ptr; } } dev86-0.16.21/tests/wc.c000066400000000000000000000042101231050321700145230ustar00rootroot00000000000000 #include #include int lflag; /* Want count lines */ int wflag; /* Want count words */ int cflag; /* Want count characters */ long lcount; /* File count of lines */ long wcount; /* File count of words */ long ccount; /* File count of characters */ long ltotal; /* Total count of lines */ long wtotal; /* Total count of words */ long ctotal; /* Total count of characters */ int main(argc, argv) int argc; char **argv; { char *p; int ar; if (argc > 1 && argv[1][0] == '-') { for (p = argv[1] + 1; *p; p++) { switch (*p) { case 'l': lflag++; break; case 'w': wflag++; break; case 'c': cflag++; break; default: Usage(); } } argc--; argv++; } /* If no flags are set, treat as wc -lwc. */ if (!lflag && !wflag && !cflag) lflag = wflag = cflag = 1; /* No filename, use stdin */ if (argc == 1) { count(stdin, ""); exit(0); } /* There is an explicit list of files. Loop on files. */ for (ar = 1; ar < argc; ar++) { FILE *f; if ((f = fopen(argv[ar], "r")) == NULL) fprintf(stderr, "wc: cannot open %s\n", argv[ar]); else { count(f, argv[ar]); fclose(f); } } if (argc > 2) { if (lflag) printf("%7ld ", ltotal); if (wflag) printf("%7ld ", wtotal); if (cflag) printf("%7ld ", ctotal); printf("total\n"); } exit(0); } count(f, fname) FILE *f; char *fname; { register int c; register int inword = 0; lcount = 0; wcount = 0; ccount = 0; while ((c = getc(f)) != EOF) { ccount++; if (isspace(c)) { if (inword) wcount++; inword = 0; } else inword = 1; if (c == '\n' || c == '\f') lcount++; } ltotal += lcount; wtotal += wcount; ctotal += ccount; if (lflag) printf("%7ld ", lcount); if (wflag) printf("%7ld ", wcount); if (cflag) printf("%7ld ", ccount); if (fname && *fname) printf("%s", fname); printf("\n"); } Usage() { fprintf(stderr, "Usage: wc [-lwc] [name ...]\n"); exit(1); } dev86-0.16.21/unproto/000077500000000000000000000000001231050321700143155ustar00rootroot00000000000000dev86-0.16.21/unproto/Makefile000066400000000000000000000106671231050321700157670ustar00rootroot00000000000000# @(#) Makefile 1.6 93/06/18 22:29:40 ## BEGIN CONFIGURATION STUFF # In the unlikely case that your compiler has no hooks for alternate # compiler passes, use a "cc cflags -E file.c | unproto >file.i" # pipeline, then "cc cflags -c file.i" to compile the resulting # intermediate file. # # Otherwise, the "/lib/cpp | unproto" pipeline can be packaged as an # executable shell script (see the provided "cpp.sh" script) that should # be installed as "/whatever/cpp". This script should then be specified # to the C compiler as a non-default preprocessor. # PROG = unproto PIPE = # The overhead and problems of shell script interpretation can be # eliminated by having the unprototyper program itself open the pipe to # the preprocessor. In that case, define the PIPE_THROUGH_CPP macro as # the path name of the default C preprocessor (usually "/lib/cpp"), # install the unprototyper as "/whatever/cpp" and specify that to the C # compiler as a non-default preprocessor. # # PROG = cpp # PIPE = -DPIPE_THROUGH_CPP=\"/lib/cpp\" # Some compilers complain about some #directives. The following is only a # partial solution, because the directives are still seen by /lib/cpp. # Be careful with filtering out #pragma, because some pre-ANSI compilers # (SunOS) rely on its use. # # SKIP = -DIGNORE_DIRECTIVES=\"pragma\",\"foo\",\"bar\" # SKIP = # The bell character code depends on the character set. With ASCII, it is # 7. Specify a string constant with exactly three octal digits. If you # change this definition, you will have to update the example.out file. # # BELL = -DBELL=\"007\" # Some C compilers have problems with "void". The nature of the problems # depends on the age of the compiler. # # If your compiler does not understand "void" at all, compile with # -DMAP_VOID. The unprototyper will replace "void *" by "char *", a # (void) argument list by an empty one, and will replace all other # instances of "void" by "int". # # If your compiler has problems with "void *" only, compile with # -DMAP_VOID_STAR. The unprototyper will replace "void *" by "char *", # and will replace a (void) argument list by an empty one. All other # instances of "void" will be left alone. # # If neither of these are defined, (void) argument lists will be replaced # by empty ones. # # MAP = -DMAP_VOID_STAR # Now that we have brought up the subject of antique C compilers, here's # a couple of aliases that may be useful, too. # # ALIAS = -Dstrchr=index # If you need support for functions that implement ANSI-style variable # length argument lists, edit the stdarg.h file provided with this # package so that it contains the proper definitions for your machine. ## END CONFIGURATION STUFF SHELL = /bin/sh CFILES = unproto.c tok_io.c tok_class.c tok_pool.c vstring.c symbol.c error.c \ hash.c strsave.c HFILES = error.h token.h vstring.h symbol.h SCRIPTS = cpp.sh acc.sh SAMPLES = stdarg.h stddef.h stdlib.h varargs.c example.c example.out SOURCES = README $(CFILES) $(HFILES) Makefile $(SCRIPTS) $(SAMPLES) FILES = $(SOURCES) unproto.1 OBJECTS = tok_io.o tok_class.o tok_pool.o unproto.o vstring.o symbol.o error.o \ hash.o strsave.o CFLAGS = -O LDFLAGS = CCFLAGS = $(CFLAGS) -w $(PIPE) $(SKIP) $(BELL) $(MAP) $(ALIAS) -DREOPEN #CFLAGS = -O $(PIPE) $(SKIP) $(BELL) $(MAP) $(ALIAS) -p -Dstatic= #CFLAGS = -g $(PIPE) $(SKIP) $(BELL) $(MAP) $(ALIAS) -DDEBUG $(PROG): $(OBJECTS) $(CC) $(CCFLAGS) $(LDFLAGS) -o $@ $(OBJECTS) $(MALLOC) .c.o: $(CC) $(CCFLAGS) -c $< -o $@ # For linting, enable all bells and whistles. lint: lint -DPIPE_THROUGH_CPP=\"foo\" -DIGNORE_DIRECTIVES=\"foo\",\"bar\" \ $(BELL) -DMAP_VOID $(ALIAS) $(CFILES) # Testing requires that the program is compiled with -DDEBUG. test: $(PROG) cpp example.c example.out ./cpp example.c >example.tmp @echo the following diff command should produce no output diff -b example.out example.tmp rm -f example.tmp shar: $(FILES) @shar $(FILES) archive: $(ARCHIVE) $(SOURCES) clean realclean: rm -f *.o core cpp unproto mon.out varargs.o varargs example.tmp error.o : error.c token.h error.h Makefile hash.o : hash.c Makefile strsave.o : strsave.c error.h Makefile symbol.o : symbol.c error.h token.h symbol.h Makefile tok_class.o : tok_class.c error.h vstring.h token.h symbol.h Makefile tok_io.o : tok_io.c token.h vstring.h error.h Makefile tok_pool.o : tok_pool.c token.h vstring.h error.h Makefile unproto.o : unproto.c vstring.h stdarg.h token.h error.h symbol.h Makefile varargs.o : varargs.c stdarg.h Makefile vstring.o : vstring.c vstring.h Makefile dev86-0.16.21/unproto/README000066400000000000000000000151511231050321700152000ustar00rootroot00000000000000@(#) README 1.6 93/06/18 22:29:34 unproto - Compile ANSI C with traditional UNIX C compiler Description: ------------ This is a filter that sits in between the UNIX C preprocessor and the next UNIX C compiler stage, on the fly transforming ANSI C syntax to old C syntax. Line number information is preserved so that compiler diagnostics still make sense. It runs at roughly the same speed as /lib/cpp, so it has negligible impact on compilation time. Typically, the program is invoked by the native UNIX C compiler as an alternate preprocessor. The unprototyper in turn invokes the native C preprocessor and massages its output. Similar tricks can be used with the lint(1) command. Details are given below. The filter rewrites ANSI-style function headings, function pointer types and type casts, function prototypes, and combinations thereof. Unlike some other unprototypers, this one is fully recursive and does not depend on source file layout (see the example.c file). Besides the rewriting of argument lists, the program does the following transformations: string concatenation, conversion of \a and \x escape sequences to their octal equivalents, translation of the __TIME__ and __DATE__ macros, optional mapping of `void *' to `char *', and optional mapping of plain `void' to `int'. The unprototyper provides hooks for compilers that require special tricks for variadic functions (fortunately, many don't). support is provided for sparc, mips, mc68k, 80x86, vax, and others. The program has been tested with SunOS 4.1.1 (sparc), Ultrix 4.0 and 4.2 (mips), and Microport System V Release 2 (80286). It should work with almost every PCC-based UNIX C compiler. Restrictions: ------------- A description of restrictions and workarounds can be found in the unproto.1 manual page. Problems fixed with this release: --------------------------------- Prototypes and definitions of functions returning pointer to function were not rewritten to old style. Operation: ---------- This package implements a non-default C preprocessor (the output from the default C preprocessor being piped through the unprototyper). How one tells the C compiler to use a non-default preprocessor program is somewhat compiler-dependent: SunOS 4.x: cc -Qpath directory_with_alternate_cpp ... Ultrix 4.x: cc -tp -hdirectory_with_alternate_cpp -B ... System V.2: cc -Bdirectory_with_alternate_cpp/ -tp ... Examples of these, and others, can be found in the acc.sh shell script that emulates an ANSI C compiler. Your C compiler manual page should provide the necessary information. A more portable, but less efficient, approach relies on the observation that almost every UNIX C compiler supports the -E (write preprocessor output to stdout) and -P options (preprocess file.c into file.i). Just add the following lines to your Makefiles: .c.o: $(CC) $(CFLAGS) -E $*.c | unproto >$*.i # simulate -P option $(CC) $(CFLAGS) -c $*.i rm -f $*.i On some systems the lint(1) command is just a shell script, and writing a version that uses the unprototyper should not be too hard. With SunOS 4.x, /usr/bin/lint is not a shell script, but it does accept the same syntax as the cc(1) command for the specification of a non-default compiler pass. You may have to do some research on the lint command provided with your own machine. Configuration: -------------- Check the contents of the `stdarg.h' file provided with this package. This file serves a dual purpose: (1) on systems that do not provide a stdarg.h file, it should be included by C source files that implements ANSI-style variadic functions; (2) it is also used to configure the unprototyper so that it emits the proper magic when it sees `...'. The `stdarg.h' file has support for sparc, mips, and for compilers that pass arguments via the stack (typical for 80*86, mc68k and vax). It gives general hints for other compilers. The other sample header files (stddef.h and stdlib.h) are not required to build the unprototyper. The `varargs.c' file provided with this package can be used to verify that the `stdarg.h' file has been set up correctly. If your C compiler has no hooks for an alternate preprocessor (the unprototyper will be used as: `cc cflags -E file.c | unproto >file.i'), build the `unproto' executable without the `PIPE_THROUGH_CPP' feature. Details are given in the Makefile. Otherwise, the `cpp.sh' shell script can be used to set up the pipe between the native C preprocessor and the unprototyper command. The script assumes that the unprototyper binary is called `unproto', and that it was compiled without the `PIPE_THROUGH_CPP' feature. See the Makefile and the `cpp.sh' script for details and for a description of possible problems with this approach. The overhead and problems of shell-script interpretation can be avoided by letting the unprototyper itself pipe its standard input through the C preprocessor. For this mode of operation, the unprototyper binary should be called `cpp', and the `unproto.c' source file should be compiled with the `PIPE_THROUGH_CPP' macro defined as the absolute pathname of the native C preprocessor (usually `/lib/cpp'). See the Makefile for details. Installation: ------------- Install the `unproto.1' manual page in a suitable place. If your system does not provide a `stdarg.h' file, find a suitable place for the one provided with the unprototyper and install it there. The same goes for the sample stddef.h and stdlib.h files; make sure that the definitions in there apply to your environment. Most or all of the latter files are already part of Ultrix 4.x and SunOS 4.1.1. The ANSI float.h and limits.h files can be generated with the config program by Steve Pemberton (comp.sources.misc volume 10, issue 62, available from ftp.uu.net as comp.sources.misc/volume10/config42.Z). If you run the unprototyper with "cc -E" just install the `unproto' binary; the `cpp' and `acc' shell scripts will not be needed. If you use the `cpp' shell script to pipe the preprocessor output through the unprototyper program, install the `unproto' binary in a place where the `cpp' shell script can find it, and install the `cpp' shell script in a suitable place. Edit the `acc' shell script and install it in a suitable place. From now on, type `acc' instead of `cc'. If the unprototyper itself opens the pipe to the C preprocessor (i.e. the unprototyper was built with the `PIPE_THROUGH_CPP' macro defined), install the `cpp' unprototyper binary in a suitable place. Edit the `acc' shell script and install it in a suitable place. From now on, type `acc' instead of `cc'. Wietse Venema wietse@wzv.win.tue.nl Mathematics and Computing Science Eindhoven University of Technology The Netherlands dev86-0.16.21/unproto/Sharheader000066400000000000000000000004521231050321700163070ustar00rootroot00000000000000 # Contents: README unproto.c tok_io.c tok_class.c tok_pool.c vstring.c # symbol.c error.c hash.c strsave.c error.h token.h vstring.h # symbol.h Makefile cpp.sh acc.sh stdarg.h stddef.h stdlib.h # varargs.c example.c example.out unproto.1 # Wrapped by wietse@wzv on Fri Jun 18 22:48:56 1993 dev86-0.16.21/unproto/acc.sh000066400000000000000000000023321231050321700153770ustar00rootroot00000000000000#!/bin/sh # @(#) acc.sh 1.1 93/06/18 22:29:42 # # Script to emulate most of an ANSI C compiler with a traditional UNIX # C compiler. # INCDIR should be the directory with auxiliary include files from the # unproto source distribution (stdarg.h, stdlib.h, stddef.h, and other # stuff that is missing from your compilation environment). With Ultrix # 4.[0-2] you need unproto's stdarg.h even though the system provides # one. # INCDIR=. # CPPDIR should be the directory with the unprototypeing cpp filter # (preferably the version with the PIPE_THROUGH_CPP feature). # CPPDIR=. # DEFINES: you will want to define volatile and const, and maybe even # __STDC__. # DEFINES="-Dvolatile= -Dconst= -D__STDC__" # Possible problem: INCDIR should be listed after the user-specified -I # command-line options, not before them as we do here. This is a problem # only if you attempt to redefine system libraries. # # Choose one of the commands below that is appropriate for your system. # exec cc -Qpath ${CPPDIR} -I${INCDIR} ${DEFINES} "$@" # SunOS 4.x exec cc -tp -h${CPPDIR} -B -I${INCDIR} ${DEFINES} "$@" # Ultrix 4.2 exec cc -Yp,${CPPDIR} -I${INCDIR} ${DEFINES} "$@" # M88 SysV.3 exec cc -B${CPPDIR}/ -tp -I${INCDIR} ${DEFINES} "$@" # System V.2 dev86-0.16.21/unproto/cpp.sh000066400000000000000000000014671231050321700154430ustar00rootroot00000000000000#!/bin/sh # @(#) cpp.sh 1.3 92/01/15 21:53:22 # Unprototypeing preprocessor for pre-ANSI C compilers. On some systems, # this script can be as simple as: # # /lib/cpp "$@" | unproto # # However, some cc(1) drivers specify output file names on the # preprocessor command line, so this shell script must be prepared to # intercept them. Depending on the driver program, the cpp options may # even go before or after the file name argument(s). The script below # tries to tackle all these cases. # # You may want to add -Ipath_to_stdarg.h_file, -Dvoid=, -Dvolatile=, # and even -D__STDC__. cpp_args="" while : do case $1 in "") break;; -*) cpp_args="$cpp_args $1";; *) cpp_args="$cpp_args $1" case $2 in ""|-*) ;; *) exec 1> $2 || exit 1; shift;; esac;; esac shift done /lib/cpp $cpp_args | unproto dev86-0.16.21/unproto/error.c000066400000000000000000000036261231050321700156210ustar00rootroot00000000000000/*++ /* NAME /* error 3 /* SUMMARY /* diagnostics /* PACKAGE /* unproto /* SYNOPSIS /* #include "error.h" /* /* int errcount; /* /* void error(text) /* char *text; /* /* void error_where(path, line, text) /* char *path; /* int line; /* char *text; /* /* void fatal(text) /* char *text; /* DESCRIPTION /* The routines in this file print a diagnostic (text). Some also /* terminate the program. Upon each error*() call, the errcount variable /* is incremented. /* /* error() provides a default context, i.e. the source-file /* coordinate of the last read token. /* /* error_where() allows the caller to explicitly specify context: path /* is a source-file name, and line is a line number. /* /* fatal() is like error() but terminates the program with a non-zero /* exit status. /* /* context is ignored if the line number is zero or if the path /* is an empty string. /* AUTHOR(S) /* Wietse Venema /* Eindhoven University of Technology /* Department of Mathematics and Computer Science /* Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands /* LAST MODIFICATION /* 92/01/15 21:53:10 /* VERSION/RELEASE /* 1.2 /*--*/ static char error_sccsid[] = "@(#) error.c 1.2 92/01/15 21:53:10"; /* C library */ #include extern void exit(); /* Application-specific stuff */ #include "token.h" #include "error.h" int errcount = 0; /* error counter */ /* error - report problem (implicit context) */ void error(text) char *text; { error_where(in_path, in_line, text); } /* error_where - report problem (explicit context) */ void error_where(path, line, text) char *path; int line; char *text; { errcount++; /* Suppress context info if there is none. */ if (line && path[0]) fprintf(stderr, "%s, line %d: ", path, line); fprintf(stderr, "%s\n", text); } /* fatal - report problem and terminate unsuccessfully */ void fatal(text) char *text; { error(text); exit(1); } dev86-0.16.21/unproto/error.h000066400000000000000000000003441231050321700156200ustar00rootroot00000000000000/* @(#) error.h 1.2 92/01/15 21:53:14 */ extern int errcount; /* error counter */ extern void error(); /* default context */ extern void error_where(); /* user-specified context */ extern void fatal(); /* fatal error */ dev86-0.16.21/unproto/example.c000066400000000000000000000067051231050321700161240ustar00rootroot00000000000000 /* * @(#) example.c 1.5 93/06/18 22:29:46 * * Examples of things that can be done with the unproto package */ typedef char *charstar; /* * New-style argument list with structured argument, one field being pointer * to function returning pointer to function with function-pointer argument */ x(struct { struct { int (*(*foo) (int (*arg1) (double))) (float arg2); } foo; } baz) { return (0); } /* New-style function-pointer declaration. */ int (*(*bar0) (float)) (int); /* Old-style argument list with new-style argument type. */ baz0(bar) int (*(*bar) (float)) (int); {} /* * New-style argument list with new-style argument type, declaration * embedded within block. Plus a couple assignments with function calls that * look like casts. */ foo(int (*(*bar) (float)) (int)) { int (*baz) (int) = (int (*) (int)) 0, y = (y * (*baz) (y)), *(*z) (int) = (int *(*) (int)) 0; struct { int (*foo)(int); } *(*s)(int) = (struct { int (*foo)(int); } *(*)(int)) 0; { y = (y * (*baz) (y)); } { z = (int *(*) (int)) 0; } { s = (struct { int (*foo)(int); } *(*)(int)) 0; } return (0); } /* Multiple declarations in one statement */ test1() { int foo2,*(*(*bar)(int))(float),*baz(double); } /* Discriminate declarations from executable statements */ test2(charstar y) { int foo = 5,atoi(charstar); foo = 5,atoi(y); } /* Declarations without explicit type */ test3,test4(int); test5(int y) { { test3; } { test4(y); } } test6[1],test7(int); test7(int x) { { test6[1]; } { test7(x); } } /* Checking a complicated cast */ struct { struct { int (*f)(int), o; } bar; } (*baz2)(int) = (struct { struct { int (*f)(int), o; } bar; } (*)(int)) 0; /* Distinguish things with the same shape but with different meaning */ test8(x) { { struct { int foo; } bar(charstar); } { do { int foo; } while (x); } } /* Do not think foo(*bar) is a function pointer declaration */ test9(char *bar) { foo(*bar); } /* another couple of special-cased words. */ test10(int x) { { int test10(int); do test10(x); while (x); } { return test10(x); } } test11(int *x) { while (*x) (putchar(*x++)); } test11a(int *x) { for (*x;;) (putchar(*x++)); } /* #include directive between stuff that requires lookahead */ test12() { char *x = "\xf\0002\002\02\2" /* foo */ #include "/dev/null" "\abar"; printf("foo" /* 1 */ "bar" /* 2 */ "baz"); *x = '\a'; *x = '\xff'; } int test13(void); /* line continuations in the middle of tokens */ te\ st14(); charstar test15 = "foo\ bar"; char test16 = "foo\\ abar"; /* Array dimensions with unexpanded macros */ test17(charstar foo[bar]){} int (*(*test18[bar])(charstar))(charstar) = \ (int (*(*[bar])(charstar))(charstar)) 0; /* Function returning pointer to function */ int (*(*test19(long))(int))(double); /* GCC accepts the following stuff, K&R C does not... */ void test20(int test21(double)) {} void test22(struct { int foo; } test23(short)) {} /* Do not blindly rewrite (*name(stuff))(otherstuff) */ void test23() { int (*test24(int)) (int), y = (*test24(2)) (3), z = ((*test24(2)) (3)); } /* Function returning pointer to function */ int (*(*test25(long foo))(int bar))(double baz){ /* body */ } int (*(*test26(foo))())() long foo; { /* body */ } #define ARGSTR() struct {int l; char c[1];} void functie(ARGSTR() *cmdlin, ARGSTR() *c1) { } dev86-0.16.21/unproto/example.out000066400000000000000000000060511231050321700165030ustar00rootroot00000000000000# 1 "example.c" typedef char *charstar; x( baz) # 14 "example.c" struct { struct { int (*(*foo)())(); } foo; } baz; # 18 "example.c" {/*1*/ /* end dcls */return (0); }/*1*/ int (*(*bar0)())(); baz0(bar) int (*(*bar)())(); {/*1*/}/*1*/ foo(bar) # 38 "example.c" int (*(*bar)())(); {/*1*/ int (*baz)()= (int (*)()) 0, y = (y * (*baz)(y)), *(*z)()= (int *(*)()) 0; struct {/*2*/ int (*foo)(); }/*2*/ *(*s)()= (struct { int (*foo)(); } *(*)()) 0; /* end dcls */{/*2*/ y /* end dcls */= (y * (*baz)(y)); }/*2*/ {/*2*/ z /* end dcls */= (int *(*)()) 0; }/*2*/ {/*2*/ s /* end dcls */= (struct { int (*foo)(); } *(*)()) 0; }/*2*/ return (0); }/*1*/ test1() {/*1*/ int foo2,*(*(*bar)())(),*baz(); }/*1*/ test2(y) # 69 "example.c" charstar y; {/*1*/ int foo = 5,atoi(); foo /* end dcls */= 5,atoi(y); }/*1*/ test3,test4(); test5(y) # 80 "example.c" int y; {/*1*/ /* end dcls */{/*2*/ test3/* end dcls */; }/*2*/ {/*2*/ test4/* end dcls */(y); }/*2*/ }/*1*/ test6[1],test7(); test7(x) # 92 "example.c" int x; {/*1*/ /* end dcls */{/*2*/ test6/* end dcls */[1]; }/*2*/ {/*2*/ test7/* end dcls */(x); }/*2*/ }/*1*/ struct {/*1*/ struct {/*2*/ int (*f)(), o; }/*2*/ bar; }/*1*/ (*baz2)()= (struct { struct { int (*f)(), o; } bar; } (*)()) 0; test8(x) {/*1*/ /* end dcls */{/*2*/ struct {/*3*/ int foo; }/*3*/ bar(); }/*2*/ {/*2*/ /* end dcls */do {/*3*/ int foo; }/*3*/ while (x); }/*2*/ }/*1*/ test9(bar) # 128 "example.c" char *bar; {/*1*/ foo/* end dcls */(*bar); }/*1*/ test10(x) # 135 "example.c" int x; {/*1*/ /* end dcls */{/*2*/ int test10(); /* end dcls */do test10(x); while (x); }/*2*/ {/*2*/ /* end dcls */return test10(x); }/*2*/ }/*1*/ test11(x) # 147 "example.c" int *x; {/*1*/ /* end dcls */while (*x) (putchar(*x++)); }/*1*/ test11a(x) # 153 "example.c" int *x; {/*1*/ /* end dcls */for (*x;;) (putchar(*x++)); }/*1*/ test12() {/*1*/ char *x = # 1 "/dev/null" 1 # 165 "example.c" 2 # 163 "example.c" "\017\0002\002\002\002\007bar" ; printf/* end dcls */("foobarbaz" ); *x = '\007'; *x = '\377'; }/*1*/ int test13(); test14(); charstar test15 = "foobar"; char test16 = "foo\007bar"; test17(foo) # 186 "example.c" charstar foo[bar]; # 186 "example.c" {/*1*/}/*1*/ int (*(*test18[bar])())()= (int (*(*[bar])())()) 0; int (*(*test19())())(); void test20(test21) # 197 "example.c" int test21(); # 197 "example.c" {/*1*/}/*1*/ void test22(test23) # 199 "example.c" struct { int foo; } test23(); # 199 "example.c" {/*1*/}/*1*/ void test23() {/*1*/ int (*test24())(), y = (*test24(2)) (3), z = ((*test24(2))(3)); }/*1*/ int (*(*test25(foo))())() # 212 "example.c" long foo; # 212 "example.c" {/*1*/ }/*1*/ int (*(*test26(foo))())() long foo; {/*1*/ }/*1*/ void functie(cmdlin,c1) # 220 "example.c" struct {int l; char c[1];} *cmdlin; # 220 "example.c" struct {int l; char c[1];} *c1; {/*1*/ }/*1*/ dev86-0.16.21/unproto/hash.c000066400000000000000000000024221231050321700154040ustar00rootroot00000000000000/*++ /* NAME /* hash 3 /* SUMMARY /* compute hash value for string /* SYNOPSIS /* int hash(string, size) /* char *string; /* int size; /* DESCRIPTION /* This function computes for the given null-terminated string an /* integer hash value in the range 0..size-1. /* SEE ALSO /* .fi /* Alfred V. Aho, Ravi Sethi and Jeffrey D. Ullman: Compilers: /* principles, techniques and tools; Addison-Wesley, Amsterdam, 1986. /* AUTHOR(S) /* Wietse Venema /* Eindhoven University of Technology /* Department of Mathematics and Computer Science /* Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands /* /* Originally written by: P. J. Weinberger at Bell Labs. /* LAST MODIFICATION /* 92/01/15 21:53:12 /* VERSION/RELEASE /* %I /*--*/ static char hash_sccsid[] = "@(#) hash.c 1.1 92/01/15 21:53:12"; /* hash - hash a string; original author: P. J. Weinberger at Bell Labs. */ int hash(s, size) register char *s; unsigned size; { register unsigned long h = 0; register unsigned long g; /* * For a performance comparison with the hash function presented in K&R, * first edition, see the "Dragon" book by Aho, Sethi and Ullman. */ while (*s) { h = (h << 4) + *s++; if (g = (h & 0xf0000000)) { h ^= (g >> 24); h ^= g; } } return (h % size); } dev86-0.16.21/unproto/stdarg.h000066400000000000000000000060031231050321700157510ustar00rootroot00000000000000 /* * @(#) stdarg.h 1.4 93/06/18 22:29:44 * * Sample stdarg.h file for use with the unproto filter. * * This file serves two purposes. * * 1 - On systems that do not have a /usr/include/stdarg.h file, it should be * included by C source files that implement ANSI-style variadic functions. * Ultrix 4.[0-2] comes with stdarg.h but still needs the one that is * provided with the unproto filter. * * 2 - To configure the unprototyper itself. If the _VA_ALIST_ macro is * defined, its value will appear in the place of the "..." at the end of * argument lists of variadic function *definitions* (not declarations). * Some compilers (such as Greenhills m88k) have a non-empty va_dcl * definition in the system header file varargs.h. If that is the case, * define "_VA_DCL_" with the same value as va_dcl. If _VA_DCL_ is defined, * the unprototyper will emit its value just before the opening "{". * * Compilers that always pass arguments via the stack can use the default code * at the end of this file (this usually applies for the vax, mc68k and * 80*86 architectures). * * Special tricks are needed for compilers that pass some or all function * arguments via registers. Examples of the latter are given for the mips * and sparc architectures. Usually the compiler special-cases an argument * declaration such as "va_alist" or "__builtin_va_alist". For inspiration, * see the local /usr/include/varargs.h file. * * You can use the varargs.c program provided with the unproto package to * verify that the stdarg.h file has been set up correctly. */ #ifdef sparc /* tested with SunOS 4.1.1 */ #define _VA_ALIST_ "__builtin_va_alist" typedef char *va_list; #define va_start(ap, p) (ap = (char *) &__builtin_va_alist) #define va_arg(ap, type) ((type *) __builtin_va_arg_incr((type *) ap))[0] #define va_end(ap) #else #ifdef mips /* tested with Ultrix 4.0 and 4.2 */ #define _VA_ALIST_ "va_alist" #include "/usr/include/stdarg.h" #else #ifdef m88k /* Motorola SYSTEM V/88 R32V3 */ #define _VA_ALIST_ "va_alist" #define _VA_DCL_ "va_type va_alist;" typedef struct _va_struct { int va_narg; int *va_stkaddr; int *va_iregs; } va_list; #define va_start(ap, p) \ ((ap).va_narg=(int *)&va_alist-va_stkarg, \ (ap).va_stkaddr=va_stkarg, \ (ap).va_iregs=(int *)va_intreg) #define va_end(p) #if defined(LittleEndian) #define va_arg(p,mode) \ (*(mode *)_gh_va_arg(&p, va_align(mode), va_regtyp(mode), sizeof(mode))) #else /* defined(LittleEndian) */ #define va_arg(p,mode) ( \ (p).va_narg += ((p).va_narg & (va_align(mode) == 8)) + \ (sizeof(mode)+3)/4, \ ((mode *)((va_regtyp(mode) && (p).va_narg <= 8 ? \ (p).va_iregs: \ (p).va_stkaddr) + (p).va_narg))[-1]) #endif /* defined(LittleEndian) */ #else /* vax, mc68k, 80*86 */ typedef char *va_list; #define va_start(ap, p) (ap = (char *) (&(p)+1)) #define va_arg(ap, type) ((type *) (ap += sizeof(type)))[-1] #define va_end(ap) #endif /* m88k */ #endif /* mips */ #endif /* sparc */ dev86-0.16.21/unproto/stddef.h000066400000000000000000000011131231050321700157330ustar00rootroot00000000000000/* @(#) stddef.h 1.1 92/02/15 17:25:46 */ #ifndef _stddef_h_ #define _stddef_h_ /* NULL is also defined in */ #ifndef NULL #define NULL 0 #endif /* Structure member offset - some compilers barf on this. */ #define offsetof(type, member) ((size_t) &((type *)0)->member) /* Some of the following types may already be defined in . */ /* #include */ /* typedef long ptrdiff_t; /* type of pointer difference */ /* typedef unsigned short wchar_t; /* wide character type */ /* typedef unsigned size_t; /* type of sizeof */ #endif /* _stddef_h_ */ dev86-0.16.21/unproto/stdlib.h000066400000000000000000000017541231050321700157560ustar00rootroot00000000000000/* @(#) stdlib.h 1.1 92/02/15 17:25:45 */ #ifndef _stdlib_h_ #define _stdlib_h_ /* NULL is also defined in */ #ifndef NULL #define NULL 0 #endif /* * Some functions in this file will be missing from the typical pre-ANSI * UNIX library. Some pre-ANSI UNIX library functions have return types * that differ from what ANSI requires. */ extern double atof(); extern int atoi(); extern long atol(); extern double strtod(); extern long strtol(); extern unsigned long strtoul(); extern int rand(); extern void srand(); extern char *calloc(); extern char *malloc(); extern char *realloc(); extern void free(); extern void abort(); extern void exit(); extern int atextit(); extern int system(); extern char *getenv(); extern char *bsearch(); extern void qsort(); extern int abs(); extern long labs(); typedef struct { int quot; int rem; } div_t; typedef struct { long quot; long rem; } ldiv_t; extern div_t div(); extern ldiv_t ldiv(); #endif /* _stdlib_h_ */ dev86-0.16.21/unproto/strsave.c000066400000000000000000000031121231050321700161450ustar00rootroot00000000000000/*++ /* NAME /* strsave 3 /* SUMMARY /* maintain unique copy of a string /* SYNOPSIS /* char *strsave(string) /* char *string; /* DESCRIPTION /* This function returns a pointer to an unique copy of its /* argument. /* DIAGNOSTISC /* strsave() calls fatal() when it runs out of memory. /* AUTHOR(S) /* Wietse Venema /* Eindhoven University of Technology /* Department of Mathematics and Computer Science /* Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands /* LAST MODIFICATION /* 92/01/15 21:53:13 /* VERSION/RELEASE /* 1.1 /*--*/ static char strsave_sccsid[] = "@(#) strsave.c 1.1 92/01/15 21:53:13"; /* C library */ extern char *strcpy(); extern char *malloc(); /* Application-specific stuff */ #include "error.h" #define STR_TABSIZE 100 struct string { char *strval; /* unique string copy */ struct string *next; /* next one in hash chain */ }; static struct string *str_tab[STR_TABSIZE] = {0,}; /* More string stuff. Maybe it should go to an #include file. */ #define STREQ(x,y) (*(x) == *(y) && strcmp((x),(y)) == 0) /* strsave - save unique copy of string */ char *strsave(str) register char *str; { register struct string *s; register int where = hash(str, STR_TABSIZE); /* Look for existing entry. */ for (s = str_tab[where]; s; s = s->next) if (STREQ(str, s->strval)) return (s->strval); /* Add new entry. */ if ((s = (struct string *) malloc(sizeof(*s))) == 0 || (s->strval = malloc(strlen(str) + 1)) == 0) fatal("out of memory"); s->next = str_tab[where]; str_tab[where] = s; return (strcpy(s->strval, str)); } dev86-0.16.21/unproto/symbol.c000066400000000000000000000061631231050321700157740ustar00rootroot00000000000000/*++ /* NAME /* symbol 3 /* SUMMARY /* rudimentary symbol table package /* SYNOPSIS /* #include "symbol.h" /* /* void sym_init() /* /* void sym_enter(name, type) /* char *name; /* int type; /* /* struct symbol *sym_find(name) /* char *name; /* DESCRIPTION /* This is a rudimentary symbol-table package, just enough to /* keep track of a couple of C keywords. /* /* sym_init() primes the table with C keywords. At present, most of /* the keywords that have to do with types are left out. /* We need a different strategy to detect type definitions because /* we do not keep track of typedef names. /* /* sym_enter() adds an entry to the symbol table. /* /* sym_find() locates a symbol table entry (it returns 0 if /* it is not found). /* AUTHOR(S) /* Wietse Venema /* Eindhoven University of Technology /* Department of Mathematics and Computer Science /* Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands /* LAST MODIFICATION /* 92/02/15 18:59:56 /* VERSION/RELEASE /* 1.4 /*--*/ static char symbol_sccsid[] = "@(#) symbol.c 1.4 92/02/15 18:59:56"; /* C library */ extern char *strcpy(); extern char *malloc(); /* Application-specific stuff */ #include "error.h" #include "token.h" #include "symbol.h" #define SYM_TABSIZE 20 static struct symbol *sym_tab[SYM_TABSIZE] = {0,}; /* More string stuff. Maybe it should go to an #include file. */ #define STREQ(x,y) (*(x) == *(y) && strcmp((x),(y)) == 0) /* sym_enter - enter symbol into table */ void sym_enter(name, type) char *name; int type; { struct symbol *s; int where; if ((s = (struct symbol *) malloc(sizeof(*s))) == 0 || (s->name = malloc(strlen(name) + 1)) == 0) fatal("out of memory"); (void) strcpy(s->name, name); s->type = type; where = hash(name, SYM_TABSIZE); s->next = sym_tab[where]; sym_tab[where] = s; } /* sym_find - locate symbol definition */ struct symbol *sym_find(name) register char *name; { register struct symbol *s; /* * This function is called for almost every "word" token, so it better be * fast. */ for (s = sym_tab[hash(name, SYM_TABSIZE)]; s; s = s->next) if (STREQ(name, s->name)) return (s); return (0); } /* * Initialization data for symbol table. We do not enter keywords for types. * We use a different strategy to detect type declarations because we do not * keep track of typedef names. */ struct sym { char *name; int tokno; }; static struct sym syms[] = { "if", TOK_CONTROL, "else", TOK_CONTROL, "for", TOK_CONTROL, "while", TOK_CONTROL, "do", TOK_CONTROL, "switch", TOK_CONTROL, "case", TOK_CONTROL, "default", TOK_CONTROL, "return", TOK_CONTROL, "continue", TOK_CONTROL, "break", TOK_CONTROL, "goto", TOK_CONTROL, "struct", TOK_COMPOSITE, "union", TOK_COMPOSITE, "__DATE__", TOK_DATE, "__TIME__", TOK_TIME, #if defined(MAP_VOID_STAR) || defined(MAP_VOID) "void", TOK_VOID, #endif "asm", TOK_OTHER, 0, }; /* sym_init - enter known keywords into symbol table */ void sym_init() { register struct sym *p; for (p = syms; p->name; p++) sym_enter(p->name, p->tokno); } dev86-0.16.21/unproto/symbol.h000066400000000000000000000004761231050321700160020ustar00rootroot00000000000000/* @(#) symbol.h 1.1 91/09/22 21:21:42 */ struct symbol { char *name; /* symbol name */ int type; /* symbol type */ struct symbol *next; }; extern void sym_enter(); /* add symbol to table */ extern struct symbol *sym_find(); /* locate symbol */ extern void sym_init(); /* prime the table */ dev86-0.16.21/unproto/tok_class.c000066400000000000000000000266701231050321700164560ustar00rootroot00000000000000/*++ /* NAME /* tok_class 3 /* SUMMARY /* token classification /* PACKAGE /* unproto /* SYNOPSIS /* #include "token.h" /* /* void tok_unget(t) /* struct token *t; /* /* struct token *tok_class() /* DESCRIPTION /* tok_class() collects single and composite tokens, and /* recognizes keywords. /* At present, the only composite tokens are ()-delimited, /* comma-separated lists, and non-whitespace tokens with attached /* whitespace or comment tokens. /* /* Source transformations are: __DATE__ and __TIME__ are rewritten /* to string constants with the current date and time, respectively. /* Multiple string constants are concatenated. Optionally, "void *" /* is mapped to "char *", and plain "void" to "int". /* /* tok_unget() implements an arbitrary amount of token pushback. /* Only tokens obtained through tok_class() should be given to /* tok_unget(). This function accepts a list of tokens in /* last-read-first order. /* DIAGNOSTICS /* The code complains if input terminates in the middle of a list. /* BUGS /* Does not preserve white space at the beginning of a list element /* or after the end of a list. /* AUTHOR(S) /* Wietse Venema /* Eindhoven University of Technology /* Department of Mathematics and Computer Science /* Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands /* LAST MODIFICATION /* 92/01/15 21:53:02 /* VERSION/RELEASE /* 1.4 /*--*/ static char class_sccsid[] = "@(#) tok_class.c 1.4 92/01/15 21:53:02"; /* C library */ #include extern char *strcpy(); extern long time(); extern char *ctime(); /* Application-specific stuff */ #include "error.h" #include "vstring.h" #include "token.h" #include "symbol.h" static struct token *tok_list(); static void tok_list_struct(); static void tok_list_append(); static void tok_strcat(); static void tok_time(); static void tok_date(); static void tok_space_append(); #if defined(MAP_VOID_STAR) || defined(MAP_VOID) static void tok_void(); /* rewrite void keyword */ #endif static struct token *tok_buf = 0; /* token push-back storage */ /* TOK_PREPEND - add token to LIFO queue, return head */ #define TOK_PREPEND(list,t) (t->next = list, list = t) /* tok_space_append - append trailing space except at start of or after list */ static void tok_space_append(list, t) register struct token *list; register struct token *t; { /* * The head/tail fields of a token do triple duty. They are used to keep * track of the members that make up a (list); to keep track of the * non-blank tokens that make up one list member; and, finally, to tack * whitespace and comment tokens onto the non-blank tokens that make up * one list member. * * Within a (list), white space and comment tokens are always tacked onto * the non-blank tokens to avoid parsing complications later on. For this * reason, blanks and comments at the beginning of a list member are * discarded because there is no token to tack them onto. (Well, we could * start each list member with a dummy token, but that would mess up the * whole unprototyper). * * Blanks or comments that follow a (list) are discarded, because the * head/tail fields of a (list) are already being used for other * purposes. * * Newlines within a (list) are discarded because they can mess up the * output when we rewrite function headers. The output routines will * regenerate discarded newlines, anyway. */ if (list == 0 || list->tokno == TOK_LIST) { tok_free(t); } else { tok_list_append(list, t); } } /* tok_class - discriminate single tokens, keywords, and composite tokens */ struct token *tok_class() { register struct token *t; register struct symbol *s; /* * Use push-back token, if available. Push-back tokens are already * canonical and can be passed on to the caller without further * inspection. */ if (t = tok_buf) { tok_buf = t->next; t->next = 0; return (t); } /* Read a new token and canonicalize it. */ if (t = tok_get()) { switch (t->tokno) { case '(': /* beginning of list */ t = tok_list(t); break; case TOK_WORD: /* look up keyword */ if ((s = sym_find(t->vstr->str))) { switch (s->type) { case TOK_TIME: /* map __TIME__ to string */ tok_time(t); tok_strcat(t); /* look for more strings */ break; case TOK_DATE: /* map __DATE__ to string */ tok_date(t); tok_strcat(t); /* look for more strings */ break; #if defined(MAP_VOID_STAR) || defined(MAP_VOID) case TOK_VOID: /* optionally map void types */ tok_void(t); break; #endif default: /* other keyword */ t->tokno = s->type; break; } } break; case '"': /* string, look for more */ tok_strcat(t); break; } } return (t); } /* tok_list - collect ()-delimited, comma-separated list of tokens */ static struct token *tok_list(t) struct token *t; { register struct token *list = tok_alloc(); char *filename; int lineno; /* Save context of '(' for diagnostics. */ filename = t->path; lineno = t->line; list->tokno = TOK_LIST; list->head = list->tail = t; list->path = t->path; list->line = t->line; #ifdef DEBUG strcpy(list->vstr->str, "LIST"); #endif /* * Read until the matching ')' is found, accounting for structured stuff * (enclosed by '{' and '}' tokens). Break the list up at each ',' token, * and try to preserve as much whitespace as possible. Newlines are * discarded so that they will not mess up the layout when we rewrite * argument lists. The output routines will regenerate discarded * newlines. */ while (t = tok_class()) { /* skip blanks */ switch (t->tokno) { case ')': /* end of list */ tok_list_append(list, t); return (list); case '{': /* struct/union type */ tok_list_struct(list->tail, t); break; case TOK_WSPACE: /* preserve trailing blanks */ tok_space_append(list->tail->tail, t); /* except after list */ break; case '\n': /* fix newlines later */ tok_free(t); break; case ',': /* list separator */ tok_list_append(list, t); break; default: /* other */ tok_list_append(list->tail, t); break; } } error_where(filename, lineno, "unmatched '('"); return (list); /* do not waste any data */ } /* tok_list_struct - collect structured type info within list */ static void tok_list_struct(list, t) register struct token *list; register struct token *t; { char *filename; int lineno; /* * Save context of '{' for diagnostics. This routine is called by the one * that collects list members. If the '}' is not found, the list * collector will not see the closing ')' either. */ filename = t->path; lineno = t->line; tok_list_append(list, t); /* * Collect tokens until the matching '}' is found. Try to preserve as * much whitespace as possible. Newlines are discarded so that they do * not interfere when rewriting argument lists. The output routines will * regenerate discarded newlines. */ while (t = tok_class()) { switch (t->tokno) { case TOK_WSPACE: /* preserve trailing blanks */ tok_space_append(list->tail, t); /* except after list */ break; case '\n': /* fix newlines later */ tok_free(t); break; case '{': /* recurse */ tok_list_struct(list, t); break; case '}': /* done */ tok_list_append(list, t); return; default: /* other */ tok_list_append(list, t); break; } } error_where(filename, lineno, "unmatched '{'"); } /* tok_strcat - concatenate multiple string constants */ static void tok_strcat(t1) register struct token *t1; { register struct token *t2; register struct token *lookahead = 0; /* * Read ahead past whitespace, comments and newlines. If we find a string * token, concatenate it with the previous one and push back the * intervening tokens (thus preserving as much information as possible). * If we find something else, push back all lookahead tokens. */ #define PUSHBACK_AND_RETURN { if (lookahead) tok_unget(lookahead); return; } while (t2 = tok_class()) { switch (t2->tokno) { case TOK_WSPACE: /* read past comments/blanks */ case '\n': /* read past newlines */ TOK_PREPEND(lookahead, t2); break; case '"': /* concatenate string tokens */ if (vs_strcpy(t1->vstr, t1->vstr->str + strlen(t1->vstr->str) - 1, t2->vstr->str + 1) == 0) fatal("out of memory"); tok_free(t2); PUSHBACK_AND_RETURN; default: /* something else, push back */ tok_unget(t2); PUSHBACK_AND_RETURN; } } PUSHBACK_AND_RETURN; /* hit EOF */ } #if defined(MAP_VOID_STAR) || defined(MAP_VOID) /* tok_void - support for compilers that have problems with "void" */ static void tok_void(t) register struct token *t; { register struct token *t2; register struct token *lookahead = 0; /* * Look ahead beyond whitespace, comments and newlines until we see a '*' * token. If one is found, replace "void" by "char". If we find something * else, and if "void" should always be mapped, replace "void" by "int". * Always push back the lookahead tokens. * * XXX The code also replaces the (void) argument list; this must be * accounted for later on. The alternative would be to add (in unproto.c) * TOK_VOID cases all over the place and that would be too error-prone. */ #define PUSHBACK_AND_RETURN { if (lookahead) tok_unget(lookahead); return; } while (t2 = tok_class()) { switch (TOK_PREPEND(lookahead, t2)->tokno) { case TOK_WSPACE: /* read past comments/blanks */ case '\n': /* read past newline */ break; case '*': /* "void *" -> "char *" */ if (vs_strcpy(t->vstr, t->vstr->str, "char") == 0) fatal("out of memory"); PUSHBACK_AND_RETURN; default: #ifdef MAP_VOID /* plain "void" -> "int" */ if (vs_strcpy(t->vstr, t->vstr->str, "int") == 0) fatal("out of memory"); #endif PUSHBACK_AND_RETURN; } } PUSHBACK_AND_RETURN; /* hit EOF */ } #endif /* tok_time - rewrite __TIME__ to "hh:mm:ss" string constant */ static void tok_time(t) struct token *t; { long now; char *cp; char buf[BUFSIZ]; /* * Using sprintf() to select parts of a string is gross, but this should * be fast enough. */ (void) time(&now); cp = ctime(&now); sprintf(buf, "\"%.8s\"", cp + 11); if (vs_strcpy(t->vstr, t->vstr->str, buf) == 0) fatal("out of memory"); t->tokno = buf[0]; } /* tok_date - rewrite __DATE__ to "Mmm dd yyyy" string constant */ static void tok_date(t) struct token *t; { long now; char *cp; char buf[BUFSIZ]; /* * Using sprintf() to select parts of a string is gross, but this should * be fast enough. */ (void) time(&now); cp = ctime(&now); sprintf(buf, "\"%.3s %.2s %.4s\"", cp + 4, cp + 8, cp + 20); if (vs_strcpy(t->vstr, t->vstr->str, buf) == 0) fatal("out of memory"); t->tokno = buf[0]; } /* tok_unget - push back one or more possibly composite tokens */ void tok_unget(t) register struct token *t; { register struct token *next; do { next = t->next; TOK_PREPEND(tok_buf, t); } while (t = next); } /* tok_list_append - append data to list */ static void tok_list_append(h, t) struct token *h; struct token *t; { if (h->head == 0) { h->head = h->tail = t; } else { h->tail->next = t; h->tail = t; } } dev86-0.16.21/unproto/tok_io.c000066400000000000000000000364401231050321700157540ustar00rootroot00000000000000/*++ /* NAME /* tok_io 3 /* SUMMARY /* token I/O /* PACKAGE /* unproto /* SYNOPSIS /* #include "token.h" /* /* struct token *tok_get() /* /* void tok_flush(t) /* struct token *t; /* /* void tok_show(t) /* struct token *t; /* /* void tok_show_ch(t) /* struct token *t; /* /* void put_str(s) /* char *s; /* /* void put_ch(c) /* int c; /* /* void put_nl() /* /* char *in_path; /* int in_line; /* DESCRIPTION /* These functions read from stdin and write to stdout. The /* tokenizer keeps track of where the token appeared in the input /* stream; on output, this information is used to preserve correct /* line number information (even after lots of token lookahead or /* after function-header rewriting) so that diagnostics from the /* next compiler stage make sense. /* /* tok_get() reads the next token from standard input. It returns /* a null pointer when the end of input is reached. /* /* tok_show() displays the contents of a (possibly composite) token /* on the standard output. /* /* tok_show_ch() displays the contents of a single-character token /* on the standard output. The character should not be a newline. /* /* tok_flush() displays the contents of a (possibly composite) token /* on the standard output and makes it available for re-use. /* /* put_str() writes a null-terminated string to standard output. /* There should be no newline characters in the string argument. /* /* put_ch() writes one character to standard output. The character /* should not be a newline. /* /* put_nl() outputs a newline character and adjusts the program's idea of /* the current output line. /* /* The in_path and in_line variables contain the file name and /* line number of the most recently read token. /* BUGS /* The tokenizer is just good enough for the unproto filter. /* As a benefit, it is quite fast. /* AUTHOR(S) /* Wietse Venema /* Eindhoven University of Technology /* Department of Mathematics and Computer Science /* Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands /* LAST MODIFICATION /* 92/01/15 21:52:59 /* VERSION/RELEASE /* 1.3 /*--*/ static char io_sccsid[] = "@(#) tok_io.c 1.3 92/01/15 21:52:59"; /* C library */ #include #include extern char *strchr(); extern char *malloc(); extern char *realloc(); extern char *strcpy(); /* Application-specific stuff */ #include "token.h" #include "vstring.h" #include "error.h" extern char *strsave(); /* XXX need include file */ /* Stuff to keep track of original source file name and position */ static char def_path[] = ""; /* default path name */ char *in_path = def_path; /* current input file name */ int in_line = 1; /* current input line number */ static char *out_path = def_path; /* last name in output line control */ static int out_line = 1; /* current output line number */ int last_ch; /* type of last output */ /* Forward declarations */ static int read_quoted(); static void read_comment(); static int backslash_newline(); static char *read_hex(); static char *read_octal(); static void fix_line_control(); /* * Character input with one level of pushback. The INPUT() macro recursively * strips backslash-newline pairs from the input stream. The UNPUT() macro * should be used only for characters obtained through the INPUT() macro. * * After skipping a backslash-newline pair, the input line counter is not * updated, and we continue with the same logical source line. We just * update a counter with the number of backslash-newline sequences that must * be accounted for (backslash_newline() updates the counter). At the end of * the logical source line, an appropriate number of newline characters is * pushed back (in tok_get()). I do not know how GCC handles this, but it * seems to produce te same output. * * Because backslash_newline() recursively calls itself (through the INPUT() * macro), we will run out of stack space, given a sufficiently long * sequence of backslash-newline pairs. */ static char in_char = 0; /* push-back storage */ static int in_flag = 0; /* pushback available */ static int nl_compensate = 0; /* line continuation kluge */ #define INPUT(c) (in_flag ? (in_flag = 0, c = in_char) : \ (c = getchar()) != '\\' ? c : \ (c = getchar()) != '\n' ? (ungetc(c, stdin), c = '\\') : \ (c = backslash_newline())) #define UNPUT(c) (in_flag = 1, in_char = c) /* Directives that should be ignored. */ #ifdef IGNORE_DIRECTIVES static char *ignore_directives[] = { IGNORE_DIRECTIVES, 0, }; #endif /* Modified string and ctype stuff. */ #define STREQUAL(x,y) (*(x) == *(y) && strcmp((x),(y)) == 0) #define ISALNUM(c) (isalnum(c) || (c) == '_') #define ISALPHA(c) (isalpha(c) || (c) == '_') #define ISSPACE(c) (isspace(c) && c != '\n') #define ISDOT(c) (c == '.') #define ISHEX(c) (isdigit(c) || strchr("abcdefABCDEF", c) != 0) #define ISOCTAL(c) (isdigit(c) && (c) != '8' && (c) != '9') /* Collect all characters that satisfy one condition */ #define COLLECT(v,c,cond) { \ register struct vstring *vs = v; \ register char *cp = vs->str; \ *cp++ = c; \ while (INPUT(c) != EOF) { \ if (cond) { \ if (VS_ADDCH(vs, cp, c) == 0) \ fatal("out of memory"); \ } else { \ UNPUT(c); \ break; \ } \ } \ *cp = 0; \ } /* Ensure that output line information is correct */ #define CHECK_LINE_CONTROL(p,l) { if (out_path != (p) || out_line != (l)) \ fix_line_control((p),(l)); } /* do_control - parse control line */ static int do_control() { struct token *t; int line; char *path; /* Make sure that the directive shows up in the right place. */ CHECK_LINE_CONTROL(in_path, in_line); while (t = tok_get()) { switch (t->tokno) { case TOK_WSPACE: /* Ignore blanks after "#" token. */ tok_free(t); break; case TOK_NUMBER: /* * Line control is of the form: number pathname junk. Since we * have no idea what junk the preprocessor may generate, we copy * all line control tokens to stdout. */ put_str("# "); line = atoi(t->vstr->str); /* extract line number */ tok_flush(t); while ((t = tok_get()) && t->tokno == TOK_WSPACE) tok_flush(t); /* copy white space */ if (t) { /* extract path name */ path = (t->tokno == '"') ? strsave(t->vstr->str) : in_path; do { tok_flush(t); /* copy until newline */ } while (t->tokno != '\n' && (t = tok_get())); } out_line = in_line = line; /* synchronize */ out_path = in_path = path; /* synchronize */ return; #ifdef IGNORE_DIRECTIVES case TOK_WORD: /* * Optionally ignore other #directives. This is only a partial * solution, because the preprocessor will still see them. */ { char **cpp; char *cp = t->vstr->str; for (cpp = ignore_directives; *cpp; cpp++) { if (STREQUAL(cp, *cpp)) { do { tok_free(t); } while (t->tokno != '\n' && (t = tok_get())); return; } } } /* FALLTHROUGH */ #endif default: /* Pass through. */ put_ch('#'); do { tok_flush(t); } while (t->tokno != '\n' && (t = tok_get())); return; case 0: /* Hit EOF, punt. */ put_ch('#'); return; } } } /* backslash_newline - fix up things after reading a backslash-newline pair */ static int backslash_newline() { register int c; nl_compensate++; return (INPUT(c)); } /* tok_get - get next token */ static int last_tokno = '\n'; struct token *tok_get() { register struct token *t; register int c; int d; /* * Get one from the pool and fill it in. The loop is here in case we hit * a preprocessor control line, which happens in a minority of all cases. * We update the token input path and line info *after* backslash-newline * processing or the newline compensation would go wrong. */ t = tok_alloc(); for (;;) { if ((INPUT(c)) == EOF) { tok_free(t); return (0); } else if ((t->line = in_line, t->path = in_path), !isascii(c)) { t->vstr->str[0] = c; t->vstr->str[1] = 0; t->tokno = TOK_OTHER; break; } else if (ISSPACE(c)) { COLLECT(t->vstr, c, ISSPACE(c)); t->tokno = TOK_WSPACE; break; } else if (ISALPHA(c)) { COLLECT(t->vstr, c, ISALNUM(c)); t->tokno = TOK_WORD; break; } else if (isdigit(c)) { COLLECT(t->vstr, c, isdigit(c)); t->tokno = TOK_NUMBER; break; } else if (c == '"' || c == '\'') { t->tokno = read_quoted(t->vstr, c); /* detect missing end quote */ break; } else if (ISDOT(c)) { COLLECT(t->vstr, c, ISDOT(c)); t->tokno = TOK_OTHER; break; } else if (c == '#' && last_tokno == '\n') { do_control(); continue; } else { t->vstr->str[0] = c; if (c == '\n') { in_line++; if (nl_compensate > 0) { /* compensation for bs-nl */ UNPUT('\n'); nl_compensate--; } } else if (c == '/') { if ((INPUT(d)) == '*') { t->vstr->str[1] = d; /* comment */ read_comment(t->vstr); t->tokno = TOK_WSPACE; break; } else { if (d != EOF) UNPUT(d); } } else if (c == '\\') { t->vstr->str[1] = (INPUT(c) == EOF ? 0 : c); t->vstr->str[2] = 0; t->tokno = TOK_OTHER; break; } t->vstr->str[1] = 0; t->tokno = c; break; } } last_tokno = t->tokno; t->end_line = in_line; return (t); } /* read_quoted - read string or character literal, canonicalize escapes */ static int read_quoted(vs, ch) register struct vstring *vs; int ch; { register char *cp = vs->str; register int c; int ret = TOK_OTHER; *cp++ = ch; /* * Clobber the token type in case of a premature newline or EOF. This * prevents us from attempting to concatenate string constants with * broken ones that have no closing quote. */ while (INPUT(c) != EOF) { if (c == '\n') { /* newline in string */ UNPUT(c); break; } if (VS_ADDCH(vs, cp, c) == 0) /* store character */ fatal("out of memory"); if (c == ch) { /* closing quote */ ret = c; break; } if (c == '\\') { /* parse escape sequence */ if ((INPUT(c)) == EOF) { /* EOF, punt */ break; } else if (c == 'a') { /* \a -> audible bell */ #ifdef BELL if ((cp = vs_strcpy(vs, cp, BELL)) == 0) #else if ((cp = vs_strcpy(vs, cp, "\007")) == 0) #endif fatal("out of memory"); } else if (c == 'x') { /* \xhh -> \nnn */ cp = read_hex(vs, cp); } else if (ISOCTAL(c) && ch != '\'') { cp = read_octal(vs, cp, c); /* canonicalize \octal */ } else { if (VS_ADDCH(vs, cp, c) == 0) /* \other: leave alone */ fatal("out of memory"); } } } *cp = 0; return (ret); } /* read_comment - stuff a whole comment into one huge token */ static void read_comment(vs) register struct vstring *vs; { register char *cp = vs->str + 2; /* skip slash star */ register int c; register int d; while (INPUT(c) != EOF) { if (VS_ADDCH(vs, cp, c) == 0) fatal("out of memory"); if (c == '*') { if ((INPUT(d)) == '/') { if (VS_ADDCH(vs, cp, d) == 0) fatal("out of memory"); break; } else { if (d != EOF) UNPUT(d); } } else if (c == '\n') { in_line++; } else if (c == '\\') { if ((INPUT(d)) != EOF && VS_ADDCH(vs, cp, d) == 0) fatal("out of memory"); } } *cp = 0; } /* read_hex - rewrite hex escape to three-digit octal escape */ static char *read_hex(vs, cp) struct vstring *vs; register char *cp; { register int c; register int i; char buf[BUFSIZ]; int len; unsigned val; /* * Eat up all subsequent hex digits. Complain later when there are too * many. */ for (i = 0; i < sizeof(buf) && (INPUT(c) != EOF) && ISHEX(c); i++) buf[i] = c; buf[i] = 0; if (i < sizeof(buf) && c) UNPUT(c); /* * Convert hex form to three-digit octal form. The three-digit form is * used so that strings can be concatenated without problems. Complain * about malformed input; truncate the result to at most three octal * digits. */ if (i == 0) { error("\\x escape sequence without hexadecimal digits"); if (VS_ADDCH(vs, cp, 'x') == 0) fatal("out of memory"); } else { (void) sscanf(buf, "%x", &val); sprintf(buf, "%03o", val); if ((len = strlen(buf)) > 3) error("\\x escape sequence yields non-character value"); if ((cp = vs_strcpy(vs, cp, buf + len - 3)) == 0) fatal("out of memory"); } return (cp); } /* read_octal - convert octal escape to three-digit format */ static char obuf[] = "00123"; static char *read_octal(vs, cp, c) register struct vstring *vs; register char *cp; register int c; { register int i; #define buf_input (obuf + 2) /* Eat up at most three octal digits. */ buf_input[0] = c; for (i = 1; i < 3 && (INPUT(c) != EOF) && ISOCTAL(c); i++) buf_input[i] = c; buf_input[i] = 0; if (i < 3 && c) UNPUT(c); /* * Leave three-digit octal escapes alone. Convert one-digit and two-digit * octal escapes to three-digit form by prefixing them with a suitable * number of '0' characters. This is done so that strings can be * concatenated without problems. */ if ((cp = vs_strcpy(vs, cp, buf_input + i - 3)) == 0) fatal("out of memory"); return (cp); } /* put_nl - emit newline and adjust output line count */ void put_nl() { put_ch('\n'); out_line++; } /* fix_line_control - to adjust path and/or line count info in output */ static void fix_line_control(path, line) register char *path; register int line; { /* * This function is called sporadically, so it should not be a problem * that we repeat some of the tests that preceded this function call. * * Emit a newline if we are not at the start of a line. * * If we switch files, or if we jump backwards, emit line control. If we * jump forward, emit the proper number of newlines to compensate. */ if (last_ch != '\n') /* terminate open line */ put_nl(); if (path != out_path || line < out_line) { /* file switch or back jump */ printf("# %d %s\n", out_line = line, out_path = path); last_ch = '\n'; } else { /* forward jump */ while (line > out_line) put_nl(); } } /* tok_show_ch - output single-character token (not newline) */ void tok_show_ch(t) register struct token *t; { CHECK_LINE_CONTROL(t->path, t->line); put_ch(t->tokno); /* show token contents */ } /* tok_show - output (possibly composite) token */ void tok_show(t) register struct token *t; { register struct token *p; if (t->tokno == TOK_LIST) { register struct token *s; /* * This branch is completely in terms of tok_xxx() primitives, so * there is no need to check the line control information. */ for (s = t->head; s; s = s->next) { tok_show_ch(s); /* '(' or ',' or ')' */ for (p = s->head; p; p = p->next) tok_show(p); /* show list element */ } } else { register char *cp = t->vstr->str; /* * Measurements show that it pays off to give special treatment to * single-character tokens. Note that both types of token may cause a * change of output line number. */ CHECK_LINE_CONTROL(t->path, t->line); if (cp[1] == 0) { put_ch(*cp); /* single-character token */ } else { put_str(cp); /* multi_character token */ } out_line = t->end_line; /* may span multiple lines */ for (p = t->head; p; p = p->next) tok_show(p); /* trailing blanks */ } } dev86-0.16.21/unproto/tok_pool.c000066400000000000000000000041771231050321700163200ustar00rootroot00000000000000/*++ /* NAME /* tok_pool 3 /* SUMMARY /* maintain pool of unused token structures /* PACKAGE /* unproto /* SYNOPSIS /* #include "token.h" /* /* struct token *tok_alloc() /* /* void tok_free(t) /* struct token *t; /* DESCRIPTION /* tok_alloc() and tok_free() maintain a pool of unused token /* structures. /* /* tok_alloc() takes the first free token structure from the pool /* or allocates a new one if the pool is empty. /* /* tok_free() adds a (possibly composite) token structure to the pool. /* BUGS /* The pool never shrinks. /* AUTHOR(S) /* Wietse Venema /* Eindhoven University of Technology /* Department of Mathematics and Computer Science /* Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands /* LAST MODIFICATION /* 92/01/15 21:53:04 /* VERSION/RELEASE /* 1.2 /*--*/ static char pool_sccsid[] = "@(#) tok_pool.c 1.2 92/01/15 21:53:04"; /* C library */ extern char *malloc(); /* Application-specific stuff */ #include "token.h" #include "vstring.h" #include "error.h" #define TOKLEN 5 /* initial string buffer length */ struct token *tok_pool = 0; /* free token pool */ /* tok_alloc - allocate token structure from pool or heap */ struct token *tok_alloc() { register struct token *t; if (tok_pool) { /* re-use an old one */ t = tok_pool; tok_pool = t->next; } else { /* create a new one */ if ((t = (struct token *) malloc(sizeof(struct token))) == 0 || (t->vstr = vs_alloc(TOKLEN)) == 0) fatal("out of memory"); } t->next = t->head = t->tail = 0; #ifdef DEBUG strcpy(t->vstr->str, "BUSY"); #endif return (t); } /* tok_free - return (possibly composite) token to pool of free tokens */ void tok_free(t) register struct token *t; { #ifdef DEBUG /* Check if we are freeing free token */ register struct token *p; for (p = tok_pool; p; p = p->next) if (p == t) fatal("freeing free token"); #endif /* Free neighbours and subordinates first */ if (t->next) tok_free(t->next); if (t->head) tok_free(t->head); /* Free self */ t->next = tok_pool; t->head = t->tail = 0; tok_pool = t; #ifdef DEBUG strcpy(t->vstr->str, "FREE"); #endif } dev86-0.16.21/unproto/token.h000066400000000000000000000035221231050321700156100ustar00rootroot00000000000000/* @(#) token.h 1.4 92/01/15 21:53:17 */ struct token { int tokno; /* token value, see below */ char *path; /* file name */ int line; /* line number at token start */ int end_line; /* line number at token end */ struct vstring *vstr; /* token contents */ struct token *next; struct token *head; struct token *tail; }; /* Special token values */ #define TOK_LIST 256 /* () delimited list */ #define TOK_WORD 257 /* keyword or identifier */ #define TOK_NUMBER 258 /* one or more digits */ #define TOK_WSPACE 259 /* comment, white space, not newline */ #define TOK_OTHER 260 /* other token */ #define TOK_CONTROL 261 /* flow control keyword */ #define TOK_COMPOSITE 262 /* struct or union keyword */ #define TOK_DATE 263 /* date: Mmm dd yyyy */ #define TOK_TIME 264 /* time: hh:mm:ss */ #define TOK_VOID 265 /* void keyword */ /* Input/output functions and macros */ extern struct token *tok_get(); /* read next single token */ extern void tok_show(); /* display (composite) token */ extern struct token *tok_class(); /* classify tokens */ extern void tok_unget(); /* stuff token back into input */ extern void put_nl(); /* print newline character */ extern void tok_show_ch(); /* emit single-character token */ #define tok_flush(t) (tok_show(t), tok_free(t)) #ifdef DEBUG #define put_ch(c) (putchar(last_ch = c),fflush(stdout)) #define put_str(s) (fputs(s,stdout),last_ch = 0,fflush(stdout)) #else #define put_ch(c) putchar(last_ch = c) #define put_str(s) (fputs(s,stdout),last_ch = 0) #endif /* Memory management */ struct token *tok_alloc(); /* allocate token storage */ extern void tok_free(); /* re-cycle storage */ /* Context */ extern char *in_path; /* current input path name */ extern int in_line; /* current input line number */ extern int last_ch; /* type of last output */ dev86-0.16.21/unproto/unproto.1000066400000000000000000000115321231050321700161070ustar00rootroot00000000000000.TH UNPROTO 1 .ad .fi .SH NAME unproto \- compile ANSI C with traditional UNIX C compiler .SH PACKAGE .na .nf unproto .SH SYNOPSIS .na .nf /somewhere/cpp ... cc cflags -E file.c | unproto >file.i; cc cflags -c file.i .SH DESCRIPTION .ad .fi This document describes a filter that sits in between the UNIX C preprocessor and the next UNIX C compiler stage, on the fly rewriting ANSI-style syntax to old-style syntax. Typically, the program is invoked by the native UNIX C compiler as an alternate preprocessor. The unprototyper in turn invokes the native C preprocessor and massages its output. Similar tricks can be used with the lint(1) command. Language constructs that are always rewritten: .TP function headings, prototypes, pointer types ANSI-C style function headings, function prototypes, function pointer types and type casts are rewritten to old style. support is provided for functions with variable-length argument lists. .TP character and string constants The \\a and \\x escape sequences are rewritten to their (three-digit) octal equivalents. Multiple string tokens are concatenated; an arbitrary number of whitespace or comment tokens may appear between successive string tokens. Within string constants, octal escape sequences are rewritten to the three-digit \\ddd form, so that string concatenation produces correct results. .TP date and time The __DATE__ and __TIME__ tokens are replaced by string constants of the form "Mmm dd yyyy" and "hh:mm:ss", respectively. The result is subjected to string concatenation, just like any other string constant. .PP Language constructs that are rewritten only if the program has been configured to do so: .TP void types The unprototyper can be configured to rewrite "void *" to "char *", and even to rewrite plain "void" to "int". These features are configurable because many traditional UNIX C compilers do not need them. Note: (void) argument lists are always replaced by empty ones. .PP ANSI C constructs that are not rewritten because the traditional UNIX C preprocessor provides suitable workarounds: .TP const and volatile Use the "-Dconst=" and/or "-Dvolatile=" preprocessor directives to get rid of unimplemented keywords. .TP token pasting and stringizing The traditional UNIX C preprocessor provides excellent alternatives. For example: .nf .ne 2 #define string(bar) "bar" /* instead of: # x */ #define paste(x,y) x/**\/y /* instead of: x##y */ .fi There is a good reason why the # and ## operators are not implemented in the unprototyper. After program text has gone through a non-ANSI C preprocessor, all information about the grouping of the operands of # and ## is lost. Thus, if the unprototyper were to perform these operations, it would produce correct results only in the most trivial cases. Operands with embedded blanks, operands that expand to null tokens, and nested use of # and/or ## would cause all kinds of obscure problems. .PP Unsupported ANSI features: .TP trigraphs and #pragmas Trigraphs are useful only for systems with broken character sets. If the local compiler chokes on #pragma, insert a blank before the "#" character, and enclose the offending directive between #ifdef and #endif. .SH SEE ALSO .na .nf .ad .fi cc(1), how to specify a non-default C preprocessor. Some versions of the lint(1) command are implemented as a shell script. It should require only minor modification for integration with the unprototyper. Other versions of the lint(1) command accept the same command syntax as the C compiler for the specification of a non-default preprocessor. Some research may be needed. .SH FILES .na .nf /wherever/stdarg.h, provided with the unproto filter. .SH DIAGNOSTICS .ad .fi Problems are reported on the standard error stream. A non-zero exit status means that there was a problem. .SH BUGS .ad .fi The unprototyper should be run on preprocessed source only: unexpanded macros may confuse the program. Declarations of (object) are misunderstood and will result in syntax errors: the objects between parentheses disappear. Sometimes does not preserve whitespace after parentheses and commas. This is a purely aesthetical matter, and the compiler should not care. Whitespace within string constants is, of course, left intact. Does not generate explicit type casts for function-argument expressions. The lack of explicit conversions between integral and/or pointer argument types should not be a problem in environments where sizeof(int) == sizeof(long) == sizeof(pointer). A more serious problem is the lack of automatic type conversions between integral and floating-point argument types. Let lint(1) be your friend. .SH AUTHOR(S) .na .nf Wietse Venema (wietse@wzv.win.tue.nl) Eindhoven University of Technology Department of Mathematics and Computer Science Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands .SH LAST MODIFICATION .na .nf 93/06/18 22:29:37 .SH VERSION/RELEASE .na .nf 1.6 dev86-0.16.21/unproto/unproto.c000066400000000000000000000663041231050321700162000ustar00rootroot00000000000000/*++ /* NAME /* unproto 1 /* SUMMARY /* compile ANSI C with traditional UNIX C compiler /* PACKAGE /* unproto /* SYNOPSIS /* /somewhere/cpp ... /* /* cc cflags -E file.c | unproto >file.i; cc cflags -c file.i /* DESCRIPTION /* This document describes a filter that sits in between the UNIX /* C preprocessor and the next UNIX C compiler stage, on the fly rewriting /* ANSI-style syntax to old-style syntax. Typically, the program is /* invoked by the native UNIX C compiler as an alternate preprocessor. /* The unprototyper in turn invokes the native C preprocessor and /* massages its output. Similar tricks can be used with the lint(1) /* command. /* /* Language constructs that are always rewritten: /* .TP /* function headings, prototypes, pointer types /* ANSI-C style function headings, function prototypes, function /* pointer types and type casts are rewritten to old style. /* support is provided for functions with variable-length /* argument lists. /* .TP /* character and string constants /* The \\a and \\x escape sequences are rewritten to their (three-digit) /* octal equivalents. /* /* Multiple string tokens are concatenated; an arbitrary number of /* whitespace or comment tokens may appear between successive /* string tokens. /* /* Within string constants, octal escape sequences are rewritten to the /* three-digit \\ddd form, so that string concatenation produces correct /* results. /* .TP /* date and time /* The __DATE__ and __TIME__ tokens are replaced by string constants /* of the form "Mmm dd yyyy" and "hh:mm:ss", respectively. The result /* is subjected to string concatenation, just like any other string /* constant. /* .PP /* Language constructs that are rewritten only if the program has been /* configured to do so: /* .TP /* void types /* The unprototyper can be configured to rewrite "void *" to "char *", /* and even to rewrite plain "void" to "int". /* These features are configurable because many traditional UNIX C /* compilers do not need them. /* /* Note: (void) argument lists are always replaced by empty ones. /* .PP /* ANSI C constructs that are not rewritten because the traditional /* UNIX C preprocessor provides suitable workarounds: /* .TP /* const and volatile /* Use the "-Dconst=" and/or "-Dvolatile=" preprocessor directives to /* get rid of unimplemented keywords. /* .TP /* token pasting and stringizing /* The traditional UNIX C preprocessor provides excellent alternatives. /* For example: /* /* .nf /* .ne 2 /* #define string(bar) "bar" /* instead of: # x */ /* #define paste(x,y) x/**\/y /* instead of: x##y */ /* .fi /* /* There is a good reason why the # and ## operators are not implemented /* in the unprototyper. /* After program text has gone through a non-ANSI C preprocessor, all /* information about the grouping of the operands of # and ## is lost. /* Thus, if the unprototyper were to perform these operations, it would /* produce correct results only in the most trivial cases. Operands /* with embedded blanks, operands that expand to null tokens, and nested /* use of # and/or ## would cause all kinds of obscure problems. /* .PP /* Unsupported ANSI features: /* .TP /* trigraphs and #pragmas /* Trigraphs are useful only for systems with broken character sets. /* If the local compiler chokes on #pragma, insert a blank before the /* "#" character, and enclose the offending directive between #ifdef /* and #endif. /* SEE ALSO /* .ad /* .fi /* cc(1), how to specify a non-default C preprocessor. /* Some versions of the lint(1) command are implemented as a shell /* script. It should require only minor modification for integration /* with the unprototyper. Other versions of the lint(1) command accept /* the same command syntax as the C compiler for the specification of a /* non-default preprocessor. Some research may be needed. /* FILES /* /wherever/stdarg.h, provided with the unproto filter. /* DIAGNOSTICS /* Problems are reported on the standard error stream. /* A non-zero exit status means that there was a problem. /* BUGS /* The unprototyper should be run on preprocessed source only: /* unexpanded macros may confuse the program. /* /* Declarations of (object) are misunderstood and will result in /* syntax errors: the objects between parentheses disappear. /* /* Sometimes does not preserve whitespace after parentheses and commas. /* This is a purely aesthetical matter, and the compiler should not care. /* Whitespace within string constants is, of course, left intact. /* /* Does not generate explicit type casts for function-argument /* expressions. The lack of explicit conversions between integral /* and/or pointer argument types should not be a problem in environments /* where sizeof(int) == sizeof(long) == sizeof(pointer). A more serious /* problem is the lack of automatic type conversions between integral and /* floating-point argument types. Let lint(1) be your friend. /* AUTHOR(S) /* Wietse Venema (wietse@wzv.win.tue.nl) /* Eindhoven University of Technology /* Department of Mathematics and Computer Science /* Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands /* LAST MODIFICATION /* 93/06/18 22:29:37 /* VERSION/RELEASE /* 1.6 /*--*/ static char unproto_sccsid[] = "@(#) unproto.c 1.6 93/06/18 22:29:37"; /* C library */ #include #include #include #include extern void exit(); extern int optind; extern char *optarg; extern int getopt(); /* Application-specific stuff */ #ifdef __STDC__ #include #else #include "stdarg.h" #endif #include "vstring.h" #include "token.h" #include "error.h" #include "symbol.h" /* Forward declarations. */ static struct token *dcl_flush(); static void block_flush(); static void block_dcls(); static struct token *show_func_ptr_type(); static struct token *show_struct_type(); static void show_arg_name(); static void show_type(); static void pair_flush(); static void check_cast(); static void show_empty_list(); #define check_cast_flush(t) (check_cast(t), tok_free(t)) #ifdef PIPE_THROUGH_CPP static int pipe_stdin_through_cpp(); #endif /* Disable debugging printfs while preserving side effects. */ #ifdef DEBUG #define DPRINTF printf #else #define DPRINTF (void) #endif /* An attempt to make some complicated expressions a bit more readable. */ #define STREQ(x,y) (*(x) == *(y) && !strcmp((x),(y))) #define LAST_ARG_AND_EQUAL(s,c) ((s)->next && (s)->next->next == 0 \ && (s)->head && ((s)->head == (s)->tail) \ && (STREQ((s)->head->vstr->str, (c)))) #define LIST_BEGINS_WITH_STAR(s) (s->head->head && s->head->head->tokno == '*') #define IS_FUNC_PTR_TYPE(s) (s->tokno == TOK_LIST && s->next \ && s->next->tokno == TOK_LIST \ && LIST_BEGINS_WITH_STAR(s)) /* What to look for to detect a (void) argument list. */ #ifdef MAP_VOID #define VOID_ARG "int" /* bare "void" is mapped to "int" */ #else #define VOID_ARG "void" /* bare "void" is left alone */ #endif /* main - driver */ int main(argc, argv) int argc; char **argv; { register struct token *t; #ifdef PIPE_THROUGH_CPP /* pipe through /lib/cpp */ int cpp_status; int wait_pid; int cpp_pid; cpp_pid = pipe_stdin_through_cpp(argv); #endif #if defined(REOPEN) || defined(MSDOS) #ifdef PIPE_THROUGH_CPP #error Defines REOPEN and PIPE_THROUGH_CPP are incompatible. #endif if ( argc > 1 ) { if( freopen(argv[1], "r", stdin) == 0 ) { fprintf(stderr, "Cannot open '%s'\n", argv[1]); exit(9); } } if ( argc > 2 ) { if( freopen(argv[2], "w", stdout) == 0 ) { fprintf(stderr, "Cannot open '%s'\n", argv[2]); exit(9); } } #endif sym_init(); /* prime the symbol table */ while (t = tok_class()) { if (t = dcl_flush(t)) { /* try declaration */ if (t->tokno == '{') { /* examine rejected token */ block_flush(t); /* body */ } else { tok_flush(t); /* other, recover */ } } } #ifdef PIPE_THROUGH_CPP /* pipe through /lib/cpp */ while ((wait_pid = wait(&cpp_status)) != -1 && wait_pid != cpp_pid) /* void */ ; return (errcount != 0 || wait_pid != cpp_pid || cpp_status != 0); #else return (errcount != 0); #endif } #ifdef PIPE_THROUGH_CPP /* pipe through /lib/cpp */ /* pipe_stdin_through_cpp - avoid shell script overhead */ static int pipe_stdin_through_cpp(argv) char **argv; { int pipefds[2]; int pid; char **cpptr = argv; int i; struct stat st; /* * The code that sets up the pipe requires that file descriptors 0,1,2 * are already open. All kinds of mysterious things will happen if that * is not the case. The following loops makes sure that descriptors 0,1,2 * are set up properly. */ for (i = 0; i < 3; i++) { if (fstat(i, &st) == -1 && open("/dev/null", 2) != i) { perror("open /dev/null"); exit(1); } } /* * With most UNIX implementations, the second non-option argument to * /lib/cpp specifies the output file. If an output file other than * stdout is specified, we must force /lib/cpp to write to stdout, and we * must redirect our own standard output to the specified output file. */ #define IS_OPTION(cp) ((cp)[0] == '-' && (cp)[1] != 0) /* Skip to first non-option argument, if any. */ while (*++cpptr && IS_OPTION(*cpptr)) /* void */ ; /* * Assume that the first non-option argument is the input file name. The * next argument could be the output destination or an option (System V * Release 2 /lib/cpp gets the options *after* the file arguments). */ if (*cpptr && *++cpptr && **cpptr != '-') { /* * The first non-option argument is followed by another argument that * is not an option ("-stuff") or a hyphen ("-"). Redirect our own * standard output before we clobber the file name. */ if (freopen(*cpptr, "w", stdout) == 0) { perror(*cpptr); exit(1); } /* Clobber the file name argument so that /lib/cpp writes to stdout */ *cpptr = "-"; } /* Set up the pipe that connects /lib/cpp to our standard input. */ if (pipe(pipefds)) { perror("pipe"); exit(1); } switch (pid = fork()) { case -1: /* error */ perror("fork"); exit(1); /* NOTREACHED */ case 0: /* child */ (void) close(pipefds[0]); /* close reading end */ (void) close(1); /* connect stdout to pipe */ if (dup(pipefds[1]) != 1) fatal("dup() problem"); (void) close(pipefds[1]); /* close redundant fd */ (void) execv(PIPE_THROUGH_CPP, argv); perror(PIPE_THROUGH_CPP); exit(1); /* NOTREACHED */ default: /* parent */ (void) close(pipefds[1]); /* close writing end */ (void) close(0); /* connect stdin to pipe */ if (dup(pipefds[0]) != 0) fatal("dup() problem"); close(pipefds[0]); /* close redundant fd */ return (pid); } } #endif /* show_arg_names - display function argument names */ static void show_arg_names(t) register struct token *t; { register struct token *s; /* Do argument names, but suppress void and rewrite trailing ... */ if (LAST_ARG_AND_EQUAL(t->head, VOID_ARG)) { show_empty_list(t); /* no arguments */ } else { for (s = t->head; s; s = s->next) { /* foreach argument... */ if (LAST_ARG_AND_EQUAL(s, "...")) { #ifdef _VA_ALIST_ /* see ./stdarg.h */ tok_show_ch(s); /* ',' */ put_str(_VA_ALIST_); /* varargs magic */ #endif } else { tok_show_ch(s); /* '(' or ',' or ')' */ show_arg_name(s); /* extract argument name */ } } } } /* show_arg_types - display function argument types */ static void show_arg_types(t) register struct token *t; { register struct token *s; /* Do argument types, but suppress void and trailing ... */ if (!LAST_ARG_AND_EQUAL(t->head, VOID_ARG)) { for (s = t->head; s; s = s->next) { /* foreach argument... */ if (LAST_ARG_AND_EQUAL(s, "...")) { #ifdef _VA_DCL_ /* see ./stdarg.h */ put_str(_VA_DCL_); /* varargs magic */ put_nl(); /* make output look nicer */ #endif } else { if (s->head != s->tail) { /* really new-style argument? */ show_type(s); /* rewrite type info */ put_ch(';'); put_nl(); /* make output look nicer */ } } } } } /* header_flush - rewrite new-style function heading to old style */ static void header_flush(t) register struct token *t; { show_arg_names(t); /* show argument names */ put_nl(); /* make output look nicer */ show_arg_types(t); /* show argument types */ tok_free(t); /* discard token */ } /* fpf_header_names - define func returning ptr to func, no argument types */ static void fpf_header_names(list) struct token *list; { register struct token *s; register struct token *p; /* * Recurse until we find the argument list. Account for the rare case * that list is a comma-separated list (which should be a syntax error). * Display old-style fuction argument names. */ for (s = list->head; s; s = s->next) { tok_show_ch(s); /* '(' or ',' or ')' */ for (p = s->head; p; p = p->next) { if (p->tokno == TOK_LIST) { if (IS_FUNC_PTR_TYPE(p)) { /* recurse */ fpf_header_names(p); show_empty_list(p = p->next); } else { /* display argument names */ show_arg_names(p); } } else { /* pass through other stuff */ tok_show(p); } } } } /* fpf_header_types - define func returning ptr to func, argument types only */ static void fpf_header_types(list) struct token *list; { register struct token *s; register struct token *p; /* * Recurse until we find the argument list. Account for the rare case * that list is a comma-separated list (which should be a syntax error). * Display old-style function argument types. */ for (s = list->head; s; s = s->next) { for (p = s->head; p; p = p->next) { if (p->tokno == TOK_LIST) { if (IS_FUNC_PTR_TYPE(p)) { /* recurse */ fpf_header_types(p); p = p->next; } else { /* display argument types */ show_arg_types(p); } } } } } /* fpf_header - define function returning pointer to function */ static void fpf_header(l1, l2) struct token *l1; struct token *l2; { fpf_header_names(l1); /* strip argument types */ show_empty_list(l2); /* strip prototype */ put_nl(); /* nicer output */ fpf_header_types(l1); /* show argument types */ } /* skip_enclosed - skip over enclosed tokens */ static struct token *skip_enclosed(p, stop) register struct token *p; register int stop; { register int start = p->tokno; /* Always return a pointer to the last processed token, never NULL. */ while (p->next) { p = p->next; if (p->tokno == start) { p = skip_enclosed(p, stop); /* recurse */ } else if (p->tokno == stop) { break; /* done */ } } return (p); } /* show_arg_name - extract argument name from argument type info */ static void show_arg_name(s) register struct token *s; { if (s->head) { register struct token *p; register struct token *t = 0; /* Find the last interesting item. */ for (p = s->head; p; p = p->next) { if (p->tokno == TOK_WORD) { t = p; /* remember last word */ } else if (p->tokno == '{') { p = skip_enclosed(p, '}'); /* skip structured stuff */ } else if (p->tokno == '[') { break; /* dimension may be a macro */ } else if (IS_FUNC_PTR_TYPE(p)) { t = p; /* or function pointer */ p = p->next; } } /* Extract argument name from last interesting item. */ if (t) { if (t->tokno == TOK_LIST) show_arg_name(t->head); /* function pointer, recurse */ else tok_show(t); /* print last word */ } } } /* show_type - rewrite type to old-style syntax */ static void show_type(s) register struct token *s; { register struct token *p; /* * Rewrite (*stuff)(args) to (*stuff)(). Rewrite word(args) to word(), * but only if the word was preceded by a word, '*' or '}'. Leave * anything else alone. */ for (p = s->head; p; p = p->next) { if (IS_FUNC_PTR_TYPE(p)) { p = show_func_ptr_type(p, p->next); /* function pointer type */ } else { register struct token *q; register struct token *r; tok_show(p); /* other */ if ((p->tokno == TOK_WORD || p->tokno == '*' || p->tokno == '}') && (q = p->next) && q->tokno == TOK_WORD && (r = q->next) && r->tokno == TOK_LIST) { tok_show(q); /* show name */ show_empty_list(p = r); /* strip args */ } } } } /* show_func_ptr_type - display function_pointer type using old-style syntax */ static struct token *show_func_ptr_type(t1, t2) struct token *t1; struct token *t2; { register struct token *s; /* * Rewrite (list1) (list2) to (list1) (). Account for the rare case that * (list1) is a comma-separated list. That should be an error, but we do * not want to waste any information. */ for (s = t1->head; s; s = s->next) { tok_show_ch(s); /* '(' or ',' or ')' */ show_type(s); /* recurse */ } show_empty_list(t2); return (t2); } /* show_empty_list - display opening and closing parentheses (if available) */ static void show_empty_list(t) register struct token *t; { tok_show_ch(t->head); /* opening paren */ if (t->tail->tokno == ')') tok_show_ch(t->tail); /* closing paren */ } /* show_struct_type - display structured type, rewrite function-pointer types */ static struct token *show_struct_type(p) register struct token *p; { tok_show(p); /* opening brace */ while (p->next) { /* XXX cannot return 0 */ p = p->next; if (IS_FUNC_PTR_TYPE(p)) { p = show_func_ptr_type(p, p->next); /* function-pointer member */ } else if (p->tokno == '{') { p = show_struct_type(p); /* recurse */ } else { tok_show(p); /* other */ if (p->tokno == '}') { return (p); /* done */ } } } DPRINTF("/* missing '}' */"); return (p); } /* is_func_ptr_cast - recognize function-pointer type cast */ static int is_func_ptr_cast(t) register struct token *t; { register struct token *p; /* * Examine superficial structure. Require (list1) (list2). Require that * list1 begins with a star. */ if (!IS_FUNC_PTR_TYPE(t)) return (0); /* * Make sure that there is no name in (list1). Do not worry about * unexpected tokens, because the compiler will complain anyway. */ for (p = t->head->head; p; p = p->next) { switch (p->tokno) { case TOK_LIST: /* recurse */ return (is_func_ptr_cast(p)); case TOK_WORD: /* name in list */ return (0); case '[': return (1); /* dimension may be a macro */ } } return (1); /* no name found */ } /* check_cast - display ()-delimited, comma-separated list */ static void check_cast(t) struct token *t; { register struct token *s; register struct token *p; /* * Rewrite function-pointer types and function-pointer casts. Do not * blindly rewrite (*list1)(list2) to (*list1)(). Function argument lists * are about the only thing we can discard without provoking diagnostics * from the compiler. */ for (s = t->head; s; s = s->next) { tok_show_ch(s); /* '(' or ',' or ')' */ for (p = s->head; p; p = p->next) { switch (p->tokno) { case TOK_LIST: if (is_func_ptr_cast(p)) { /* not: IS_FUNC_PTR_TYPE(p) */ p = show_func_ptr_type(p, p->next); } else { check_cast(p); /* recurse */ } break; case '{': p = show_struct_type(p); /* rewrite func. ptr. types */ break; default: tok_show(p); break; } } } } /* block_dcls - on the fly rewrite decls/initializers at start of block */ static void block_dcls() { register struct token *t; /* * Away from the top level, a declaration should be preceded by type or * storage-class information. That is why inside blocks, structs and * unions we insist on reading one word before passing the _next_ token * to the dcl_flush() function. * * Struct and union declarations look the same everywhere: we make an * exception for these more regular constructs and pass the "struct" and * "union" tokens to the type_dcl() function. */ while (t = tok_class()) { switch (t->tokno) { case TOK_WSPACE: /* preserve white space */ case '\n': /* preserve line count */ tok_flush(t); break; case TOK_WORD: /* type declarations? */ tok_flush(t); /* advance to next token */ t = tok_class(); /* null return is ok */ /* FALLTRHOUGH */ case TOK_COMPOSITE: /* struct or union */ if ((t = dcl_flush(t)) == 0) break; /* FALLTRHOUGH */ default: /* end of declarations */ DPRINTF("/* end dcls */"); /* FALLTRHOUGH */ case '}': /* end of block */ tok_unget(t); return; } } } /* block_flush - rewrite struct, union or statement block on the fly */ static void block_flush(t) register struct token *t; { static int count = 0; tok_flush(t); DPRINTF("/*%d*/", ++count); /* * Rewrite function pointer types in declarations and function pointer * casts in initializers at start of block. */ block_dcls(); /* Remainder of block: only rewrite function pointer casts. */ while (t = tok_class()) { if (t->tokno == TOK_LIST) { check_cast_flush(t); } else if (t->tokno == '{') { block_flush(t); } else { tok_flush(t); if (t->tokno == '}') { DPRINTF("/*%d*/", count--); return; } } } DPRINTF("/* missing '}' */"); } /* pair_flush - on the fly rewrite casts in grouped stuff */ static void pair_flush(t, start, stop) register struct token *t; register int start; register int stop; { tok_flush(t); while (t = tok_class()) { if (t->tokno == start) { /* recurse */ pair_flush(t, start, stop); } else if (t->tokno == TOK_LIST) { /* expression or cast */ check_cast_flush(t); } else { /* other, copy */ tok_flush(t); if (t->tokno == stop) { /* done */ return; } } } DPRINTF("/* missing '%c' */", stop); } /* initializer - on the fly rewrite casts in initializer */ static void initializer() { register struct token *t; while (t = tok_class()) { switch (t->tokno) { case ',': /* list separator */ case ';': /* list terminator */ tok_unget(t); return; case TOK_LIST: /* expression or cast */ check_cast_flush(t); break; case '[': /* array subscript, may nest */ pair_flush(t, '[', ']'); break; case '{': /* structured data, may nest */ pair_flush(t, '{', '}'); break; default: /* other, just copy */ tok_flush(t); break; } } } /* func_ptr_dcl_flush - rewrite function pointer stuff */ static struct token *func_ptr_dcl_flush(list) register struct token *list; { register struct token *t; register struct token *t2; /* * Ignore blanks and newlines because we are too lazy to maintain more * than one token worth of lookahead. The output routines will regenerate * discarded newline tokens. */ while (t = tok_class()) { switch (t->tokno) { case TOK_WSPACE: case '\n': tok_free(t); break; case TOK_LIST: /* Function pointer or function returning pointer to function. */ while ((t2 = tok_class()) /* skip blanks etc. */ &&(t2->tokno == TOK_WSPACE || t2->tokno == '\n')) tok_free(t2); switch (t2 ? t2->tokno : 0) { case '{': /* function heading (new) */ fpf_header(list, t); break; case TOK_WORD: /* function heading (old) */ tok_show(list); tok_show(t); break; default: /* func pointer type */ (void) show_func_ptr_type(list, t); break; } tok_free(list); tok_free(t); if (t2) tok_unget(t2); return (0); default: /* not a declaration */ tok_unget(t); return (list); } } /* Hit EOF; must be mistake, but do not waste any information. */ return (list); } /* function_dcl_flush - rewrite function { heading, type declaration } */ static struct token *function_dcl_flush(list) register struct token *list; { register struct token *t; /* * Ignore blanks and newlines because we are too lazy to maintain more * than one token worth of lookahead. The output routines will regenerate * ignored newline tokens. */ while (t = tok_class()) { switch (t->tokno) { case TOK_WSPACE: case '\n': tok_free(t); break; case '{': /* Function heading: word (list) { -> old style heading */ header_flush(list); tok_unget(t); return (0); case TOK_WORD: /* Old-style function heading: word (list) word... */ tok_flush(list); tok_unget(t); return (0); case TOK_LIST: /* Function pointer: word (list1) (list2) -> word (list1) () */ tok_flush(list); show_empty_list(t); tok_free(t); return (0); case ',': case ';': /* Function type declaration: word (list) -> word () */ show_empty_list(list); tok_free(list); tok_unget(t); return (0); default: /* Something else, reject the list. */ tok_unget(t); return (list); } } /* Hit EOF; must be mistake, but do not waste any information. */ return (list); } /* dcl_flush - parse declaration on the fly, return rejected token */ static struct token *dcl_flush(t) register struct token *t; { register int got_word; /* * Away from the top level, type or storage-class information is required * for an (extern or forward) function type declaration or a variable * declaration. * * With our naive word-counting approach, this means that the caller should * read one word before passing the next token to us. This is how we * distinguish, for example, function declarations from function calls. * * An exception are structs and unions, because they look the same at any * level. The caller should give is the "struct" or "union" token. */ for (got_word = 0; t; t = tok_class()) { switch (t->tokno) { case TOK_WSPACE: /* advance past blanks */ case '\n': /* advance past newline */ case '*': /* indirection: keep trying */ tok_flush(t); break; case TOK_WORD: /* word: keep trying */ case TOK_COMPOSITE: /* struct or union */ got_word = 1; tok_flush(t); break; default: /* * Function pointer types can be preceded by zero or more words * (at least one when not at the top level). Other stuff can be * accepted only after we have seen at least one word (two words * when not at the top level). See also the above comment on * structs and unions. */ if (t->tokno == TOK_LIST && LIST_BEGINS_WITH_STAR(t)) { if (t = func_ptr_dcl_flush(t)) { return (t); /* reject token */ } else { got_word = 1; /* for = and [ and , and ; */ } } else if (got_word == 0) { return (t); /* reject token */ } else { switch (t->tokno) { case TOK_LIST: /* function type */ if (t = function_dcl_flush(t)) return (t); /* reject token */ break; case '[': /* dimension, does not nest */ pair_flush(t, '[', ']'); break; case '=': /* initializer follows */ tok_flush(t); initializer(); /* rewrite casts */ break; case '{': /* struct, union, may nest */ block_flush(t); /* use code for stmt blocks */ break; case ',': /* separator: keep trying */ got_word = 0; tok_flush(t); break; case ';': /* terminator: succeed */ tok_flush(t); return (0); default: /* reject token */ return (t); } } } } return (0); /* hit EOF */ } dev86-0.16.21/unproto/varargs.c000066400000000000000000000011361231050321700161270ustar00rootroot00000000000000 /* * @(#) varargs.c 1.1 91/09/01 23:08:45 * * This program can be used to verify that the stdarg.h file is set up * correctly for your system. If it works, it should print one line with the * text "stdarg.h works". */ #include #include "stdarg.h" main(int argc, char *argv[]) { varargs_test("%s %s\n", "stdarg.h", "works"); } varargs_test(char *fmt, ...) { va_list ap; va_start(ap, fmt); while (*fmt) { if (strncmp("%s", fmt, 2) == 0) { fputs(va_arg(ap, char *), stdout); fmt += 2; } else { putchar(*fmt); fmt++; } } va_end(ap); } dev86-0.16.21/unproto/vstring.c000066400000000000000000000057611231050321700161660ustar00rootroot00000000000000/*++ /* NAME /* vs_alloc(), VS_ADDCH() /* SUMMARY /* auto-resizing string library /* PACKAGE /* vstring /* SYNOPSIS /* #include "vstring.h" /* /* struct vstring *vs_alloc(len) /* int len; /* /* int VS_ADDCH(vs, wp, ch) /* struct vstring *vs; /* char *wp; /* int ch; /* /* char *vs_strcpy(vp, dst, src) /* struct vstring *vp; /* char *dst; /* char *src; /* DESCRIPTION /* These functions and macros implement a small library for /* arbitrary-length strings that grow automatically when /* they fill up. The allocation strategy is such that there /* will always be place for the terminating null character. /* /* vs_alloc() allocates storage for a variable-length string /* of at least "len" bytes. /* /* VS_ADDCH() adds a character to a variable-length string /* and automagically extends the string if fills up. /* \fIvs\fP is a pointer to a vstring structure; \fIwp\fP /* the current write position in the corresponding character /* array; \fIch\fP the character value to be written. /* Note that VS_ADDCH() is a macro that evaluates some /* arguments more than once. /* /* vs_strcpy() appends a null-terminated string to a variable-length /* string. \fIsrc\fP provides the data to be copied; \fIvp\fP is the /* target, and \fIdst\fP the current write position within the target. /* The result is null-terminated. The return value is the new write /* position. /* DIAGNOSTICS /* VS_ADDCH() returns zero if it was unable to dynamically /* resize a string. /* /* vs_alloc() returns a null pointer in case of problems. /* /* vs_strcpy() returns a null pointer if the request failed. /* BUGS /* Auto-resizing may change the address of the string data in /* a vstring structure. Beware of dangling pointers. /* AUTHOR(S) /* Wietse Venema /* Eindhoven University of Technology /* Department of Mathematics and Computer Science /* Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands /* LAST MODIFICATION /* 92/01/15 21:53:06 /* VERSION/RELEASE /* 1.3 /*--*/ static char vstring_sccsid[] = "@(#) vstring.c 1.3 92/01/15 21:53:06"; /* C library */ extern char *malloc(); extern char *realloc(); /* Application-specific stuff */ #include "vstring.h" /* vs_alloc - initial string allocation */ struct vstring *vs_alloc(len) int len; { register struct vstring *vp; if (len < 1 || (vp = (struct vstring *) malloc(sizeof(struct vstring))) == 0 || (vp->str = malloc(len)) == 0) return (0); vp->last = vp->str + len - 1; return (vp); } /* vs_realloc - extend string, update write pointer */ char *vs_realloc(vp, cp) register struct vstring *vp; char *cp; { int where = cp - vp->str; int len = vp->last - vp->str + 1; if ((vp->str = realloc(vp->str, len *= 2)) == 0) return (0); vp->last = vp->str + len - 1; return (vp->str + where); } /* vs_strcpy - copy string */ char *vs_strcpy(vp, dst, src) register struct vstring *vp; register char *dst; register char *src; { while (*src) { if (VS_ADDCH(vp, dst, *src) == 0) return (0); src++; } *dst = '\0'; return (dst); } dev86-0.16.21/unproto/vstring.h000066400000000000000000000007071231050321700161660ustar00rootroot00000000000000/* @(#) vstring.h 1.2 92/01/15 21:53:19 */ struct vstring { char *str; /* string value */ char *last; /* last position */ }; extern struct vstring *vs_alloc(); /* initial allocation */ extern char *vs_realloc(); /* string extension */ extern char *vs_strcpy(); /* copy string */ /* macro to add one character to auto-resized string */ #define VS_ADDCH(vs,wp,c) \ ((wp < (vs)->last || (wp = vs_realloc(vs,wp))) ? (*wp++ = c) : 0)