home *** CD-ROM | disk | FTP | other *** search
- Subject: v13i007: Perl, a "replacement" for awk and sed, Part07/10
- Newsgroups: comp.sources.unix
- Sender: sources
- Approved: rsalz@uunet.UU.NET
-
- Submitted-by: Larry Wall <lwall@jpl-devvax.jpl.nasa.gov>
- Posting-number: Volume 13, Issue 7
- Archive-name: perl/part07
-
-
-
- #! /bin/sh
-
- # Make a new directory for the perl sources, cd to it, and run kits 1
- # thru 10 through sh. When all 10 kits have been run, read README.
-
- echo "This is perl 1.0 kit 7 (of 10). If kit 7 is complete, the line"
- echo '"'"End of kit 7 (of 10)"'" will echo at the end.'
- echo ""
- export PATH || (echo "You didn't use sh, you clunch." ; kill $$)
- mkdir t 2>/dev/null
- mkdir x2p 2>/dev/null
- echo Extracting x2p/a2py.c
- sed >x2p/a2py.c <<'!STUFFY!FUNK!' -e 's/X//'
- X/* $Header: a2py.c,v 1.0 87/12/18 17:50:33 root Exp $
- X *
- X * $Log: a2py.c,v $
- X * Revision 1.0 87/12/18 17:50:33 root
- X * Initial revision
- X *
- X */
- X
- X#include "util.h"
- Xchar *index();
- X
- Xchar *filename;
- X
- Xmain(argc,argv,env)
- Xregister int argc;
- Xregister char **argv;
- Xregister char **env;
- X{
- X register STR *str;
- X register char *s;
- X int i;
- X STR *walk();
- X STR *tmpstr;
- X
- X linestr = str_new(80);
- X str = str_new(0); /* first used for -I flags */
- X for (argc--,argv++; argc; argc--,argv++) {
- X if (argv[0][0] != '-' || !argv[0][1])
- X break;
- X reswitch:
- X switch (argv[0][1]) {
- X#ifdef DEBUGGING
- X case 'D':
- X debug = atoi(argv[0]+2);
- X#ifdef YYDEBUG
- X yydebug = (debug & 1);
- X#endif
- X break;
- X#endif
- X case '0': case '1': case '2': case '3': case '4':
- X case '5': case '6': case '7': case '8': case '9':
- X maxfld = atoi(argv[0]+1);
- X absmaxfld = TRUE;
- X break;
- X case 'F':
- X fswitch = argv[0][2];
- X break;
- X case 'n':
- X namelist = savestr(argv[0]+2);
- X break;
- X case '-':
- X argc--,argv++;
- X goto switch_end;
- X case 0:
- X break;
- X default:
- X fatal("Unrecognized switch: %s\n",argv[0]);
- X }
- X }
- X switch_end:
- X
- X /* open script */
- X
- X if (argv[0] == Nullch)
- X argv[0] = "-";
- X filename = savestr(argv[0]);
- X if (strEQ(filename,"-"))
- X argv[0] = "";
- X if (!*argv[0])
- X rsfp = stdin;
- X else
- X rsfp = fopen(argv[0],"r");
- X if (rsfp == Nullfp)
- X fatal("Awk script \"%s\" doesn't seem to exist.\n",filename);
- X
- X /* init tokener */
- X
- X bufptr = str_get(linestr);
- X symtab = hnew();
- X
- X /* now parse the report spec */
- X
- X if (yyparse())
- X fatal("Translation aborted due to syntax errors.\n");
- X
- X#ifdef DEBUGGING
- X if (debug & 2) {
- X int type, len;
- X
- X for (i=1; i<mop;) {
- X type = ops[i].ival;
- X len = type >> 8;
- X type &= 255;
- X printf("%d\t%d\t%d\t%-10s",i++,type,len,opname[type]);
- X if (type == OSTRING)
- X printf("\t\"%s\"\n",ops[i].cval),i++;
- X else {
- X while (len--) {
- X printf("\t%d",ops[i].ival),i++;
- X }
- X putchar('\n');
- X }
- X }
- X }
- X if (debug & 8)
- X dump(root);
- X#endif
- X
- X /* first pass to look for numeric variables */
- X
- X prewalk(0,0,root,&i);
- X
- X /* second pass to produce new program */
- X
- X tmpstr = walk(0,0,root,&i);
- X str = str_make("#!/bin/perl\n\n");
- X if (do_opens && opens) {
- X str_scat(str,opens);
- X str_free(opens);
- X str_cat(str,"\n");
- X }
- X str_scat(str,tmpstr);
- X str_free(tmpstr);
- X#ifdef DEBUGGING
- X if (!(debug & 16))
- X#endif
- X fixup(str);
- X putlines(str);
- X exit(0);
- X}
- X
- X#define RETURN(retval) return (bufptr = s,retval)
- X#define XTERM(retval) return (expectterm = TRUE,bufptr = s,retval)
- X#define XOP(retval) return (expectterm = FALSE,bufptr = s,retval)
- X#define ID(x) return (yylval=string(x,0),expectterm = FALSE,bufptr = s,VAR)
- X
- Xyylex()
- X{
- X register char *s = bufptr;
- X register char *d;
- X register int tmp;
- X
- X retry:
- X#ifdef YYDEBUG
- X if (yydebug)
- X if (index(s,'\n'))
- X fprintf(stderr,"Tokener at %s",s);
- X else
- X fprintf(stderr,"Tokener at %s\n",s);
- X#endif
- X switch (*s) {
- X default:
- X fprintf(stderr,
- X "Unrecognized character %c in file %s line %d--ignoring.\n",
- X *s++,filename,line);
- X goto retry;
- X case '\\':
- X case 0:
- X s = str_get(linestr);
- X *s = '\0';
- X if (!rsfp)
- X RETURN(0);
- X line++;
- X if ((s = str_gets(linestr, rsfp)) == Nullch) {
- X if (rsfp != stdin)
- X fclose(rsfp);
- X rsfp = Nullfp;
- X s = str_get(linestr);
- X RETURN(0);
- X }
- X goto retry;
- X case ' ': case '\t':
- X s++;
- X goto retry;
- X case '\n':
- X *s = '\0';
- X XTERM(NEWLINE);
- X case '#':
- X yylval = string(s,0);
- X *s = '\0';
- X XTERM(COMMENT);
- X case ';':
- X tmp = *s++;
- X if (*s == '\n') {
- X s++;
- X XTERM(SEMINEW);
- X }
- X XTERM(tmp);
- X case '(':
- X case '{':
- X case '[':
- X case ')':
- X case ']':
- X tmp = *s++;
- X XOP(tmp);
- X case 127:
- X s++;
- X XTERM('}');
- X case '}':
- X for (d = s + 1; isspace(*d); d++) ;
- X if (!*d)
- X s = d - 1;
- X *s = 127;
- X XTERM(';');
- X case ',':
- X tmp = *s++;
- X XTERM(tmp);
- X case '~':
- X s++;
- X XTERM(MATCHOP);
- X case '+':
- X case '-':
- X if (s[1] == *s) {
- X s++;
- X if (*s++ == '+')
- X XTERM(INCR);
- X else
- X XTERM(DECR);
- X }
- X /* FALL THROUGH */
- X case '*':
- X case '%':
- X tmp = *s++;
- X if (*s == '=') {
- X yylval = string(s-1,2);
- X s++;
- X XTERM(ASGNOP);
- X }
- X XTERM(tmp);
- X case '&':
- X s++;
- X tmp = *s++;
- X if (tmp == '&')
- X XTERM(ANDAND);
- X s--;
- X XTERM('&');
- X case '|':
- X s++;
- X tmp = *s++;
- X if (tmp == '|')
- X XTERM(OROR);
- X s--;
- X XTERM('|');
- X case '=':
- X s++;
- X tmp = *s++;
- X if (tmp == '=') {
- X yylval = string("==",2);
- X XTERM(RELOP);
- X }
- X s--;
- X yylval = string("=",1);
- X XTERM(ASGNOP);
- X case '!':
- X s++;
- X tmp = *s++;
- X if (tmp == '=') {
- X yylval = string("!=",2);
- X XTERM(RELOP);
- X }
- X if (tmp == '~') {
- X yylval = string("!~",2);
- X XTERM(MATCHOP);
- X }
- X s--;
- X XTERM(NOT);
- X case '<':
- X s++;
- X tmp = *s++;
- X if (tmp == '=') {
- X yylval = string("<=",2);
- X XTERM(RELOP);
- X }
- X s--;
- X yylval = string("<",1);
- X XTERM(RELOP);
- X case '>':
- X s++;
- X tmp = *s++;
- X if (tmp == '=') {
- X yylval = string(">=",2);
- X XTERM(RELOP);
- X }
- X s--;
- X yylval = string(">",1);
- X XTERM(RELOP);
- X
- X#define SNARFWORD \
- X d = tokenbuf; \
- X while (isalpha(*s) || isdigit(*s) || *s == '_') \
- X *d++ = *s++; \
- X *d = '\0'; \
- X d = tokenbuf;
- X
- X case '$':
- X s++;
- X if (*s == '0') {
- X s++;
- X do_chop = TRUE;
- X need_entire = TRUE;
- X ID("0");
- X }
- X do_split = TRUE;
- X if (isdigit(*s)) {
- X for (d = s; isdigit(*s); s++) ;
- X yylval = string(d,s-d);
- X tmp = atoi(d);
- X if (tmp > maxfld)
- X maxfld = tmp;
- X XOP(FIELD);
- X }
- X split_to_array = set_array_base = TRUE;
- X XOP(VFIELD);
- X
- X case '/': /* may either be division or pattern */
- X if (expectterm) {
- X s = scanpat(s);
- X XTERM(REGEX);
- X }
- X tmp = *s++;
- X if (*s == '=') {
- X yylval = string("/=",2);
- X s++;
- X XTERM(ASGNOP);
- X }
- X XTERM(tmp);
- X
- X case '0': case '1': case '2': case '3': case '4':
- X case '5': case '6': case '7': case '8': case '9':
- X s = scannum(s);
- X XOP(NUMBER);
- X case '"':
- X s++;
- X s = cpy2(tokenbuf,s,s[-1]);
- X if (!*s)
- X fatal("String not terminated:\n%s",str_get(linestr));
- X s++;
- X yylval = string(tokenbuf,0);
- X XOP(STRING);
- X
- X case 'a': case 'A':
- X SNARFWORD;
- X ID(d);
- X case 'b': case 'B':
- X SNARFWORD;
- X if (strEQ(d,"break"))
- X XTERM(BREAK);
- X if (strEQ(d,"BEGIN"))
- X XTERM(BEGIN);
- X ID(d);
- X case 'c': case 'C':
- X SNARFWORD;
- X if (strEQ(d,"continue"))
- X XTERM(CONTINUE);
- X ID(d);
- X case 'd': case 'D':
- X SNARFWORD;
- X ID(d);
- X case 'e': case 'E':
- X SNARFWORD;
- X if (strEQ(d,"END"))
- X XTERM(END);
- X if (strEQ(d,"else"))
- X XTERM(ELSE);
- X if (strEQ(d,"exit")) {
- X saw_line_op = TRUE;
- X XTERM(EXIT);
- X }
- X if (strEQ(d,"exp")) {
- X yylval = OEXP;
- X XTERM(FUN1);
- X }
- X ID(d);
- X case 'f': case 'F':
- X SNARFWORD;
- X if (strEQ(d,"FS")) {
- X saw_FS++;
- X if (saw_FS == 1 && in_begin) {
- X for (d = s; *d && isspace(*d); d++) ;
- X if (*d == '=') {
- X for (d++; *d && isspace(*d); d++) ;
- X if (*d == '"' && d[2] == '"')
- X const_FS = d[1];
- X }
- X }
- X ID(tokenbuf);
- X }
- X if (strEQ(d,"FILENAME"))
- X d = "ARGV";
- X if (strEQ(d,"for"))
- X XTERM(FOR);
- X ID(d);
- X case 'g': case 'G':
- X SNARFWORD;
- X if (strEQ(d,"getline"))
- X XTERM(GETLINE);
- X ID(d);
- X case 'h': case 'H':
- X SNARFWORD;
- X ID(d);
- X case 'i': case 'I':
- X SNARFWORD;
- X if (strEQ(d,"if"))
- X XTERM(IF);
- X if (strEQ(d,"in"))
- X XTERM(IN);
- X if (strEQ(d,"index")) {
- X set_array_base = TRUE;
- X XTERM(INDEX);
- X }
- X if (strEQ(d,"int")) {
- X yylval = OINT;
- X XTERM(FUN1);
- X }
- X ID(d);
- X case 'j': case 'J':
- X SNARFWORD;
- X ID(d);
- X case 'k': case 'K':
- X SNARFWORD;
- X ID(d);
- X case 'l': case 'L':
- X SNARFWORD;
- X if (strEQ(d,"length")) {
- X yylval = OLENGTH;
- X XTERM(FUN1);
- X }
- X if (strEQ(d,"log")) {
- X yylval = OLOG;
- X XTERM(FUN1);
- X }
- X ID(d);
- X case 'm': case 'M':
- X SNARFWORD;
- X ID(d);
- X case 'n': case 'N':
- X SNARFWORD;
- X if (strEQ(d,"NF"))
- X do_split = split_to_array = set_array_base = TRUE;
- X if (strEQ(d,"next")) {
- X saw_line_op = TRUE;
- X XTERM(NEXT);
- X }
- X ID(d);
- X case 'o': case 'O':
- X SNARFWORD;
- X if (strEQ(d,"ORS")) {
- X saw_ORS = TRUE;
- X d = "$\\";
- X }
- X if (strEQ(d,"OFS")) {
- X saw_OFS = TRUE;
- X d = "$,";
- X }
- X if (strEQ(d,"OFMT")) {
- X d = "$#";
- X }
- X ID(d);
- X case 'p': case 'P':
- X SNARFWORD;
- X if (strEQ(d,"print")) {
- X XTERM(PRINT);
- X }
- X if (strEQ(d,"printf")) {
- X XTERM(PRINTF);
- X }
- X ID(d);
- X case 'q': case 'Q':
- X SNARFWORD;
- X ID(d);
- X case 'r': case 'R':
- X SNARFWORD;
- X if (strEQ(d,"RS")) {
- X d = "$/";
- X saw_RS = TRUE;
- X }
- X ID(d);
- X case 's': case 'S':
- X SNARFWORD;
- X if (strEQ(d,"split")) {
- X set_array_base = TRUE;
- X XOP(SPLIT);
- X }
- X if (strEQ(d,"substr")) {
- X set_array_base = TRUE;
- X XTERM(SUBSTR);
- X }
- X if (strEQ(d,"sprintf"))
- X XTERM(SPRINTF);
- X if (strEQ(d,"sqrt")) {
- X yylval = OSQRT;
- X XTERM(FUN1);
- X }
- X ID(d);
- X case 't': case 'T':
- X SNARFWORD;
- X ID(d);
- X case 'u': case 'U':
- X SNARFWORD;
- X ID(d);
- X case 'v': case 'V':
- X SNARFWORD;
- X ID(d);
- X case 'w': case 'W':
- X SNARFWORD;
- X if (strEQ(d,"while"))
- X XTERM(WHILE);
- X ID(d);
- X case 'x': case 'X':
- X SNARFWORD;
- X ID(d);
- X case 'y': case 'Y':
- X SNARFWORD;
- X ID(d);
- X case 'z': case 'Z':
- X SNARFWORD;
- X ID(d);
- X }
- X}
- X
- Xchar *
- Xscanpat(s)
- Xregister char *s;
- X{
- X register char *d;
- X
- X switch (*s++) {
- X case '/':
- X break;
- X default:
- X fatal("Search pattern not found:\n%s",str_get(linestr));
- X }
- X s = cpytill(tokenbuf,s,s[-1]);
- X if (!*s)
- X fatal("Search pattern not terminated:\n%s",str_get(linestr));
- X s++;
- X yylval = string(tokenbuf,0);
- X return s;
- X}
- X
- Xyyerror(s)
- Xchar *s;
- X{
- X fprintf(stderr,"%s in file %s at line %d\n",
- X s,filename,line);
- X}
- X
- Xchar *
- Xscannum(s)
- Xregister char *s;
- X{
- X register char *d;
- X
- X switch (*s) {
- X case '1': case '2': case '3': case '4': case '5':
- X case '6': case '7': case '8': case '9': case '0' : case '.':
- X d = tokenbuf;
- X while (isdigit(*s) || *s == '_')
- X *d++ = *s++;
- X if (*s == '.' && index("0123456789eE",s[1]))
- X *d++ = *s++;
- X while (isdigit(*s) || *s == '_')
- X *d++ = *s++;
- X if (index("eE",*s) && index("+-0123456789",s[1]))
- X *d++ = *s++;
- X if (*s == '+' || *s == '-')
- X *d++ = *s++;
- X while (isdigit(*s))
- X *d++ = *s++;
- X *d = '\0';
- X yylval = string(tokenbuf,0);
- X break;
- X }
- X return s;
- X}
- X
- Xstring(ptr,len)
- Xchar *ptr;
- X{
- X int retval = mop;
- X
- X ops[mop++].ival = OSTRING + (1<<8);
- X if (!len)
- X len = strlen(ptr);
- X ops[mop].cval = safemalloc(len+1);
- X strncpy(ops[mop].cval,ptr,len);
- X ops[mop++].cval[len] = '\0';
- X return retval;
- X}
- X
- Xoper0(type)
- Xint type;
- X{
- X int retval = mop;
- X
- X if (type > 255)
- X fatal("type > 255 (%d)\n",type);
- X ops[mop++].ival = type;
- X return retval;
- X}
- X
- Xoper1(type,arg1)
- Xint type;
- Xint arg1;
- X{
- X int retval = mop;
- X
- X if (type > 255)
- X fatal("type > 255 (%d)\n",type);
- X ops[mop++].ival = type + (1<<8);
- X ops[mop++].ival = arg1;
- X return retval;
- X}
- X
- Xoper2(type,arg1,arg2)
- Xint type;
- Xint arg1;
- Xint arg2;
- X{
- X int retval = mop;
- X
- X if (type > 255)
- X fatal("type > 255 (%d)\n",type);
- X ops[mop++].ival = type + (2<<8);
- X ops[mop++].ival = arg1;
- X ops[mop++].ival = arg2;
- X return retval;
- X}
- X
- Xoper3(type,arg1,arg2,arg3)
- Xint type;
- Xint arg1;
- Xint arg2;
- Xint arg3;
- X{
- X int retval = mop;
- X
- X if (type > 255)
- X fatal("type > 255 (%d)\n",type);
- X ops[mop++].ival = type + (3<<8);
- X ops[mop++].ival = arg1;
- X ops[mop++].ival = arg2;
- X ops[mop++].ival = arg3;
- X return retval;
- X}
- X
- Xoper4(type,arg1,arg2,arg3,arg4)
- Xint type;
- Xint arg1;
- Xint arg2;
- Xint arg3;
- Xint arg4;
- X{
- X int retval = mop;
- X
- X if (type > 255)
- X fatal("type > 255 (%d)\n",type);
- X ops[mop++].ival = type + (4<<8);
- X ops[mop++].ival = arg1;
- X ops[mop++].ival = arg2;
- X ops[mop++].ival = arg3;
- X ops[mop++].ival = arg4;
- X return retval;
- X}
- X
- Xoper5(type,arg1,arg2,arg3,arg4,arg5)
- Xint type;
- Xint arg1;
- Xint arg2;
- Xint arg3;
- Xint arg4;
- Xint arg5;
- X{
- X int retval = mop;
- X
- X if (type > 255)
- X fatal("type > 255 (%d)\n",type);
- X ops[mop++].ival = type + (5<<8);
- X ops[mop++].ival = arg1;
- X ops[mop++].ival = arg2;
- X ops[mop++].ival = arg3;
- X ops[mop++].ival = arg4;
- X ops[mop++].ival = arg5;
- X return retval;
- X}
- X
- Xint depth = 0;
- X
- Xdump(branch)
- Xint branch;
- X{
- X register int type;
- X register int len;
- X register int i;
- X
- X type = ops[branch].ival;
- X len = type >> 8;
- X type &= 255;
- X for (i=depth; i; i--)
- X printf(" ");
- X if (type == OSTRING) {
- X printf("%-5d\"%s\"\n",branch,ops[branch+1].cval);
- X }
- X else {
- X printf("(%-5d%s %d\n",branch,opname[type],len);
- X depth++;
- X for (i=1; i<=len; i++)
- X dump(ops[branch+i].ival);
- X depth--;
- X for (i=depth; i; i--)
- X printf(" ");
- X printf(")\n");
- X }
- X}
- X
- Xbl(arg,maybe)
- Xint arg;
- Xint maybe;
- X{
- X if (!arg)
- X return 0;
- X else if ((ops[arg].ival & 255) != OBLOCK)
- X return oper2(OBLOCK,arg,maybe);
- X else if ((ops[arg].ival >> 8) != 2)
- X return oper2(OBLOCK,ops[arg+1].ival,maybe);
- X else
- X return arg;
- X}
- X
- Xfixup(str)
- XSTR *str;
- X{
- X register char *s;
- X register char *t;
- X
- X for (s = str->str_ptr; *s; s++) {
- X if (*s == ';' && s[1] == ' ' && s[2] == '\n') {
- X strcpy(s+1,s+2);
- X s++;
- X }
- X else if (*s == '\n') {
- X for (t = s+1; isspace(*t & 127); t++) ;
- X t--;
- X while (isspace(*t & 127) && *t != '\n') t--;
- X if (*t == '\n' && t-s > 1) {
- X if (s[-1] == '{')
- X s--;
- X strcpy(s+1,t);
- X }
- X s++;
- X }
- X }
- X}
- X
- Xputlines(str)
- XSTR *str;
- X{
- X register char *d, *s, *t, *e;
- X register int pos, newpos;
- X
- X d = tokenbuf;
- X pos = 0;
- X for (s = str->str_ptr; *s; s++) {
- X *d++ = *s;
- X pos++;
- X if (*s == '\n') {
- X *d = '\0';
- X d = tokenbuf;
- X pos = 0;
- X putone();
- X }
- X else if (*s == '\t')
- X pos += 7;
- X if (pos > 78) { /* split a long line? */
- X *d-- = '\0';
- X newpos = 0;
- X for (t = tokenbuf; isspace(*t & 127); t++) {
- X if (*t == '\t')
- X newpos += 8;
- X else
- X newpos += 1;
- X }
- X e = d;
- X while (d > tokenbuf && (*d != ' ' || d[-1] != ';'))
- X d--;
- X if (d < t+10) {
- X d = e;
- X while (d > tokenbuf &&
- X (*d != ' ' || d[-1] != '|' || d[-2] != '|') )
- X d--;
- X }
- X if (d < t+10) {
- X d = e;
- X while (d > tokenbuf &&
- X (*d != ' ' || d[-1] != '&' || d[-2] != '&') )
- X d--;
- X }
- X if (d < t+10) {
- X d = e;
- X while (d > tokenbuf && (*d != ' ' || d[-1] != ','))
- X d--;
- X }
- X if (d < t+10) {
- X d = e;
- X while (d > tokenbuf && *d != ' ')
- X d--;
- X }
- X if (d > t+3) {
- X *d = '\0';
- X putone();
- X putchar('\n');
- X if (d[-1] != ';' && !(newpos % 4)) {
- X *t++ = ' ';
- X *t++ = ' ';
- X newpos += 2;
- X }
- X strcpy(t,d+1);
- X newpos += strlen(t);
- X d = t + strlen(t);
- X pos = newpos;
- X }
- X else
- X d = e + 1;
- X }
- X }
- X}
- X
- Xputone()
- X{
- X register char *t;
- X
- X for (t = tokenbuf; *t; t++) {
- X *t &= 127;
- X if (*t == 127) {
- X *t = ' ';
- X strcpy(t+strlen(t)-1, "\t#???\n");
- X }
- X }
- X t = tokenbuf;
- X if (*t == '#') {
- X if (strnEQ(t,"#!/bin/awk",10) || strnEQ(t,"#! /bin/awk",11))
- X return;
- X }
- X fputs(tokenbuf,stdout);
- X}
- X
- Xnumary(arg)
- Xint arg;
- X{
- X STR *key;
- X int dummy;
- X
- X key = walk(0,0,arg,&dummy);
- X str_cat(key,"[]");
- X hstore(symtab,key->str_ptr,str_make("1"));
- X str_free(key);
- X set_array_base = TRUE;
- X return arg;
- X}
- !STUFFY!FUNK!
- echo Extracting cmd.c
- sed >cmd.c <<'!STUFFY!FUNK!' -e 's/X//'
- X/* $Header: cmd.c,v 1.0 87/12/18 13:04:51 root Exp $
- X *
- X * $Log: cmd.c,v $
- X * Revision 1.0 87/12/18 13:04:51 root
- X * Initial revision
- X *
- X */
- X
- X#include "handy.h"
- X#include "EXTERN.h"
- X#include "search.h"
- X#include "util.h"
- X#include "perl.h"
- X
- Xstatic STR str_chop;
- X
- X/* This is the main command loop. We try to spend as much time in this loop
- X * as possible, so lots of optimizations do their activities in here. This
- X * means things get a little sloppy.
- X */
- X
- XSTR *
- Xcmd_exec(cmd)
- Xregister CMD *cmd;
- X{
- X SPAT *oldspat;
- X#ifdef DEBUGGING
- X int olddlevel;
- X int entdlevel;
- X#endif
- X register STR *retstr;
- X register char *tmps;
- X register int cmdflags;
- X register bool match;
- X register char *go_to = goto_targ;
- X ARG *arg;
- X FILE *fp;
- X
- X retstr = &str_no;
- X#ifdef DEBUGGING
- X entdlevel = dlevel;
- X#endif
- Xtail_recursion_entry:
- X#ifdef DEBUGGING
- X dlevel = entdlevel;
- X#endif
- X if (cmd == Nullcmd)
- X return retstr;
- X cmdflags = cmd->c_flags; /* hopefully load register */
- X if (go_to) {
- X if (cmd->c_label && strEQ(go_to,cmd->c_label))
- X goto_targ = go_to = Nullch; /* here at last */
- X else {
- X switch (cmd->c_type) {
- X case C_IF:
- X oldspat = curspat;
- X#ifdef DEBUGGING
- X olddlevel = dlevel;
- X#endif
- X retstr = &str_yes;
- X if (cmd->ucmd.ccmd.cc_true) {
- X#ifdef DEBUGGING
- X debname[dlevel] = 't';
- X debdelim[dlevel++] = '_';
- X#endif
- X retstr = cmd_exec(cmd->ucmd.ccmd.cc_true);
- X }
- X if (!goto_targ) {
- X go_to = Nullch;
- X } else {
- X retstr = &str_no;
- X if (cmd->ucmd.ccmd.cc_alt) {
- X#ifdef DEBUGGING
- X debname[dlevel] = 'e';
- X debdelim[dlevel++] = '_';
- X#endif
- X retstr = cmd_exec(cmd->ucmd.ccmd.cc_alt);
- X }
- X }
- X if (!goto_targ)
- X go_to = Nullch;
- X curspat = oldspat;
- X#ifdef DEBUGGING
- X dlevel = olddlevel;
- X#endif
- X break;
- X case C_BLOCK:
- X case C_WHILE:
- X if (!(cmdflags & CF_ONCE)) {
- X cmdflags |= CF_ONCE;
- X loop_ptr++;
- X loop_stack[loop_ptr].loop_label = cmd->c_label;
- X#ifdef DEBUGGING
- X if (debug & 4) {
- X deb("(Pushing label #%d %s)\n",
- X loop_ptr,cmd->c_label);
- X }
- X#endif
- X }
- X switch (setjmp(loop_stack[loop_ptr].loop_env)) {
- X case O_LAST: /* not done unless go_to found */
- X go_to = Nullch;
- X retstr = &str_no;
- X#ifdef DEBUGGING
- X olddlevel = dlevel;
- X#endif
- X curspat = oldspat;
- X#ifdef DEBUGGING
- X if (debug & 4) {
- X deb("(Popping label #%d %s)\n",loop_ptr,
- X loop_stack[loop_ptr].loop_label);
- X }
- X#endif
- X loop_ptr--;
- X cmd = cmd->c_next;
- X goto tail_recursion_entry;
- X case O_NEXT: /* not done unless go_to found */
- X go_to = Nullch;
- X goto next_iter;
- X case O_REDO: /* not done unless go_to found */
- X go_to = Nullch;
- X goto doit;
- X }
- X oldspat = curspat;
- X#ifdef DEBUGGING
- X olddlevel = dlevel;
- X#endif
- X if (cmd->ucmd.ccmd.cc_true) {
- X#ifdef DEBUGGING
- X debname[dlevel] = 't';
- X debdelim[dlevel++] = '_';
- X#endif
- X cmd_exec(cmd->ucmd.ccmd.cc_true);
- X }
- X if (!goto_targ) {
- X go_to = Nullch;
- X goto next_iter;
- X }
- X#ifdef DEBUGGING
- X dlevel = olddlevel;
- X#endif
- X if (cmd->ucmd.ccmd.cc_alt) {
- X#ifdef DEBUGGING
- X debname[dlevel] = 'a';
- X debdelim[dlevel++] = '_';
- X#endif
- X cmd_exec(cmd->ucmd.ccmd.cc_alt);
- X }
- X if (goto_targ)
- X break;
- X go_to = Nullch;
- X goto finish_while;
- X }
- X cmd = cmd->c_next;
- X if (cmd && cmd->c_head == cmd) /* reached end of while loop */
- X return retstr; /* targ isn't in this block */
- X goto tail_recursion_entry;
- X }
- X }
- X
- Xuntil_loop:
- X
- X#ifdef DEBUGGING
- X if (debug & 2) {
- X deb("%s (%lx) r%lx t%lx a%lx n%lx cs%lx\n",
- X cmdname[cmd->c_type],cmd,cmd->c_expr,
- X cmd->ucmd.ccmd.cc_true,cmd->ucmd.ccmd.cc_alt,cmd->c_next,curspat);
- X }
- X debname[dlevel] = cmdname[cmd->c_type][0];
- X debdelim[dlevel++] = '!';
- X#endif
- X while (tmps_max >= 0) /* clean up after last eval */
- X str_free(tmps_list[tmps_max--]);
- X
- X /* Here is some common optimization */
- X
- X if (cmdflags & CF_COND) {
- X switch (cmdflags & CF_OPTIMIZE) {
- X
- X case CFT_FALSE:
- X retstr = cmd->c_first;
- X match = FALSE;
- X if (cmdflags & CF_NESURE)
- X goto maybe;
- X break;
- X case CFT_TRUE:
- X retstr = cmd->c_first;
- X match = TRUE;
- X if (cmdflags & CF_EQSURE)
- X goto flipmaybe;
- X break;
- X
- X case CFT_REG:
- X retstr = STAB_STR(cmd->c_stab);
- X match = str_true(retstr); /* => retstr = retstr, c2 should fix */
- X if (cmdflags & (match ? CF_EQSURE : CF_NESURE))
- X goto flipmaybe;
- X break;
- X
- X case CFT_ANCHOR: /* /^pat/ optimization */
- X if (multiline) {
- X if (*cmd->c_first->str_ptr && !(cmdflags & CF_EQSURE))
- X goto scanner; /* just unanchor it */
- X else
- X break; /* must evaluate */
- X }
- X /* FALL THROUGH */
- X case CFT_STROP: /* string op optimization */
- X retstr = STAB_STR(cmd->c_stab);
- X if (*cmd->c_first->str_ptr == *str_get(retstr) &&
- X strnEQ(cmd->c_first->str_ptr, str_get(retstr),
- X cmd->c_flen) ) {
- X if (cmdflags & CF_EQSURE) {
- X match = !(cmdflags & CF_FIRSTNEG);
- X retstr = &str_yes;
- X goto flipmaybe;
- X }
- X }
- X else if (cmdflags & CF_NESURE) {
- X match = cmdflags & CF_FIRSTNEG;
- X retstr = &str_no;
- X goto flipmaybe;
- X }
- X break; /* must evaluate */
- X
- X case CFT_SCAN: /* non-anchored search */
- X scanner:
- X retstr = STAB_STR(cmd->c_stab);
- X if (instr(str_get(retstr),cmd->c_first->str_ptr)) {
- X if (cmdflags & CF_EQSURE) {
- X match = !(cmdflags & CF_FIRSTNEG);
- X retstr = &str_yes;
- X goto flipmaybe;
- X }
- X }
- X else if (cmdflags & CF_NESURE) {
- X match = cmdflags & CF_FIRSTNEG;
- X retstr = &str_no;
- X goto flipmaybe;
- X }
- X break; /* must evaluate */
- X
- X case CFT_GETS: /* really a while (<file>) */
- X last_in_stab = cmd->c_stab;
- X fp = last_in_stab->stab_io->fp;
- X retstr = defstab->stab_val;
- X if (fp && str_gets(retstr, fp)) {
- X last_in_stab->stab_io->lines++;
- X match = TRUE;
- X }
- X else if (last_in_stab->stab_io->flags & IOF_ARGV)
- X goto doeval; /* doesn't necessarily count as EOF yet */
- X else {
- X retstr = &str_no;
- X match = FALSE;
- X }
- X goto flipmaybe;
- X case CFT_EVAL:
- X break;
- X case CFT_UNFLIP:
- X retstr = eval(cmd->c_expr,Null(char***));
- X match = str_true(retstr);
- X if (cmd->c_expr->arg_type == O_FLIP) /* undid itself? */
- X cmdflags = copyopt(cmd,cmd->c_expr[3].arg_ptr.arg_cmd);
- X goto maybe;
- X case CFT_CHOP:
- X retstr = cmd->c_stab->stab_val;
- X match = (retstr->str_cur != 0);
- X tmps = str_get(retstr);
- X tmps += retstr->str_cur - match;
- X str_set(&str_chop,tmps);
- X *tmps = '\0';
- X retstr->str_nok = 0;
- X retstr->str_cur = tmps - retstr->str_ptr;
- X retstr = &str_chop;
- X goto flipmaybe;
- X }
- X
- X /* we have tried to make this normal case as abnormal as possible */
- X
- X doeval:
- X retstr = eval(cmd->c_expr,Null(char***));
- X match = str_true(retstr);
- X goto maybe;
- X
- X /* if flipflop was true, flop it */
- X
- X flipmaybe:
- X if (match && cmdflags & CF_FLIP) {
- X if (cmd->c_expr->arg_type == O_FLOP) { /* currently toggled? */
- X retstr = eval(cmd->c_expr,Null(char***)); /* let eval undo it */
- X cmdflags = copyopt(cmd,cmd->c_expr[3].arg_ptr.arg_cmd);
- X }
- X else {
- X retstr = eval(cmd->c_expr,Null(char***)); /* let eval do it */
- X if (cmd->c_expr->arg_type == O_FLOP) /* still toggled? */
- X cmdflags = copyopt(cmd,cmd->c_expr[4].arg_ptr.arg_cmd);
- X }
- X }
- X else if (cmdflags & CF_FLIP) {
- X if (cmd->c_expr->arg_type == O_FLOP) { /* currently toggled? */
- X match = TRUE; /* force on */
- X }
- X }
- X
- X /* at this point, match says whether our expression was true */
- X
- X maybe:
- X if (cmdflags & CF_INVERT)
- X match = !match;
- X if (!match && cmd->c_type != C_IF) {
- X cmd = cmd->c_next;
- X goto tail_recursion_entry;
- X }
- X }
- X
- X /* now to do the actual command, if any */
- X
- X switch (cmd->c_type) {
- X case C_NULL:
- X fatal("panic: cmd_exec\n");
- X case C_EXPR: /* evaluated for side effects */
- X if (cmd->ucmd.acmd.ac_expr) { /* more to do? */
- X retstr = eval(cmd->ucmd.acmd.ac_expr,Null(char***));
- X }
- X break;
- X case C_IF:
- X oldspat = curspat;
- X#ifdef DEBUGGING
- X olddlevel = dlevel;
- X#endif
- X if (match) {
- X retstr = &str_yes;
- X if (cmd->ucmd.ccmd.cc_true) {
- X#ifdef DEBUGGING
- X debname[dlevel] = 't';
- X debdelim[dlevel++] = '_';
- X#endif
- X retstr = cmd_exec(cmd->ucmd.ccmd.cc_true);
- X }
- X }
- X else {
- X retstr = &str_no;
- X if (cmd->ucmd.ccmd.cc_alt) {
- X#ifdef DEBUGGING
- X debname[dlevel] = 'e';
- X debdelim[dlevel++] = '_';
- X#endif
- X retstr = cmd_exec(cmd->ucmd.ccmd.cc_alt);
- X }
- X }
- X curspat = oldspat;
- X#ifdef DEBUGGING
- X dlevel = olddlevel;
- X#endif
- X break;
- X case C_BLOCK:
- X case C_WHILE:
- X if (!(cmdflags & CF_ONCE)) { /* first time through here? */
- X cmdflags |= CF_ONCE;
- X loop_ptr++;
- X loop_stack[loop_ptr].loop_label = cmd->c_label;
- X#ifdef DEBUGGING
- X if (debug & 4) {
- X deb("(Pushing label #%d %s)\n",
- X loop_ptr,cmd->c_label);
- X }
- X#endif
- X }
- X switch (setjmp(loop_stack[loop_ptr].loop_env)) {
- X case O_LAST:
- X retstr = &str_no;
- X curspat = oldspat;
- X#ifdef DEBUGGING
- X if (debug & 4) {
- X deb("(Popping label #%d %s)\n",loop_ptr,
- X loop_stack[loop_ptr].loop_label);
- X }
- X#endif
- X loop_ptr--;
- X cmd = cmd->c_next;
- X goto tail_recursion_entry;
- X case O_NEXT:
- X goto next_iter;
- X case O_REDO:
- X goto doit;
- X }
- X oldspat = curspat;
- X#ifdef DEBUGGING
- X olddlevel = dlevel;
- X#endif
- X doit:
- X if (cmd->ucmd.ccmd.cc_true) {
- X#ifdef DEBUGGING
- X debname[dlevel] = 't';
- X debdelim[dlevel++] = '_';
- X#endif
- X cmd_exec(cmd->ucmd.ccmd.cc_true);
- X }
- X /* actually, this spot is never reached anymore since the above
- X * cmd_exec() returns through longjmp(). Hooray for structure.
- X */
- X next_iter:
- X#ifdef DEBUGGING
- X dlevel = olddlevel;
- X#endif
- X if (cmd->ucmd.ccmd.cc_alt) {
- X#ifdef DEBUGGING
- X debname[dlevel] = 'a';
- X debdelim[dlevel++] = '_';
- X#endif
- X cmd_exec(cmd->ucmd.ccmd.cc_alt);
- X }
- X finish_while:
- X curspat = oldspat;
- X#ifdef DEBUGGING
- X dlevel = olddlevel - 1;
- X#endif
- X if (cmd->c_type != C_BLOCK)
- X goto until_loop; /* go back and evaluate conditional again */
- X }
- X if (cmdflags & CF_LOOP) {
- X cmdflags |= CF_COND; /* now test the condition */
- X goto until_loop;
- X }
- X cmd = cmd->c_next;
- X goto tail_recursion_entry;
- X}
- X
- X#ifdef DEBUGGING
- X/*VARARGS1*/
- Xdeb(pat,a1,a2,a3,a4,a5,a6,a7,a8)
- Xchar *pat;
- X{
- X register int i;
- X
- X for (i=0; i<dlevel; i++)
- X fprintf(stderr,"%c%c ",debname[i],debdelim[i]);
- X fprintf(stderr,pat,a1,a2,a3,a4,a5,a6,a7,a8);
- X}
- X#endif
- X
- Xcopyopt(cmd,which)
- Xregister CMD *cmd;
- Xregister CMD *which;
- X{
- X cmd->c_flags &= CF_ONCE|CF_COND|CF_LOOP;
- X cmd->c_flags |= which->c_flags;
- X cmd->c_first = which->c_first;
- X cmd->c_flen = which->c_flen;
- X cmd->c_stab = which->c_stab;
- X return cmd->c_flags;
- X}
- !STUFFY!FUNK!
- echo Extracting x2p/str.c
- sed >x2p/str.c <<'!STUFFY!FUNK!' -e 's/X//'
- X/* $Header: str.c,v 1.0 87/12/18 13:07:26 root Exp $
- X *
- X * $Log: str.c,v $
- X * Revision 1.0 87/12/18 13:07:26 root
- X * Initial revision
- X *
- X */
- X
- X#include "handy.h"
- X#include "EXTERN.h"
- X#include "util.h"
- X#include "a2p.h"
- X
- Xstr_numset(str,num)
- Xregister STR *str;
- Xdouble num;
- X{
- X str->str_nval = num;
- X str->str_pok = 0; /* invalidate pointer */
- X str->str_nok = 1; /* validate number */
- X}
- X
- Xchar *
- Xstr_2ptr(str)
- Xregister STR *str;
- X{
- X register char *s;
- X
- X if (!str)
- X return "";
- X GROWSTR(&(str->str_ptr), &(str->str_len), 24);
- X s = str->str_ptr;
- X if (str->str_nok) {
- X sprintf(s,"%.20g",str->str_nval);
- X while (*s) s++;
- X }
- X *s = '\0';
- X str->str_cur = s - str->str_ptr;
- X str->str_pok = 1;
- X#ifdef DEBUGGING
- X if (debug & 32)
- X fprintf(stderr,"0x%lx ptr(%s)\n",str,str->str_ptr);
- X#endif
- X return str->str_ptr;
- X}
- X
- Xdouble
- Xstr_2num(str)
- Xregister STR *str;
- X{
- X if (!str)
- X return 0.0;
- X if (str->str_len && str->str_pok)
- X str->str_nval = atof(str->str_ptr);
- X else
- X str->str_nval = 0.0;
- X str->str_nok = 1;
- X#ifdef DEBUGGING
- X if (debug & 32)
- X fprintf(stderr,"0x%lx num(%g)\n",str,str->str_nval);
- X#endif
- X return str->str_nval;
- X}
- X
- Xstr_sset(dstr,sstr)
- XSTR *dstr;
- Xregister STR *sstr;
- X{
- X if (!sstr)
- X str_nset(dstr,No,0);
- X else if (sstr->str_nok)
- X str_numset(dstr,sstr->str_nval);
- X else if (sstr->str_pok)
- X str_nset(dstr,sstr->str_ptr,sstr->str_cur);
- X else
- X str_nset(dstr,"",0);
- X}
- X
- Xstr_nset(str,ptr,len)
- Xregister STR *str;
- Xregister char *ptr;
- Xregister int len;
- X{
- X GROWSTR(&(str->str_ptr), &(str->str_len), len + 1);
- X bcopy(ptr,str->str_ptr,len);
- X str->str_cur = len;
- X *(str->str_ptr+str->str_cur) = '\0';
- X str->str_nok = 0; /* invalidate number */
- X str->str_pok = 1; /* validate pointer */
- X}
- X
- Xstr_set(str,ptr)
- Xregister STR *str;
- Xregister char *ptr;
- X{
- X register int len;
- X
- X if (!ptr)
- X ptr = "";
- X len = strlen(ptr);
- X GROWSTR(&(str->str_ptr), &(str->str_len), len + 1);
- X bcopy(ptr,str->str_ptr,len+1);
- X str->str_cur = len;
- X str->str_nok = 0; /* invalidate number */
- X str->str_pok = 1; /* validate pointer */
- X}
- X
- Xstr_chop(str,ptr) /* like set but assuming ptr is in str */
- Xregister STR *str;
- Xregister char *ptr;
- X{
- X if (!(str->str_pok))
- X str_2ptr(str);
- X str->str_cur -= (ptr - str->str_ptr);
- X bcopy(ptr,str->str_ptr, str->str_cur + 1);
- X str->str_nok = 0; /* invalidate number */
- X str->str_pok = 1; /* validate pointer */
- X}
- X
- Xstr_ncat(str,ptr,len)
- Xregister STR *str;
- Xregister char *ptr;
- Xregister int len;
- X{
- X if (!(str->str_pok))
- X str_2ptr(str);
- X GROWSTR(&(str->str_ptr), &(str->str_len), str->str_cur + len + 1);
- X bcopy(ptr,str->str_ptr+str->str_cur,len);
- X str->str_cur += len;
- X *(str->str_ptr+str->str_cur) = '\0';
- X str->str_nok = 0; /* invalidate number */
- X str->str_pok = 1; /* validate pointer */
- X}
- X
- Xstr_scat(dstr,sstr)
- XSTR *dstr;
- Xregister STR *sstr;
- X{
- X if (!(sstr->str_pok))
- X str_2ptr(sstr);
- X if (sstr)
- X str_ncat(dstr,sstr->str_ptr,sstr->str_cur);
- X}
- X
- Xstr_cat(str,ptr)
- Xregister STR *str;
- Xregister char *ptr;
- X{
- X register int len;
- X
- X if (!ptr)
- X return;
- X if (!(str->str_pok))
- X str_2ptr(str);
- X len = strlen(ptr);
- X GROWSTR(&(str->str_ptr), &(str->str_len), str->str_cur + len + 1);
- X bcopy(ptr,str->str_ptr+str->str_cur,len+1);
- X str->str_cur += len;
- X str->str_nok = 0; /* invalidate number */
- X str->str_pok = 1; /* validate pointer */
- X}
- X
- Xchar *
- Xstr_append_till(str,from,delim,keeplist)
- Xregister STR *str;
- Xregister char *from;
- Xregister int delim;
- Xchar *keeplist;
- X{
- X register char *to;
- X register int len;
- X
- X if (!from)
- X return Nullch;
- X len = strlen(from);
- X GROWSTR(&(str->str_ptr), &(str->str_len), str->str_cur + len + 1);
- X str->str_nok = 0; /* invalidate number */
- X str->str_pok = 1; /* validate pointer */
- X to = str->str_ptr+str->str_cur;
- X for (; *from; from++,to++) {
- X if (*from == '\\' && from[1] && delim != '\\') {
- X if (!keeplist) {
- X if (from[1] == delim || from[1] == '\\')
- X from++;
- X else
- X *to++ = *from++;
- X }
- X else if (index(keeplist,from[1]))
- X *to++ = *from++;
- X else
- X from++;
- X }
- X else if (*from == delim)
- X break;
- X *to = *from;
- X }
- X *to = '\0';
- X str->str_cur = to - str->str_ptr;
- X return from;
- X}
- X
- XSTR *
- Xstr_new(len)
- Xint len;
- X{
- X register STR *str;
- X
- X if (freestrroot) {
- X str = freestrroot;
- X freestrroot = str->str_link.str_next;
- X }
- X else {
- X str = (STR *) safemalloc(sizeof(STR));
- X bzero((char*)str,sizeof(STR));
- X }
- X if (len)
- X GROWSTR(&(str->str_ptr), &(str->str_len), len + 1);
- X return str;
- X}
- X
- Xvoid
- Xstr_grow(str,len)
- Xregister STR *str;
- Xint len;
- X{
- X if (len && str)
- X GROWSTR(&(str->str_ptr), &(str->str_len), len + 1);
- X}
- X
- X/* make str point to what nstr did */
- X
- Xvoid
- Xstr_replace(str,nstr)
- Xregister STR *str;
- Xregister STR *nstr;
- X{
- X safefree(str->str_ptr);
- X str->str_ptr = nstr->str_ptr;
- X str->str_len = nstr->str_len;
- X str->str_cur = nstr->str_cur;
- X str->str_pok = nstr->str_pok;
- X if (str->str_nok = nstr->str_nok)
- X str->str_nval = nstr->str_nval;
- X safefree((char*)nstr);
- X}
- X
- Xvoid
- Xstr_free(str)
- Xregister STR *str;
- X{
- X if (!str)
- X return;
- X if (str->str_len)
- X str->str_ptr[0] = '\0';
- X str->str_cur = 0;
- X str->str_nok = 0;
- X str->str_pok = 0;
- X str->str_link.str_next = freestrroot;
- X freestrroot = str;
- X}
- X
- Xstr_len(str)
- Xregister STR *str;
- X{
- X if (!str)
- X return 0;
- X if (!(str->str_pok))
- X str_2ptr(str);
- X if (str->str_len)
- X return str->str_cur;
- X else
- X return 0;
- X}
- X
- Xchar *
- Xstr_gets(str,fp)
- Xregister STR *str;
- Xregister FILE *fp;
- X{
- X#ifdef STDSTDIO /* Here is some breathtakingly efficient cheating */
- X
- X register char *bp; /* we're going to steal some values */
- X register int cnt; /* from the stdio struct and put EVERYTHING */
- X register char *ptr; /* in the innermost loop into registers */
- X register char newline = '\n'; /* (assuming at least 6 registers) */
- X int i;
- X int bpx;
- X
- X cnt = fp->_cnt; /* get count into register */
- X str->str_nok = 0; /* invalidate number */
- X str->str_pok = 1; /* validate pointer */
- X if (str->str_len <= cnt) /* make sure we have the room */
- X GROWSTR(&(str->str_ptr), &(str->str_len), cnt+1);
- X bp = str->str_ptr; /* move these two too to registers */
- X ptr = fp->_ptr;
- X for (;;) {
- X while (--cnt >= 0) { /* this */ /* eat */
- X if ((*bp++ = *ptr++) == newline) /* really */ /* dust */
- X goto thats_all_folks; /* screams */ /* sed :-) */
- X }
- X
- X fp->_cnt = cnt; /* deregisterize cnt and ptr */
- X fp->_ptr = ptr;
- X i = _filbuf(fp); /* get more characters */
- X cnt = fp->_cnt;
- X ptr = fp->_ptr; /* reregisterize cnt and ptr */
- X
- X bpx = bp - str->str_ptr; /* prepare for possible relocation */
- X GROWSTR(&(str->str_ptr), &(str->str_len), str->str_cur + cnt + 1);
- X bp = str->str_ptr + bpx; /* reconstitute our pointer */
- X
- X if (i == newline) { /* all done for now? */
- X *bp++ = i;
- X goto thats_all_folks;
- X }
- X else if (i == EOF) /* all done for ever? */
- X goto thats_all_folks;
- X *bp++ = i; /* now go back to screaming loop */
- X }
- X
- Xthats_all_folks:
- X fp->_cnt = cnt; /* put these back or we're in trouble */
- X fp->_ptr = ptr;
- X *bp = '\0';
- X str->str_cur = bp - str->str_ptr; /* set length */
- X
- X#else /* !STDSTDIO */ /* The big, slow, and stupid way */
- X
- X static char buf[4192];
- X
- X if (fgets(buf, sizeof buf, fp) != Nullch)
- X str_set(str, buf);
- X else
- X str_set(str, No);
- X
- X#endif /* STDSTDIO */
- X
- X return str->str_cur ? str->str_ptr : Nullch;
- X}
- X
- Xvoid
- Xstr_inc(str)
- Xregister STR *str;
- X{
- X register char *d;
- X
- X if (!str)
- X return;
- X if (str->str_nok) {
- X str->str_nval += 1.0;
- X str->str_pok = 0;
- X return;
- X }
- X if (!str->str_pok) {
- X str->str_nval = 1.0;
- X str->str_nok = 1;
- X return;
- X }
- X for (d = str->str_ptr; *d && *d != '.'; d++) ;
- X d--;
- X if (!isdigit(*str->str_ptr) || !isdigit(*d) ) {
- X str_numset(str,atof(str->str_ptr) + 1.0); /* punt */
- X return;
- X }
- X while (d >= str->str_ptr) {
- X if (++*d <= '9')
- X return;
- X *(d--) = '0';
- X }
- X /* oh,oh, the number grew */
- X GROWSTR(&(str->str_ptr), &(str->str_len), str->str_cur + 2);
- X str->str_cur++;
- X for (d = str->str_ptr + str->str_cur; d > str->str_ptr; d--)
- X *d = d[-1];
- X *d = '1';
- X}
- X
- Xvoid
- Xstr_dec(str)
- Xregister STR *str;
- X{
- X register char *d;
- X
- X if (!str)
- X return;
- X if (str->str_nok) {
- X str->str_nval -= 1.0;
- X str->str_pok = 0;
- X return;
- X }
- X if (!str->str_pok) {
- X str->str_nval = -1.0;
- X str->str_nok = 1;
- X return;
- X }
- X for (d = str->str_ptr; *d && *d != '.'; d++) ;
- X d--;
- X if (!isdigit(*str->str_ptr) || !isdigit(*d) || (*d == '0' && d == str->str_ptr)) {
- X str_numset(str,atof(str->str_ptr) - 1.0); /* punt */
- X return;
- X }
- X while (d >= str->str_ptr) {
- X if (--*d >= '0')
- X return;
- X *(d--) = '9';
- X }
- X}
- X
- X/* make a string that will exist for the duration of the expression eval */
- X
- XSTR *
- Xstr_static(oldstr)
- XSTR *oldstr;
- X{
- X register STR *str = str_new(0);
- X static long tmps_size = -1;
- X
- X str_sset(str,oldstr);
- X if (++tmps_max > tmps_size) {
- X tmps_size = tmps_max;
- X if (!(tmps_size & 127)) {
- X if (tmps_size)
- X tmps_list = (STR**)saferealloc((char*)tmps_list,
- X (tmps_size + 128) * sizeof(STR*) );
- X else
- X tmps_list = (STR**)safemalloc(128 * sizeof(char*));
- X }
- X }
- X tmps_list[tmps_max] = str;
- X return str;
- X}
- X
- XSTR *
- Xstr_make(s)
- Xchar *s;
- X{
- X register STR *str = str_new(0);
- X
- X str_set(str,s);
- X return str;
- X}
- X
- XSTR *
- Xstr_nmake(n)
- Xdouble n;
- X{
- X register STR *str = str_new(0);
- X
- X str_numset(str,n);
- X return str;
- X}
- !STUFFY!FUNK!
- echo Extracting malloc.c
- sed >malloc.c <<'!STUFFY!FUNK!' -e 's/X//'
- X/* $Header: malloc.c,v 1.0 87/12/18 13:05:35 root Exp $
- X *
- X * $Log: malloc.c,v $
- X * Revision 1.0 87/12/18 13:05:35 root
- X * Initial revision
- X *
- X */
- X
- X#ifndef lint
- Xstatic char sccsid[] = "@(#)malloc.c 4.3 (Berkeley) 9/16/83";
- X#endif
- X#include <stdio.h>
- X
- X#define RCHECK
- X/*
- X * malloc.c (Caltech) 2/21/82
- X * Chris Kingsley, kingsley@cit-20.
- X *
- X * This is a very fast storage allocator. It allocates blocks of a small
- X * number of different sizes, and keeps free lists of each size. Blocks that
- X * don't exactly fit are passed up to the next larger size. In this
- X * implementation, the available sizes are 2^n-4 (or 2^n-12) bytes long.
- X * This is designed for use in a program that uses vast quantities of memory,
- X * but bombs when it runs out.
- X */
- X
- X#include <sys/types.h>
- X
- X#define NULL 0
- X
- X/*
- X * The overhead on a block is at least 4 bytes. When free, this space
- X * contains a pointer to the next free block, and the bottom two bits must
- X * be zero. When in use, the first byte is set to MAGIC, and the second
- X * byte is the size index. The remaining bytes are for alignment.
- X * If range checking is enabled and the size of the block fits
- X * in two bytes, then the top two bytes hold the size of the requested block
- X * plus the range checking words, and the header word MINUS ONE.
- X */
- Xunion overhead {
- X union overhead *ov_next; /* when free */
- X struct {
- X u_char ovu_magic; /* magic number */
- X u_char ovu_index; /* bucket # */
- X#ifdef RCHECK
- X u_short ovu_size; /* actual block size */
- X u_int ovu_rmagic; /* range magic number */
- X#endif
- X } ovu;
- X#define ov_magic ovu.ovu_magic
- X#define ov_index ovu.ovu_index
- X#define ov_size ovu.ovu_size
- X#define ov_rmagic ovu.ovu_rmagic
- X};
- X
- X#define MAGIC 0xff /* magic # on accounting info */
- X#define RMAGIC 0x55555555 /* magic # on range info */
- X#ifdef RCHECK
- X#define RSLOP sizeof (u_int)
- X#else
- X#define RSLOP 0
- X#endif
- X
- X/*
- X * nextf[i] is the pointer to the next free block of size 2^(i+3). The
- X * smallest allocatable block is 8 bytes. The overhead information
- X * precedes the data area returned to the user.
- X */
- X#define NBUCKETS 30
- Xstatic union overhead *nextf[NBUCKETS];
- Xextern char *sbrk();
- X
- X#ifdef MSTATS
- X/*
- X * nmalloc[i] is the difference between the number of mallocs and frees
- X * for a given block size.
- X */
- Xstatic u_int nmalloc[NBUCKETS];
- X#include <stdio.h>
- X#endif
- X
- X#ifdef debug
- X#define ASSERT(p) if (!(p)) botch("p"); else
- Xstatic
- Xbotch(s)
- X char *s;
- X{
- X
- X printf("assertion botched: %s\n", s);
- X abort();
- X}
- X#else
- X#define ASSERT(p)
- X#endif
- X
- Xchar *
- Xmalloc(nbytes)
- X register unsigned nbytes;
- X{
- X register union overhead *p;
- X register int bucket = 0;
- X register unsigned shiftr;
- X
- X /*
- X * Convert amount of memory requested into
- X * closest block size stored in hash buckets
- X * which satisfies request. Account for
- X * space used per block for accounting.
- X */
- X nbytes += sizeof (union overhead) + RSLOP;
- X nbytes = (nbytes + 3) &~ 3;
- X shiftr = (nbytes - 1) >> 2;
- X /* apart from this loop, this is O(1) */
- X while (shiftr >>= 1)
- X bucket++;
- X /*
- X * If nothing in hash bucket right now,
- X * request more memory from the system.
- X */
- X if (nextf[bucket] == NULL)
- X morecore(bucket);
- X if ((p = (union overhead *)nextf[bucket]) == NULL)
- X return (NULL);
- X /* remove from linked list */
- X if (*((int*)p) > 0x10000000)
- X fprintf(stderr,"Corrupt malloc ptr 0x%x at 0x%x\n",*((int*)p),p);
- X nextf[bucket] = nextf[bucket]->ov_next;
- X p->ov_magic = MAGIC;
- X p->ov_index= bucket;
- X#ifdef MSTATS
- X nmalloc[bucket]++;
- X#endif
- X#ifdef RCHECK
- X /*
- X * Record allocated size of block and
- X * bound space with magic numbers.
- X */
- X if (nbytes <= 0x10000)
- X p->ov_size = nbytes - 1;
- X p->ov_rmagic = RMAGIC;
- X *((u_int *)((caddr_t)p + nbytes - RSLOP)) = RMAGIC;
- X#endif
- X return ((char *)(p + 1));
- X}
- X
- X/*
- X * Allocate more memory to the indicated bucket.
- X */
- Xstatic
- Xmorecore(bucket)
- X register bucket;
- X{
- X register union overhead *op;
- X register int rnu; /* 2^rnu bytes will be requested */
- X register int nblks; /* become nblks blocks of the desired size */
- X register int siz;
- X
- X if (nextf[bucket])
- X return;
- X /*
- X * Insure memory is allocated
- X * on a page boundary. Should
- X * make getpageize call?
- X */
- X op = (union overhead *)sbrk(0);
- X if ((int)op & 0x3ff)
- X sbrk(1024 - ((int)op & 0x3ff));
- X /* take 2k unless the block is bigger than that */
- X rnu = (bucket <= 8) ? 11 : bucket + 3;
- X nblks = 1 << (rnu - (bucket + 3)); /* how many blocks to get */
- X if (rnu < bucket)
- X rnu = bucket;
- X op = (union overhead *)sbrk(1 << rnu);
- X /* no more room! */
- X if ((int)op == -1)
- X return;
- X /*
- X * Round up to minimum allocation size boundary
- X * and deduct from block count to reflect.
- X */
- X if ((int)op & 7) {
- X op = (union overhead *)(((int)op + 8) &~ 7);
- X nblks--;
- X }
- X /*
- X * Add new memory allocated to that on
- X * free list for this hash bucket.
- X */
- X nextf[bucket] = op;
- X siz = 1 << (bucket + 3);
- X while (--nblks > 0) {
- X op->ov_next = (union overhead *)((caddr_t)op + siz);
- X op = (union overhead *)((caddr_t)op + siz);
- X }
- X}
- X
- Xfree(cp)
- X char *cp;
- X{
- X register int size;
- X register union overhead *op;
- X
- X if (cp == NULL)
- X return;
- X op = (union overhead *)((caddr_t)cp - sizeof (union overhead));
- X#ifdef debug
- X ASSERT(op->ov_magic == MAGIC); /* make sure it was in use */
- X#else
- X if (op->ov_magic != MAGIC)
- X return; /* sanity */
- X#endif
- X#ifdef RCHECK
- X ASSERT(op->ov_rmagic == RMAGIC);
- X if (op->ov_index <= 13)
- X ASSERT(*(u_int *)((caddr_t)op + op->ov_size + 1 - RSLOP) == RMAGIC);
- X#endif
- X ASSERT(op->ov_index < NBUCKETS);
- X size = op->ov_index;
- X op->ov_next = nextf[size];
- X nextf[size] = op;
- X#ifdef MSTATS
- X nmalloc[size]--;
- X#endif
- X}
- X
- X/*
- X * When a program attempts "storage compaction" as mentioned in the
- X * old malloc man page, it realloc's an already freed block. Usually
- X * this is the last block it freed; occasionally it might be farther
- X * back. We have to search all the free lists for the block in order
- X * to determine its bucket: 1st we make one pass thru the lists
- X * checking only the first block in each; if that fails we search
- X * ``realloc_srchlen'' blocks in each list for a match (the variable
- X * is extern so the caller can modify it). If that fails we just copy
- X * however many bytes was given to realloc() and hope it's not huge.
- X */
- Xint realloc_srchlen = 4; /* 4 should be plenty, -1 =>'s whole list */
- X
- Xchar *
- Xrealloc(cp, nbytes)
- X char *cp;
- X unsigned nbytes;
- X{
- X register u_int onb;
- X union overhead *op;
- X char *res;
- X register int i;
- X int was_alloced = 0;
- X
- X if (cp == NULL)
- X return (malloc(nbytes));
- X op = (union overhead *)((caddr_t)cp - sizeof (union overhead));
- X if (op->ov_magic == MAGIC) {
- X was_alloced++;
- X i = op->ov_index;
- X } else {
- X /*
- X * Already free, doing "compaction".
- X *
- X * Search for the old block of memory on the
- X * free list. First, check the most common
- X * case (last element free'd), then (this failing)
- X * the last ``realloc_srchlen'' items free'd.
- X * If all lookups fail, then assume the size of
- X * the memory block being realloc'd is the
- X * smallest possible.
- X */
- X if ((i = findbucket(op, 1)) < 0 &&
- X (i = findbucket(op, realloc_srchlen)) < 0)
- X i = 0;
- X }
- X onb = (1 << (i + 3)) - sizeof (*op) - RSLOP;
- X /* avoid the copy if same size block */
- X if (was_alloced &&
- X nbytes <= onb && nbytes > (onb >> 1) - sizeof(*op) - RSLOP)
- X return(cp);
- X if ((res = malloc(nbytes)) == NULL)
- X return (NULL);
- X if (cp != res) /* common optimization */
- X bcopy(cp, res, (nbytes < onb) ? nbytes : onb);
- X if (was_alloced)
- X free(cp);
- X return (res);
- X}
- X
- X/*
- X * Search ``srchlen'' elements of each free list for a block whose
- X * header starts at ``freep''. If srchlen is -1 search the whole list.
- X * Return bucket number, or -1 if not found.
- X */
- Xstatic
- Xfindbucket(freep, srchlen)
- X union overhead *freep;
- X int srchlen;
- X{
- X register union overhead *p;
- X register int i, j;
- X
- X for (i = 0; i < NBUCKETS; i++) {
- X j = 0;
- X for (p = nextf[i]; p && j != srchlen; p = p->ov_next) {
- X if (p == freep)
- X return (i);
- X j++;
- X }
- X }
- X return (-1);
- X}
- X
- X#ifdef MSTATS
- X/*
- X * mstats - print out statistics about malloc
- X *
- X * Prints two lines of numbers, one showing the length of the free list
- X * for each size category, the second showing the number of mallocs -
- X * frees for each size category.
- X */
- Xmstats(s)
- X char *s;
- X{
- X register int i, j;
- X register union overhead *p;
- X int totfree = 0,
- X totused = 0;
- X
- X fprintf(stderr, "Memory allocation statistics %s\nfree:\t", s);
- X for (i = 0; i < NBUCKETS; i++) {
- X for (j = 0, p = nextf[i]; p; p = p->ov_next, j++)
- X ;
- X fprintf(stderr, " %d", j);
- X totfree += j * (1 << (i + 3));
- X }
- X fprintf(stderr, "\nused:\t");
- X for (i = 0; i < NBUCKETS; i++) {
- X fprintf(stderr, " %d", nmalloc[i]);
- X totused += nmalloc[i] * (1 << (i + 3));
- X }
- X fprintf(stderr, "\n\tTotal in use: %d, total free: %d\n",
- X totused, totfree);
- X}
- X#endif
- !STUFFY!FUNK!
- echo Extracting t/cmd.while
- sed >t/cmd.while <<'!STUFFY!FUNK!' -e 's/X//'
- X#!./perl
- X
- X# $Header: cmd.while,v 1.0 87/12/18 13:12:15 root Exp $
- X
- Xprint "1..10\n";
- X
- Xopen (tmp,'>Cmd.while.tmp') || die "Can't create Cmd.while.tmp.";
- Xprint tmp "tvi925\n";
- Xprint tmp "tvi920\n";
- Xprint tmp "vt100\n";
- Xprint tmp "Amiga\n";
- Xprint tmp "paper\n";
- Xclose tmp;
- X
- X# test "last" command
- X
- Xopen(fh,'Cmd.while.tmp') || die "Can't open Cmd.while.tmp.";
- Xwhile (<fh>) {
- X last if /vt100/;
- X}
- Xif (!eof && /vt100/) {print "ok 1\n";} else {print "not ok 1\n";}
- X
- X# test "next" command
- X
- X$bad = '';
- Xopen(fh,'Cmd.while.tmp') || die "Can't open Cmd.while.tmp.";
- Xwhile (<fh>) {
- X next if /vt100/;
- X $bad = 1 if /vt100/;
- X}
- Xif (!eof || /vt100/ || $bad) {print "not ok 2\n";} else {print "ok 2\n";}
- X
- X# test "redo" command
- X
- X$bad = '';
- Xopen(fh,'Cmd.while.tmp') || die "Can't open Cmd.while.tmp.";
- Xwhile (<fh>) {
- X if (s/vt100/VT100/g) {
- X s/VT100/Vt100/g;
- X redo;
- X }
- X $bad = 1 if /vt100/;
- X $bad = 1 if /VT100/;
- X}
- Xif (!eof || $bad) {print "not ok 3\n";} else {print "ok 3\n";}
- X
- X# now do the same with a label and a continue block
- X
- X# test "last" command
- X
- X$badcont = '';
- Xopen(fh,'Cmd.while.tmp') || die "Can't open Cmd.while.tmp.";
- Xline: while (<fh>) {
- X if (/vt100/) {last line;}
- X} continue {
- X $badcont = 1 if /vt100/;
- X}
- Xif (!eof && /vt100/) {print "ok 4\n";} else {print "not ok 4\n";}
- Xif (!$badcont) {print "ok 5\n";} else {print "not ok 5\n";}
- X
- X# test "next" command
- X
- X$bad = '';
- X$badcont = 1;
- Xopen(fh,'Cmd.while.tmp') || die "Can't open Cmd.while.tmp.";
- Xentry: while (<fh>) {
- X next entry if /vt100/;
- X $bad = 1 if /vt100/;
- X} continue {
- X $badcont = '' if /vt100/;
- X}
- Xif (!eof || /vt100/ || $bad) {print "not ok 6\n";} else {print "ok 6\n";}
- Xif (!$badcont) {print "ok 7\n";} else {print "not ok 7\n";}
- X
- X# test "redo" command
- X
- X$bad = '';
- X$badcont = '';
- Xopen(fh,'Cmd.while.tmp') || die "Can't open Cmd.while.tmp.";
- Xloop: while (<fh>) {
- X if (s/vt100/VT100/g) {
- X s/VT100/Vt100/g;
- X redo loop;
- X }
- X $bad = 1 if /vt100/;
- X $bad = 1 if /VT100/;
- X} continue {
- X $badcont = 1 if /vt100/;
- X}
- Xif (!eof || $bad) {print "not ok 8\n";} else {print "ok 8\n";}
- Xif (!$badcont) {print "ok 9\n";} else {print "not ok 9\n";}
- X
- X`/bin/rm -f Cmd.while.tmp`;
- X
- X#$x = 0;
- X#while (1) {
- X# if ($x > 1) {last;}
- X# next;
- X#} continue {
- X# if ($x++ > 10) {last;}
- X# next;
- X#}
- X#
- X#if ($x < 10) {print "ok 10\n";} else {print "not ok 10\n";}
- X
- X$i = 9;
- X{
- X $i++;
- X}
- Xprint "ok $i\n";
- !STUFFY!FUNK!
- echo Extracting t/op.push
- sed >t/op.push <<'!STUFFY!FUNK!' -e 's/X//'
- X#!./perl
- X
- X# $Header: op.push,v 1.0 87/12/18 13:14:10 root Exp $
- X
- Xprint "1..2\n";
- X
- X@x = (1,2,3);
- Xpush(@x,@x);
- Xif (join(x,':') eq '1:2:3:1:2:3') {print "ok 1\n";} else {print "not ok 1\n";}
- Xpush(x,4);
- Xif (join(x,':') eq '1:2:3:1:2:3:4') {print "ok 2\n";} else {print "not ok 2\n";}
- !STUFFY!FUNK!
- echo ""
- echo "End of kit 7 (of 10)"
- cat /dev/null >kit7isdone
- config=true
- for iskit in 1 2 3 4 5 6 7 8 9 10; do
- if test -f kit${iskit}isdone; then
- echo "You have run kit ${iskit}."
- else
- echo "You still need to run kit ${iskit}."
- config=false
- fi
- done
- case $config in
- true)
- echo "You have run all your kits. Please read README and then type Configure."
- chmod 755 Configure
- ;;
- esac
- : Someone might mail this, so...
- exit
-