📄 xrm.c
字号:
bzero((char *)&resourceQuarks[oldsize], size - oldsize); maxResourceQuark = (size << 3) - 1; } else { maxResourceQuark = -1; } } if (q > 0 && resourceQuarks) resourceQuarks[q >> 3] |= 1 << (q & 0x7); GROW(firstpprev);#undef NEWTABLE}void XrmQPutResource(pdb, bindings, quarks, type, value) XrmDatabase *pdb; XrmBindingList bindings; XrmQuarkList quarks; XrmRepresentation type; XrmValuePtr value;{ if (!*pdb) *pdb = NewDatabase(); _XLockMutex(&(*pdb)->linfo); PutEntry(*pdb, bindings, quarks, type, value); _XUnlockMutex(&(*pdb)->linfo);}#if NeedFunctionPrototypesvoid XrmPutResource( XrmDatabase *pdb, _Xconst char *specifier, _Xconst char *type, XrmValuePtr value)#elsevoid XrmPutResource(pdb, specifier, type, value) XrmDatabase *pdb; char *specifier; char *type; XrmValuePtr value;#endif{ XrmBinding bindings[MAXDBDEPTH+1]; XrmQuark quarks[MAXDBDEPTH+1]; if (!*pdb) *pdb = NewDatabase(); _XLockMutex(&(*pdb)->linfo); XrmStringToBindingQuarkList(specifier, bindings, quarks); PutEntry(*pdb, bindings, quarks, XrmStringToQuark(type), value); _XUnlockMutex(&(*pdb)->linfo);}#if NeedFunctionPrototypesvoid XrmQPutStringResource( XrmDatabase *pdb, XrmBindingList bindings, XrmQuarkList quarks, _Xconst char *str)#elsevoid XrmQPutStringResource(pdb, bindings, quarks, str) XrmDatabase *pdb; XrmBindingList bindings; XrmQuarkList quarks; char *str;#endif{ XrmValue value; if (!*pdb) *pdb = NewDatabase(); value.addr = (XPointer) str; value.size = strlen(str)+1; _XLockMutex(&(*pdb)->linfo); PutEntry(*pdb, bindings, quarks, XrmQString, &value); _XUnlockMutex(&(*pdb)->linfo);}/* Function Name: GetDatabase * Description: Parses a string and stores it as a database. * Arguments: db - the database. * str - a pointer to the string containing the database. * filename - source filename, if any. * doall - whether to do all lines or just one *//* * This function is highly optimized to inline as much as possible. * Be very careful with modifications, or simplifications, as they * may adversely affect the performance. * * Chris Peterson, MIT X Consortium 5/17/90. *//* * Xlib spec says max 100 quarks in a lookup, will stop and return if * return if any single production's lhs has more than 100 components. */#define QLIST_SIZE 100/* * This should be big enough to handle things like the XKeysymDB or biggish * ~/.Xdefaults or app-defaults files. Anything bigger will be allocated on * the heap. */#define DEF_BUFF_SIZE 8192static void GetIncludeFile();static void GetDatabase(db, str, filename, doall) XrmDatabase db; register char *str; char *filename; Bool doall;{ char *rhs; char *lhs, lhs_s[DEF_BUFF_SIZE]; XrmQuark quarks[QLIST_SIZE + 1]; /* allow for a terminal NullQuark */ XrmBinding bindings[QLIST_SIZE + 1]; register char *ptr; register XrmBits bits = 0; register char c; register Signature sig; register char *ptr_max; register int num_quarks; register XrmBindingList t_bindings; int len, alloc_chars; unsigned long str_len; XrmValue value; Bool only_pcs; Bool dolines; if (!db) return; /* * if strlen (str) < DEF_BUFF_SIZE allocate buffers on the stack for * speed otherwise malloc the buffer. From a buffer overflow standpoint * we can be sure that neither: a) a component on the lhs, or b) a * value on the rhs, will be longer than the overall length of str, * i.e. strlen(str). * * This should give good performance when parsing "*foo: bar" type * databases as might be passed with -xrm command line options; but * with larger databases, e.g. .Xdefaults, app-defaults, or KeysymDB * files, the size of the buffers will be overly large. One way * around this would be to double-parse each production with a resulting * performance hit. In any event we can be assured that a lhs component * name or a rhs value won't be longer than str itself. */ str_len = strlen (str); if (DEF_BUFF_SIZE > str_len) lhs = lhs_s; else if ((lhs = (char*) Xmalloc (str_len)) == NULL) return; alloc_chars = DEF_BUFF_SIZE < str_len ? str_len : DEF_BUFF_SIZE; if ((rhs = (char*) Xmalloc (alloc_chars)) == NULL) { if (lhs != lhs_s) Xfree (lhs); return; } (*db->methods->mbinit)(db->mbstate); str--; dolines = True; while (!is_EOF(bits) && dolines) { dolines = doall; /* * First: Remove extra whitespace. */ do { bits = next_char(c, str); } while is_space(bits); /* * Ignore empty lines. */ if (is_EOL(bits)) continue; /* start a new line. */ /* * Second: check the first character in a line to see if it is * "!" signifying a comment, or "#" signifying a directive. */ if (c == '!') { /* Comment, spin to next newline */ while (is_simple(bits = next_char(c, str))) {} if (is_EOL(bits)) continue; while (!is_EOL(bits = next_mbchar(c, len, str))) {} str--; continue; /* start a new line. */ } if (c == '#') { /* Directive */ /* remove extra whitespace */ only_pcs = True; while (is_space(bits = next_char(c, str))) {}; /* only "include" directive is currently defined */ if (!strncmp(str, "include", 7)) { str += (7-1); /* remove extra whitespace */ while (is_space(bits = next_char(c, str))) {}; /* must have a starting " */ if (c == '"') { char *fname = str+1; len = 0; do { if (only_pcs) { bits = next_char(c, str); if (is_nonpcs(bits)) only_pcs = False; } if (!only_pcs) bits = next_mbchar(c, len, str); } while (c != '"' && !is_EOL(bits)); /* must have an ending " */ if (c == '"') GetIncludeFile(db, filename, fname, str - len - fname); } } /* spin to next newline */ if (only_pcs) { while (is_simple(bits)) bits = next_char(c, str); if (is_EOL(bits)) continue; } while (!is_EOL(bits)) bits = next_mbchar(c, len, str); str--; continue; /* start a new line. */ } /* * Third: loop through the LHS of the resource specification * storing characters and converting this to a Quark. */ num_quarks = 0; t_bindings = bindings; sig = 0; ptr = lhs; *t_bindings = XrmBindTightly; for(;;) { if (!is_binding(bits)) { while (!is_EOQ(bits)) { *ptr++ = c; sig = (sig << 1) + c; /* Compute the signature. */ bits = next_char(c, str); } quarks[num_quarks++] = _XrmInternalStringToQuark(lhs, ptr - lhs, sig, False); if (num_quarks > QLIST_SIZE) { Xfree(rhs); if (lhs != lhs_s) Xfree (lhs); (*db->methods->mbfinish)(db->mbstate); return; } if (is_separator(bits)) { if (!is_space(bits)) break; /* Remove white space */ do { *ptr++ = c; sig = (sig << 1) + c; /* Compute the signature. */ } while (is_space(bits = next_char(c, str))); /* * The spec doesn't permit it, but support spaces * internal to resource name/class */ if (is_separator(bits)) break; num_quarks--; continue; } if (c == '.') *(++t_bindings) = XrmBindTightly; else *(++t_bindings) = XrmBindLoosely; sig = 0; ptr = lhs; } else { /* * Magic unspecified feature #254. * * If two separators appear with no Text between them then * ignore them. * * If anyone of those separators is a '*' then the binding * will be loose, otherwise it will be tight. */ if (c == '*') *t_bindings = XrmBindLoosely; } bits = next_char(c, str); } quarks[num_quarks] = NULLQUARK; /* * Make sure that there is a ':' in this line. */ if (c != ':') { char oldc; /* * A parsing error has occured, toss everything on the line * a new_line can still be escaped with a '\'. */ while (is_normal(bits)) bits = next_char(c, str); if (is_EOL(bits)) continue; bits = next_mbchar(c, len, str); do { oldc = c; bits = next_mbchar(c, len, str); } while (c && (c != '\n' || oldc == '\\')); str--; continue; } /* * I now have a quark and binding list for the entire left hand * side. "c" currently points to the ":" separating the left hand * side for the right hand side. It is time to begin processing * the right hand side. */ /* * Fourth: Remove more whitespace */ for(;;) { if (is_space(bits = next_char(c, str))) continue; if (c != '\\') break; bits = next_char(c, str); if (c == '\n') continue; str--; bits = BSLASH; c = '\\'; break; } /* * Fifth: Process the right hand side. */ ptr = rhs; ptr_max = ptr + alloc_chars - 4; only_pcs = True; len = 1; for(;;) { /* * Tight loop for the normal case: Non backslash, non-end of value * character that will fit into the allocated buffer. */ if (only_pcs) { while (is_normal(bits) && ptr < ptr_max) { *ptr++ = c; bits = next_char(c, str); } if (is_EOL(bits)) break; if (is_nonpcs(bits)) { only_pcs = False; bits = next_mbchar(c, len, str); } } while (!is_special(bits) && ptr + len <= ptr_max) { len = -len; while (len) *ptr++ = str[len++]; if (*str == '\0') { bits = EOS; break; } bits = next_mbchar(c, len, str); } if (is_EOL(bits)) { str--; break; } if (c == '\\') { /* * We need to do some magic after a backslash. */ Bool read_next = True; if (only_pcs) { bits = next_char(c, str); if (is_nonpcs(bits)) only_pcs = False; } if (!only_pcs) bits = next_mbchar(c, len, str); if (is_EOL(bits)) { if (is_EOF(bits)) continue; } else if (c == 'n') { /* * "\n" means insert a newline. */ *ptr++ = '\n'; } else if (c == '\\') { /* * "\\" completes to just one backslash. */ *ptr++ = '\\'; } else { /* * pick up to three octal digits after the '\'. */ char temp[3]; int count = 0; while (is_odigit(bits) && count < 3) { temp[count++] = c; if (only_pcs) { bits = next_char(c, str); if (is_nonpcs(bits)) only_pcs = False; } if (!only_pcs) bits = next_mbchar(c, len, str); } /* * If we found three digits then insert that octal code * into the value string as a character. */ if (count == 3) { *ptr++ = (unsigned char) ((temp[0] - '0') * 0100 + (temp[1] - '0') * 010 + (temp[2] - '0')); } else { int tcount; /* * Otherwise just insert those characters into the * string, since no special processing is needed on * numerics we can skip the special processing. */ for (tcount = 0; tcount < count; tcount++) { *ptr++ = temp[tcount]; /* print them in the correct order */ } } read_next = False; } if (read_next) { if (only_pcs) { bits = next_char(c, str); if (is_nonpcs(bits)) only_pcs = False; } if (!only_pcs) bits = next_mbchar(c, len, str); } } /* * It is important to make sure that there is room for at least * four more characters in the buffer, since I can add that * many characters into the buffer after a backslash has occured. */ if (ptr + len > ptr_max) { char * temp_str;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -