v07i044: CRISP release 1.9 part 23/32
Brandon S. Allbery - comp.sources.misc
allbery at uunet.UU.NET
Sun Jul 23 09:27:29 AEST 1989
Posting-number: Volume 7, Issue 44
Submitted-by: fox at marlow.UUCP (Paul Fox)
Archive-name: crisp1.9/part24
#!/bin/sh
# this is part 3 of a multipart archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file ./anchor.c continued
#
CurArch=3
if test ! -r s2_seq_.tmp
then echo "Please unpack part 1 first!"
exit 1; fi
( read Scheck
if test "$Scheck" != $CurArch
then echo "Please unpack part $Scheck next!"
exit 1;
else exit 0; fi
) < s2_seq_.tmp || exit 1
echo "x - Continuing file ./anchor.c"
sed 's/^X//' << 'SHAR_EOF' >> ./anchor.c
X
Xint start_line, start_col;
Xint end_line, end_col;
Xint mark_type;
X
Xdrop_anchor()
X{
X ANCHOR *ap = (ANCHOR *) chk_alloc(sizeof (ANCHOR));
X int previous_anchor = curbp->b_alist != NULL;
X
X u_raise();
X ap->a_line = *cur_line;
X ap->a_offset = *cur_col;
X ap->a_type = argv[1].l_flags == F_NULL ?
X (u_int16) MK_NORMAL :
X (u_int16) (argv[1].l_int & 0xffff);
X ll_push(curbp->b_alist, (char *) ap);
X curbp->b_anchor = ap;
X win_modify(previous_anchor ? WFHARD : WFMOVE);
X return 0;
X}
Xraise_anchor()
X{
X accumulator = 0;
X if (curbp->b_anchor == NULL)
X return 0;
X u_drop();
X accumulator = 1;
X if (ll_pop(curbp->b_alist))
X curbp->b_anchor = (ANCHOR *) ll_elem(ll_first(curbp->b_alist));
X else
X curbp->b_anchor = NULL;
X win_modify(WFHARD);
X return 0;
X}
Xmark()
X{
X if (curbp->b_anchor)
X raise_anchor();
X else
X drop_anchor();
X return 0;
X}
Xwrite_block()
X{ char *cp;
X FILE *fp;
X char buf[BUFSIZ];
X char *open_mode = argv[2].l_flags == F_NULL ? "w" :
X argv[2].l_int == 0 ? "w" : "a";
X accumulator = 0;
X if (check_mark())
X return;
X
X cp = get_arg1("Write marked area as: ", buf, sizeof buf);
X if (cp == NULL)
X return;
X if ((fp = fopen(cp, open_mode)) == NULL) {
X ewprintf("Write failed.");
X accumulator = -1;
X return;
X }
X copyregion(fp);
X fclose(fp);
X raise_anchor();
X accumulator = 1;
X
X}
Xinq_marked()
X{
X accumulator = 0;
X if (get_marked_areas((WINDOW *) NULL)) {
X accumulator = mark_type;
X if (argv[1].l_flags != F_NULL)
X int_assign(argv[1].l_sym, (long) start_line);
X if (argv[2].l_flags != F_NULL)
X int_assign(argv[2].l_sym, (long) start_col);
X if (argv[3].l_flags != F_NULL)
X int_assign(argv[3].l_sym, (long) end_line);
X if (argv[4].l_flags != F_NULL) {
X if (mark_type == MK_LINE)
X end_col = get_longest_line();
X int_assign(argv[4].l_sym, (long) end_col);
X }
X }
X return 0;
X}
Xget_longest_line()
X{
X int ln = start_line;
X int max_ecol = 0;
X int old_cur_line = *cur_line;
X int col;
X
X while (ln <= end_line) {
X LINE *lp = linep(ln);
X *cur_line = ln++;
X col = current_col(llength(lp));
X if (col > max_ecol)
X max_ecol = col;
X }
X *cur_line = old_cur_line;
X return max_ecol;
X}
Xswap_anchor()
X{
X int col = *cur_col;
X
X if (curbp->b_anchor) {
X *cur_line = curbp->b_anchor->a_line;
X curbp->b_anchor->a_line = *cur_line;
X *cur_col = curbp->b_anchor->a_offset;
X curbp->b_anchor->a_offset = col;
X }
X return 0;
X}
Xget_marked_areas(wp)
XWINDOW *wp;
X{ ANCHOR *ap;
X int tmpl;
X
X if (wp == NULL)
X ap = curbp->b_anchor;
X else
X ap = wp->w_bufp->b_anchor;
X if (ap == NULL) {
X start_line = *cur_line;
X end_line = curbp->b_numlines;
X return FALSE;
X }
X mark_type = ap->a_type;
X start_line = ap->a_line;
X start_col = ap->a_offset;
X end_line = wp ? wp->w_line : *cur_line;
X end_col = wp ? wp->w_col : *cur_col;
X
X if (mark_type == MK_COLUMN) {
X if (start_line > end_line)
X SWAP(start_line, end_line, tmpl);
X if (start_col > end_col)
X SWAP(start_col, end_col, tmpl);
X return TRUE;
X }
X if (start_line > end_line) {
X SWAP(start_line, end_line, tmpl);
X SWAP(start_col, end_col, tmpl);
X }
X if (start_line == end_line && start_col > end_col)
X SWAP(start_col, end_col, tmpl);
X if (mark_type == MK_LINE) {
X end_col = 32767;
X start_col = 1;
X }
X else if (mark_type == MK_NONINC)
X end_col--;
X return TRUE;
X}
SHAR_EOF
echo "File ./anchor.c is complete"
chmod 0444 ./anchor.c || echo "restore of ./anchor.c fails"
mkdir . >/dev/null 2>&1
echo "x - extracting ./basic.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > ./basic.c &&
X/**************************************************************
X *
X * CRISP - Custom Reduced Instruction Set Programmers Editor
X *
X * (C) Paul Fox, 1989
X * 43, Jerome Close Tel: +44 6284 4222
X * Marlow
X * Bucks.
X * England SL7 1TX
X *
X *
X * Please See COPYRIGHT notice.
X *
X **************************************************************/
X#include "list.h"
X
XSCCSID("@(#) basic.c 1.5, (C) P. Fox");
X/*
X * Go to beginning of line.
X */
X/*ARGSUSED*/
Xbeginning_of_line()
X{
X u_dot();
X *cur_col = 1;
X win_modify(WFMOVE);
X return 0;
X}
X
X/*
X * Go to end of line.
X */
Xend_of_line()
X{ register LINE *lp = linep(*cur_line);
X u_dot();
X
X *cur_col = current_col(llength(lp));
X win_modify(WFMOVE);
X return 0;
X}
Xnext_char()
X{ int n = argv[1].l_flags == F_INT ? argv[1].l_int : 1;
X
X if (n < 0) {
X argv[1].l_int = -n;
X prev_char();
X return;
X }
X u_dot();
X win_modify(WFMOVE);
X while (n > 0 && *cur_line != curbp->b_numlines) {
X LINE *lp = linep(*cur_line);
X int offset = current_offset(*cur_col, FALSE);
X
X if (n + offset <= llength(lp)) {
X *cur_col = current_col(offset + n);
X break;
X }
X n -= llength(lp) - offset + 1;
X *cur_col = 1;
X (*cur_line)++;
X }
X win_modify(WFMOVE);
X accumulator = 1;
X return;
X}
Xprev_char()
X{ int offset;
X LINE *lp;
X int n = argv[1].l_flags == F_INT ? argv[1].l_int : 1;
X
X if (n < 0) {
X argv[1].l_int = -n;
X next_char();
X return;
X }
X if (*cur_col == 1 && *cur_line == 1) {
X accumulator = 0;
X return;
X }
X
X offset = current_offset(*cur_col, FALSE);
X u_dot();
X win_modify(WFMOVE);
X while (n > 0) {
X if (offset > n) {
X offset -= n;
X n = 0;
X }
X else if (offset) {
X n -= offset;
X offset = 0;
X }
X else {
X if (*cur_line == 1)
X break;
X (*cur_line)--;
X lp = linep(*cur_line);
X offset = lp->l_used;
X n--;
X }
X }
X accumulator = 1;
X win_modify(WFMOVE);
X *cur_col = current_col(offset);
X return;
X}
X/*
X * Move cursor forwards. Do the
X * right thing if the count is less than
X * 0.
X */
Xforwchar(n)
X{ int col = *cur_col;
X
X u_dot();
X *cur_col += n;
X if (*cur_col < 1)
X *cur_col = 1;
X if (col != *cur_col) {
X accumulator = 1;
X win_modify(WFMOVE);
X }
X else
X accumulator = 0;
X return 0;
X}
X/*
X * Move cursor backwards. Do the
X * right thing if the count is less than
X * 0. Error if you try to move back from
X * the beginning of the buffer.
X */
Xbackchar(n)
X{
X u_dot();
X win_modify(WFMOVE);
X if (*cur_col == 1 && *cur_line > 1) {
X (*cur_line)--;
X return end_of_line();
X }
X return forwchar(-n);
X}
X
X
X/*
X * Go to the beginning of the
X * buffer.
X */
Xgotobob()
X{
X u_dot();
X win_modify(WFMOVE);
X *cur_col = *cur_line = 1;
X win_modify(WFMOVE);
X return 0;
X}
X
X/*
X * Go to the end of the buffer.
X */
Xgotoeob()
X{ int n;
X
X u_dot();
X win_modify(WFMOVE);
X *cur_line = curbp->b_numlines;
X if (*cur_line > 1)
X (*cur_line)--;
X n = end_of_line();
X if (hooked)
X set_buffer_bottom(curwp);
X return n;
X}
X
X/*
X * Move forward by full lines.
X * If the number of lines to move is less
X * than zero, call the backward line function to
X * actually do it. The last command controls how
X * the goal column is set.
X */
Xforwline(n)
X{
X int old_line = *cur_line;
X
X u_dot();
X win_modify(WFMOVE);
X if (n < 0 && *cur_line + n < 1)
X *cur_line = 1;
X else if (*cur_line + n > numlines())
X *cur_line = numlines();
X else
X *cur_line += n;
X accumulator = *cur_line != old_line;
X win_modify(WFMOVE);
X return 0;
X}
X
Xbackline(n)
X{
X return forwline(-n);
X}
Xnumlines()
X{
X return curbp->b_numlines;
X}
Xpage_down()
X{
X forwline(curwp->w_h);
X return 0;
X}
X
Xpage_up()
X{
X backline(curwp->w_h);
X return 0;
X}
Xgotoline(n)
X{
X
X u_dot();
X win_modify(WFMOVE);
X
X *cur_col = 1;
X *cur_line = 1;
X return forwline(n - 1);
X}
Xdist_to_tab()
X{
X accumulator = next_tab_stop(*cur_col) - *cur_col + 1;
X/* assert(accumulator >= 0);*/
X return 0;
X}
SHAR_EOF
chmod 0444 ./basic.c || echo "restore of ./basic.c fails"
mkdir . >/dev/null 2>&1
echo "x - extracting ./bookmark.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > ./bookmark.c &&
X/**************************************************************
X *
X * CRISP - Custom Reduced Instruction Set Programmers Editor
X *
X * (C) Paul Fox, 1989
X * 43, Jerome Close Tel: +44 6284 4222
X * Marlow
X * Bucks.
X * England SL7 1TX
X *
X *
X * Please See COPYRIGHT notice.
X *
X **************************************************************/
X# include "list.h"
X
XSCCSID("@(#) bookmark.c 1.2, (C) P. Fox");
X# define MAX_BOOKMARKS 10
X
Xstruct bookmark {
X u_int16 b_buffer;
X int b_line;
X int b_col;
X int b_ref;
X } bookmarks[MAX_BOOKMARKS];
X
Xdrop_bookmark()
X{ struct bookmark *bk;
X
X if (argv[1].l_int == 0)
X argv[1].l_int = 10;
X if (argv[1].l_int < 1 || argv[1].l_int > MAX_BOOKMARKS) {
X ewprintf("drop_bookmark: invalid bookmark.");
X return 0;
X }
X
X bk = &bookmarks[argv[1].l_int - 1];
X if (argv[3].l_flags == F_INT && argv[4].l_flags == F_INT &&
X argv[5].l_flags == F_INT) {
X bk->b_buffer = argv[3].l_int;
X bk->b_line = argv[4].l_int;
X bk->b_col = argv[5].l_int;
X }
X else {
X bk->b_buffer = curbp->b_bufnum;
X bk->b_line = *cur_line;
X bk->b_col = *cur_col;
X }
X bk->b_ref = TRUE;
X infof("Bookmark dropped.");
X return 0;
X}
Xgoto_bookmark()
X{
X struct bookmark *bk;
X int move = TRUE;
X long book_no;
X
X accumulator = 0;
X if (get_iarg1("Go to bookmark [1-10]: ", &book_no))
X return 0;
X
X if (book_no == 0)
X book_no = 10;
X if (book_no < 1 || book_no > MAX_BOOKMARKS) {
X ewprintf("goto_bookmark: invalid bookmark.");
X return 0;
X }
X
X bk = &bookmarks[book_no - 1];
X if (bk->b_ref == FALSE)
X return 0;
X if (argv[2].l_flags != F_NULL) {
X move = FALSE;
X int_assign(argv[2].l_sym, (long) bk->b_buffer);
X }
X if (argv[3].l_flags != F_NULL) {
X move = FALSE;
X int_assign(argv[3].l_sym, (long) bk->b_line);
X }
X if (argv[4].l_flags != F_NULL) {
X move = FALSE;
X int_assign(argv[4].l_sym, (long) bk->b_col);
X }
X
X if (move) {
X WINDOW *wp;
X for (wp = wheadp; wp; wp->w_wndp)
X if (wp->w_bufp->b_bufnum == bk->b_buffer)
X break;
X if (wp == NULL) {
X BUFFER *bp = numberb(bk->b_buffer);
X if (bp == NULL) {
X ewprintf("goto_bookmark: no such buffer.");
X return 0;
X }
X showbuffer(bp, curwp);
X curbp = bp;
X }
X else {
X curwp = wp;
X curbp = curwp->w_bufp;
X }
X argv[1].l_int = bk->b_line;
X argv[2].l_int = bk->b_col;
X move_abs();
X }
X accumulator = 1;
X return 0;
X}
SHAR_EOF
chmod 0444 ./bookmark.c || echo "restore of ./bookmark.c fails"
mkdir . >/dev/null 2>&1
echo "x - extracting ./buffer.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > ./buffer.c &&
X/**************************************************************
X *
X * CRISP - Custom Reduced Instruction Set Programmers Editor
X *
X * (C) Paul Fox, 1989
X * 43, Jerome Close Tel: +44 6284 4222
X * Marlow
X * Bucks.
X * England SL7 1TX
X *
X *
X * Please See COPYRIGHT notice.
X *
X **************************************************************/
X#include "list.h"
X
XSCCSID("@(#) buffer.c 1.14, (C) P. Fox");
X
XBUFFER *
Xnumberb(n)
Xu_int16 n;
X{
X register BUFFER *bp;
X
X for (bp = bheadp; bp; bp = bp->b_bufp)
X if (bp->b_bufnum == n)
X return bp;
X return (BUFFER *) NULL;
X}
X/*
X * Dispose of a buffer, by name.
X */
Xkillbuffer(n)
Xu_int16 n;
X{
X register BUFFER *bp;
X register BUFFER *bp1;
X register WINDOW *wp;
X extern BUFFER *numberb();
X
X if ((bp = numberb(n)) == NULL)
X return FALSE;
X
X if (bclear(bp) != TRUE)
X return TRUE;
X p_cleanup(bp);
X if (bp->b_nwnd != 0) {
X for (wp = wheadp; wp && bp->b_nwnd; wp = wp->w_wndp) {
X if (wp->w_bufp == bp) {
X --bp->b_nwnd;
X wp->w_bufp = NULL;
X }
X }
X }
X if (bp->b_title)
X chk_free(bp->b_title);
X ll_clear(bp->b_register);
X ll_free(bp->b_register);
X ll_free(bp->b_alist);
X delete_buffer_symbols(bp);
X free_line(bp->b_linep);
X if (bheadp == bp)
X bheadp = bp->b_bufp;
X else {
X for (bp1 = bheadp; bp1 && bp1->b_bufp != bp; )
X bp1 = bp1->b_bufp;
X if (bp1)
X bp1->b_bufp = bp->b_bufp;
X }
X
X chk_free((char *) bp);
X if (curbp == bp)
X curbp = NULL;
X return (TRUE);
X}
X
X
X
X/*
X * Look through the list of buffers, giving the user
X * a chance to save them. Return TRUE if there are
X * any changed buffers afterwards. Buffers that don't
X * have an associated file don't count. Return FALSE
X * if there are no changed buffers.
X */
Xanycb()
X{
X register BUFFER *bp;
X int nbuf = 0;
X char buf[80];
X char reply[4];
X extern BUFFER *scrap_bp;
X
X for (bp = bheadp; bp != NULL; bp = bp->b_bufp)
X if (*bp->b_fname && bp->b_nummod && bp->b_system == 0 && bp != scrap_bp)
X nbuf++;
X
X if (nbuf == 0)
X return FALSE;
X (void) sprintf(buf, "%d buffer%s not been saved. Exit [ynw]? ",
X nbuf, nbuf == 1 ? " has" : "s have");
X
X reply[0] = NULL;
X ereply(buf, reply, 1);
X if (reply[0] == 'Y' || reply[0] == 'y')
X return FALSE;
X if (reply[0] != 'W' && reply[0] != 'w')
X return TRUE;
X
X for (bp = bheadp; bp != NULL; bp = bp->b_bufp)
X if (*bp->b_fname && bp->b_nummod && bp->b_system == 0 && bp != scrap_bp)
X writeout(bp, bp->b_fname, TRUE, FALSE);
X return FALSE;
X}
Xchar *
Xfilename(fn)
Xchar *fn;
X{ static char buf[NFILEN];
X register char *cp;
X extern char *get_cwd();
X extern char *sys_delim();
X
X for (cp = fn; *cp; )
X if (*cp == '/' && cp[1] == '/')
X strcpy(cp, cp+1);
X else
X cp++;
X# if defined(VMS)
X {char buf1[256];
X if (strchr(fn, '/') != NULL)
X fn = sys_fname_unix_to_vms(fn, buf1, sizeof buf1);
X if (strchr(fn, ':') != NULL)
X return fn;
X }
X# endif
X if (fn[0] == '/')
X return fn;
X cp = get_cwd();
X if (cp[0] == '/' && cp[1] == NULL)
X sprintf(buf, "/%s", fn);
X else
X sprintf(buf, "%s%s%s", cp, sys_delim(), fn);
X# if defined(VMS)
X {char *vms_filename_canon();
X return vms_filename_canon(buf);
X }
X# else
X /*-----------------------------------------
X * Map dir/./file to dir/file, and
X * dir1/dir2/../file to dir1/file.
X *-----------------------------------------*/
Xagain:
X for (cp = buf; *cp; cp++) {
X if (*cp == '/' && cp[1] == '.' && cp[2] == '/') {
X strcpy(cp, cp+2);
X goto again;
X }
X if (*cp == '/' && cp[1] == '.' && cp[2] == '.' && cp[3] == '/') {
X char *cp1;
X if (cp == buf) {
X strcpy(buf, cp+3);
X goto again;
X }
X for (cp1 = cp - 1; cp1 >= buf; cp1--)
X if (*cp1 == '/')
X break;
X strcpy(cp1, cp+3);
X goto again;
X }
X }
X return buf;
X# endif
X}
Xinq_file_buffer()
X{ BUFFER *bp = bfind(get_str(1), FALSE);
X
X if (bp == NULL)
X accumulator = 0;
X else
X accumulator = bp->b_bufnum;
X}
X/*
X * Search for a buffer, by name.
X * If not found, and the "cflag" is TRUE,
X * create a buffer and put it in the list of
X * all buffers. Return pointer to the BUFFER
X * block for the buffer.
X */
XBUFFER *
Xbfind(buffer_name, cflag)
Xregister char *buffer_name;
X{
X register BUFFER *bp;
X register LINE *lp;
X register BUFFER *bp1;
X u_int16 i;
X static u_int16 buffer_number = 0;
X static BUFFER null_buffer = {0};
X
X for (bp = bheadp; bp; bp = bp->b_bufp)
X if (strcmp(buffer_name, bp->b_fname) == 0)
X return bp;
X
X if (!cflag)
X return NULL;
X /*NOSTRICT*/
X if ((bp= (BUFFER *) chk_alloc(sizeof(BUFFER))) == NULL) {
X ewprintf("Can't get %d bytes", sizeof(BUFFER));
X return NULL;
X }
X if ((lp=lalloc((RSIZE) 0)) == NULL) {
X chk_free((char *) bp);
X return NULL;
X }
X *bp = null_buffer;
X strcpy(bp->b_fname, filename(buffer_name));
X bp->b_alist = ll_init();
X bp->b_syms = spinit();
X bp->b_register = ll_init();
X# ifdef S_IRUSR
X bp->b_mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
X# else
X bp->b_mode = 0644;
X# endif
X bp->b_bufnum = ++buffer_number;
X bp->b_linep = lp;
X bp->b_numlines = bp->b_line = bp->b_col = 1;
X for (i = 0; i < NTABS; i++)
X bp->b_tabs[i] = i*8;
X lp->l_fp = lp;
X lp->l_bp = lp;
X
X if (bheadp == NULL)
X bheadp = bp;
X else {
X for (bp1 = bheadp; bp1->b_bufp; )
X bp1 = bp1->b_bufp;
X bp1->b_bufp = bp;
X }
X
X return (bp);
X}
X
Xbclear(bp)
Xregister BUFFER *bp;
X{
X bp->b_flag &= ~(BFCHG|BFRO);
X while (bp->b_numlines > 1)
X lfree(bp, 1);
X
X bp->b_line = bp->b_col = 1;
X
X while (ll_pop(bp->b_alist))
X ;
X return TRUE;
X}
X
X/*
X * Display the given buffer in the given window.
X */
Xshowbuffer(bp, wp)
Xregister BUFFER *bp;
Xregister WINDOW *wp;
X{
X register WINDOW *owp;
X
X if (wp->w_bufp == bp) { /* Easy case! */
X wp->w_flag |= WFHARD;
X return;
X }
X
X detach_buffer(wp);
X wp->w_bufp = bp;
X wp->w_old_line = 1;
X
X w_title(wp, bname(bp->b_fname), "");
X
X if (bp->b_nwnd++ == 0) { /* First use. */
X set_window_parms(wp, bp);
X return;
X }
X
X wp->w_flag |= WFHARD;
X /* already on screen, steal values from other window */
X for (owp = wheadp; owp; owp = owp->w_wndp)
X if (owp->w_bufp == bp && owp != wp) {
X wp->w_top_line = owp->w_top_line; /* PDF */
X wp->w_line = owp->w_line;
X wp->w_col = owp->w_col;
X wp->w_old_line = owp->w_old_line;
X break;
X }
X}
Xset_window_parms(wp, bp)
Xregister WINDOW *wp;
Xregister BUFFER *bp;
X{
X wp->w_flag |= WFHARD;
X wp->w_top_line = bp->b_top;
X wp->w_line = bp->b_line;
X wp->w_col = bp->b_col;
X if (wp->w_line - wp->w_top_line >= wp->w_h)
X wp->w_top_line = wp->w_line;
X}
Xset_buffer_parms(wp, bp)
Xregister WINDOW *wp;
Xregister BUFFER *bp;
X{
X bp->b_line = wp->w_line;
X bp->b_col = wp->w_col;
X bp->b_top = wp->w_top_line;
X}
Xinq_buffer_flags()
X{
X BUFFER *bp = argv[1].l_flags == F_INT ?
X numberb(argv[1].l_int) : curbp;
X
X if (bp == NULL)
X accumulator = -1;
X else {
X accumulator = bp->b_flag & 0xff;
X if (bp->b_display)
X accumulator |= BFPROC;
X accumulator &= ~BFCHG;
X if (curbp->b_nummod)
X accumulator |= BFCHG;
X }
X}
SHAR_EOF
chmod 0444 ./buffer.c || echo "restore of ./buffer.c fails"
mkdir . >/dev/null 2>&1
echo "x - extracting ./builtin.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > ./builtin.c &&
X/**************************************************************
X *
X * CRISP - Custom Reduced Instruction Set Programmers Editor
X *
X * (C) Paul Fox, 1989
X * 43, Jerome Close Tel: +44 6284 4222
X * Marlow
X * Bucks.
X * England SL7 1TX
X *
X *
X * Please See COPYRIGHT notice.
X *
X **************************************************************/
X# include "list.h"
XSCCSID("@(#) builtin.c 1.8, (C) P. Fox");
X
X# define ERROR -1
X# define EXECUTE -2
Xint action;
X
Xstatic LIST f_halt = F_HALT;
XLISTV *argv;
Xint argc;
Xint hooked;
Xint *cur_line;
Xint *cur_col;
Xextern int break_flag;
Xchar *command_name; /* Name of macro primitive currently being */
X /* executed. */
Xint autoloading = FALSE; /* TRUE if autoloading a macro - avoids the */
X /* 'macro successfully loaded' message */
X /* being printed. */
Xint doing_return = FALSE; /* Set to TRUE when a 'return' is executed.*/
X
Xvoid set_hooked();
Xextern int ctrl_c;
X
Xvoid
Xeval_expr(lp)
XLISTV *lp;
X{
X if (lp->l_flags == F_INT)
X accumulator = lp->l_int;
X else if (lp->l_flags == F_LIST)
X (void) execute_macro(lp->l_list);
X else
X ewprintf("Internal evaluation error");
X}
Xstr_exec(str)
Xchar *str;
X{
X register char *cp = str;
X char buf[256];
X char *dp = buf;
X extern char *strtok();
X int i;
X# define LIST_BUF_SIZE 128
X LIST lp[LIST_BUF_SIZE];
X LIST *lp1;
X
X while (isspace(*cp))
X cp++;
X lp[0] = F_STR;
X LPUT32(lp, (long) dp);
X lp1 = lp + 5;
X while (*cp && !isspace(*cp))
X *dp++ = *cp++;
X *dp++ = NULL;
X while (*cp) {
X while (isspace(*cp))
X cp++;
X if (*cp == NULL)
X break;
X if (lp1 >= &lp[LIST_BUF_SIZE-10]) {
X ewprintf("Out of space in str_exec");
X return 0;
X }
X if (*cp == '-' || (*cp >= '0' && *cp <= '9')) {
X *lp1 = F_INT;
X LPUT32(lp1, (long) atoi(cp));
X while (*cp && *cp != ' ' && *cp != '\t')
X cp++;
X }
X else {
X register char *cp1;
X char ch_term = ' ';
X
X if (*cp == '"')
X ch_term = '"', cp++;
X cp1 = cp;
X
X while (*cp) {
X if (*cp == '\\')
X cp++;
X else if (*cp == ch_term)
X break;
X cp++;
X }
X
X *lp1 = F_LIT;
X LPUT32(lp1, (long) dp);
X for (cp = cp1; *cp && *cp != ch_term; ) {
X/* if (*cp == '\\')
X ++cp;*/
X *dp++ = *cp++;
X }
X
X *dp++ = NULL;
X if (*cp)
X cp++;
X }
X lp1 += 5;
X }
X *lp1 = F_HALT;
X i = nexecute_macro(lp);
X return i;
X}
Xnexecute_macro(lp)
XLIST *lp;
X{
X if (++nest_level >= MAX_NESTING)
X panic("Macro nesting overflow.");
X execute_macro(lp);
X delete_local_symbols();
X}
Xexecute_macro(lp)
Xregister LIST *lp;
X{ static int handling_ctrlc = FALSE;
X u_int16 i;
X
X while (*lp == F_LIST) {
X if (ctrl_c && !handling_ctrlc) {
X handling_ctrlc = TRUE;
X trigger(REG_CTRLC);
X ctrl_c = FALSE;
X handling_ctrlc = FALSE;
X }
X execute_macro(lp + sizeof_atoms[*lp]);
X if (break_flag || doing_return)
X return;
X if ((i = LGET16(lp)) == 0)
X return;
X lp += i;
X }
X if (*lp == F_HALT)
X return;
X trace_list(lp);
X exec1(lp, lp + sizeof_atoms[*lp]);
X}
Xexec1(lp_0, lp_argv)
Xregister LIST *lp_0;
XLIST *lp_argv;
X{
X register BUILTIN *bp;
X char *macro_name;
X register MACRO *mptr;
X int saved_msg_level;
X int loop_count;
X MACRO *saved_macro;
X int opc = *lp_0;
X
X if (opc == F_ID)
X bp = &builtin[LGET16(lp_0)];
X else if (opc == F_INT) {
X acc_type = F_INT;
X accumulator = LGET32(lp_0);
X return;
X }
X else if (opc == F_LIT) {
X strl_acc_assign((char *) LGET32(lp_0));
X return;
X }
X else {
X char *str = opc == F_RSTR ? ((r_str *) LGET32(lp_0))->r_str
X : (char *) LGET32(lp_0);
X bp = lookup_builtin(str);
X }
X
X
X if (bp) {
X if (bp->flags & B_REDEFINE) {
X if (bp->macro == NULL) {
X bp->macro = bp->first_macro;
X goto hell;
X }
X if (bp->macro == bp->first_macro)
X bp->argv = lp_argv;
X mptr = saved_macro = bp->macro;
X bp->macro = bp->macro->m_next;
X macro_name = bp->name;
X goto exec_macro;
X }
X else {
Xhell: if (bp->func == NULL) {
X trace_log("*** Not yet implemented - %s ***\n",
X bp->name);
X return;
X }
X eval_args(bp, lp_argv);
X bp->argv = &f_halt;
X return;
X }
X }
X /*-------------------------------------------------*/
X /* Lookup-defined macros. */
X /*-------------------------------------------------*/
X macro_name = opc == F_ID ? builtin[LGET16(lp_0)].name :
X (char *) LGET32(lp_0);
X for (loop_count = 0; loop_count < 2; loop_count++) {
X if (bp)
X mptr = saved_macro;
X else
X mptr = lookup_macro(macro_name);
X if (mptr)
X break;
X if (ld_macro(macro_name)) {
X extern int m_flag;
Xundefined_macro:
X if (m_flag == FALSE)
X errorf("%s undefined.", macro_name);
X return;
X }
X }
X if (mptr == NULL)
X goto undefined_macro;
X /*-------------------------------------------------*/
X /* Check to see whether we need to autoload the */
X /* macro. */
X /*-------------------------------------------------*/
Xexec_macro:
X if (mptr->m_flags & M_AUTOLOAD) {
X int saved_auto = autoloading;
X autoloading = TRUE;
X if (ld_macro((char *) mptr->m_list)) {
X autoloading = saved_auto;
X return;
X }
X autoloading = saved_auto;
X mptr = lookup_macro(macro_name);
X if (mptr->m_flags & M_AUTOLOAD)
X return;
X }
X lp_0 = mptr->m_list;
X if (*lp_0 == F_HALT)
X return;
X mac_stack[ms_cnt].name = macro_name;
X mac_stack[ms_cnt].argv = lp_argv;
X if (ms_cnt++ == 0) {
X saved_msg_level = msg_level;
X msg_level = 1;
X }
X trace_log("Execute macro: %s\n", macro_name);
X nexecute_macro(lp_0);
X if (bp)
X bp->macro = saved_macro;
X mptr->m_ftime = FALSE;
X if (--ms_cnt == 0)
X msg_level = saved_msg_level;
X}
X
Xstruct saved {
X OPCODE save_type;
X char *save_str;
X };
Xeval_args(bp, lp)
Xregister BUILTIN *bp;
Xregister LIST *lp;
X{
X extern LIST *copy_list();
X LISTV local_argv[MAX_ARGC];
X register LISTV *lap = &local_argv[1];
X register char *as = bp->args;
X int optional;
X LIST *bpargv = bp->argv;
X LIST *optarg = &f_halt;
X LIST *argp;
X register int largc = 1;
X struct saved saved_str[MAX_ARGC];
X int ss_cnt = 0;
X register int i;
X r_str *rp;
X
X
X if (*lp == F_HALT) {
X lp = bpargv;
X bpargv = &f_halt;
X }
X# define RS(x) ((r_str *) (x))
X while (*as && lp && *lp != F_HALT) {
X int type;
X char *str;
X
X str = *lp == F_STR ? (char *) LGET32(lp) : "";
X rp = RS(str);
X if (optional = *as == '*')
X as++;
X if (*bpargv != F_HALT) {
X optarg = bpargv;
X if (*bpargv == F_LIST)
X bpargv += LGET16(lp);
X else
X bpargv += sizeof_atoms[*bpargv];
X }
X argp = lp;
X ++largc;
X if (*as != 'R' && str[0] == 'N' && strcmp(str, "NULL") == 0) {
X if (optarg[0] != F_HALT) {
X argp = optarg;
X rp = RS(LGET32(lp));
X str = *argp == F_STR ? rp->r_str : "";
X type = eval_expr2(*as, argp, lap, str);
X }
X else {
X if (!optional)
X return arg_error(bp, TRUE, saved_str, ss_cnt, lap - local_argv);
X lap->l_int = 0;
X lap->l_flags = F_NULL;
X type = F_HALT;
X }
X }
X else
X type = eval_expr2(*as, argp, lap, str);
X as++;
X switch (type) {
X case F_INT:
X lap->l_flags = F_INT;
X lap->l_int = accumulator;
X break;
X case EXECUTE:
X goto execute;
X case F_HALT:
X break;
X case F_LIT:
X break;
X case F_STR:
X saved_str[ss_cnt].save_str = lap->l_str = strdup(lap->l_str);
X saved_str[ss_cnt++].save_type = F_STR;
X break;
X case F_RSTR:
X saved_str[ss_cnt].save_str = (char *)
X (lap->l_rstr = r_inc(lap->l_rstr));
X saved_str[ss_cnt++].save_type = F_RSTR;
X lap->l_flags = F_RSTR;
X break;
X case F_LIST:
X i = length_of_list(lap->l_list);
X if (i) {
X saved_str[ss_cnt].save_str = chk_alloc(i);
X memcpy(saved_str[ss_cnt].save_str, lap->l_list, i);
X lap->l_list = (LIST *) saved_str[ss_cnt].save_str;
X saved_str[ss_cnt++].save_type = F_LIST;
X }
X break;
X case ERROR:
X return arg_error(bp, TRUE, saved_str, ss_cnt, lap - local_argv);
X default:
X ewprintf("%s: default case", bp->name);
X panic("default case");
X }
X lap++;
X if ((i = *lp) == F_LIST) {
X u_int16 i = LGET16(lp);
X if (i == 0)
X goto check_rest_of_arguments;
X lp += i;
X }
X else if (i == F_HALT)
X lp = bpargv;
X else
X lp += sizeof_atoms[i];
X }
X
X if (lp && *lp != F_HALT) {
X ewprintf("%s: Too many arguments", bp->name);
X return arg_error(bp, FALSE, saved_str, ss_cnt);
X }
Xcheck_rest_of_arguments:
X while (*as) {
X if (*as != '*')
X return arg_error(bp, TRUE, saved_str, ss_cnt, lap - local_argv);
X as += 2;
X lap->l_flags = F_NULL;
X lap->l_int = 0;
X lap++;
X }
X
Xexecute:
X acc_type = F_INT;
X argv = local_argv;
X argc = largc;
X command_name = bp->name;
X set_hooked();
X (*bp->func)(bp->arg);
X# ifndef PRODUCTION
X if ((bp->flags & B_NOVALUE) == 0)
X trace_acc();
X bp->reference++;
X# endif
X return free_saved(saved_str, ss_cnt);
X}
Xfree_saved(saved_str, ss_cnt)
Xregister struct saved *saved_str;
Xregister int ss_cnt;
X{
X while (ss_cnt > 0) {
X switch (saved_str[--ss_cnt].save_type) {
X case F_LIST:
X case F_STR:
X chk_free(saved_str[ss_cnt].save_str);
X break;
X case F_RSTR:
X r_dec((r_str *) saved_str[ss_cnt].save_str);
X break;
X }
X }
X}
Xchar state_tbl[][9] = {
X/* F_INT, F_STR, F_LIST, NULL, F_ID, F_END, POLY, F_LIT, F_RSTR */
X/*a*/ { -1, F_STR, F_LIST, -1, F_ID, -1, -1, F_LIT, F_RSTR},
X/*b*/ {F_INT, F_STR, -1, -1, F_ID, -1, -1, F_LIT, F_RSTR},
X/*c*/ { -1, -1, -1, -1, -1, -1, -1, -1, -1},
X/*d*/ { -1, -1, -1, -1, -1, -1, -1, -1, -1},
X/*e*/ { -1, -1, -1, -1, -1, -1, -1, -1, -1},
X/*f*/ { -1, -1, -1, -1, -1, -1, -1, -1, -1},
X/*g*/ { -1, -1, -1, -1, -1, -1, -1, -1, -1},
X/*h*/ { -1, -1, -1, -1, -1, -1, -1, -1, -1},
X/*i*/ {F_INT, -1, -1, -1, -1, -1, -1, -1, -1},
X/*j*/ { -1, -1, -1, -1, -1, -1, -1, -1, -1},
X/*k*/ { -1, -1, -1, -1, -1, -1, -1, -1, -1},
X/*l*/ { -1, -1, F_LIST, -1, -1, -1, -1, -1, -1},
X/*m*/ { -1, -1, -1, -1, -1, -1, -1, -1, -1},
X/*n*/ { -1, -1, -1, -1, -1, -1, -1, -1, -1},
X/*o*/ { -1, -1, -1, -1, -1, -1, -1, -1, -1},
X/*p*/ { -1, -1, -1, -1, -1, -1, -1, -1, -1},
X/*q*/ { -1, -1, -1, -1, -1, -1, -1, -1, -1},
X/*r*/ { -1, -1, -1, -1, -1, -1, -1, -1, -1},
X/*s*/ { -1, F_STR, -1, -1, F_ID, -1, -1, F_LIT, F_RSTR},
X/*t*/ {F_INT, F_STR, F_LIST, -1, F_ID, -1, -1, F_LIT, F_RSTR},
X };
Xeval_expr2(ch, argp, lap, str)
XLIST *argp;
Xregister LISTV *lap;
Xchar *str;
X{ SYMBOL *sp;
X int type;
X
X if (isupper(ch)) {
X if (ch == 'R') {
X lap->l_list = argp;
X lap->l_flags = F_LIST;
X return EXECUTE;
X }
X if (ch == 'C') {
X lap->l_list = argp;
X lap->l_flags = F_LIST;
X return F_HALT;
X }
X if (!(*argp == F_STR || *argp == F_ID) ||
X (sp = lookup(str)) == NULL)
X return -1;
X lap->l_sym = sp;
X switch (ch) {
X case 'S':
X if (sp->s_type == F_STR) {
X lap->l_flags = F_STR;
X return F_HALT;
X }
X return ERROR;
X case 'I':
X if (sp->s_type == F_INT) {
X lap->l_flags = F_INT;
X return F_HALT;
X }
X return ERROR;
X case 'L':
X if (sp->s_type == F_LIST) {
X lap->l_flags = F_LIST;
X return F_HALT;
X }
X return ERROR;
X case 'T':
X if (sp->s_type == F_LIST) {
X lap->l_flags = F_LIST;
X return F_HALT;
X }
X case 'B':
X if (sp->s_type == F_INT || sp->s_type == F_STR) {
X lap->l_flags = sp->s_type;
X return F_HALT;
X }
X return ERROR;
X }
X }
X if (ch == 'm') {
X if (*argp == F_STR) {
X lap->l_flags = F_STR;
X lap->l_str = str;
X return F_LIT;
X }
X if (*argp == F_ID) {
X eval(argp, lap);
X return F_STR;
X }
X return ERROR;
X }
X type = eval(argp, lap);
X ch -= 'a';
X if (ch < 0 || ch >= sizeof state_tbl / sizeof state_tbl[0]) {
X ewprintf("Unknown case string for '%c'", ch + 'a');
X panic("");
X }
X return state_tbl[ch][type - F_INT];
X}
Xarg_error(bp, msg, saved_str, cnt, arg)
Xchar *saved_str[MAX_ARGC];
XBUILTIN *bp;
X{
X if (msg)
X errorf("%s: parameter %d invalid", bp->name, arg);
X free_saved(saved_str, cnt);
X acc_type = F_INT;
X return -1;
X}
Xvoid
Xset_hooked()
X{
X
X if (hooked = curwp->w_bufp == curbp) {
X cur_line = &curwp->w_line;
X cur_col = &curwp->w_col;
X }
X else {
X cur_line = &curbp->b_line;
X cur_col = &curbp->b_col;
X }
X}
Xget_iarg1(str, l)
Xchar *str;
Xlong *l;
X{
X char buf[80];
X
X if (argv[1].l_flags == F_INT) {
X *l = argv[1].l_int;
X return 0;
X }
X if (ereply(str, buf, sizeof buf - 1) != TRUE)
X return -1;
X (void) sscanf(buf, "%ld", l);
X return 0;
X}
Xchar *
Xget_arg1(str, buf, bufsiz)
Xchar *str;
Xchar *buf;
X{ register char *cp;
X
X if (argv[1].l_flags == F_STR)
X return argv[1].l_str;
X if (argv[1].l_flags == F_RSTR)
X return argv[1].l_rstr->r_str;
X
X if (ereply(str, buf, bufsiz - 1) != TRUE || buf[0] == NULL)
X return (char *) NULL;
X for (cp = buf; *cp; cp++)
X if (*cp != ' ')
X break;
X return *cp == NULL ? (char *) NULL : buf;
X}
SHAR_EOF
chmod 0444 ./builtin.c || echo "restore of ./builtin.c fails"
mkdir . >/dev/null 2>&1
echo "x - extracting ./clock.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > ./clock.c &&
X/**************************************************************
X *
X * CRISP - Custom Reduced Instruction Set Programmers Editor
X *
X * (C) Paul Fox, 1989
X * 43, Jerome Close Tel: +44 6284 4222
X * Marlow
X * Bucks.
X * England SL7 1TX
X *
X *
X * Please See COPYRIGHT notice.
X *
X **************************************************************/
X# include "list.h"
X# include "clk.h"
X# include <signal.h>
XSCCSID("@(#) clock.c 1.7, (C) 1989, P. Fox");
X
X# define MAX_TIMEOUTS 10
X
Xstruct callout {
X int (*func)();
X int arg;
X long id;
X long timeout;
X };
X
X/*# define ALARM(x) (trace_log("alarm(%d)\n", x), alarm(x))*/
X# define ALARM(x) alarm(x)
Xstruct callout callo[MAX_TIMEOUTS];
Xint ntmo = 0;
Xstatic long clk_id = 0;
Xint clock_ticked = FALSE;
Xint clock_handler();
X
Xclk_timeout(func, arg, timeout)
Xint (*func)();
Xlong timeout;
X{ register struct callout *cp = callo;
X register int i, j;
X
X clk_remove(func);
X if (ntmo && clock_ticked == FALSE) {
X int secs = ALARM(0);
X callo[0].timeout = secs;
X }
X
X timeout /= 1 SECOND;
X if (ntmo == 0)
X goto end_of_function;
X
X if (ntmo >= MAX_TIMEOUTS-1)
X return 0;
X for (i = 0; i < ntmo; i++, cp++) {
X if (cp->timeout > timeout) {
X for (j = ntmo; j > i; j--)
X callo[j] = callo[j-1];
X cp[1].timeout -= timeout;
X goto end_of_function;
X }
X timeout -= cp->timeout;
X }
Xend_of_function:
X cp->func = func;
X cp->arg = arg;
X cp->id = ++clk_id;
X cp->timeout = timeout;
X ntmo++;
X if (clock_ticked == FALSE) {
X if (callo[0].timeout == 0)
X clock_handler();
X else {
X signal(SIGALRM, clock_handler);
X ALARM(callo[0].timeout);
X }
X }
X return clk_id;
X}
Xclk_remove(func)
Xint (*func)();
X{ register struct callout *cp;
X register struct callout *cend = &callo[ntmo];
X
X for (cp = callo; cp < cend; cp++)
X if (cp->func == func) {
X cp[1].timeout += cp->timeout;
X for (; cp < cend; cp++)
X *cp = cp[1];
X ntmo--;
X break;
X }
X}
Xclock_check()
X{ int i;
X int (*func)();
X int arg;
X int clock_handler();
X
X if (clock_ticked == FALSE)
X return 1;
X callo[0].timeout = 0;
X while (ntmo && callo[0].timeout == 0) {
X func = callo[0].func;
X arg = callo[0].arg;
X for (i = 0; i < MAX_TIMEOUTS; i++)
X callo[i] = callo[i+1];
X ntmo--;
X if (func)
X (*func)(arg);
X }
X signal(SIGALRM, clock_handler);
X clock_ticked = FALSE;
X if (ntmo)
X ALARM(callo[0].timeout);
X return 1;
X}
Xclock_handler()
X{
X signal(SIGALRM, SIG_IGN);
X# if defined(VMS)
X sys_cancel_io();
X# endif
X clock_ticked = TRUE;
X}
Xdump_callo()
X{
X int i;
X trace_log("CALLOUTS = %d\n", ntmo);
X for (i = 0; i < ntmo; i++) {
X trace_log("%d: func=", i);
X trace_log("%08lx ", callo[i].func);
X trace_log("tmo=%ld.\n", callo[i].timeout);
X }
X}
SHAR_EOF
chmod 0444 ./clock.c || echo "restore of ./clock.c fails"
mkdir . >/dev/null 2>&1
echo "x - extracting ./cm.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > ./cm.c &&
X/**************************************************************
X *
X * CRISP - Custom Reduced Instruction Set Programmers Editor
X *
X * (C) Paul Fox, 1989
X * 43, Jerome Close Tel: +44 6284 4222
X * Marlow
X * Bucks.
X * England SL7 1TX
X *
X *
X * Please See COPYRIGHT notice.
X *
X **************************************************************/
X# define _DECLS
X# include "list.h"
X# include "cm.h"
XSCCSID("@(#) cm.c 1.12, (C) 1989 P. Fox");
X
X# define MAX_ATOMS 32000 /* Max. number of atoms in a macro */
X /* definition. */
X# define MAX_STRINGS 2048 /* Max. strings in macro file. */
X# define MAX_GLOBALS 256 /* Max. no. of global statements */
X /* in program. */
X#ifndef TRUE
X# define TRUE 1
X# define FALSE 0
X# endif
X
X/* Resolves dummy references *************/
Xchar *K[1];
XOPCODE acc_type;
Xlong accumulator;
Xchar *saccumulator;
Xexec1() {}
X/**************/
Xvoid patom();
Xextern char *strdup();
Xextern char *chk_alloc();
Xextern char *get_string();
X
X/*-------------------*/
XBUFFER *bheadp;
XBUFFER *curbp;
XWINDOW *wheadp;
XWINDOW *curwp;
Xint hooked;
Xint *cur_line;
Xint *cur_col;
Xint nest_level;
XLISTV *argv;
Xint pflag = 0;
Xint flush_flag = TRUE;
X/*-------------------*/
XMACRO macro_tbl[MAX_MACROS];
Xu_int32 m_offsets[MAX_MACROS];
Xint macro_cnt;
Xchar *bpath;
Xextern int cm_running;
Xstruct f fps[MAX_FILES];
Xstruct f *fp_ptr;
Xint a_flag = FALSE;
Xint l_flag = 0;
Xint L_flag = 0; /* TRUE if we want more disassembly info. */
Xint s_flag = FALSE; /* TRUE if size info. only. */
Xint nglobals; /* Number of global statements found so far. */
Xu_int32 globals[MAX_GLOBALS]; /* Table of indexes to global statements. */
Xlong nlist; /* Number of list atoms. */
Xlong nint; /* Number of int atoms. */
Xlong nstr; /* Number of F_STR atoms. */
Xlong nid; /* Number of F_ID atoms. */
Xlong nnull; /* Number of flags==0 atoms. */
Xlong ndontknow; /* Number of Don't knows. */
Xlong nhalt; /* Number of HALT opcodes. */
X
Xextern DEFINE *def_head,
X *def_ptr;
Xextern int cm_version;
Xextern u_int32 WGET32();
Xextern u_int16 WGET16();
X
XFILE *fp; /* File pointer for output file. */
X
Xchar buf[BUFSIZ]; /* Temporary working buffer. */
Xchar *output_file; /* Name of output file. */
XCM cm_header = {CM_MAGIC}; /* Header for output file. */
Xint string_count; /* Count of literals in list. */
Xchar **string_table;
Xchar *str_table; /* Pointer to string table for disassembly.*/
XLIST *atom_start; /* Pointer to base of compiled macro. */
Xint atom_count; /* Count of atoms in buffer. */
X
Xextern BUILTIN builtin[];
Xextern int sizeof_builtin;
Xextern BUILTIN *lookup_builtin();
X
Xint do_switches();
Xvoid usage();
X/*---------------------------------------
X * Prototype definitions.
X *---------------------------------------*/
Xextern char *bsearch();
Xvoid disassemble();
Xvoid write_output_file();
Xint init_fp();
Xint yyparse();
Xvoid list_macro();
Xvoid delete_macro();
Xvoid yyerror();
Xvoid execute_macro();
X
Xmain(argc, argv)
Xchar **argv;
X{ int arg_index = do_switches(argc, argv);
X int len;
X extern int dflag;
X extern char *crisp_log;
X MACRO *mp;
X static char argv_buf[1024];
X int exit_status = 0;
X int print_msg;
X
X/* dflag = 1;
X crisp_log = "/dev/tty";*/
X
X cm_running = TRUE;
X if ((bpath = getenv("BPATH")) == NULL)
X bpath = "/usr/local/crisp/macros";
X
X
X fp_ptr = &fps[0]-1;
X if (arg_index >= argc)
X usage();
X malloc_hack();
X print_msg = arg_index < argc - 1;
X for ( ; arg_index < argc; arg_index++) {
X char *file = argv[arg_index];
X int len = strlen(file);
X atom_count = 0;
X if (strlen(file) > 3 && strcmp(file + len -3, ".cm") == 0) {
X disassemble(file);
X continue;
X }
X if (print_msg)
X printf("Compiling %s...\n", file);
X if (init_fp(TERMINAL, file) < 0) {
X perror(file);
X continue;
X }
X
X macro_cnt = 0;
X nglobals = 0;
X if (yyparse() != 0) {
X printf("Compilation of %s unsuccessful.\n", file);
X exit_status = -1;
X continue;
X }
X
X /*----------------------------------------------
X * Open output file.
X *----------------------------------------------*/
X if (output_file == NULL) {
X if (len <= 2 || strcmp(file + len -2, ".m") != 0)
X sprintf(buf, "%s.cm", file);
X else
X sprintf(buf, "%.*s.cm", len - 2, file);
X output_file = buf;
X }
X
X write_output_file();
X if (a_flag)
X print_perc();
X /*----------------------------------------------
X * Dump internal form of macro if asked for.
X *----------------------------------------------*/
X for (mp = macro_tbl; mp < ¯o_tbl[macro_cnt]; mp++) {
X if (l_flag) {
X list_macro(0, mp->m_list);
X printf("\n");
X }
X /*chk_free(mp->m_name);*/
X /*chk_free(mp->m_list);*/
X }
X
X def_head = NULL;
X def_ptr = NULL;
X output_file = NULL;
X# ifdef MALLOC
X{ int i;
X static int loop_count = 0;
X if (++loop_count < 10)
X continue;
X strcpy(argv_buf, "cm ");
X if (arg_index + 1 >= argc)
X continue;
X for (i = arg_index+1; i < argc; i++) {
X strcat(argv_buf, " ");
X strcat(argv_buf, argv[i]);
X }
X argv[0] = "/bin/sh", argv[1] = "-c", argv[2] = argv_buf;
X execv(argv[0], argv);
X perror("execv");
X}
X# endif
X }
X return exit(exit_status);
X}
Xvoid
Xwrite_output_file()
X{
X int i;
X u_int32 base;
X long ftell();
X u_int32 offset;
X LIST *lp;
X
X if ((fp = fopen(output_file, "w")) == NULL) {
X perror(output_file);
X exit(1);
X }
X
X if ((atom_start = (LIST *) chk_alloc(MAX_ATOMS)) == NULL) {
X fprintf(stderr, "Not enough room to compile macros\n");
X exit(1);
X }
X if ((string_table = (char **) chk_alloc(sizeof (char *) * MAX_STRINGS)) == NULL) {
X fprintf(stderr, "Not enough room to allocate string table\n");
X exit(1);
X }
X
X cm_header.cm_num_macros = macro_cnt;
X cm_header.cm_version = cm_version;
X if (fwrite((char *) &cm_header, sizeof (CM), 1, fp) != 1) {
Xoutput_error:
X perror(output_file);
X exit(1);
X }
X
X if (fwrite((char *) m_offsets, sizeof (u_int32), macro_cnt+2, fp) !=
X macro_cnt+2)
X goto output_error;
X
X base = ftell(fp);
X string_count = 0;
X for (i = 0; i < macro_cnt; i++) {
X int n = macro_tbl[i].m_size;
X LIST *lpend;
X if (L_flag)
X printf("\n*** Macro %d:\n", i);
X lp = macro_tbl[i].m_list;
X lpend = lp + n;
X m_offsets[i] = (ftell(fp) - (long) base) / sizeof (LIST);
X while (lp < lpend) {
X char *str = "";
X if (*lp == F_STR || *lp == F_LIT)
X str = get_string(lp);
X else if (*lp == F_ID) {
X int id = LGET16(lp);
X if (strcmp(builtin[id].name, "global") == 0) {
X globals[nglobals++] = m_offsets[i] +
X (lp - macro_tbl[i].m_list);
X }
X }
X if (L_flag)
X patom(macro_tbl[i].m_list, lp, str);
X lp += sizeof_atoms[*lp];
X }
X if (fwrite((char *) macro_tbl[i].m_list, sizeof (LIST), n, fp) != n)
X goto output_error;
X }
X if (ftell(fp) & 3)
X fwrite("PAD", (int) (4 - (ftell(fp) & 3)), 1, fp);
X m_offsets[macro_cnt] = ftell(fp) - (long) base;
X m_offsets[macro_cnt+1] = string_count;
X /*------------------------------------------
X * Now write out table of string offsets from here.
X *------------------------------------------*/
X for (offset = 0, i = 0; i < string_count; i++) {
X u_int32 o = WGET32(offset);
X if (fwrite((char *) &o, sizeof o, 1, fp) != 1)
X goto output_error;
X offset += strlen(string_table[i]) + 1;
X }
X /*------------------------------------------
X * Now write out string table.
X *------------------------------------------*/
X for (i = 0; i < string_count; i++) {
X int len = strlen(string_table[i]);
X if (fwrite(string_table[i], len+1, 1, fp) != 1)
X goto output_error;
X }
X if (ftell(fp) & 3)
X fwrite("PAD", (int) (4 - (ftell(fp) & 3)), 1, fp);
X cm_header.cm_globals = ftell(fp);
X swap_words(globals, nglobals);
X if (nglobals && fwrite((char *) globals, sizeof globals[0] * nglobals, 1, fp) != 1)
X goto output_error;
X rewind(fp);
X cm_header.cm_num_atoms = atom_count;
X cm_header.cm_num_globals = nglobals;
X cm_header.cm_num_strings = string_count;
X swap_cm_header(&cm_header);
X if (fwrite((char *) &cm_header, sizeof (CM), 1, fp) != 1)
X goto output_error;
X swap_words(m_offsets, macro_cnt+2);
X if (fwrite((char *) m_offsets, sizeof (u_int32), macro_cnt+2, fp) !=
X macro_cnt+2)
X goto output_error;
X fclose(fp);
X
X chk_free((char *) string_table);
X chk_free((char *) atom_start);
X}
Xchar *
Xget_string(lp)
Xregister LIST *lp;
X{
X register char **cpp;
X register char **cpend = &string_table[string_count];
X char *str = (char *) LGET32(lp);
X static char buf[128];
X
X for (cpp = string_table; cpp < cpend; cpp++)
X if (**cpp == *str && strcmp(*cpp, str) == 0) {
X strcpy(buf, str);
X LPUT32(lp, (long) (cpp - string_table));
X chk_free(str);
X return buf;
X }
X *cpp = str;
X LPUT32(lp, (long) string_count++);
X return str;
X}
Xvoid
Xusage()
X{
X fprintf(stderr, "Usage: cm [-aLl] [-o output_file] file-name ...\n\n");
X fprintf(stderr, " -a Print atom percentages.\n");
X fprintf(stderr, " -l List macro expansions.\n");
X fprintf(stderr, " -L Print detailed disassembly info.\n");
X fprintf(stderr, " -q Quiet error messages.\n");
X fprintf(stderr, " -s Print size of .cm file only.\n");
X fprintf(stderr, " (Use with .cm file only).\n");
X fprintf(stderr, " -o file Name of compiled output file.\n");
X exit(1);
X}
X
Xdo_switches(ac, av)
Xchar **av;
X
X{
X int c;
X extern char *optarg;
X int errflag = 0;
X extern int optind;
X
X while ((c = getopt(ac, av, "acLqldo:s")) != EOF)
X switch (c) {
X case 'a': a_flag = TRUE; break;
X case 'l': l_flag = 1; break;
X case 'q': {
X extern int verbose_errors;
X verbose_errors = FALSE;
X break;
X }
X case 'L': L_flag = 1; break;
X case 'o':
X output_file = optarg;
X break;
X case 's': s_flag = TRUE; break;
X default:
X errflag++;
X }
X
X if (errflag)
X usage();
X return optind;
X}
Xmac_compare(mac1, mac2)
Xchar *mac1;
XMACRO *mac2;
X{
X return strcmp(mac1, mac2->m_name);
X}
Xenter_macro(list)
XLIST *list;
X{ register MACRO *mptr;
X char name[64];
X
X if (*list != F_STR) {
X printf("Macro name must be an id\n");
X return -1;
X }
X strncpy(name, (char *) LGET32(list), 64);
X list += sizeof_atoms[F_STR];
X if (macro_cnt && (mptr = (MACRO *) bsearch(name, macro_tbl, macro_cnt,
X sizeof macro_tbl[0], mac_compare)))
X delete_macro(mptr->m_list);
X else {
X MACRO *mp_end = ¯o_tbl[macro_cnt];
X if (macro_cnt >= MAX_MACROS-1) {
X printf("Macro table full\n");
X return -1;
X }
X for (mptr = macro_tbl; mptr < mp_end; mptr++)
X if (strcmp(name, mptr->m_name) < 0) {
X for ( ; mp_end >= mptr; mp_end--)
X mp_end[1] = mp_end[0];
X break;
X }
X macro_cnt++;
X mptr->m_name = strdup(name);
X }
X mptr->m_list = list;
X return 0;
X}
Xvoid
Xdelete_macro(list)
Xregister LIST *list;
X{
X
X}
Xvoid
Xdisassemble(file)
Xchar *file;
X{
X FILE *fp = fopen(file, "r");
X int i;
X CM *cm;
X struct stat stat_buf;
X u_int32 *vm_offsets;
X u_int32 num_strings;
X u_int32 *soffsets;
X int nm;
X LIST *lp;
X LIST *base_list;
X
X printf("\n*** File: %s\n\n", file);
X nhalt = nlist = nint = nstr = nid = nnull = ndontknow = 0;
X
X if (fp == NULL || stat(file, &stat_buf) < 0) {
X perror(file);
X exit(1);
X }
X cm = (CM *) chk_alloc((unsigned) stat_buf.st_size);
X if (read(fileno(fp), (char *) cm, (int) stat_buf.st_size) !=
X (int) stat_buf.st_size) {
X fprintf(stderr, "Read() error on .cm file");
X exit(1);
X }
X if (cm->cm_version != cm_version) {
X fprintf(stderr, ".cm file has wrong version number - %d\n",
X cm->cm_version);
X fprintf(stderr, "Current version is %d\n", cm_version);
X exit(1);
X }
X
X vm_offsets = (u_int32 *) (cm + 1);
X base_list = (LIST *) (vm_offsets + cm->cm_num_macros + 2);
X num_strings = vm_offsets[cm->cm_num_macros + 1];
X soffsets = (u_int32 *) (((char *) base_list) +
X vm_offsets[cm->cm_num_macros]);
X str_table = (char *) (soffsets + num_strings);
X
X if (cm->cm_magic != CM_MAGIC) {
X fprintf(stderr, "%s: invalid magic number\n", file);
X exit(1);
X }
X printf("Version of .cm : %d\n", cm->cm_version);
X printf("Number of macros: %d\n", cm->cm_num_macros);
X printf("Number of globals: %d\n", cm->cm_num_globals);
X printf("Size : %5ld Header\n", (u_int32) (sizeof *cm));
X printf(" %5ld Atoms\n",
X (long) (sizeof (LIST) * cm->cm_num_atoms));
X printf(" + %5d Strings\n", cm->cm_num_strings);
X printf(" -------\n");
X printf(" %5ld\n", (u_int32) stat_buf.st_size);
X if (s_flag)
X goto end_of_function;
X
X for (i = 0; i < cm->cm_num_macros; i++)
X printf("Macro %d, offset = atom #%ld\n", i, vm_offsets[i]);
X printf("String table starts at %08lx. No. of strings =%ld\n",
X vm_offsets[cm->cm_num_macros], num_strings);
X
X for (nm = 0, lp = base_list; lp < base_list + cm->cm_num_atoms; ) {
X char *str = (*lp == F_STR || *lp == F_LIT)
X ? str_table + soffsets[LGET32(lp)] : "";
X if (strcmp(str, "macro") == 0 && l_flag)
X printf("\n*** Macro %d:\n", nm++);
X patom(base_list, lp, str);
X lp += sizeof_atoms[*lp];
X }
X
X if (l_flag == 0)
X goto end_of_function;
X printf("String Table:\n");
X for (i = 0; i < num_strings; i++)
X printf("\tString %2d: Offset=%04lx '%s'\n", i,
X soffsets[i], str_table + soffsets[i]);
X printf("\n");
Xend_of_function:
X if (a_flag)
X print_perc();
X chk_free((char *) cm);
X}
X# define PC(x) ((x) * 100) / natoms
Xprint_perc()
X{ long natoms = nlist + nint + nstr + nid + nnull + ndontknow + nhalt;
X if (natoms == 0)
X natoms = 1;
X printf("\n");
X printf("Number of F_HALT atoms : %5ld (%2ld%%)\n",
X nhalt, PC(nhalt));
X printf("Number of F_LIST atoms : %5ld (%2ld%%)\n",
X nlist, PC(nlist));
X printf("Number of F_INT atoms : %5ld (%2ld%%)\n",
X nint, PC(nint));
X printf(
X"Number of F_STR atoms : %5ld (%2ld%%) INT+STR=%ld (%2ld%%)\n",
X nstr, PC(nstr), nstr + nint, PC(nstr + nint));
X printf("Number of F_ID atoms : %5ld (%2ld%%)\n",
X nid, PC(nid));
X printf("Number of F_NULL atoms : %5ld (%2ld%%)\n",
X nnull, PC(nnull));
X printf("Number of <DONT KNOW> atoms : + %5ld (%2ld%%)\n",
X nnull, PC(nnull));
X printf(" -------\n", natoms);
X printf("TOTAL: %5ld\n", natoms);
X}
Xvoid
Xexecute_macro(lp)
XLIST *lp;
X{ char name[64];
X char *macro_keywd;
X extern char *strdup();
X LIST *lpn;
X extern int sizeof_macro;
X
X if (macro_cnt >= MAX_MACROS-1) {
X printf("Macro table full\n");
X return;
X }
X lpn = lp + sizeof_atoms[*lp];
X if (*lpn != F_STR && *lpn != F_ID) {
X yyerror("Macro must start with a name\n");
X exit(1);
X }
X strcpy(name, *lpn == F_ID ?
X builtin[LGET16(lpn)].name : (char *) LGET32(lpn));
X macro_keywd = *lp == F_ID ?
X builtin[LGET16(lp)].name : (char *) LGET32(lp);
X if (strcmp(macro_keywd, "macro") != 0 &&
X strcmp(macro_keywd, "replacement") != 0)
X return;
X if (strcmp(macro_keywd, "macro") == 0 && *lpn == F_ID)
X printf("Warning: '%s' redefines a builtin.\n", name);
X macro_tbl[macro_cnt].m_name = strdup(name);
X macro_tbl[macro_cnt].m_size = sizeof_macro;
X atom_count += sizeof_macro;
SHAR_EOF
echo "End of part 3"
echo "File ./cm.c is continued in part 4"
echo "4" > s2_seq_.tmp
exit 0
--
===================== Reuters Ltd PLC,
Tel: +44 628 891313 x. 212 Westthorpe House,
UUCP: fox%marlow.uucp at idec.stc.co.uk Little Marlow,
Bucks, England SL7 3RQ
More information about the Comp.sources.misc
mailing list