コード例 #1
0
ファイル: trie.c プロジェクト: krishpop/LZW
int pruneT(Trie* st, Trie *newst, int e, int oldstCodes)
{
    // if escape flag, start from 3 without checking if reserved.
    int newCount = (e) ? 3 : 259; // codeCount of new string table
    // index of old trie we are iterating thru to copy
    int oldindex = (e) ? 3 : 259;
    // copy the appearances of the first 256 non-reserved codes
    for(int i=3; i<newCount; i++){
        (*newst)[i].appearances = (*st)[i].appearances/2;
    }

    while(oldindex < oldstCodes) {
        if(((*st)[oldindex].appearances/2)) {
            if(filledTable(newCount+1)){
                expandT(newst, (newCount+1)*2);
            }
            addT(newst, (*st)[oldindex].prefix, (*st)[oldindex].suffix,
                newCount);
            (*newst)[newCount].appearances = (*st)[oldindex].appearances/2;
            
            for(int i=0; i<(*st)[oldindex].childCount; i++){
                ((*st)[(*st)[oldindex].children[i]]).prefix = newCount;
            }
            newCount++;
        }
        oldindex++;
    }
    return newCount;
}
コード例 #2
0
ファイル: macro.c プロジェクト: xrg/RPM
/**
 * Execute macro primitives.
 * @param mb		macro expansion state
 * @param negate	should logic be inverted?
 * @param f		beginning of field f
 * @param fn		length of field f
 * @param g		beginning of field g
 * @param gn		length of field g
 */
static void
doFoo(MacroBuf mb, int negate, const char * f, size_t fn,
		const char * g, size_t gn)
{
    size_t blen = MACROBUFSIZ + fn + gn;
    char *buf = xmalloc(blen);
    char *b = NULL, *be;
    int c;

    buf[0] = '\0';
    if (g != NULL) {
	strncpy(buf, g, gn);
	buf[gn] = '\0';
	(void) expandU(mb, buf, blen);
    }
    if (STREQ("basename", f, fn)) {
	if ((b = strrchr(buf, '/')) == NULL)
	    b = buf;
	else
	    b++;
#if NOTYET
    /* XXX watchout for conflict with %dir */
    } else if (STREQ("dirname", f, fn)) {
	if ((b = strrchr(buf, '/')) != NULL)
	    *b = '\0';
	b = buf;
#endif
    } else if (STREQ("suffix", f, fn)) {
	if ((b = strrchr(buf, '.')) != NULL)
	    b++;
    } else if (STREQ("expand", f, fn)) {
	b = buf;
    } else if (STREQ("verbose", f, fn)) {
	if (negate)
	    b = (rpmIsVerbose() ? NULL : buf);
	else
	    b = (rpmIsVerbose() ? buf : NULL);
    } else if (STREQ("url2path", f, fn) || STREQ("u2p", f, fn)) {
	(void)urlPath(buf, (const char **)&b);
	if (*b == '\0') b = "/";
    } else if (STREQ("uncompress", f, fn)) {
	rpmCompressedMagic compressed = COMPRESSED_OTHER;
	for (b = buf; (c = *b) && isblank(c);)
	    b++;
	for (be = b; (c = *be) && !isblank(c);)
	    be++;
	*be++ = '\0';
	(void) rpmFileIsCompressed(b, &compressed);
	switch(compressed) {
	default:
	case COMPRESSED_NOT:
	    sprintf(be, "%%__cat %s", b);
	    break;
	case COMPRESSED_OTHER:
	    sprintf(be, "%%__gzip -dc %s", b);
	    break;
	case COMPRESSED_BZIP2:
	    sprintf(be, "%%__bzip2 -dc %s", b);
	    break;
	case COMPRESSED_ZIP:
	    sprintf(be, "%%__unzip %s", b);
	    break;
        case COMPRESSED_LZMA:
            sprintf(be, "%%__lzma -dc %s", b);
            break;
	}
	b = be;
    } else if (STREQ("getenv", f, fn)) {
	b = getenv(buf);
    } else if (STREQ("S", f, fn)) {
	for (b = buf; (c = *b) && risdigit(c);)
	    b++;
	if (!c) {	/* digit index */
	    b++;
	    sprintf(b, "%%SOURCE%s", buf);
	} else
	    b = buf;
    } else if (STREQ("P", f, fn)) {
	for (b = buf; (c = *b) && risdigit(c);)
	    b++;
	if (!c) {	/* digit index */
	    b++;
	    sprintf(b, "%%PATCH%s", buf);
	} else
			b = buf;
    } else if (STREQ("F", f, fn)) {
	b = buf + strlen(buf) + 1;
	sprintf(b, "file%s.file", buf);
    }

    if (b) {
	(void) expandT(mb, b, strlen(b));
    }
    free(buf);
}
コード例 #3
0
ファイル: lzw.c プロジェクト: krishpop/LZW
// encodes the input stream by taking advantage of lzw algorithm
// also implements logic to prune the trie structure used to store the string
// table, and escapes single character codes
void encode(int e, int m, int p) {
    Trie st;
    createT(&st, e);
    int c = EMPTY;                    // same as (EMPTY, K), index of the prefix

    // int value of char k we are testing to see if c,k exists in the table
    int k;

    // number of codes you have inserted, 256 without escape flag...
    int codeCount = (e) ? 3 : 259;
    int bitCount = (e) ? 2 : 9;
    int maxbits = (m<=8 || m>20) ? 12 : m;
    int maxcodes = (1 << maxbits);
    int firstRead = false;   // if first read of k when e flag is present

    int pruneCount = 0;

    printf("%02d:%d:%d:", maxbits, p, e);
    while((k = getchar())!= EOF) {
        st[c].appearances++;
        int ck = searchT(&st, c, k, e);    // will increment c's appearance once

        // if ck is not in the table
        if(ck<0) {
            // if prune flag & reached maxcodes, do a prune before next insert
            // into the table, putBits 0 to indicate a prune has occurred
            // a prune should likewise happen in decode
            if(c!=EMPTY) {
                putBits(bitCount, c);
            }
            // add ck to the table as long as (e && c == EMPTY) is false
            // we will add (empty, k) to the table after this condition
            // !e and c==EMPTY will never happen, bc all chars will have been
            // added as children to empty

            // prune right before we reach maxcodes, we would have lost the next
            // code we insert anyways, now we won't lose k
            if(p&&(codeCount+1==maxcodes)) {
                putBits(bitCount, 0);
                pruneCount++;
                Trie newst;
                createT(&newst, e);
                int oldCodeCount = codeCount;
                codeCount=pruneT(&st, &newst, e, oldCodeCount);
                destroyT(&st, oldCodeCount);
                st = newst;
                bitCount=codeLength(codeCount);
                c=EMPTY;
                ungetc(k, stdin);
                continue;
            }
            //
            if(!e || c!=EMPTY) {
                if(codeCount<maxcodes) {
                    if(tableFilled(codeCount+1)) {
                        int newSize = (codeCount+1)*2;
                        expandT(&st, newSize);
                        bitCount++;
                    }
                    addT(&st, c, k, codeCount);
                    codeCount++;
                }
            }
            // if escape flag is on and k is not yet added to the table
            if(e && searchT(&st, EMPTY, k, e) < 0) {
                putBits(bitCount, ESC); // 1 is the index of escape character
                putBits(8, k);
                if(codeCount<maxcodes) {
                    if(codeLength(codeCount+1)-codeLength(codeCount)) {
                        int newSize = (codeCount+1)*2;
                        expandT(&st, newSize);
                        bitCount++;
                    }
                    addT(&st, EMPTY, k, codeCount);
                    codeCount++;
                }
                firstRead=true; // encode escaped something, don't unget(k)
                // if this happens
            }

            c = EMPTY; // make c empty again
            if(!firstRead) {
                ungetc(k, stdin);   // put k back to start reading
            }
            // a new character
            else {
                firstRead = false;
            }
        }
        else {
            c=ck; // set c to index of next code
        }
    }


    if(c!=EMPTY) {
        putBits(bitCount, c);
    }

    putBits(bitCount, EOFILE);   // puts EOF
    flushBits();
    destroyT(&st, codeCount);
}
コード例 #4
0
ファイル: macro.c プロジェクト: xrg/RPM
/**
 * The main macro recursion loop.
 * @todo Dynamically reallocate target buffer.
 * @param mb		macro expansion state
 * @return		0 on success, 1 on failure
 */
static int
expandMacro(MacroBuf mb)
{
    rpmMacroEntry *mep;
    rpmMacroEntry me;
    const char *s = mb->s, *se;
    const char *f, *fe;
    const char *g, *ge;
    size_t fn, gn;
    char *t = mb->t;	/* save expansion pointer for printExpand */
    int c;
    int rc = 0;
    int negate;
    const char * lastc;
    int chkexist;

    if (++mb->depth > max_macro_depth) {
	rpmlog(RPMLOG_ERR,
		_("Recursion depth(%d) greater than max(%d)\n"),
		mb->depth, max_macro_depth);
	mb->depth--;
	mb->expand_trace = 1;
	return 1;
    }

    while (rc == 0 && mb->nb > 0 && (c = *s) != '\0') {
	s++;
	/* Copy text until next macro */
	switch(c) {
	case '%':
		if (*s) {	/* Ensure not end-of-string. */
		    if (*s != '%')
			break;
		    s++;	/* skip first % in %% */
		}
	default:
		SAVECHAR(mb, c);
		continue;
		break;
	}

	/* Expand next macro */
	f = fe = NULL;
	g = ge = NULL;
	if (mb->depth > 1)	/* XXX full expansion for outermost level */
		t = mb->t;	/* save expansion pointer for printExpand */
	negate = 0;
	lastc = NULL;
	chkexist = 0;
	switch ((c = *s)) {
	default:		/* %name substitution */
		while (strchr("!?", *s) != NULL) {
			switch(*s++) {
			case '!':
				negate = ((negate + 1) % 2);
				break;
			case '?':
				chkexist++;
				break;
			}
		}
		f = se = s;
		if (*se == '-')
			se++;
		while((c = *se) && (risalnum(c) || c == '_'))
			se++;
		/* Recognize non-alnum macros too */
		switch (*se) {
		case '*':
			se++;
			if (*se == '*') se++;
			break;
		case '#':
			se++;
			break;
		default:
			break;
		}
		fe = se;
		/* For "%name " macros ... */
		if ((c = *fe) && isblank(c))
			if ((lastc = strchr(fe,'\n')) == NULL)
                lastc = strchr(fe, '\0');
		break;
	case '(':		/* %(...) shell escape */
		if ((se = matchchar(s, c, ')')) == NULL) {
			rpmlog(RPMLOG_ERR,
				_("Unterminated %c: %s\n"), (char)c, s);
			rc = 1;
			continue;
		}
		if (mb->macro_trace)
			printMacro(mb, s, se+1);

		s++;	/* skip ( */
		rc = doShellEscape(mb, s, (se - s));
		se++;	/* skip ) */

		s = se;
		continue;
		break;
	case '{':		/* %{...}/%{...:...} substitution */
		if ((se = matchchar(s, c, '}')) == NULL) {
			rpmlog(RPMLOG_ERR,
				_("Unterminated %c: %s\n"), (char)c, s);
			rc = 1;
			continue;
		}
		f = s+1;/* skip { */
		se++;	/* skip } */
		while (strchr("!?", *f) != NULL) {
			switch(*f++) {
			case '!':
				negate = ((negate + 1) % 2);
				break;
			case '?':
				chkexist++;
				break;
			}
		}
		for (fe = f; (c = *fe) && !strchr(" :}", c);)
			fe++;
		switch (c) {
		case ':':
			g = fe + 1;
			ge = se - 1;
			break;
		case ' ':
			lastc = se-1;
			break;
		default:
			break;
		}
		break;
	}

	/* XXX Everything below expects fe > f */
	fn = (fe - f);
	gn = (ge - g);
	if ((fe - f) <= 0) {
/* XXX Process % in unknown context */
		c = '%';	/* XXX only need to save % */
		SAVECHAR(mb, c);
#if 0
		rpmlog(RPMLOG_ERR,
			_("A %% is followed by an unparseable macro\n"));
#endif
		s = se;
		continue;
	}

	if (mb->macro_trace)
		printMacro(mb, s, se);

	/* Expand builtin macros */
	if (STREQ("global", f, fn)) {
		s = doDefine(mb, se, RMIL_GLOBAL, 1);
		continue;
	}
	if (STREQ("define", f, fn)) {
		s = doDefine(mb, se, mb->depth, 0);
		continue;
	}
	if (STREQ("undefine", f, fn)) {
		s = doUndefine(mb->mc, se);
		continue;
	}

	if (STREQ("echo", f, fn) ||
	    STREQ("warn", f, fn) ||
	    STREQ("error", f, fn)) {
		int waserror = 0;
		if (STREQ("error", f, fn))
			waserror = 1;
		if (g != NULL && g < ge)
			doOutput(mb, waserror, g, gn);
		else
			doOutput(mb, waserror, f, fn);
		s = se;
		continue;
	}

	if (STREQ("trace", f, fn)) {
		/* XXX TODO restore expand_trace/macro_trace to 0 on return */
		mb->expand_trace = mb->macro_trace = (negate ? 0 : mb->depth);
		if (mb->depth == 1) {
			print_macro_trace = mb->macro_trace;
			print_expand_trace = mb->expand_trace;
		}
		s = se;
		continue;
	}

	if (STREQ("dump", f, fn)) {
		rpmDumpMacroTable(mb->mc, NULL);
		while (iseol(*se))
			se++;
		s = se;
		continue;
	}

#ifdef	WITH_LUA
	if (STREQ("lua", f, fn)) {
		rpmlua lua = NULL; /* Global state. */
		const char *ls = s+sizeof("{lua:")-1;
		const char *lse = se-sizeof("}")+1;
		char *scriptbuf = (char *)xmalloc((lse-ls)+1);
		const char *printbuf;
		memcpy(scriptbuf, ls, lse-ls);
		scriptbuf[lse-ls] = '\0';
		rpmluaSetPrintBuffer(lua, 1);
		if (rpmluaRunScript(lua, scriptbuf, NULL) == -1)
		    rc = 1;
		printbuf = rpmluaGetPrintBuffer(lua);
		if (printbuf) {
		    size_t len = strlen(printbuf);
		    if (len > mb->nb)
			len = mb->nb;
		    memcpy(mb->t, printbuf, len);
		    mb->t += len;
		    mb->nb -= len;
		}
		rpmluaSetPrintBuffer(lua, 0);
		free(scriptbuf);
		s = se;
		continue;
	}
#endif

	/* XXX necessary but clunky */
	if (STREQ("basename", f, fn) ||
	    STREQ("suffix", f, fn) ||
	    STREQ("expand", f, fn) ||
	    STREQ("verbose", f, fn) ||
	    STREQ("uncompress", f, fn) ||
	    STREQ("url2path", f, fn) ||
	    STREQ("u2p", f, fn) ||
	    STREQ("getenv", f, fn) ||
	    STREQ("S", f, fn) ||
	    STREQ("P", f, fn) ||
	    STREQ("F", f, fn)) {
		/* FIX: verbose may be set */
		doFoo(mb, negate, f, fn, g, gn);
		s = se;
		continue;
	}

	/* Expand defined macros */
	mep = findEntry(mb->mc, f, fn);
	me = (mep ? *mep : NULL);

	/* XXX Special processing for flags */
	if (*f == '-') {
		if (me)
			me->used++;	/* Mark macro as used */
		if ((me == NULL && !negate) ||	/* Without -f, skip %{-f...} */
		    (me != NULL && negate)) {	/* With -f, skip %{!-f...} */
			s = se;
			continue;
		}

		if (g && g < ge) {		/* Expand X in %{-f:X} */
			rc = expandT(mb, g, gn);
		} else
		if (me && me->body && *me->body) {/* Expand %{-f}/%{-f*} */
			rc = expandT(mb, me->body, strlen(me->body));
		}
		s = se;
		continue;
	}

	/* XXX Special processing for macro existence */
	if (chkexist) {
		if ((me == NULL && !negate) ||	/* Without -f, skip %{?f...} */
		    (me != NULL && negate)) {	/* With -f, skip %{!?f...} */
			s = se;
			continue;
		}
		if (g && g < ge) {		/* Expand X in %{?f:X} */
			rc = expandT(mb, g, gn);
		} else
		if (me && me->body && *me->body) { /* Expand %{?f}/%{?f*} */
			rc = expandT(mb, me->body, strlen(me->body));
		}
		s = se;
		continue;
	}
	
	if (me == NULL) {	/* leave unknown %... as is */
#ifndef HACK
#if DEAD
		/* XXX hack to skip over empty arg list */
		if (fn == 1 && *f == '*') {
			s = se;
			continue;
		}
#endif
		/* XXX hack to permit non-overloaded %foo to be passed */
		c = '%';	/* XXX only need to save % */
		SAVECHAR(mb, c);
#else
		rpmlog(RPMLOG_ERR,
			_("Macro %%%.*s not found, skipping\n"), fn, f);
		s = se;
#endif
		continue;
	}

	/* Setup args for "%name " macros with opts */
	if (me && me->opts != NULL) {
		if (lastc != NULL) {
			se = grabArgs(mb, me, fe, lastc);
		} else {
			addMacro(mb->mc, "**", NULL, "", mb->depth);
			addMacro(mb->mc, "*", NULL, "", mb->depth);
			addMacro(mb->mc, "#", NULL, "0", mb->depth);
			addMacro(mb->mc, "0", NULL, me->name, mb->depth);
		}
	}

	/* Recursively expand body of macro */
	if (me->body && *me->body) {
		mb->s = me->body;
		rc = expandMacro(mb);
		if (rc == 0)
			me->used++;	/* Mark macro as used */
	}

	/* Free args for "%name " macros with opts */
	if (me->opts != NULL)
		freeArgs(mb);

	s = se;
    }

    *mb->t = '\0';
    mb->s = s;
    mb->depth--;
    if (rc != 0 || mb->expand_trace)
	printExpansion(mb, t, mb->t);
    return rc;
}
コード例 #5
0
ファイル: lzw.c プロジェクト: krishpop/LZW
// decodes using lzw algorithm
void decode() {
    int code, newcode;
    int maxbits = getFlags(2);
    int maxcodes = (1 << maxbits);

    int p = getFlags(1);
    int e = getFlags(1);

    Trie st;
    createT(&st, e);

    int bitCount = (e) ? 2 : 9;
    int codeCount = (e) ? 3 : 259;

    int oldc = EMPTY;
    bool kwk = false;
    char baseK;
    int pruneCount=0, kwkcount=0;

    while((newcode=code=getBits(bitCount))!=EOFILE) {

        // under these conditions, a valid prune can occur
        if(p && code==EMPTY) {
            pruneCount++;

            Trie newst;
            createT(&newst, e);
            int oldCodeCount=codeCount;
            codeCount=pruneT(&st, &newst, e, oldCodeCount);
            destroyT(&st, oldCodeCount);
            st=newst;
            bitCount=codeLength(codeCount);
            oldc=EMPTY;
            continue;
        }

        if(newcode>=codeCount+1) {
            ERROR("code impossible to decode\n");
        }
        // read an escaped character
        else if(e && code==ESC) {
            if(tableFilled(codeCount+1)&&bitCount!=codeLength(codeCount+1)) {
                if(bitCount<maxbits) {
                    bitCount++;
                }
            }
            code=getBits(8);
            baseK=(char)code;
            putchar(baseK);
            if(codeCount<maxcodes) {
                if(tableFilled(codeCount+1)) {
                    expandT(&st, (codeCount)*2);
                }
                addT(&st, oldc, code, codeCount);
                codeCount++;
                // then we need to add the char k as it's own code
                if(oldc!=EMPTY) {
                    if(tableFilled(codeCount+1)) {
                        expandT(&st, (codeCount)*2);
                    }
                    addT(&st, EMPTY, code, codeCount);
                    codeCount++;
                    if(tableFilled(codeCount)&&bitCount!=codeLength(codeCount)) {
                        if(bitCount<maxbits) {
                            bitCount++;
                        }
                    }
                }
            }
            oldc=EMPTY;
        }

        else { // no escape character called, would read c and k normally
            if(newcode==codeCount) {
                kwk=true;
                code=oldc; // omega, need to print k after
            }
            baseK=outputCode(&st, code, true);
            if(kwk) {
                putchar(baseK);
                kwkcount++;
            }
            // oldc is empty on the first read, and when the e-flag is present
            // oldc is zero when the last character read was escaped
            if(oldc!=EMPTY) {
                if(codeCount<maxcodes) {
                    if(tableFilled(codeCount+1)) {
                        expandT(&st, (codeCount)*2);
                    }
                    addT(&st, oldc, (int)baseK, codeCount);
                    codeCount++;
                    if(kwk) {
                        // we added kwk after seeing it once already in the prev
                        // scan through so we should increase its number of apps
                        st[newcode].appearances++;
                        // this scenario means we have kkk, without w in between
                        // so
                        if(st[st[oldc].prefix].prefix==EMPTY&&kwkcount==1) {
                            st[oldc].appearances--;
                        }
                        kwk=false;
                    }
                    if(tableFilled(codeCount+1)) {
                        if(bitCount<maxbits&&bitCount!=codeLength(codeCount+1)) {
                            bitCount++;
                        }
                    }
                }
            } else if(e) {
                // if e-flag & last char was excaped, increase bit count if
                // table is filled now
                if(tableFilled(codeCount+1)) {
                    if(bitCount<maxbits) {
                        bitCount++;
                    }
                }
            }
            oldc = newcode;
        }
    }
    destroyT(&st, codeCount);
}