home *** CD-ROM | disk | FTP | other *** search
- From mipos3!omepd!uoregon!hp-pcd!hplabs!decwrl!decvax!ima!necntc!ncoast!allbery Tue Mar 8 19:24:28 PST 1988
- Article 322 of comp.sources.misc:
- Path: td2cad!mipos3!omepd!uoregon!hp-pcd!hplabs!decwrl!decvax!ima!necntc!ncoast!allbery
- From: asjoshi@phoenix.princeton.edu (Amit S. Joshi)
- Newsgroups: comp.sources.misc
- Subject: v02i069: Timer and CTRL BRK functions in Turbo C
- Keywords: Turbo C, timers, ^C
- Message-ID: <7472@ncoast.UUCP>
- Date: 5 Mar 88 23:26:25 GMT
- Sender: allbery@ncoast.UUCP
- Reply-To: asjoshi@phoenix.princeton.edu (Amit S. Joshi)
- Organization: Princeton University, NJ
- Lines: 637
- Approved: allbery@ncoast.UUCP
- Comp.sources.misc: Volume 2, Issue 69
- Submitted-By: "Amit S. Joshi" <asjoshi@phoenix.princeton.edu>
- Archive-Name: turbo-C-timers
-
- Comp.sources.misc: Volume 2, Issue 69
- Submitted-By: "Amit S. Joshi" <asjoshi@phoenix.princeton.edu>
- Archive-Name: turbo-C-timers
-
- [*Another* ARCed source?! Egads! ++bsa]
-
- Here are a set of four functions to handle timers and ^C breaks slightly
- more easily from Turbo C. Includes a small 'manual' page to use the
- functions. Could be ported to MSC (but I don't have that expensive
- compiler ;-). For some reason the functions cause a stack overflow in
- the small, tiny and medium models. There is a small test program to
- excercise the timer functions included. Also included is the makefile
- and the default rules file. I used NDMAKE.
-
- UUdecode and then unarchive. Any old arc program (even tthe UNIX ones)
- should be able to do it.
-
- [Not any more; it's now a shar. ++bsa]
-
- ----- cut above this line -----
- #! /bin/sh
- #
- # This is a shell archive. Save this into a file, edit it
- # and delete all lines above this comment. Then give this
- # file to sh by executing the command "sh file". The files
- # will be extracted into the current directory owned by
- # you with default permissions.
- #
- # The files contained herein are:
- #
- # -rw-r--r-- 1 allbery System 1622 Feb 27 00:55 MAKE.INI
- # -rw-r--r-- 1 allbery System 1129 Mar 4 15:01 MAKEFILE
- # -rw-r--r-- 1 allbery System 1574 Mar 4 15:37 TEST.C
- # -rw-r--r-- 1 allbery System 5556 Feb 25 12:35 TICK.C
- # -rw-r--r-- 1 allbery System 2511 Mar 4 14:56 TICK.DOC
- # -rw-r--r-- 1 allbery System 1442 Feb 25 11:49 TICK.H
- #
- echo 'x - MAKE.INI'
- if test -f MAKE.INI; then echo 'shar: not overwriting MAKE.INI'; else
- sed 's/^X//' << '________This_Is_The_END________' > MAKE.INI
- X# rules especially for the Turbo C package.
- X
- XCC=tcc
- XAS=masm
- XLB=lib
- XCPP=cpp
- XLINK=tlink
- XMODEL=s
- X
- XLIB=c:\turboc\lib
- XINCLUDE=c:\turboc\include
- X
- XLIBS=
- XSTDLIBFILES=$(LIB)\math$(MODEL) $(LIB)\c$(MODEL) $(LIB)\fp87
- XSTDOBJFILES=$(LIB)\c0$(MODEL)
- X
- X
- XTCFLAGS=-DTURBOC -m$(MODEL)
- XASFLAGS=/E
- XLFLAGS=/d
- XCFLAGS=
- X
- X.SUFFIXES: .i .com .exe .obj .asm .c .for .pas
- X
- X# create response files for tlink too.
- X.RESPONSE_LINK: tlink
- X
- X# ASM -> EXE using masm and tlink
- X.asm.exe:
- X $(AS) $<;
- X $(LINK) $(STDOBJFILES) $*,$*,,$(STDLIBFILES) $(LFLAGS)
- X @rm -f $*.obj
- X
- X# ASM -> OBJ using MASM
- X.asm.obj:
- X $(AS) $<;
- X
- X# C -> ASM using tcc -S option
- X.c.asm:
- X $(CC) $(TCFLAGS) -S $(CFLAGS) -I$(INCLUDE) -L$(LIB) $(LIBS) $<
- X @tcod $*
- X @mv $*.cod $*.asm
- X
- X# C -> COM using tcc and then exe2bin
- X.c.com:
- X $(CC) $(TCFLAGS) $(CFLAGS) -I$(INCLUDE) -L$(LIB) $(LIBS) $<
- X -(@exe2bin $*.exe $*.com)
- X @rm -f $*.obj $*.exe
- X
- X# C -> EXE using tcc ; use this since it is faster than C -> OBJ -> EXE
- X.c.exe:
- X $(CC) $(TCFLAGS) $(CFLAGS) -I$(INCLUDE) -L$(LIB) $(LIBS) $<
- X @rm -fi- $*.obj
- X
- X# C -> OBJ using tcc -c option
- X.c.obj:
- X $(CC) $(TCFLAGS) -c $(CFLAGS) -I$(INCLUDE) -L$(LIB) $(LIBS) $<
- X
- X# OBJ -> EXE using tcc
- X.obj.exe:
- X $(CC) $(TCFLAGS) $(CFLAGS) -I$(INCLUDE) -L$(LIB) $(LIBS) $<
- X
- X# EXE -> COM using exe2bin
- X.exe.com:
- X exe2bin $< $*.com
- X @rm -f $*.exe
- X
- X# C -> I run preprocessor only
- X.c.i:
- X $(CPP) $(TCFLAGS) -P $(CFLAGS) -I$(INCLUDE) -L$(LIB) $(LIBS) $<
- X
- X# cleans the current directory - always needed
- Xclean:; @rm -f *.bak *.map *.lst
- X
- X# make makefile using mkmf interactively
- ________This_Is_The_END________
- if test `wc -l < MAKE.INI` -ne 75; then
- echo 'shar: MAKE.INI was damaged during transit (should have been 75 bytes)'
- fi
- fi ; : end of overwriting check
- echo 'x - MAKEFILE'
- if test -f MAKEFILE; then echo 'shar: not overwriting MAKEFILE'; else
- sed 's/^X//' << '________This_Is_The_END________' > MAKEFILE
- X
- XMODEL = ml
- X# turn optimization on by default
- XCFLAGS = -O
- X
- XDEST = .
- X
- XEXTHDRS = /turboc/include/dos.h \
- X /turboc/include/stdarg.h \
- X /turboc/include/stdio.h \
- X /turboc/include/stdlib.h
- X
- XHDRS = TICK.H
- X
- XLIBS =
- X
- XMAKEFILE = makefile
- X
- XOBJS = TEST.OBJ \
- X TICK.OBJ
- X
- X# Print over the ethernet
- XPRINT = eprint
- X
- XPROGRAM = test.exe
- X
- XSRCS = TEST.C \
- X TICK.C
- X
- Xall: $(PROGRAM)
- X
- X$(PROGRAM): $(OBJS) $(LIBS)
- X $(LINK) $(STDOBJFILES) $(OBJS),$@,,$(LIBS) $(STDLIBFILES)
- X
- Xclean:; rm -f *.bak *.lst *.map $(OBJS)
- X
- Xdepend:; @mkmf -f $(MAKEFILE) PROGRAM=$(PROGRAM) DEST=$(DEST)
- X
- Xinstall: $(PROGRAM)
- X @mv $(PROGRAM) $(DEST)
- X
- Xprint:; $(PRINT) $(HDRS) $(SRCS)
- X
- Xprogram: $(PROGRAM)
- X
- Xupdate: $(DEST)/$(PROGRAM)
- X
- X$(DEST)/$(PROGRAM): $(SRCS) $(LIBS) $(HDRS) $(EXTHDRS)
- X @make -f $(MAKEFILE) DEST=$(DEST) install
- X###
- XTEST.OBJ: /turboc/include/stdio.h /turboc/include/stdarg.h tick.h \
- X /turboc/include/dos.h
- XTICK.OBJ: /turboc/include/stdlib.h /turboc/include/stdio.h \
- X /turboc/include/stdarg.h tick.h /turboc/include/dos.h
- ________This_Is_The_END________
- if test `wc -l < MAKEFILE` -ne 54; then
- echo 'shar: MAKEFILE was damaged during transit (should have been 54 bytes)'
- fi
- fi ; : end of overwriting check
- echo 'x - TEST.C'
- if test -f TEST.C; then echo 'shar: not overwriting TEST.C'; else
- sed 's/^X//' << '________This_Is_The_END________' > TEST.C
- X/* test.c - gently excersise the tick.c functions */
- X
- X#include <stdio.h>
- X#include "tick.h"
- X
- X#define NT 300
- X#define ND 5
- X
- Xvoid test1(void) {
- X printf("1");
- X}
- X
- Xvoid test2(void) {
- X putc('a',stderr);
- X}
- X
- Xmain() {
- X int i;
- X void test1(), test2();
- X
- X for (i = NT; i > 0; i--) {
- X test1(); test2();
- X delay(ND);
- X }
- X
- X if ((i = install_timer(test1)) != 0) {
- X printf("Install_timer failed: %d\n",i);
- X exit(1);
- X }
- X
- X printf("\nInstalled timer 1\n");
- X
- X for (i = NT; i > 0; i--) delay(ND);
- X
- X if ((i = install_timer(test2)) != 0) {
- X printf("Install_timer failed: %d\n",i);
- X exit(1);
- X }
- X
- X printf("\nInstalled timer 2\n");
- X
- X for (i = NT; i > 0; i--) delay(ND);
- X
- X if ((i = remove_timer(test2)) != 0) {
- X printf("Remove timer failed: %d\n",i);
- X exit(1);
- X }
- X printf("\nRemoved timer 2\n");
- X for (i = NT; i > 0; i--) delay(ND);
- X if ((i = install_timer(test2)) != 0) {
- X printf("Install_timer failed: %d\n",i);
- X exit(1);
- X }
- X
- X printf("\nInstalled timer 2\n");
- X
- X for (i = NT; i > 0; i--) delay(ND);
- X if ((i = remove_timer(test1)) != 0) {
- X printf("Remove timer failed: %d\n",i);
- X exit(1);
- X }
- X printf("\nRemoved timer 1\n");
- X for (i = NT; i > 0; i--) delay(ND);
- X
- X if ((i = install_timer(test1)) != 0) {
- X printf("Install_timer failed: %d\n",i);
- X exit(1);
- X }
- X
- X printf("\nInstalled timer 1\n");
- X for (i = NT; i > 0; i--) delay(ND);
- X
- X if ((i = remove_timer(NULLVFP)) != 0) {
- X printf("Remove timer failed: %d\n",i);
- X exit(1);
- X }
- X printf("\nRemoved all timers\n");
- X for (i = NT; i < 0; i--) delay(ND);
- X}
- X
- ________This_Is_The_END________
- if test `wc -l < TEST.C` -ne 80; then
- echo 'shar: TEST.C was damaged during transit (should have been 80 bytes)'
- fi
- fi ; : end of overwriting check
- echo 'x - TICK.C'
- if test -f TICK.C; then echo 'shar: not overwriting TICK.C'; else
- sed 's/^X//' << '________This_Is_The_END________' > TICK.C
- X/* tick.c - installs a function which is called every clock tick */
- X/* (c) - Amit Joshi, Princeton University
- X
- X This code may be used freely for any noncommercial use. It may NOT
- X be used in any commercial package without written permission from
- X the author. This clause is to protect me from legal hassles with
- X the university about code developed here. This code is supplied
- X "AS IS" i.e. with no warranty. Do not remove this notice. Any
- X modifications should be clearly noted before redistribution.
- X**/
- X
- X/** Amit Joshi
- X MAE Dept., Engg. Quad.
- X Princeton University
- X December 1987
- X**/
- X
- X/**
- X The __tick__() and dosbusy() functions have been stolen from the
- X "rdir.c" code by Dean D. McCrory. The __tick__() has been
- X rewritten (and renamed from timer_handler()) to be more general.
- X Amit Joshi
- X January 1988
- X**/
- X
- X#include <stdlib.h>
- X#include <stdio.h>
- X#include "tick.h"
- X
- X/* Stuff for to handle the ctrl break functions */
- Xstatic int __nc_brks = 0;
- Xstatic char __abort = 1;
- Xstatic void (* __c_brks[NCBRKS])();
- X
- X/* Stuff to run timers */
- Xstatic void interrupt (* __otimer)() = NULLIVFP;
- Xstatic int __ntimers = 0;
- Xstatic void (* __timers[NTIMERS])();
- Xstatic char far * dosbusy_fl; /* dos maintains this */
- X
- X/* The functions used in this file */
- Xstatic int __cbrk(void);
- Xstatic void __clean_timer(void);
- Xstatic void interrupt __tick__(void);
- Xstatic char far * getdosbusy(void);
- X
- Xstatic int
- X__cbrk(void) {
- X int nf;
- X
- X if (!abort) {
- X for (nf = 0; nf < __nc_brks; ++nf)
- X (* __c_brks[nf])();
- X exit(1);
- X } else return 1;
- X}
- X
- Xstatic void
- X__clean_timer(void) {
- X if (__otimer == NULLIVFP) return; /* nothing set yet */
- X setvect(TIMER_INT,__otimer);
- X}
- X
- X/* __tick__ ()
- X *
- X * This function intercepts the hardware timer interrupt. It checks the
- X * dosbusy flag and runs through a list of timer driven functions if safe
- X * to do so.
- X */
- X
- Xstatic void interrupt
- X__tick__(void)
- X{
- X static int in_fl = 0;
- X int timer;
- X
- X /* if the following statement is NOT coded, the 8259 blocks all hardware
- X interrupts including the keyboard interrupt. Since we wait for a key
- X in list_directory (), this causes the PC to lock up. This one took
- X a while to figure out */
- X outportb (0x20, 0x20); /* send eoi to 8259 */
- X (*__otimer) (); /* chain to previous timer handler */
- X
- X if (! in_fl)
- X {
- X in_fl = 1; /* we are in our ISR */
- X if (! *dosbusy_fl )
- X /* run through the list of timers */
- X for (timer = 0; timer < __ntimers; ++timer)
- X if (__timers[timer] != NULLVFP)
- X (* __timers[timer])();
- X in_fl = 0;
- X }
- X return; /* return from ISR */
- X}
- X
- X/* getdosbusy ()
- X *
- X * Gets the Dos busy flag through interrupt 34h. This Dos function returnes
- X * the busy flag address in es:bx. This is an UNDOCUMENTED feature of Dos,
- X * however it has worked in Dos versions 2.11 - 3.30 for me - Dean McCrory.
- X */
- Xstatic char far *
- Xgetdosbusy (void)
- X{
- X struct SREGS sregs; /* segment registers */
- X union REGS regs; /* normal registers */
- X
- X regs.h.ah = 0x34; /* get dos busy flag address (UNDOCUMENTED) */
- X intdosx (®s, ®s, &sregs);
- X return (MK_FP (sregs.es, regs.x.bx));
- X}
- X
- Xint
- Xinstall_timer(void (*func)(void))
- X{
- X int i = 0;
- X void __clean_timer();
- X void interrupt __tick__();
- X
- X /* check if the function is already installed */
- X
- X if (!__ntimers) {
- X __otimer = getvect(TIMER_INT);
- X /* Get address of DOS busy flag. */
- X dosbusy_fl = getdosbusy();
- X if (atexit(__clean_timer)) return 2;
- X install_cbrk(NULLVFP);
- X setvect(TIMER_INT,__tick__);
- X }
- X /* are we already installed ? */
- X for (i=0; i < __ntimers; i++)
- X if (__timers[i] == func) return 0;
- X /* enough space for another function ? */
- X if (__ntimers >= NTIMERS) return 1;
- X __timers[__ntimers++] = func;
- X return 0;
- X}
- X
- Xint
- Xremove_timer(void (*func)(void))
- X{
- X int i = 0;
- X
- X if (func == NULLVFP) {
- X __clean_timer();
- X __ntimers = 0;
- X return 0;
- X }
- X
- X if (!__ntimers) return 1; /* No timers return func not there */
- X
- X do {
- X /* have we found the function ? */
- X if (__timers[i] == func) {
- X /* is it the last one in the chain ? */
- X if (i++ == __ntimers) {
- X __timers[i-1] = NULLVFP;
- X } else {
- X /* move the chain backwards */
- X do {
- X __timers[i-1] = __timers[i]; i++;
- X } while(i <= __ntimers);
- X }
- X __ntimers--;
- X return 0;
- X } else i++;
- X } while (i < __ntimers);
- X return 1;
- X}
- X
- Xint
- Xinstall_cbrk (void (* func)(void))
- X{
- X int i = 0;
- X
- X
- X
- X if (!__nc_brks) {
- X setcbrk(1); /* ensure that ctrl break is enabled */
- X ctrlbrk(__cbrk);
- X __abort = 1;
- X }
- X
- X if (func == NULLVFP) __abort = 1;
- X
- X for (i = 0; i < __nc_brks; i++)
- X if (__c_brks[i] == func) return 0;
- X /* enough space for another function ? */
- X if (__nc_brks >= NCBRKS) return 1;
- X __c_brks[__nc_brks++] = func;
- X return 0;
- X}
- X
- Xint
- Xremove_cbrk (void (* func)(void))
- X{
- X int i = 0;
- X
- X if (func == NULLVFP) __abort = 0;
- X
- X if (!__nc_brks) return 1; /* No timers return func not there */
- X
- X do {
- X /* have we found the function ? */
- X if (__c_brks[i] == func) {
- X /* is it the last one in the chain ? */
- X if (i++ == __nc_brks) {
- X __c_brks[i-1] = NULLVFP;
- X } else {
- X /* move the chain backwards */
- X do {
- X __c_brks[i-1] = __c_brks[i]; i++;
- X } while(i <= __nc_brks);
- X }
- X __nc_brks--;
- X return 0;
- X } else i++;
- X } while (i < __nc_brks);
- X return 1;
- ________This_Is_The_END________
- if test `wc -l < TICK.C` -ne 220; then
- echo 'shar: TICK.C was damaged during transit (should have been 220 bytes)'
- fi
- fi ; : end of overwriting check
- echo 'x - TICK.DOC'
- if test -f TICK.DOC; then echo 'shar: not overwriting TICK.DOC'; else
- sed 's/^X//' << '________This_Is_The_END________' > TICK.DOC
- XAll the functions in this file make heavy use of TurboC and PCDOS
- Xfacilities and are not portable.
- X
- XWARNING:
- X DO NOT compile with tiny, small or medium models. Stack overflow
- X occurs and if the stack checking option of the compiler is used
- X then the timers are not unloaded and the system crashes - in fact
- X you have to setup the entire system from scratch.
- X
- XUSAGE:
- X #include "tick.h"
- X
- X int install_timer(vod (*func());
- X Installs the function "func()" to be called EVERY tick.
- X Removes the function on exit from the program - both if
- X ^C or normal. You MUST NOT use the Turbo C supplied
- X ctrlbrk() function if you use this one. Use
- X "install_cbrk()" instead.
- X
- X int install_cbrk(void (*func)());
- X Installs the function "func()" to be called when ^C is hit.
- X You can chain a series of functions. If you use this DO NOT
- X use the Turbo C supplied ctrlbrk(). If argument is NULLVFP
- X ^C exits from the program.
- X
- X int remove_timer(void (*func)());
- X Removes "func()" from timer list. If NULLVFP is given as an
- X argument all timers are cleaned.
- X
- X int remove_cbrk(void (*func)());
- X Removes "func()" from ctrlbrk list. If argument is NULLVFP
- X ^C has no action.
- XRETURN VALUES:
- X 0 => function was successfully installed or removed.
- X 1 => Install failed because of lack of space. Compile again with a
- X larger NTIMER or NCBRK in "tick.h"
- X Remove failed because function not found.
- X 2 => Install timer failed because we could not hook timer cleaner
- X onto atexit(). Try again with fewer atexit() functions.
- X
- XNOTES:
- X * DO NOT use the Turbo C ctrlbrk() function if using these functions
- X - it can have quite disasterous effects. Use install_cbrk() - it
- X is more general in any case !.
- X * Both the install functions try to check if the function is already
- X present and do not duplicate installations.
- X * Define HARDTIMER in "tick.h" if you want to use the hardware
- X interrupt rather than the DOS 'soft' interrupt. This is at your own
- X peril. I have not used this.
- X
- XBUGS:
- X Notify all bugs to :
- X Q3696@PUCC.BITNET or
- X {seismo, rutgers}\!princeton\!phoenix\!asjoshi
- X
- XACKNOWLEDGEMENTS:
- X Dean D. McCrory for two functions which really form the heart of the
- X timer portion : timer_handler, and dosbusy. The first has been
- X modified and made more general. It is also renamed to __tick__().
- X The rest of the code was written using Turbo C v1.5 entirely by me
- X Thanks to Borland for the wonderful (and inexpensive) C compiler.
- X
- ________This_Is_The_END________
- if test `wc -l < TICK.DOC` -ne 62; then
- echo 'shar: TICK.DOC was damaged during transit (should have been 62 bytes)'
- fi
- fi ; : end of overwriting check
- echo 'x - TICK.H'
- if test -f TICK.H; then echo 'shar: not overwriting TICK.H'; else
- sed 's/^X//' << '________This_Is_The_END________' > TICK.H
- X/* tick.h - the include file for timer and c_brk function installation */
- X/* (c) - Amit Joshi, Princeton University
- X
- X This code may be used freely for any noncommercial use. It may NOT
- X be used in any commercial package without written permission from
- X the author. This clause is to protect me from legal hassles with
- X the university about code developed here. This code is supplied
- X "AS IS" i.e. with no warranty. Do not remove this notice. Any
- X modifications should be clearly noted before redistribution.
- X**/
- X
- X/** Amit Joshi
- X MAE Dept., Engg. Quad.
- X Princeton University
- X December 1987
- X**/
- X
- X/**
- X Change the values defined for NTIMERS and NCBRKS to increase
- X number of timer and cbrk functions installed.
- X
- X Amit Joshi
- X January 1988
- X**/
- X
- X#ifndef __TICK_H__
- X#define __TICK_H__
- X
- X#include <dos.h>
- X
- X/* Change the following definitions to increase number of timers and cbrks */
- X#define NTIMERS 2 /* number of timers installable */
- X#define NCBRKS 2 /* number of cbrks installable */
- X
- X#define NULLIVFP (void interrupt (*)())NULL
- X#define NULLVFP (void (*)())NULL
- X#define NULLFP (int (*)())NULL
- X
- X#ifdef HARDTIMER
- X#define TIMER_INT 0x08
- X#else
- X#define TIMER_INT 0x1C
- X#endif
- X
- X/* user callable functions */
- Xint _Cdecl install_timer(void (*func)());
- Xint _Cdecl install_cbrk(void (*func)());
- Xint _Cdecl remove_timer(void (*func)());
- Xint _Cdecl remove_cbrk(void (*func)());
- X
- X#endif __TICK_H__
- ________This_Is_The_END________
- if test `wc -l < TICK.H` -ne 51; then
- echo 'shar: TICK.H was damaged during transit (should have been 51 bytes)'
- fi
- fi ; : end of overwriting check
- exit 0
- ---- cut below this line -----
-
- Amit Joshi BITNET | Q3696@PUCC.BITNET
- USENET | {seismo, rutgers}\!princeton\!phoenix\!asjoshi
- "There's a pleasure in being mad... which none but madmen know!" - St.Dryden
- --
- Amit Joshi BITNET | Q3696@PUCC.BITNET
- USENET | {seismo, rutgers}\!princeton\!phoenix\!asjoshi
- "There's a pleasure in being mad... which none but madmen know!" - St.Dryden
-
-
-