home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS 1992 September
/
Simtel20_Sept92.cdr
/
msdos
/
ddjmag
/
ddj8712.arc
/
NARO.ARC
/
MISC.C
< prev
next >
Wrap
Text File
|
1987-12-21
|
22KB
|
234 lines
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include <dos.h>
#include <errno.h>
#include "loc.h"
#include "externs.h"
extern int errno ;
char *get_mem(size)
unsigned long size ;
{
union REGS regs ;
char *p ;
/*
This function is a substitute for allocation of huge arrays. It
uses DOS system calls to directly allocate up to 64K for a memory
block.
*/
regs.x.bx = (unsigned int) (size / 16 + 1) ;
regs.h.ah = 0x48 ;
FP_SEG(p) = intdos(®s, ®s) ;
if (regs.x.cflag) {
errno = ENOMEM ;
p = NULL ;
}
else
FP_OFF(p) = 0 ;
return p ;
}
void free_mem(p)
char *p ;
{
union REGS regs ;
struct SREGS sregs ;
/*
This function is the complement of get_mem() in that it releases
any memory previously acquired with get_mem().
*/
sregs.es = FP_SEG(p) ;
regs.h.ah = 0x49 ;
intdosx(®s, ®s, &sregs) ;
return ;
}
int assign_physical_segment(class, seg)
char *class ;
unsigned int seg ;
{
int error = ERROR ;
SEG_DESCRIPTOR *p ;
/*
This function assigns the specified class name the physical
segment number. The first segment within a named class will
have an offset of zero. All other segments have a segment
offset relative to the first segment in the class.
*/
p = seg_list ;
while (p != NULL) {
if (strcmp(p->class, class) == 0) {
p->pseg += seg ;
p->inited = TRUE ;
error = OK ;
}
p = p->next ;
}
return error ;
}
int get_next_segment(pclass, cclass, seg)
char *pclass ;
char *cclass ;
unsigned int *seg ;
{
int error = ERROR ;
BOOLEAN found = FALSE ;
SEG_DESCRIPTOR *p, *q, *last ;
/*
This function returns the next physical segment address
available for use by CCLASS (current class) after PCLASS
(previous class). A typical use is to force the concatenation
of independent classes.
*/
/* Search the class list for the occurrence of the CCLASS */
p = q = seg_list ;
while (q != NULL) {
if (strcmp(q->class, cclass) == 0) {
found = TRUE ;
break ;
}
q = q->next ;
}
if (found == FALSE)
return ERROR ; /* Error if it can't be found */
/* Search for PCLASS and then to the end of PCLASS. */
while (p != NULL) {
if (strcmp(p->class, pclass) == 0) {
last = p ;
while(strcmp(p->class, pclass) == 0) {
last = p ;
p = p->next ;
}
/* Return the next available segment and adjust the segment
value for an overflow if necessary. */
*seg = last->pseg + last->len / 16 ;
if (q->offset < (last->len + last->offset) % 16)
*seg += 1 ;
return OK ;
}
p = p->next ;
}
return ERROR ;
}
int dup_class(old_class, new_class)
char *old_class ;
char *new_class ;
{
int error = ERROR ;
SEG_DESCRIPTOR *p, *q, *prev, *head ;
/*
Copies the contents of the OLD_CLASS entry to the newly created
NEW_CLASS entry.
*/
p = seg_list ;
while (p != NULL) {
if (strcmp(p->class, old_class) == 0) {
prev = head = NULL ;
while (p != NULL) {
if (strcmp(p->class, old_class) != 0)
break ;
/* Create the new segment descriptor */
if ((q = (SEG_DESCRIPTOR *) malloc(sizeof (*q))) == NULL) {
perror(__FILE__) ;
exit(1) ;
}
if (prev == NULL)
head = q ;
else
prev->next = q ;
/* Copy the contents and add the new entry to the list */
*q = *p ;
strcpy(q->class, new_class) ;
q->next = NULL ;
prev = q ;
if (p->next == NULL)
break ;
else
p = p->next ;
}
while (p->next != NULL)
p = p->next ;
p->next = head ;
return OK ;
}
p = p->next ;
}
return ERROR ;
}
int rom_class(rom_class)
char *rom_class;
{
int error = ERROR ;
SEG_DESCRIPTOR *p ;
/*
Sets the romable field for the specified class to TRUE permitting
the output of the segment in the absolute object file.
*/
p = seg_list ;
while (p != NULL) {
if (strcmp(p->class, rom_class) == 0) {
p->romable = TRUE ;
error = OK ;
}
p = p->next ;
}
return error ;
}
int locate_virtual_segment(vseg, pseg)
unsigned int vseg;
unsigned int *pseg;
{
SEG_DESCRIPTOR *p ;
/*
Finds an initialized segment with the specified virtual segment
number and returns the corresponding physical segment number.
*/
p = seg_list ;
while (p != NULL) {
if (p->inited == TRUE && p->vseg == vseg && p->len != 0) {
*pseg = p->pseg ;
return OK ;
}
p = p->next ;
}
return ERROR ;
}