1
0
mirror of https://github.com/Interlisp/maiko.git synced 2026-01-15 15:57:13 +00:00
Interlisp.maiko/src/mkatom.c
Nick Briggs 364420db88
Fix lispcmp bytecmp (#211)
* Correct signedness of 2nd parameter of lispcmp().

* Be clear that comparison of characters in bytecmp is unsigned since GETBYTE returns unsigned char.

* Make bytecmp() and lispcmp() helper functions static and removed from mkatomdefs.h.

* If no BYTESWAP we need to include <string.h> for memcmp()

* Use (uint8_t) rather than (unsigned char) in bytecmp when comparing to GETBYTE()
2021-01-25 09:57:55 -08:00

403 lines
12 KiB
C

/* $Id: mkatom.c,v 1.4 2001/12/24 01:09:05 sybalsky Exp $ (C) Copyright Venue, All Rights Reserved
*/
/************************************************************************/
/* */
/* (C) Copyright 1989-95 Venue. All Rights Reserved. */
/* Manufactured in the United States of America. */
/* */
/************************************************************************/
#include "version.h"
/**********************************************************************/
/*
File Name : makeatom.c
Desc. : Create atom
Date : January 29, 1987
Edited by : Takeshi Shimizu
Change : create_symbol
take,30-Jun
1 May 1987 take
28 Aug. 1987 take
Including : make_atom
compute_hash
create_symbol
compare_chars
parse_number
*/
/**********************************************************************/
#ifndef BYTESWAP
#include <string.h>
#endif
#include <stdint.h>
#include "lispemul.h"
#include "adr68k.h"
#include "lsptypes.h"
#include "lispmap.h"
#include "cell.h"
#include "dbprint.h"
#include "mkatomdefs.h"
#include "commondefs.h"
#include "mkcelldefs.h"
#define ATOMoffset 2 /* NIL NOBIND */
#define MAX_ATOMINDEX 0xffff /* max number of atoms */
#define Atom_reprobe(hash, char) ((((char)^(hash)) | 1) & 63)
extern DLword *Lisp_world;
/**********************************************************************/
/*
Func name : compute_hash
Compute hash value from chars.
THIS ONLY WORKS CORRECTLY ON EMULATOR STRINGS.
Don't use it with strings in lisp-space.
Date : January 29, 1987
Chan. Aug. 27 87 take
Edited by : Takeshi Shimizu
*/
/**********************************************************************/
DLword compute_hash(const char *char_base, DLword offset, DLword length) {
DLword hash;
DLword number;
DLword temp1;
char_base += offset;
hash = (int)(*(char_base)) << 8; /* get first byte */
char_base++; /* skip length area */
for (number = 1; number <= length - 1; char_base++, number++) {
hash = (hash + ((hash & 4095) << 2)) & 0x0ffff;
temp1 = (hash + ((hash & 255) << 8)) & 0x0ffff;
hash = (int)(temp1 + (*(char_base))) & 0x0ffff;
}
return (hash);
} /* end compute_hash */
/**********************************************************************/
/*
Func name : compute_lisp_hash
Compute hash value from chars. WORKS ONLY ON LISP CHARS.
Date : January 29, 1987
Chan. Aug. 27 87 take
Edited by : Takeshi Shimizu
*/
/**********************************************************************/
DLword compute_lisp_hash(const char *char_base, DLword offset, DLword length, DLword fatp) {
DLword hash;
DLword number;
DLword temp1;
DLword *word_base;
if (length == 0) return (0);
if (fatp) { /* fat characters in the string to be searched. */
word_base = (DLword *)char_base;
word_base += offset;
hash = (DLword)(0xFF & GETWORD(word_base)) << 8; /* get first byte */
word_base++; /* skip length area */
for (number = 1; number <= length - 1; word_base++, number++) {
hash = (hash + ((hash & 4095) << 2)) & 0x0ffff;
temp1 = (hash + ((hash & 255) << 8)) & 0x0ffff;
hash = (int)(temp1 + (0xFF & GETWORD(word_base))) & 0x0ffff;
}
} else {
char_base += offset;
hash = (int)(0xFF & GETBYTE(char_base)) << 8; /* get first byte */
char_base++; /* skip length area */
for (number = 1; number <= length - 1; char_base++, number++) {
hash = (hash + ((hash & 4095) << 2)) & 0x0ffff;
temp1 = (hash + ((hash & 255) << 8)) & 0x0ffff;
hash = (int)(temp1 + (0xFF & GETBYTE(char_base))) & 0x0ffff;
}
}
return (hash);
} /* end compute_lisp_hash */
#ifdef BYTESWAP
int bytecmp(const char *char1, const char *char2, int len)
{
int index;
for (index = 0; index < len; index++) {
if (GETBYTE(char1++) != *(uint8_t *)(char2++)) return (0);
}
return (1);
}
#endif /* BYTESWAP */
/**********************************************************************/
/*
Func name : compare_chars
Compare two strings, char1, char2
char1 -- in the LISP address space (& potentially
byte swapped!)
char2 -- in emulator space, and obeying the "natural"
ordering of bytes in a string.
Date : January 29, 1987
Edited by : Takeshi Shimizu
(why not call strncmp directly??)
Because we need to account for byte ordering!! --JDS
AND we need to compare NS chars (which have 0s in the string) correctly!
*/
/**********************************************************************/
LispPTR compare_chars(register const char *char1, register const char *char2, register DLword length) {
#ifndef BYTESWAP
if (memcmp(char1, char2, length) == 0)
#else
if (bytecmp(char1, char2, length))
#endif /* BYTESWAP */
{
return (T);
} else {
return (NIL);
}
} /* end compare_chars */
int lispcmp(const DLword *char1, const char *char2, int len) {
int index;
for (index = 0; index < len; index++) {
if (GETWORD(char1++) != GETBYTE(char2++)) return (0);
}
return (1);
}
/**********************************************************************/
/*
Func name : compare_lisp_chars
Compare two strings, char1, char2
in the LISP address space (& potentially
byte swapped!)
Date : January 29, 1987
Edited by : Takeshi Shimizu
(why not call strncmp directly??)
Because we need to account for byte ordering!! --JDS
And for fat/thin differences.
OFFSETs must be accounted for in the pointers already.
*/
/**********************************************************************/
LispPTR compare_lisp_chars(register const char *char1, register const char *char2, register DLword length,
DLword fat1, DLword fat2) {
if ((!fat1) == (!fat2)) { /* both fat or both non-fat. */
#ifdef BYTESWAP
if (fat1) { /* both fat, so compare 'em a word at a time */
int i;
for (i = 0; i < length; i++) {
if (GETWORD(char1) != GETWORD(char2)) return (NIL);
/* increment by size of fat character, i.e., DLword, 2 bytes */
char1+= sizeof(DLword); char2+=sizeof(DLword);
}
return (T);
} else { /* both thin, so compare 'em a byte at a time */
/* (it's this way in case we're byte-swapped.)*/
int i;
for (i = 0; i < length; i++)
if (GETBYTE(char1++) != GETBYTE(char2++)) return (NIL);
return (T);
}
#else
/* This one fails for byte-swapped machines */
if (fat1) length = length + length;
if (memcmp(char1, char2, length) == 0)
return (T);
else {
return (NIL);
}
#endif /* BYTESWAP */
} else if (fat1) { /* char1 is fat, char2 isn't */
if (lispcmp((DLword *)char1, char2, length))
return (T);
else
return (NIL);
} else { /* char2 is fat, char1 isn't */
if (lispcmp((DLword *)char2, char1, length))
return (T);
else
return (NIL);
}
} /* end compare_lisp_chars */
/**********************************************************************/
/*
Func name : make_atom
If the atom already existed then return
else create new atom . Returns the Atom's index.
This function does not handle FAT pname's.
Date : January 29, 1987
Edited by : Takeshi Shimizu
Changed : take 20-Jan
Changed : March 27 '87 take
Changed : May 1 '87 take
Changed : May 9 '87 take
Changed : May 13 '87 take
May 15 '87 take
*/
/**********************************************************************/
LispPTR make_atom(const char *char_base, DLword offset, DLword length, short int non_numericp)
/* if it is NIL then these chars are treated as NUMBER */
{
extern DLword *Spospspace;
extern DLword *AtomHT;
extern DLword *Pnamespace;
extern DLword *AtomSpace;
DLword hash;
LispPTR hash_entry; /* hash entry contents */
DLword atom_index;
DLword reprobe;
PNCell *pnptr;
char *pname_base;
unsigned short first_char;
#ifdef TRACE2
printf("TRACE: make_atom( %s , offset= %d, len= %d, non_numericp = %d)\n", char_base, offset,
length, non_numericp);
#endif
first_char = (*(char_base + offset)) & 0xff;
if (length != 0) {
if (length == 1) /* one char. atoms */
{
if (first_char > 57) /* greater than '9 */
return ((LispPTR)(ATOMoffset + (first_char - 10)));
else if (first_char > 47) /* between '0 to '9 */
return ((LispPTR)(S_POSITIVE + (first_char - 48)));
/* fixed S_... mar-27-87 take */
else /* other one char. atoms */
return ((LispPTR)(ATOMoffset + first_char));
} /* if(length==1.. end */
else if ((non_numericp == NIL) && (first_char <= '9'))
/* more than 10 arithmetic aon + - mixed atom process */
{
if ((hash_entry = parse_number(char_base + offset, length)) != 0)
return ((LispPTR)hash_entry); /* if NIL that means THE ATOM is +- mixed litatom */
/* 15 may 87 take */
}
hash = compute_hash(char_base, offset, length);
} /* if(lengt.. end */
else {
hash = 0;
first_char = 255;
}
/* This point corresponds with LP in Lisp source */
/* following for loop never exits until it finds new hash entry or same atom */
for (reprobe = Atom_reprobe(hash, first_char); (hash_entry = GETWORD(AtomHT + hash)) != 0;
hash = ((hash + reprobe) & 0xffff)) {
atom_index = hash_entry - 1;
/* get pname pointer */
pnptr = (PNCell *)GetPnameCell(atom_index);
pname_base = (char *)Addr68k_from_LADDR(POINTERMASK & pnptr->pnamebase);
if ((length == GETBYTE(pname_base)) &&
(compare_chars(++pname_base, char_base + offset, length) == T)) {
DBPRINT(("FOUND the atom. \n"));
return (atom_index); /* find already existed atom */
}
DBPRINT(("HASH doesn't hit. reprobe!\n"));
} /* for end */
/* we can't find that atom, then we should make new atom */
DBPRINT(("HASH NEVER HIT. Returning -1.\n"));
return (0xffffffff);
/** Don't create newatom now **/
} /* make_atom end */
/*********************************************************************/
/*
Func name : parse_number
Desc : It can treat -65534 to 65535 integer
Returns SMALLP PTR
Date : 1,May 1987 Take
15 May 87 take
*/
/*********************************************************************/
/* Assume this func. should be called with C string in "char_base" */
LispPTR parse_number(const char *char_base, short int length) {
register LispPTR sign_mask;
register LispPTR val;
register int radix;
register int *cell68k;
#ifdef TRACE2
printf("TRACE: parse_number()\n");
#endif
/* Check for Radix 8(Q) postfixed ?? */
if ((*(char_base + (length - 1))) == 'Q') {
radix = 8;
length--;
} else
radix = 10;
/* Check for Sign */
sign_mask = S_POSITIVE;
if ((*(char_base) == '+') || (*(char_base) == '-')) {
sign_mask = ((*char_base++) == '+') ? S_POSITIVE : S_NEGATIVE;
length--;
}
for (val = 0; length > 0; length--) {
if ((((*char_base)) < '0') || ('9' < ((*char_base)))) return (NIL);
val = radix * val + (*char_base++) - '0';
}
if (val > 0xffffffff) error("parse_number : Overflow ...exceeded range of FIXP");
if ((sign_mask == S_POSITIVE) && (val > 0xffff)) {
cell68k = (int *)createcell68k(TYPE_FIXP);
*cell68k = val;
return (LADDR_from_68k(cell68k));
} else if ((sign_mask == S_NEGATIVE) && (val > 0xffff)) {
cell68k = (int *)createcell68k(TYPE_FIXP);
*cell68k = ~val + 1;
return (LADDR_from_68k(cell68k));
}
else if (sign_mask == S_NEGATIVE)
return (sign_mask | (~((DLword)val) + 1));
else {
return (sign_mask | val);
}
}
/* end parse_number */