📄 script.cpp
字号:
// Avisynth v0.3. Copyright 2000 Ben Rudiak-Gould. For distribution
// conditions, please see http://www.math.berkeley.edu/~benrg/avisynth.html .
#include "avisynth.h"
#include "internal-filters.h"
#include <stdio.h>
#define MAX_IDENTIFIER_LENGTH 50
// types: 'c' = clip; 's' = string; 'i' = int; 'f' = float; 'z' = filter;
const char* Sprintf(const char* fmt, ...) {
va_list val;
va_start(val, fmt);
static char buf[1024];
wvsprintf(buf, fmt, val);
va_end(val);
return buf;
}
bool TypeMatch(const char* param_types, const char* arg_types, bool strict) {
for (;;) {
if (*param_types == *arg_types) {
// perfect match
if (*param_types == 0)
return true;
++param_types; ++arg_types;
} else if (*param_types == '*') {
// var-args
return true;
} else if (*param_types == '+') {
// var-args: eat args of this type
while (*arg_types == param_types[-1])
++arg_types;
++param_types;
} else if (!strict && *param_types == 'f' && *arg_types == 'i') {
// non-strict match
++param_types; ++arg_types;
} else {
// complete failure
return false;
}
}
}
int num_filter_sets = 5;
FilterInfo* filter_sets[64] = { edit_filters, effects_filters, misc_filters, source_filters, text_filters };
const char* SearchForFilterName(const char* search_name) {
for (int i=num_filter_sets-1; i>=0; --i)
for (FilterInfo* j = filter_sets[i]; j->name; ++j)
if (!lstrcmpi(j->name, search_name))
return j->name;
return 0;
}
FilterInfo* __cdecl SearchForMatchingFilter(const char* search_name, const char* arg_types) {
for (int strict = 1; strict >= 0; --strict)
for (int i=num_filter_sets-1; i>=0; --i)
for (FilterInfo* j = filter_sets[i]; j->name; ++j)
if (!lstrcmpi(j->name, search_name) && TypeMatch(j->param_types, arg_types, strict&1))
return j;
return 0;
}
void __cdecl LoadPlugin(const char* filename) {
if (num_filter_sets == sizeof(filter_sets) / sizeof(filter_sets[0]))
throw FilterChainError(Sprintf("#loadplugin: Too many plugins loaded already", filename));
HMODULE hmodule = LoadLibrary(filename);
if (!hmodule)
throw FilterChainError(Sprintf("#loadplugin: Unable to load \"%s\"", filename));
typedef FilterInfo* (__stdcall *pPluginFunc)(const PluginCallbacks*);
pPluginFunc AvisynthPluginGetInfo = (pPluginFunc)GetProcAddress(hmodule, "AvisynthPluginGetInfo");
if (!AvisynthPluginGetInfo) {
FreeLibrary(hmodule);
throw FilterChainError(Sprintf("#loadplugin: \"%s\" does not seem to be an Avisynth 0.3 plugin", filename));
}
static const PluginCallbacks callbacks = { sizeof(callbacks), SearchForMatchingFilter };
FilterInfo* filter_info = AvisynthPluginGetInfo(&callbacks);
// avoid reloading the same plugin more than once
for (int i=0; i<num_filter_sets; ++i)
if (filter_sets[i] == filter_info) {
FreeLibrary(hmodule);
return;
}
filter_sets[num_filter_sets++] = filter_info;
}
// Variable lookup. No point doing anything fancy with hash tables;
// this doesn't need to be fast.
class VarTable {
public:
struct Variable {
Variable* const next;
char name[MAX_IDENTIFIER_LENGTH+1];
PVideoFilter val;
Variable(const char* _name, Variable* _next) : next(_next) {
lstrcpy(name, _name);
}
};
VarTable() : variables(0) {}
Variable* Lookup(const char* name) {
for (Variable* v = variables; v; v = v->next)
if (!lstrcmpi(name, v->name))
return v;
variables = new Variable(name, variables);
return variables;
}
PVideoFilter GetValue(const char* name) { return Lookup(name)->val; }
private:
Variable* variables;
};
// Tokenizer.
class Tokenizer {
char* next_char;
char* old_next_char;
int type; // 'x', 's', 'i', 'f', '+', '++', '.', ',', '(', ')', 0=eoln
union {
char identifier[MAX_IDENTIFIER_LENGTH+1];
char* string;
int integer;
float floating_pt;
};
void GetNumber();
public:
Tokenizer() {
old_next_char = next_char = "";
type = 0;
}
void Reset(char* s) {
next_char = s;
while (isspace(*next_char))
++next_char;
NextToken();
}
void NextToken();
int GetType() { return type; }
const char* GetAsIdentifier() { return identifier; }
const char* GetAsString() { return string; }
int GetAsInt() { return integer; }
float GetAsFloat() { return floating_pt; }
char* NextCharPointer() { return next_char; }
char* CurCharPointer() { return old_next_char; }
};
void Tokenizer::GetNumber() {
// start by assuming an int and switch to float if necessary
type = 'i';
integer=0;
bool negate = false;
if (*next_char == '-') {
++next_char;
negate = true;
}
do {
if (*next_char == '.') {
type = 'f';
floating_pt = float(integer);
float place = 1;
++next_char;
while (isdigit(*next_char)) {
place /= 10;
floating_pt += place * (*next_char - '0');
++next_char;
}
break;
} else {
integer = integer*10 + (*next_char - '0');
}
++next_char;
} while (isdigit(*next_char) || *next_char == '.');
if (negate) {
if (type == 'i')
integer = -integer;
else
floating_pt = -floating_pt;
}
}
void Tokenizer::NextToken() {
old_next_char = next_char;
switch (*next_char) {
case 0:
type=0;
break;
case '.':
// a '.' followed by a digit is a number, otherwise it's an operator
if (isdigit(next_char[1]))
GetNumber();
else {
++next_char;
type = '.';
}
break;
case '+':
// a '+' followed by a digit is a number, otherwise it's an operator
++next_char;
if (isdigit(*next_char)) {
GetNumber();
} else if (*next_char == '+') {
++next_char;
type = '++';
} else {
type = '+';
}
break;
case ',':
++next_char;
type = ',';
break;
case '(':
++next_char;
type = '(';
break;
case ')':
++next_char;
type = ')';
break;
case '#':
// comment
type = 0;
break;
case '$':
// hexadecimal number
type = 'i';
integer = 0;
++next_char;
do {
if (*next_char >= '0' && *next_char <= '9')
integer = integer*16 + (*next_char - '0');
else if (*next_char >= 'a' && *next_char <= 'f')
integer = integer*16 + (*next_char - 'a' + 10);
else if (*next_char >= 'A' && *next_char <= 'F')
integer = integer*16 + (*next_char - 'A' + 10);
else
throw FilterChainError(Sprintf("$ must be followed by a hexadecimal number"));
} while (isalnum(*++next_char));
break;
case '"':
{
// string
char* eos = strchr(next_char+1, '"');
if (!eos)
throw FilterChainError("string missing closing quotation mark");
*eos = 0;
type = 's';
string = next_char+1;
next_char = eos+1;
break;
}
default:
if (isdigit(*next_char) || *next_char == '-') {
// number
GetNumber();
} else if (*next_char == '_' || isalnum(*next_char)) {
// identifier
type = 'x';
memset(identifier, 0, sizeof(identifier));
int i=0;
do {
if (i == sizeof(identifier)-1)
throw FilterChainError(Sprintf("identifier too long: \"%s...\"", identifier));
identifier[i++] = *next_char++;
} while (*next_char == '_' || isalnum(*next_char));
} else if (next_char[0] == '`' && next_char[1] == '`') {
// string
char* eos = strstr(next_char+2, "''");
if (!eos)
throw FilterChainError("string missing closing double-apostrophe");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -