Пример #1
0
/* 
 * Return a processed source line list of the file contents.
 */
SrcLineList
includeFile(FileName fname)
{
	String	      fnameString;
	SrcLineList   r;

	inclSerialLineNo    = 0;
	fnameString         = strCopy(fnameUnparseStatic(fname));
	inclBuffer          = bufNew();
	includedFileCodes   = 0;
	localAssertList     = listCopy(String)(globalAssertList);

	fileState.curDir    = osCurDirName();
	fileState.fileCodes = 0;
	fileState.fileNames = 0;

	r = listNReverse(SrcLine)(
		inclFile(fnameString, false, true, &inclFileLineNo));

	strFree(fnameString);
	bufFree(inclBuffer);
	listFree(String)(localAssertList);
	listFree(Hash)(includedFileCodes);

	return r;
}
Пример #2
0
/*
 * Handle the include directive if we are in an active section
 */
local SrcLineList
inclHandleInclude(String fname)
{
	if (INCLUDING(ifState)) {
		SrcLine	sl = SysCmdLine(true);
		return addSysCmd(inclFile(fname, false, false, NULL), sl);
	}
	return listNil(SrcLine);
}
Пример #3
0
int CardSet::loadCsv(const CardDisplay& defDisplay, CsvFile& file)
{
    /*
     * This method reads Anki plain text file format:
     *  - plain text, UTF-8, BOM optional;
     *  - ignore lines starting with "#";
     *  - if first uncommented line starts with "tags:", use space-split words
     *    as additional facts;
     *  - recognize any delimiters;
     *  - use double quotes ("\"") as quote char, including quoting newline;
     *  - literal newline in field should be replaced by "<br>";
     *  - fields are interpreted as simplified HTML;
     *
     * Format is extended by following new features:
     *  - comments in format "#FCARD# <attr-name> <attr-value>" are interpreted as
     *    display attributes for following cards. Following attributes are
     *    recognized:
     *
     *      - "background <color-name>"
     *        specifies background color for cards from this set.
     *
     *      - "period <time-ms>"
     *        specifies period (in milliseconds) for which card will be shown.
     *
     *      - "split-{x|y} <width>,..."
     *        specifies horizontal or vertical split distribution.
     *
     *      - "cell <fact-index>,<cell-x>,<cell-y>,<color-name>,<font-family>,<pattern>,<stylesheet>"
     *        specifies display parameters for fact text.
     *
     *      - "protect {on|off},<keyword>,..."
     *        protects or unprotects specified keywords from further changes below that point.
     *
     *      - "include <filename>,<separator>"
     *        includes specified file; path may be relative to this file; separator
     *        may be specified as a literal character or a "#"-prefixed Unicode
     *        codepoint.
     */
    enum Keyword {
        UNKNOWN,
        BACKGROUND,
        PERIOD,
        SPLIT_X,
        SPLIT_Y,
        CELL,
        PROTECT,
        INCLUDE
    };
    static const struct KeywordDesc {
        Keyword     code;
        const char *name;
    } KEYWORD_LIST[] = {
        { BACKGROUND, "background" },
        { PERIOD,     "period"     },
        { SPLIT_X,    "split-x"    },
        { CELL,       "cell"       },
        { INCLUDE,    "include"    },
        { PROTECT,    "protect"    },
        { UNKNOWN,    0            }
    };
    QRegExp fcard("#FCARD#\\s*(\\w+)\\s+(.*)");
    fcard.setPatternSyntax(QRegExp::RegExp2);
    int cardCount = 0;
    QStringList tagSet;
    CardDisplay *display = 0;
    CardDisplay currDisplay(defDisplay);
    for (;;)
    {
        int flags = 0;
        QStringList line = file.readLine(&flags);
        if (line.isEmpty())
        {
            if (!file.lastError().isEmpty())
            {
                qWarning("ERROR: %s", qPrintable(file.lastError()));
                return -1;
            }
            return cardCount;
        }
        if (flags == CsvFile::FLAG_COMMENT)
        {
            if (fcard.exactMatch(line.first()))
            {
                QString aname = fcard.cap(1);
                QString aval = fcard.cap(2);
                QStringList alist;
                int ret;
                if ((ret = TextConv::smartSplit(alist, aval)) != 0)
                {
                    qWarning("ERROR: Field-list syntax error in '%s' near offset %d",
                             qPrintable(aval), ret - 1);
                    continue;
                }
                Keyword code = UNKNOWN;
                for (const KeywordDesc *kwd = KEYWORD_LIST; kwd->name != 0; kwd++)
                    if (aname == kwd->name)
                    {
                        code = kwd->code;
                        break;
                    }
                if (currDisplay.isProtected(code))
                    continue;
                switch (code)
                {
                case UNKNOWN:
                    break;
                case BACKGROUND:
                    {
                        QColor bgd = QColor(aval.trimmed());
                        if (bgd.isValid())
                            currDisplay.setBackground(bgd);
                    }
                    break;
                case PERIOD:
                    {
                        bool ok = false;
                        int period = aval.toInt(&ok);
                        if (ok &&
                                period >= CardDisplay::MIN_PERIOD &&
                                period <= CardDisplay::MAX_PERIOD)
                            currDisplay.setPeriod(period);
                    }
                    break;
                case SPLIT_X:
                case SPLIT_Y:
                    {
                        QList<int> spl;
                        bool ok = TextConv::toIntList(alist, spl);
                        if (ok && !spl.isEmpty())
                        {
                            if (code == SPLIT_X)
                                currDisplay.setSplitX(spl);
                            else
                                currDisplay.setSplitY(spl);
                        }
                    }
                    break;
                case CELL:
                    if (!alist.isEmpty())
                    {
                        QString indVal = alist.takeFirst();
                        bool ok = false;
                        int ind = indVal.toInt(&ok);
                        if (ok && ind >= 0)
                        {
                            CardCell cell;
                            cell.assign(alist);
                            currDisplay.setValue(ind, cell);
                        }
                    }
                    break;
                case PROTECT:
                    if (!alist.isEmpty())
                    {
                        QString bVal = alist.takeFirst();
                        bool value;
                        if (bVal == "on")
                            value = true;
                        else if (bVal == "off")
                            value = false;
                        else
                            break;
                        foreach (QString name, alist)
                        {
                            for (const KeywordDesc *kwd = KEYWORD_LIST; kwd->name != 0; kwd++)
                                if (name == kwd->name && kwd->code != PROTECT)
                                {
                                    currDisplay.setProtected(kwd->code, value);
                                    break;
                                }
                        }
                    }
                    break;
                case INCLUDE:
                    if (!alist.isEmpty())
                    {
                        QChar sep = CsvFile::DEFAULT_SEPARATOR;
                        if (alist.size() > 1)
                            sep = TextConv::toChar(alist[1], sep);
                        CsvFile inclFile(alist[0], sep);
                        int inclCnt = loadCsv(currDisplay, inclFile);
                        if (inclCnt < 0)
                            return inclCnt;
                        cardCount += inclCnt;
                    }
                    break;
                }
            }
            continue;
        }