dfoster@jarthur.Claremont.EDU (Derek R. Foster) (10/31/90)
In article <1990Oct26.223541.26634@NCoast.ORG> catfood@NCoast.ORG (Mark W. Schumann) writes: >DLV101@psuvm.psu.edu (Dwaine VanBibber) writes: >>Does anyone have some general rules for porting C programs developed under >>UNIX to MS-DOS? I've developed a small language interpreter that I would >>like to be able to run under DOS. I have already attempted this, and it >>compiles fine using TC++, however I keep getting stack overflow. I am >>using the large memory model. Setting TC++'s _stklen variable to something >>large doesn't seem to help any either. I should also point out that the >>program contains a recursive descent parser and function calls are often >>nested quite deep. Compiling with TC 2.01 yields the same results. Do I >>have to do a complete rewrite (ie. eliminate deep function calls or resort >>to bottom-up parsing), or can it be coerced to work? Any comments or >>volunteers to examine code? Thanks in advance. >>--Dwaine > >You have a problem with the Intel '86 architecture. No matter what you >do in C on an '86 machine, the stack segment cannot exceed 64K. That's >because the SS register is (wierd exceptions aside) held constant through >execution of a program. Since an Intel offset is a 16-bit pointer, you >are limited to the 64K. Although this is generally true in "nice" programs, there may be a somewhat kludgy workaround for this. DISCLAIMER: I haven't tried the following suggestion. This is all theory on my part, and I would be interested in hearing comments on it. Also the code I present is sketchy at best, and is probably outright wrong in some respects. Don't expect it to work; just use it as a model. Anyway, you might try changing the stack segment pointer to point into a new segment of your own when the old one gets filled. For instance, if you can identify a particular part of the program which will be called only when the stack is almost filled, you might try something like ... void huge char ABuffer[(some fancy calculation probably involving _stklen to preserve the ability to detect stack overflow) + 16 (the 16 is to ensure that I can always get a buffer of at least the size I want which starts on an even paragraph boundary)]; /* note that ABuffer is not meant to be a huge pointer to an array of chars, but a pointer to an array of 'huge chars'. This means it will be allocated its own data segment. I *THINK* this is the right syntax...*/ void StackSwapFunction(void) { unsigned oldSS; oldSS = _SS; _SS = FP_SEG(ABuffer+sizeof(ABuffer)); Do other function calls here.... possibly if they get too deep you could even do this same strategy with another buffer. Might even consider dynamic allocation of such buffers. Just remember that the stack segment has to start on an address that's a multiple of 16... _SS = oldSS; } All functions called by this function will put their return addresses, local variables, etc. in the new stack space, which is in the buffer. You may have other housekeeping tasks to do as well, possibly involving changing some global variables that are used internally by TC to detect end-of-stack. (If stack checking is turned on.) In fact, you would have to do quite a bit of twaddling to make this work (This is written off of the top of my head), but I bet it would be easier than rewriting the whole of a recursive-descent parser. In fact, a possibly more useful way to do this for your particular problem might involve keeping track of how much space is being used in the stack (via _SS and _stklen?) and then modify part of your parser's mutual recursion to work like: void RecursiveFunction(some parameters) { int stacksaved; if (very little stack space left) { save old _SS, point _SS at the _end_ of some (unused!) buffer. stacksaved = 1; } do whatever this function is supposed to do, possibly involving recursive calls. if (stacksaved) /* This part must happen before *EVERY* return */ restore old _SS; /* from this function. You can't return from this */ return; /* function without having done this!!! */ } Anyway, I hope this helps. If you actually succeed in getting this to work, I'd be interested in seeing the relevant chunks of your source code, so that I know the _exact_ way to do it instead of vague generalities like those above. Good luck! Derek Riippa Foster