home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
GEMini Atari
/
GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso
/
zip
/
gnu
/
gs252b.lzh
/
GS252B
/
GP_ATARI.C
< prev
next >
Wrap
C/C++ Source or Header
|
1993-07-30
|
18KB
|
750 lines
/* Copyright (C) 1989, 1992 Aladdin Enterprises. All rights reserved.
Distributed by Free Software Foundation, Inc.
This file is part of Ghostscript.
Ghostscript is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY. No author or distributor accepts responsibility
to anyone for the consequences of using it or for whether it serves any
particular purpose or works at all, unless he says so in writing. Refer
to the Ghostscript General Public License for full details.
Everyone is granted permission to copy, modify and redistribute
Ghostscript, but only under the conditions described in the Ghostscript
General Public License. A copy of this license is supposed to have been
given to you along with Ghostscript so you can know your rights and
responsibilities. It should be in a file named COPYING. Among other
things, the copyright notice and this notice must be preserved on all
copies. */
/* gp_atari.c */
/* Atari-specific routines for Ghostscript */
#include "memory_.h"
#include "string_.h"
#include "gx.h"
#include "gp.h"
#include "stat_.h"
#include "time_.h"
#include <stdarg.h>
/* popen isn't POSIX-standard, so we declare it here. */
extern FILE *popen();
extern int pclose();
/* Do platform-dependent initialization */
void
gp_init()
{
}
/* Do platform-dependent cleanup */
void
gp_exit()
{
}
/* ------ Date and time ------ */
/* Read the current date (in days since Jan. 1, 1980) */
/* and time (in milliseconds since midnight). */
void
gp_get_clock(long *pdt)
{ long secs_since_1970, secs_since_1980;
struct tm *tm, *localtime();
if ( (secs_since_1970 = time(NULL)) == 0 )
{ perror("Ghostscript: gettimeofday failed:");
exit(-1);
}
/* secs_since_1970 is #secs since Jan 1, 1970 */
/* subtract off number of seconds in 10 years */
/* leap seconds are not accounted for */
secs_since_1980 = secs_since_1970 - (long)(60 * 60 * 24 * 365.25 * 10);
/* there is no time zone adjustment for the atari st */
/* adjust for daylight savings time - assume dst offset is 1 hour */
tm = localtime(&(secs_since_1970));
if ( tm->tm_isdst )
secs_since_1980 += (60 * 60);
/* divide secs by #secs/day to get #days (integer division truncates) */
pdt[0] = secs_since_1980 / (60 * 60 * 24);
/* modulo * 1000 gives number of millisecs since midnight */
pdt[1] = (secs_since_1980 % (60 * 60 * 24)) * 1000;
#ifdef DEBUG_CLOCK
printf("secs_since_1970 = %d usecs_since_1970 = %d pdt[0] = %ld\
pdt[1] = %ld\n", secs_since_1970, pdt[1], pdt[0], pdt[1]);
#endif
}
/* ------ Screen management ------ */
/* Write a string to the console. */
void
gp_console_puts(const char *str, uint size)
{ fwrite(str, 1, size, stdout);
}
/* Make the console current on the screen. */
int
gp_make_console_current(struct gx_device_s *dev)
{ return 0;
}
/* Make the graphics current on the screen. */
int
gp_make_graphics_current(struct gx_device_s *dev)
{ return 0;
}
/* ------ Printer accessing ------ */
/* Open a file or a printing device. If gp_open_printer returns
* a NULL, the file will be sent directly to the centronics port.
* This happens if fname = "CEN:" or if gp_open_scratch_file()
* fails. Usually, GS wants to interpret a NULL return value as
* an error, so this is slightly incompatible.
* "|command" opens an output pipe.
*/
FILE *
gp_open_printer(char *fname)
{
if (!strcmp(fname, "CEN:")) { /* Direct Centronics printing. */
return NULL;
}
else {
return
(strlen(fname) == 0 ?
gp_open_scratch_file(gp_scratch_file_name_prefix, fname, "wb") :
fname[0] == '|' ?
popen(fname + 1, "wb") :
fopen(fname, "wb"));
}
}
/* Close the connection to the printer. */
void
gp_close_printer(FILE *pfile, const char *fname)
{ if ( fname[0] == '|' )
pclose(pfile);
else
fclose(pfile);
}
/* ------ File name syntax ------ */
/* Define the character used for separating file names in a list. */
char gp_file_name_list_separator = ',';
/* Define the default scratch file name prefix. */
const char gp_scratch_file_name_prefix[] = "gs_pr.";
/* Define whether case is insignificant in file names. */
const int gp_file_names_ignore_case = 1;
/* Define the string to be concatenated with the file mode */
/* for opening files without end-of-line conversion. */
const char gp_fmode_binary_suffix[] = "b";
/* Define the file modes for binary reading or writing. */
const char gp_fmode_rb[] = "rb";
const char gp_fmode_wb[] = "wb";
/* Create and open a scratch file with a given name prefix. */
/* Write the actual file name at fname. */
FILE *
gp_open_scratch_file(const char *prefix, char *fname, const char *mode)
{
strcpy(fname, prefix);
strcat(fname, "XXX");
mktemp(fname);
return fopen(fname, mode);
}
/* Answer whether a file name contains a directory/device specification, */
/* i.e. is absolute (not directory- or device-relative). */
int
gp_file_name_is_absolute(const char *fname, uint len)
{ /* A file name is absolute if it contains a drive specification */
/* (second character is a :) or if it start with / or \. */
return ( len >= 1 && (*fname == '/' || *fname == '\\' ||
(len >= 2 && fname[1] == ':')) );
}
/* Answer the string to be used for combining a directory/device prefix */
/* with a base file name. The file name is known to not be absolute. */
const char *
gp_file_name_concat_string(const char *prefix, uint plen,
const char *fname, uint len)
{ if ( plen > 0 )
switch ( prefix[plen - 1] )
{ case ':': case '/': case '\\': return "";
};
return "\\";
}
/* ------ File operations ------ */
/* If the file given by fname exists, fill in its status and return 1; */
/* otherwise return 0. */
int
gp_file_status(const char *fname, file_status *pstatus)
{ struct stat sbuf;
/* The RS/6000 prototype for stat doesn't include const, */
/* so we have to explicitly remove the const modifier. */
if ( stat((char *)fname, &sbuf) < 0 ) return 0;
pstatus->size_pages = stat_blocks(&sbuf); /* st_blocks is */
/* missing on some systems, */
/* see stat_.h */
pstatus->size_bytes = sbuf.st_size;
pstatus->time_referenced = sbuf.st_mtime;
pstatus->time_created = sbuf.st_ctime;
return 1;
}
/* ------ File enumeration ------ */
/****** THIS IS NOT SUPPORTED ON UNIX SYSTEMS. ******/
/* Amazingly enough, there is no standard Unix library routine */
/* for enumerating the files matching a pattern, */
/* or even for enumerating (conveniently) the files in a directory. */
struct file_enum_s {
char *pattern;
int first_time;
gs_memory_procs mprocs;
};
/* Initialize an enumeration. NEEDS WORK ON HANDLING * ? \. */
file_enum *
gp_enumerate_files_init(const char *pat, uint patlen,
proc_alloc_t palloc, proc_free_t pfree)
{ file_enum *pfen = (file_enum *)(*palloc)(1, sizeof(file_enum), "gp_enumerate_files");
char *pattern;
if ( pfen == 0 ) return 0;
pattern = (*palloc)(patlen + 1, 1,
"gp_enumerate_files(pattern)");
if ( pattern == 0 ) return 0;
memcpy(pattern, pat, patlen);
pattern[patlen] = 0;
pfen->pattern = pattern;
pfen->mprocs.alloc = palloc;
pfen->mprocs.free = pfree;
pfen->first_time = 1;
return pfen;
}
/* Enumerate the next file. */
uint
gp_enumerate_files_next(file_enum *pfen, char *ptr, uint maxlen)
{ if ( pfen->first_time )
{ pfen->first_time = 0;
}
return -1;
}
/* Clean up the file enumeration. */
void
gp_enumerate_files_close(file_enum *pfen)
{ proc_free_t pfree = pfen->mprocs.free;
(*pfree)(pfen->pattern, strlen(pfen->pattern) + 1, 1,
"gp_enumerate_files_close(pattern)");
(*pfree)((char *)pfen, 1, sizeof(file_enum), "gp_enumerate_files_close");
}
/*
* The remainder of this file contains printer output routines, most of
* which were contributed by Chris Strunk (some of them were written by me).
* I made some modifications to the following code (with permission), and
* may have introduced errors not in the original code.
* Tim Gallivan, 3/92.
*/
/*
* This file is Copyright (C) 1990 Christoph Strunk.
*
* You are not allowed to copy or modify it.
*/
#define ATARI_TOS (1)
#define MAKE_VOID (void *)
#define MAXLEN (256)
void con_flush();
int OutputIsAscii = 0, RTX_Found = 0;
long *old_ssp = NULL;
FILE *OutFile = NULL;
#if PC_DOS || ATARI_TOS
# define DIRECT 1 /* 1 = Direct Centronics port programming */
#endif
#if ATARI_TOS || ( PC_DOS && DIRECT )
static short prn_out ( int );
#endif
#if ATARI_TOS && LATTICE
#include <dos.h>
#endif
#ifdef __GNUC__
#include <osbind.h>
#endif
#if PC_DOS && DIRECT
#include <bios.h>
#endif
/* output one character */
static int fatal_output_error = 0;
void
lputc(c)
int c;
{
static short rc;
static unsigned char global_count = 0; /* other processes every 256 chars */
void l_stop(), fatal();
if ( fatal_output_error ) return;
global_count += 1;
c &= 255; /* New in 2.9.44: avoid signed char problems */
#if ATARI_TOS || PC_DOS
if ( ( c == '\n' ) && OutputIsAscii ) {
lputc ( '\r' ); /* recursion */
}
#endif
if ( OutFile ) {
rc = ( fputc ( c, OutFile ) == EOF );
} else {
#if ATARI_TOS || ( PC_DOS && DIRECT )
rc = prn_out ( c );
#else
rc = -1;
#endif
}
if ( rc ) {
if ( OutFile ) {
perror ( "\nlputc" );
fprintf ( stderr, "\nOutput error -- %s ?\n",
"Disk full or printer not ready" );
fclose ( OutFile );
OutFile = NULL;
} else {
fprintf ( stderr, "\nOutput error -- Printer not ready ?\n" );
}
l_stop();
fatal_output_error = 1;
fatal ( "Output error" );
}
#if ATARI_TOS
if ( RTX_Found && ! global_count ) call_yield(); /* allow other processes */
#endif
}
/* output a string */
void
lputs ( s )
char *s;
{
while ( *s ) lputc ( *s++ );
}
void
lflush()
{
if ( OutFile ) fflush ( OutFile );
}
/* start/stop lputc device */
void
l_start()
{
void l_stop(), fatal();
#if ATARI_TOS && DIRECT
volatile char *gpip = (char *) 0xFFFFFA01L;
int cnt;
if ( OutFile == NULL && old_ssp == NULL ) {
old_ssp = (void *) call_super ( NULL );
cnt = 0;
/* for ( cnt=0; ( *gpip & 1 ) && ( ++cnt <= 10 ); ) {
printf("cnt = %d\n", cnt); */
Ongibit(0x20); /* set strobe bit */
/* } */
if ( cnt > 10 ) {
l_stop();
puts ( "\n" );
fatal_output_error = 1;
fatal ( "Printer not ready" );
}
}
#endif
#if ATARI_TOS && ! DIRECT
int cnt;
if ( OutFile == NULL && old_ssp == NULL ) {
old_ssp = (void *) call_super ( NULL );
for ( cnt=0; ( ! prt_ready(0) ) && ( ++cnt <= 10 ); ) {
Ongibit(0x20); /* set strobe bit */
}
if ( cnt > 10 ) {
l_stop();
puts ( "\n" );
fatal_output_error = 1;
fatal ( "Printer not ready" );
}
}
#endif
#if PC_DOS && DIRECT
if ( OutFile == NULL && ( biosprint ( 2, 0, BiosChannel ) & 0x29 ) ) {
l_stop();
puts ( "\n" );
fatal_output_error = 1;
fatal ( "Printer not ready" );
}
#endif
}
void l_stop()
{
lflush();
#if ATARI_TOS
if ( old_ssp != NULL ) {
MAKE_VOID call_super ( old_ssp );
old_ssp = NULL;
}
#endif
}
#if ATARI_TOS && DIRECT
extern void int_off __PROTO( ( void ) );
/* int_off: ori.w #$0700,sr
* ret
*/
extern void int_on __PROTO( ( void ) );
/* int_on: andi.w #$F8FF,sr
* ret
*/
static short prn_out ( c )
int c;
{
volatile unsigned long *hz_200;
register unsigned long end_time;
volatile char *gpip = (char *) 0xFFFFFA01L;
register char g;
#if OLD
unsigned char loop_count = 0;
#endif
if ( old_ssp == NULL ) l_start();
hz_200 = (unsigned long *) 0x04BAL;
#if OLD
end_time = *hz_200 + 200; /* check once per second */
#else
end_time = *hz_200 + 2; /* check 100 times per second */
#endif
while ( *gpip & 1 ) { /* wait */
#if OLD
/* Printer 1 sec. or more not ready ? */
if ( ( end_time < *hz_200 ) ||
( ( ( ++loop_count & 7 ) == 0 ) && ( BatchMode || RTX_Found ) ) ) {
con_flush(); /* allow Control_C, other Processes etc. */
end_time = *hz_200 + 2; /* check 100 times per second */
}
#else
if ( end_time <= *hz_200 ) {
con_flush(); /* allow Control_C, other Processes etc. */
end_time = *hz_200 + 1; /* check 200 times per second */
}
#endif
}
int_off(); /* disable interrupts */
gpip = (char *) 0xFFFF8800L; /* load sound chip adress now */
*gpip = 15; /* select port B */
gpip[2] = (char) c; /* write out char */
*gpip = 14; /* select port A */
g = *gpip; /* get old value */
#if OLD
g &= 0xDF; /* clear strobe bit */
#else
g &= ~0x20; /* clear strobe bit */
#endif
gpip[2] = g;
g |= 0x20; /* set strobe bit */
g |= 0x20; /* short delay */
gpip[2] = g;
int_on(); /* enable interrupts */
return 0;
}
#endif
#if ATARI_TOS && ! DIRECT
static short prn_out ( c )
int c;
{
volatile unsigned long *hz_200 = (unsigned long *) 0x04BAL;
register unsigned long end_time;
if ( old_ssp == NULL ) l_start();
end_time = *hz_200 + 2; /* check 200 times per second */
while ( ! prt_ready(0) ) { /* wait */
if ( end_time <= *hz_200 ) {
con_flush(); /* allow Control_C, other Processes etc. */
end_time = *hz_200 + 1; /* check 200 times per second */
}
}
prt_out ( 0, c );
return 0;
}
#endif
#if PC_DOS && DIRECT
static short prn_out ( c )
int c;
{
while ( biosprint ( 0, c, BiosChannel ) & 0x29 ) {
/* wait until Ok or Control-C pressed */
con_flush();
}
return 0;
}
#endif
void
con_flush()
{
int chin;
void fatal();
chin = Crawio(0xFF);
if ((chin & 0xFF) == 3) fatal("Keyboard Interrupt");
}
void
fatal(char *message)
{
fprintf(stderr, "%s\n", message);
l_stop();
exit(-1);
}
/* The following routines are generic interfaces to Chris Strunk's
* fast printing routines. Tim Gallivan 3/92.
*/
int
csputc(int c, FILE *stream)
{
OutFile = stream;
l_start();
lputc(c);
l_stop();
return c;
}
int
csputs(const char *s, FILE *stream)
{
OutFile = stream;
l_start();
lputs(s);
l_stop();
return 1;
}
int
cswrite(const void *ptr, size_t size, size_t nobj, FILE *stream)
{
int count;
if (stream == NULL) {
OutFile = stream;
l_start();
for (count=0; count < size*nobj; count++) {
lputc(*(char *)(ptr++)); /* send the data */
}
l_stop();
return count;
}
else {
int ret;
ret = fwrite(ptr, size, nobj, stream);
con_flush();
return ret;
}
}
int
csprintf(FILE *stream, char *format, ...)
{
va_list args;
char line[MAXLEN];
va_start(args, format);
if (stream == NULL) {
OutFile = stream;
vsprintf(line, format, args);
l_start();
lputs(line);
l_stop();
va_end(args);
return 0;
}
else {
vfprintf(stream, format, args);
va_end(args);
con_flush();
return 0;
}
}
/*
#-----------------------------------------------------------------------------#
#: Simple support routines for LATTICE C 5.04.01 and other C compilers
#
#: Lattice C Assembler
#
#: The parameter comes on the stack for functions starting with '_'.
#
#: void *call_super ( void * ); supervisor mode on/off
#
#: Original code by Chris Strunk. Modified for use with gcc in
#: Ghostscript by Tim Gallivan, 3/92.
#-----------------------------------------------------------------------------#
*/
asm("\
.text 0
.globl _int_off
.globl _int_on
.globl _call_super
.globl _call_yield
.globl _call_nice
.globl _user_trace
.globl _prt_ready
.globl _prt_out
_get_la:
moveml d2/a2,sp@-
.byte 0xA0,0x00 | Adresse Line-A-Var nach A0 & D0
moveml sp@+,d2/a2
rts
_int_off:
oriw #0x0700,sr
rts
_int_on:
andiw #0xF8FF,sr
rts
_call_super:
movel a7@(4),a0
moveml d2/a2-a3,sp@-
movel a0,sp@-
movew #0x20,sp@-
movel a7,a3 | save current stack pointer
trap #1
movel a3,a7 | make bad stack pointer good again !!!!!!!
addql #6,sp
movel d0,a0 | return value in both: d0 and a0
moveml sp@+,d2/a2-a3
rts
_call_yield:
moveml d2/a2,sp@-
movew #0x00ff,sp@- | MiNT Syield() -- TOS illegal (rc -32)
trap #1
addql #2,sp
moveml sp@+,d2/a2
rts
_call_nice:
movel a7@(4),d0
moveml d2/a2,sp@-
movew d0,sp@-
movew #0x10A,sp@-
trap #1
addql #4,sp
moveml sp@+,d2/a2
rts
_user_trace:
moveml d1-d7/a0-a6,sp@-
moveql #0,d0
movel 0x3F0,a1 | TEMPLMON user trace vector
cmpal #0,a1 | not installed ?
beqs end_trace
jsr a1@ | execute it !
extl d0
end_trace:
moveml sp@+,d1-d7/a0-a6
rts
_prt_ready:
moveml d3/a3/a5,a7@-
subl a5,a5
movew d0,a7@-
movel 0x506,a0
jsr a0@
addql #2,a7
moveml a7@+,d3/a3/a5
rts
_prt_out:
moveml d3/a3/a5,a7@-
subl a5,a5
movew d1,a7@-
movew d0,a7@-
movel 0x50A,a0
jsr a0@
addql #4,a7
moveml a7@+,d3/a3/a5
rts
");