📄 parse.cxx
字号:
/* * Copyright (C) 1998, 1999, 2001, Jonathan S. Shapiro. * * This file is part of the EROS Operating System. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */#include <ctype.h>#include <string.h>#include <stdlib.h>#include <disk/DiskKey.hxx>#include <erosimg/App.hxx>#include <erosimg/Parse.hxx>#include <erosimg/ArchDescrip.hxx>#include <eros/StdKeyType.h>#define __EROS_PRIMARY_KEYDEF(name) { #name, (KT_##name >= FIRST_MISC_KEYTYPE) },/* OLD_MISCKEY(name) { #name, 0 }, */static const struct { char *name; int isValid;} KeyNames[KT_NUM_KEYTYPE] = {#include <eros/StdKeyType.h>};boolGetMiscKeyType(InternedString s, uint32_t& ty){ const char *sstr = s.str(); for (uint32_t i = 0; i < KT_NUM_KEYTYPE; i++) { if (strcasecmp(sstr, KeyNames[i].name) == 0) { if (KeyNames[i].isValid == 0) return false; ty = i; return true; } } return false;}void Parse::TrimLine(char *s){ for(; *s; s++) { if (*s == '#' || *s == '\n') *s = 0; } do { *s = 0; s--; } while(isspace(*s)); s++;}boolParse::MatchKeyword(const char *&txt, const char* kwd){ const char* s = txt; int len = strlen(kwd); while(isspace(*s)) s++; if (strncasecmp(s, kwd, len)) return false; if (isalnum(s[len])) return false; s += len; txt = s; return true;}boolParse::Match(const char *&txt, const char* tok){ const char* s = txt; int len = strlen(tok); while(isspace(*s)) s++; if (strncmp(s, tok, len)) return false; s += len; txt = s; return true;}/* identifiers can be qualified with '.' in them. We grab the whole * thing. */boolParse::MatchIdent(const char*&txt, InternedString& ident){ const char* s = txt; while(isspace(*s)) s++; if (isalpha(*s)) { const char* id = s; while (isalnum(*s) || *s == '.' || (*s == '_')) s++; ident = InternedString(id, s - id); txt = s; return true; } return false; }boolParse::MatchArchitecture(const char*&txt, InternedString& arch){ const char* s = txt; InternedString nm; if (!MatchIdent(s, nm)) return false; /* See if it's really an architecture name: */ if (RegDescrip::IsArchName(nm) == false) return false; arch = nm; txt = s; return true;}boolParse::MatchRegister(const char *&txt, InternedString& arch, RegDescrip*& rrd){ const char* s = txt; RegDescrip *rd; InternedString nm; if (!MatchIdent(s, nm)) return false; /* See if it's really an architecture name: */ if ( (rd = RegDescrip::Lookup(arch, nm)) ) { txt = s; rrd = rd; return true; } return false;}/* Basically, match a hex number no longer than the required number of * bytes */boolParse::MatchRegValue(const char *&txt, RegDescrip* prd, InternedString& v){ const char *s = txt; while(isspace(*s)) s++; /* hopefully now looking at 0x... */ if (strncasecmp(s, "0x", 2)) return false; s += 2; /* now should be looking at the raw digits. */ /* count the hex digits: */ char digits[RegDescrip::MaxRegSize*2 + 3];/* "0x" + \0 */ digits[0] = '0'; digits[1] = 'x'; char *nextDigit = &digits[2]; uint32_t hexlen = prd->len * 2; /* max hex digits to accept */ uint32_t len = 0; while(isxdigit(*s) || *s == ' ') { if (len >= hexlen) return false; if (isxdigit(*s)) *nextDigit++ = *s; s++; } *nextDigit = 0; InternedString iDigits(digits); v = iDigits; txt = s; return true;}boolParse::MatchFileName(const char*&txt, InternedString& fileName){ const char* s = txt; while(isspace(*s)) s++; if (*s == 0) { fileName = 0; return false; } /* now looking at a character that is not a space - assume * that it is the start of a file name. */ const char* name = s; while (*s && !isspace(*s)) s++; fileName = InternedString(name, s - name); txt = s; return true; }boolParse::MatchEOL(const char *&txt){ const char *s = txt; while(isspace(*s)) s++; if (*s) return false; txt = s; return true;}/* parse the arguments for the 'page' or 'node' division type: */boolParse::MatchWord(const char *&txt, uint32_t& w){ const char *s = txt; while(isspace(*s)) s++; if (isdigit(*s)) { char *next; w = strtoul(s, &next, 0); if (s != next) { s = next; txt = s; return true; } } return false;}boolParse::MatchKeyData(const char *&txt, uint32_t& w){ uint32_t w2; const char *s = txt; MatchWord(s, w2); if (w2 > EROS_KEYDATA_MAX) return false; w = w2; txt = s; return true;}boolParse::MatchSlot(const char *&txt, uint32_t& slot){ const char *s = txt; MatchWord(s, slot); if (slot >= EROS_NODE_SIZE) return false; txt = s; return true;}boolParse::MatchOID(const char *&txt, OID& oid){ const char *s = txt; while(isspace(*s)) s++; if (strncasecmp(s, "oid", 3)) return false; s += 3; while(isspace(*s)) s++; if (*s != '=') return false; s++; if (!MatchOIDVal(s, oid)) return false; txt = s; return true;}boolParse::MatchLID(const char *&txt, OID& oid){ const char *s = txt; while(isspace(*s)) s++; if (strncasecmp(s, "lid", 3) && strncasecmp(s, "oid", 3)) return false; if (strncasecmp(s, "lid", 3)) Diag::warning("use of 'oid' in cklog line is obsolete!\n"); s += 3; while(isspace(*s)) s++; if (*s != '=') return false; s++; if (!MatchOIDVal(s, oid)) return false; txt = s; return true;}boolParse::MatchOIDVal(const char *&txt, OID& oid){ const char *s = txt; while(isspace(*s)) s++; /* hopefully now looking at 0x... */ if (strncasecmp(s, "0x", 2)) return false; s += 2; /* now should be looking at the raw digits. */ /* count the hex digits: */ const char *xstr = s; while(isxdigit(*s)) s++; int len = s - xstr; if (len > 16 || len == 0) return false; char digits[17]; /* 16 hex digits plus zero */ strncpy(digits, xstr, len); digits[len] = 0; uint32_t hi = 0; uint32_t lo = 0; if (len > 8) { lo = strtoul(&digits[len-8], 0, 16); digits[len-8] = 0; hi = strtoul(digits, 0, 16); } else { lo = strtoul(digits, 0, 16); } oid = hi; oid <<= 32; oid |= lo; txt = s; return true;}boolParse::MatchNumKeyVal(const char *&txt, uint32_t& hi, uint32_t& mid, uint32_t& lo){ const char *s = txt; while(isspace(*s)) s++; /* hopefully now looking at 0x... */ if (strncasecmp(s, "0x", 2)) return false; s += 2; /* now should be looking at the raw digits. */ /* count the hex digits: */ char digits[25]; uint32_t len = 0; while(isxdigit(*s) || *s == ' ') { if (len > 24) return false; if (isxdigit(*s)) digits[len++] = *s; s++; } if (len == 0) return false; digits[len] = 0; hi = 0; mid = 0; if (len < 8) { lo = strtoul(digits, 0, 16); } else if (len < 16) { lo = strtoul(&digits[len-8], 0, 16); digits[len-8] = 0; mid = strtoul(digits, 0, 16); } else { lo = strtoul(&digits[len-8], 0, 16); digits[len-8] = 0; mid = strtoul(&digits[len-16], 0, 16); digits[len-16] = 0; hi = strtoul(digits, 0, 16); } txt = s; return true;}boolParse::MatchKey(const char *&txt, DiskKey& key){ const char *s = txt; while(isspace(*s)) s++; KeyType kt; /* looking for a string that is a plausible key type: */ if (strncasecmp(s, "start", 5) == 0) { s += 5; kt = KT_Start; } else if (strncasecmp(s, "number", 6) == 0) { s += 6; kt = KT_Number; } else if (strncasecmp(s, "range", 5) == 0) { s += 5; kt = KT_Range; } else if (strncasecmp(s, "page", 4) == 0) { s += 4; kt = KT_Page; } else if (strncasecmp(s, "node", 4) == 0) { s += 4; kt = KT_Node; } else if (strncasecmp(s, "segment", 7) == 0) { s += 7; kt = KT_Segment; } else if (strncasecmp(s, "sched", 5) == 0) { s += 5; kt = KT_Sched; } else if (strncasecmp(s, "misc", 4) == 0) { s += 4; kt = FIRST_MISC_KEYTYPE; } else { return false; } while(isspace(*s)) s++; if (!Match(s, "(")) return false; switch (kt) { case KT_Start: { uint32_t w; OID oid; if ( MatchOID(s, oid) && Match(s, ",") && MatchWord(s, w) && (w <= EROS_KEYDATA_MAX) && Match(s, ")") ) { key = StartKey(oid, w); txt = s; return true; } break; } case KT_Number: { uint32_t hi, mid, lo; if (MatchNumKeyVal(s, hi, mid, lo) && Match(s, ")") ) { key = NumberKey(lo, mid, hi); txt = s; return true; } break; } case KT_Range: { OID oidlo, oidhi; if (MatchOIDVal(s, oidlo) && Match(s, ":") && MatchOIDVal(s, oidhi) && Match(s, ")") ) { key = RangeKey(oidlo, oidhi); txt = s; return true; } break; } case KT_Page: case KT_Node: case KT_Segment: { OID oid; uint32_t blss = 0; if (kt == KT_Page) blss = EROS_PAGE_BLSS; /* Node/Seg keys have lots of attributes, so the following is * a bit tricky. First, parse the '(oid' part: */ bool expectComma = false; bool readOnly = false; bool noCall = false; bool rh = false; /* Now try to parse the various attributes: */ while (!Match(s, ")")) { if (expectComma && Match(s, ",") == false) return false; expectComma = true; const char *ssave = s; if ( MatchStart(s, ssave) && MatchKeyword(s, "oid") && Match(s, "=") && MatchOIDVal(s, oid) ) continue; if ( MatchStart(s, ssave) && MatchKeyword(s, "ro") ) { readOnly = true; continue; } if ( MatchStart(s, ssave) && MatchKeyword(s, "nocall") ) { noCall = true; continue; } if ( MatchStart(s, ssave) && MatchKeyword(s, "rh") ) { rh = true; continue; } /* accept this just for my sanity: */ if ( kt != KT_Page && MatchStart(s, ssave) && MatchKeyword(s, "lss") && Match(s, "=") && MatchWord(s, blss) ) continue; if ( kt != KT_Page && MatchStart(s, ssave) && MatchKeyword(s, "blss") && Match(s, "=") && MatchWord(s, blss) ) continue; return false; } switch(kt) { case KT_Segment: key = SegmentKey(oid, blss, readOnly, noCall); break; case KT_Page: key = DataPageKey(oid, readOnly); break; case KT_Node: key = NodeKey(oid, readOnly); break; default: break; } if (blss) key.SetBlss(blss); if (readOnly) key.SetReadOnly(); if (noCall) key.SetNoCall(); if (rh) key.SetRdHazard(); txt = s; return true; break; } case KT_Sched: { uint32_t prio; if (MatchWord(s, prio) && Match(s, ")") ) { key = SchedKey(prio); txt = s; return true; } break; } break; case FIRST_MISC_KEYTYPE: { InternedString name; if (MatchIdent(s, name) && Match(s, ")") ) { uint32_t miscType; if (GetMiscKeyType(name, miscType) == false) return false; key = MiscKey(miscType); txt = s; return true; } break; } break; default: /* Don't know how to parse the others. */ return false; } return false;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -