| /* --COPYRIGHT--,ESD |
| * Copyright (c) 2008 Texas Instruments. All rights reserved. |
| * This program and the accompanying materials are made available under the |
| * terms of the Eclipse Public License v1.0 and Eclipse Distribution License |
| * v. 1.0 which accompanies this distribution. The Eclipse Public License is |
| * available at http://www.eclipse.org/legal/epl-v10.html and the Eclipse |
| * Distribution License is available at |
| * http://www.eclipse.org/org/documents/edl-v10.php. |
| * |
| * Contributors: |
| * Texas Instruments - initial implementation |
| * --/COPYRIGHT--*/ |
| /* |
| * ======== Text.c ======== |
| */ |
| |
| #include <xdc/runtime/System.h> |
| #include <xdc/runtime/Types.h> |
| #include <xdc/runtime/Registry.h> |
| |
| #include <string.h> |
| #include <stdarg.h> |
| |
| #include "package/internal/Text.xdc.h" |
| |
| /* |
| * ======== cordText ======== |
| * This function is invoked from Core_assignLabel, which is invoked from |
| * Mod_Handle_label. |
| */ |
| String Text_cordText(Text_CordAddr cord) |
| { |
| Char *p = (Char *)cord; |
| |
| if (p >= Text_charTab && p < Text_charTab + Text_charCnt |
| && !Text_isLoaded) { |
| return (NULL); |
| } |
| |
| return ((String)cord); |
| } |
| |
| /* |
| * ======== matchRope ======== |
| */ |
| Int Text_matchRope(Types_RopeId rope, CString pat, Int *lenp) |
| { |
| Text_MatchVisState state; |
| |
| state.pat = pat; |
| state.lenp = lenp; |
| |
| /* |
| * Text_visitRopeFxn is a config parameter that references a function |
| * generated by the template Text.xdt and initialized in Text.xdc. |
| * It's visitRope() with a stack large enough for all ropes in the |
| * application. |
| */ |
| Text_visitRopeFxn(rope, (Fxn)Text_matchVisFxn, &state); |
| |
| return (state.res); |
| } |
| |
| /* |
| * ======== matchVisFxn ======== |
| * Determines whether a given pattern matches the given string. |
| * |
| * 'obj' is a pointer a MatchVisState structure. |
| * pat - The pattern string to match to, which may contain the wildcard '%' |
| * lenp - The length of the pattern string |
| * res - Used to hold the result of this comparison |
| * |
| * 'src' is the string to compare the pattern to. It is intended to be a |
| * single node within a rope. |
| * |
| * This function is intended for matching ropes one segment at a time. The |
| * return value indicates whether the comparison is complete--it returns |
| * FALSE if we need to move on to the next rope node, or TRUE if the |
| * comparison is complete. The actual result of the comparison is returned |
| * through the MatchVisState. 'res' is 1 if it's a match, -1 if not. |
| */ |
| Bool Text_matchVisFxn(Ptr obj, CString src) |
| { |
| Text_MatchVisState *state; |
| CString pat; |
| Int *lenp; |
| |
| state = obj; |
| pat = state->pat; |
| lenp = state->lenp; |
| |
| /* compare pat to src and return if pat != src or wildcard matches */ |
| for (; *lenp && *src; src++, pat++, *lenp -= 1) { |
| if (*src != *pat) { |
| state->res = *pat == '%' ? 1 : -1; |
| return (TRUE); |
| } |
| } |
| |
| /* if src[0] != 0, we reached the end of pat */ |
| if (*src) { |
| state->res = -1; |
| return (TRUE); |
| } |
| else { |
| /* we reached end of src, we need to get next part of rope */ |
| state->res = 0; |
| state->pat = pat; |
| return (FALSE); |
| } |
| } |
| |
| /* |
| * ======== printVisFxn ======== |
| */ |
| Bool Text_printVisFxn(Ptr obj, CString src) |
| { |
| Text_PrintVisState *state = obj; |
| |
| if (state->len == 0) { |
| return (TRUE); |
| } |
| else { |
| Int oc = Text_xprintf(state->bufp, state->len, "%s", src); |
| state->res += oc; |
| if (state->len > 0) { |
| state->len -= oc; |
| } |
| return (FALSE); |
| } |
| } |
| |
| /* |
| * ======== putLab ======== |
| * len == -1 => infinite output |
| */ |
| Int Text_putLab(Types_Label *lab, Char **bufp, Int len) |
| { |
| Int res; |
| |
| res = Text_putMod(lab->modId, bufp, len); |
| /* need at most 10 characters for "%p" + '\0'*/ |
| if (len < 0 || (len - res) > (8 + 1)) { |
| res += Text_xprintf(bufp, (len - res), "%p", lab->handle); |
| } |
| |
| if (lab->named |
| && (len < 0 || (len - res) >= (5 + (Int)strlen(lab->iname))) ) { |
| res += Text_xprintf(bufp, (len - res), "('%s')", lab->iname); |
| } |
| |
| return (res); |
| } |
| |
| /* |
| * ======== putMod ======== |
| */ |
| Int Text_putMod(Types_ModuleId mid, Char **bufp, Int len) |
| { |
| Text_PrintVisState state; |
| |
| /* If this is an unnamed module... */ |
| if (mid <= Text_unnamedModsLastId) { |
| return (Text_xprintf(bufp, len, "{module#%d}", mid)); |
| } |
| |
| /* If this is a dynamically registered module... */ |
| if (mid <= Text_registryModsLastId) { |
| Registry_Desc *desc = Registry_findById(mid); |
| CString fmt = desc != NULL ? desc->modName : "{module#%d}"; |
| return (Text_xprintf(bufp, len, fmt, mid)); |
| } |
| |
| /* If this is a static, named module, but the strings are not loaded... */ |
| if (!Text_isLoaded) { |
| return (Text_xprintf(bufp, len, "{module-rope:%x}", mid)); |
| } |
| else { |
| /* Otherwise, this is a static, named module. */ |
| state.bufp = bufp; |
| state.len = len < 0 ? 0x7fff : len; /* 0x7fff == infinite, almost */ |
| state.res = 0; |
| |
| Text_visitRopeFxn(mid, (Fxn)Text_printVisFxn, &state); |
| |
| return (state.res); |
| } |
| } |
| |
| /* |
| * ======== putSite ======== |
| * len == -1 => infinite output |
| * |
| * If site->mod == 0, the module is unspecified and will be omitted from |
| * the output. |
| */ |
| Int Text_putSite(Types_Site *site, Char **bufp, Int len) |
| { |
| Int res; |
| Int max = len < 0 ? 0x7fff : len; /* 0x7fff == infinite, well almost */ |
| |
| res = 0; |
| |
| if (!site) { |
| return (0); |
| } |
| |
| /* The 'mod' field is optional; 0 if it's unspecified. */ |
| if (site->mod != 0) { |
| res = Text_putMod(site->mod, bufp, max); |
| } |
| |
| if ((max - res) > 0) { |
| /* Don't output this if there's no mod */ |
| if (site->mod != 0) { |
| res += Text_xprintf(bufp, (max - res), ": "); |
| } |
| |
| if (site->line == 0) { |
| return (res); |
| } |
| |
| if (site->file && ((max - res) >= ((Int)strlen(site->file) + 5))) { |
| res += Text_xprintf(bufp, (max - res), "\"%s\", ", site->file); |
| } |
| |
| /* 7 + 1 = length of "line : " including '\0', 10 = max decimal digits |
| in 32-bit number */ |
| if ((max - res) >= (8 + 10)) { |
| res += Text_xprintf(bufp, (max - res), "line %d: ", site->line); |
| } |
| } |
| |
| return (res); |
| } |
| |
| /* |
| * ======== ropeText ======== |
| * All calls outside of this module are made only if charTab is on the target. |
| * Internal calls are from visitRope2, and that function is invoked from |
| * visitRope only when charTab is on the target. |
| */ |
| String Text_ropeText(Text_RopeId rope) |
| { |
| return (rope & 0x8000 ? NULL : Text_charTab + rope); |
| } |
| |
| /* |
| * ======== visitRope2 ======== |
| * Call visFxn on each "part" of the rope until visFxn returns TRUE or we |
| * reach the end of our rope. |
| * |
| * The stack array must be large enough to hold the maximum number of |
| * nodes "in" rope. |
| */ |
| Void Text_visitRope2(Text_RopeId rope, Fxn visFxn, Ptr visState, String stack[]) |
| { |
| Int tos = 0; |
| |
| for (;;) { |
| Text_Node *node; |
| UInt16 index; |
| String s = Text_ropeText(rope); |
| if (s) { |
| stack[tos++] = s; |
| break; |
| } |
| index = rope & 0x7fff; |
| node = Text_nodeTab + index; |
| stack[tos++] = Text_ropeText(node->right); |
| rope = node->left; |
| } |
| |
| do { |
| String s = stack[--tos]; |
| if (((Text_RopeVisitor)visFxn)(visState, s)) { |
| return; |
| } |
| } while (tos); |
| } |
| |
| /* |
| * ======== xprintf ======== |
| */ |
| Int Text_xprintf(Char **bufp, SizeT len, CString fmt, ...) |
| { |
| va_list va; |
| Char *b; |
| Int res; |
| |
| va_start(va, fmt); |
| b = (bufp && *bufp) ? *bufp : NULL; |
| |
| res = System_vsnprintf(b, len, fmt, va); |
| |
| /* |
| * vsnprintf returns num of chars that would have been written had `len` |
| * been sufficiently large. In that case, the actual num of chars written |
| * would be `len` - 1 (-1 to exclude '\0') |
| */ |
| if ((SizeT)res > len) { |
| res = len - 1; |
| } |
| |
| if (b) { |
| *bufp += res; |
| } |
| |
| va_end(va); |
| |
| return (res); |
| } |