/* asmstructs.c */
 
/*****************************************************************************/
 
/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
 
/*                                                                           */
 
/* AS-Portierung                                                             */
 
/*                                                                           */
 
/* structure handling                                                        */
 
/*                                                                           */
 
/*****************************************************************************/
 
 
 
#include "stdinc.h"
 
#include <string.h>
 
 
 
#include "nls.h"
 
#include "nlmessages.h"
 
#include "strutil.h"
 
 
 
#include "trees.h"
 
#include "errmsg.h"
 
#include "symbolsize.h"
 
 
 
#include "as.h"
 
#include "asmdef.h"
 
#include "asmsub.h"
 
#include "asmpars.h"
 
#include "asmlabel.h"
 
#include "asmstructs.h"
 
#include "errmsg.h"
 
#include "codepseudo.h"
 
 
 
#include "as.rsc"
 
 
 
/*****************************************************************************/
 
 
 
typedef struct sStructNode
 
{
 
  TTree Tree;
 
  Boolean Defined;
 
  PStructRec StructRec;
 
} TStructNode, *PStructNode;
 
 
 
/*****************************************************************************/
 
 
 
PStructStack StructStack,        /* momentan offene Strukturen */
 
             pInnermostNamedStruct;
 
as_addrspace_t StructSaveSeg;    /* gesichertes Segment waehrend Strukturdef.*/
 
PStructNode StructRoot = NULL;
 
 
 
/*****************************************************************************/
 
 
 
PStructRec CreateStructRec(void)
 
{
 
  PStructRec Neu;
 
 
 
  Neu 
= (PStructRec
) malloc(sizeof(TStructRec
)); 
  if (Neu)
 
  {
 
    Neu->TotLen = 0;
 
    Neu->Elems = NULL;
 
    Neu->ExtChar = '\0';
 
    Neu->DoExt = Neu->IsUnion = False;
 
  }
 
  return Neu;
 
}
 
 
 
/*!------------------------------------------------------------------------
 
 * \fn     DestroyStructElem(PStructElem pStructElem)
 
 * \brief  destroy/free struct element
 
 * \param  pStructElem element to destroy
 
 * ------------------------------------------------------------------------ */
 
 
 
void DestroyStructElem(PStructElem pStructElem)
 
{
 
  if (pStructElem
->pElemName
) free(pStructElem
->pElemName
);  
  if (pStructElem
->pRefElemName
) free(pStructElem
->pRefElemName
);  
}
 
 
 
void DestroyStructRec(PStructRec StructRec)
 
{
 
  PStructElem Old;
 
 
 
  while (StructRec->Elems)
 
  {
 
    Old = StructRec->Elems;
 
    StructRec->Elems = Old->Next;
 
    DestroyStructElem(Old);
 
  }
 
}
 
 
 
/*!------------------------------------------------------------------------
 
 * \fn     CreateStructElem(const char *pElemName)
 
 * \brief  create a new entry for a structure definition
 
 * \param  pElemName name of the structure element
 
 * \return * to element or NULL if allocation failed
 
 * ------------------------------------------------------------------------ */
 
 
 
void ExpandStructStd(const tStrComp *pVarName, const struct sStructElem *pStructElem, LargeWord Base)
 
{
 
  LabelHandle(pVarName, Base + pStructElem->Offset, True);
 
  if (pStructElem->OpSize != eSymbolSizeUnknown)
 
  {
 
    String ext_name_buf;
 
    tStrComp ext_name;
 
    const tStrComp *p_ext_name;
 
 
 
    StrCompMkTemp(&ext_name, ext_name_buf, sizeof(ext_name_buf));
 
    p_ext_name = ExpandStrSymbol(&ext_name, pVarName, !CaseSensitive);
 
    if (p_ext_name)
 
      SetSymbolOrStructElemSize(p_ext_name, pStructElem->OpSize);
 
  }
 
}
 
 
 
PStructElem CreateStructElem(const tStrComp *pElemName)
 
{
 
  String ext_name_buf;
 
  tStrComp ext_name;
 
  const tStrComp *p_ext_name;
 
  PStructElem pNeu;
 
 
 
  StrCompMkTemp(&ext_name, ext_name_buf, sizeof(ext_name_buf));
 
  p_ext_name = ExpandStrSymbol(&ext_name, pElemName, !CaseSensitive);
 
  if (!p_ext_name)
 
    return NULL;
 
 
 
  pNeu 
= (PStructElem
) calloc(1, sizeof(TStructElem
)); 
  if (pNeu)
 
  {
 
    pNeu->pElemName = as_strdup(p_ext_name->str.p_str);
 
    pNeu->pRefElemName = NULL;
 
    pNeu->ExpandFnc = ExpandStructStd;
 
    pNeu->Offset = 0;
 
    pNeu->BitPos = pNeu->BitWidthM1 = -1;
 
    pNeu->OpSize = eSymbolSizeUnknown;
 
    pNeu->Next = NULL;
 
  }
 
  return pNeu;
 
}
 
 
 
/*!------------------------------------------------------------------------
 
 * \fn     CloneStructElem(const struct sStrComp *pCloneElemName, const struct sStructElem *pSrc)
 
 * \brief  generate copy of struct element, with different name
 
 * \param  pCloneElemName new element's name
 
 * \param  pSrc source to clone from
 
 * \return * to new element or NULL
 
 * ------------------------------------------------------------------------ */
 
 
 
PStructElem CloneStructElem(const struct sStrComp *pCloneElemName, const struct sStructElem *pSrc)
 
{
 
  PStructElem pResult = CreateStructElem(pCloneElemName);
 
  if (!pResult)
 
    return pResult;
 
 
 
  pResult->Offset = pSrc->Offset;
 
  pResult->OpSize = pSrc->OpSize;
 
  pResult->BitPos = pSrc->BitPos;
 
  pResult->ExpandFnc = pSrc->ExpandFnc;
 
  pResult->pRefElemName = as_strdup(pSrc->pRefElemName);
 
  return pResult;
 
}
 
 
 
/*!------------------------------------------------------------------------
 
 * \fn     AddStructElem(PStructRec pStructRec, PStructElem pElement)
 
 * \brief  add a new element to a structure definition
 
 * \param  pStructRec structure to extend
 
 * \param  pElement new element
 
 * \return True if element was added
 
 * ------------------------------------------------------------------------ */
 
 
 
Boolean AddStructElem(PStructRec pStructRec, PStructElem pElement)
 
{
 
  PStructElem pRun, pPrev;
 
  Boolean Duplicate = False;
 
 
 
  if (!CaseSensitive && pElement->pRefElemName)
 
    NLS_UpString(pElement->pRefElemName);
 
 
 
  for (pPrev = NULL, pRun = pStructRec->Elems; pRun; pPrev = pRun, pRun = pRun->Next)
 
  {
 
    Duplicate 
= CaseSensitive 
? !strcmp(pElement
->pElemName
, pRun
->pElemName
) : !as_strcasecmp
(pElement
->pElemName
, pRun
->pElemName
); 
    if (Duplicate)
 
    {
 
      WrXError(ErrNum_DuplicateStructElem, pElement->pElemName);
 
      break;
 
    }
 
  }
 
 
 
  if (!Duplicate)
 
  {
 
    if (pPrev)
 
      pPrev->Next = pElement;
 
    else
 
      pStructRec->Elems = pElement;
 
  }
 
  BumpStructLength(pStructRec, pElement->Offset);
 
  if (Duplicate)
 
    DestroyStructElem(pElement);
 
  return !Duplicate;
 
}
 
 
 
/*!------------------------------------------------------------------------
 
 * \fn     SetStructElemSize(PStructRec pStructRec, const tStrComp *pElemName, tSymbolSize Size)
 
 * \brief  set the operand size of a structure's element
 
 * \param  pStructRec structure the element is contained in
 
 * \param  pElemName element's name
 
 * \param  Size operand size to set
 
 * ------------------------------------------------------------------------ */
 
 
 
void SetStructElemSize(PStructRec pStructRec, const tStrComp *pElemName, tSymbolSize Size)
 
{
 
  PStructElem pRun;
 
  String exp_name_buf;
 
  tStrComp exp_name;
 
  const tStrComp *p_exp_name;
 
 
 
  StrCompMkTemp(&exp_name, exp_name_buf, sizeof(exp_name_buf));
 
  p_exp_name = ExpandStrSymbol(&exp_name, pElemName, !CaseSensitive);
 
  if (!p_exp_name)
 
    return;
 
  for (pRun = pStructRec->Elems; pRun; pRun = pRun->Next)
 
  {
 
    if (!strcmp(p_exp_name
->str.
p_str, pRun
->pElemName
))  
    {
 
      pRun->OpSize = Size;
 
      return;
 
    }
 
  }
 
  fprintf(stderr
, "SetStructElemSize: cannot set size of '%s', something wicked is going on\n", p_exp_name
->str.
p_str);  
}
 
 
 
/*!------------------------------------------------------------------------
 
 * \fn     ResolveStructReferences(PStructRec pStructRec)
 
 * \brief  resolve referenced elements in structure
 
 * \param  pStructRec structure to work on
 
 * ------------------------------------------------------------------------ */
 
 
 
void ResolveStructReferences(PStructRec pStructRec)
 
{
 
  Boolean AllResolved, DidResolve;
 
  PStructElem pRun, pRef;
 
 
 
  /* iterate over list until all symbols resolved, or we failed to resolve at least one per pass */
 
 
 
  do
 
  {
 
    AllResolved = True;
 
    DidResolve = False;
 
 
 
    for (pRun = pStructRec->Elems; pRun; pRun = pRun->Next)
 
      if (pRun->pRefElemName)
 
      {
 
        /* Only resolve to elements that already have been resolved.
 
           That's why we may need more than one pass.  */
 
 
 
        for (pRef = pStructRec->Elems; pRef; pRef = pRef->Next)
 
        {
 
          if (!strcmp(pRun
->pRefElemName
, pRef
->pElemName
) && !pRef
->pRefElemName
)  
          {
 
            pRun->Offset = pRef->Offset;
 
            if (pRun->OpSize == eSymbolSizeUnknown)
 
              pRun->OpSize = pRef->OpSize;
 
            free(pRun
->pRefElemName
);  
            pRun->pRefElemName = NULL;
 
            DidResolve = True;
 
            break;
 
          }
 
        }
 
        if (!pRef)
 
          AllResolved = False;
 
      }
 
  }
 
  while (!AllResolved && DidResolve);
 
  if (!AllResolved)
 
  {
 
    String Str;
 
 
 
    for (pRun = pStructRec->Elems; pRun; pRun = pRun->Next)
 
      if (pRun->pRefElemName)
 
      {
 
        strmaxcpy(Str, pRun->pElemName, STRINGSIZE);
 
        strmaxcat(Str, " -> ", STRINGSIZE);
 
        strmaxcat(Str, pRun->pRefElemName, STRINGSIZE);
 
        WrXError(ErrNum_UnresolvedStructRef, Str);
 
      }
 
  }
 
}
 
 
 
void BuildStructName(char *pResult, unsigned ResultLen, const char *pName)
 
{
 
  PStructStack ZStruct;
 
  String tmp2;
 
 
 
  strmaxcpy(pResult, pName, ResultLen);
 
  for (ZStruct = StructStack; ZStruct; ZStruct = ZStruct->Next)
 
    if (ZStruct->StructRec->DoExt && ZStruct->Name[0])
 
    {
 
      as_snprintf(tmp2, sizeof(tmp2), "%s%c", ZStruct->pBaseName, ZStruct->StructRec->ExtChar);
 
      strmaxprep(pResult, tmp2, ResultLen);
 
    }
 
}
 
 
 
void AddStructSymbol(const char *pName, LargeWord Value)
 
{
 
  PStructStack ZStruct;
 
 
 
  /* what we get is offset/length in current structure.  Add to
 
     it all offsets in parent structures, i.e. leave out SaveCurrPC
 
     of bottom of stack which contains saved PC of non-struct segment: */
 
 
 
  for (ZStruct = StructStack; ZStruct->Next; ZStruct = ZStruct->Next)
 
    Value += ZStruct->SaveCurrPC;
 
 
 
  {
 
    String tmp;
 
    tStrComp TmpComp;
 
 
 
    as_snprintf(tmp, sizeof(tmp), "%s%c%s", pInnermostNamedStruct->Name, pInnermostNamedStruct->StructRec->ExtChar, pName);
 
    StrCompMkTemp(&TmpComp, tmp, sizeof(tmp));
 
    EnterIntSymbol(&TmpComp, Value, SegNone, False);
 
  }
 
}
 
 
 
void BumpStructLength(PStructRec StructRec, LongInt Length)
 
{
 
  if (StructRec->TotLen < Length)
 
    StructRec->TotLen = Length;
 
}
 
 
 
static Boolean StructAdder(PTree *PDest, PTree Neu, void *pData)
 
{
 
  PStructNode NewNode = (PStructNode) Neu, *Node;
 
  Boolean Protest = *((Boolean*)pData), Result = False;
 
 
 
  if (!PDest)
 
  {
 
    NewNode->Defined = TRUE;
 
    return True;
 
  }
 
 
 
  Node = (PStructNode*) PDest;
 
  if ((*Node)->Defined)
 
  {
 
    if (Protest)
 
      WrXError(ErrNum_DoubleStruct, Neu->Name);
 
    else
 
    {
 
      DestroyStructRec((*Node)->StructRec);
 
      (*Node)->StructRec = NewNode->StructRec;
 
    }
 
  }
 
  else
 
  {
 
    DestroyStructRec((*Node)->StructRec);
 
    (*Node)->StructRec = NewNode->StructRec;
 
    (*Node)->Defined = True;
 
    return True;
 
  }
 
  return Result;
 
}
 
 
 
void AddStruct(PStructRec StructRec, char *Name, Boolean Protest)
 
{
 
  PStructNode Node;
 
  PTree TreeRoot;
 
 
 
  Node 
= (PStructNode
) malloc(sizeof(TStructNode
)); 
  if (Node)
 
  {
 
    Node->Tree.Left = Node->Tree.Right = NULL;
 
    Node->Tree.Name = as_strdup(Name);
 
    if (!CaseSensitive)
 
      NLS_UpString(Node->Tree.Name);
 
    Node->Tree.Attribute = MomSectionHandle;
 
    Node->Defined = FALSE;
 
    Node->StructRec = StructRec;
 
    TreeRoot = &(StructRoot->Tree);
 
    EnterTree(&TreeRoot, &(Node->Tree), StructAdder, &Protest);
 
    StructRoot = (PStructNode)TreeRoot;
 
  }
 
}
 
 
 
static PStructRec FoundStruct_FNode(LongInt Handle, const char *Name)
 
{
 
  PStructNode Lauf;
 
 
 
  Lauf = (PStructNode) SearchTree((PTree)StructRoot, Name, Handle);
 
  return Lauf ? Lauf->StructRec : NULL;
 
}
 
 
 
Boolean FoundStruct(PStructRec *Erg, const char *pName)
 
{
 
  PSaveSection Lauf;
 
 
 
  *Erg = FoundStruct_FNode(MomSectionHandle, pName);
 
  if (*Erg)
 
    return True;
 
  Lauf = SectionStack;
 
  while (Lauf)
 
  {
 
    *Erg = FoundStruct_FNode(Lauf->Handle, pName);
 
    if (*Erg)
 
      return True;
 
    Lauf = Lauf->Next;
 
  }
 
  return False;
 
}
 
 
 
static void ResDef(PTree Tree, void *pData)
 
{
 
  UNUSED(pData);
 
 
 
  ((PStructNode)Tree)->Defined = FALSE;
 
}
 
 
 
void ResetStructDefines(void)
 
{
 
  IterTree((PTree)StructRoot, ResDef, NULL);
 
}
 
 
 
typedef struct
 
{
 
  LongInt Sum;
 
  as_dynstr_t num_str;
 
} TPrintContext;
 
 
 
static void PrintDef(PTree Tree, void *pData)
 
{
 
  PStructNode Node = (PStructNode)Tree;
 
  PStructElem Elem;
 
  TPrintContext *pContext = (TPrintContext*)pData;
 
  String s;
 
  char NumStr[30];
 
  TempResult t;
 
 
 
  UNUSED(pData);
 
  as_tempres_ini(&t);
 
 
 
  WrLstLine("");
 
  pContext->Sum++;
 
  strmaxcpy(s, Node->Tree.Name, STRINGSIZE);
 
  if (Node->Tree.Attribute != -1)
 
  {
 
    strmaxcat(s, "[", STRINGSIZE);
 
    strmaxcat(s, GetSectionName(Node->Tree.Attribute), STRINGSIZE);
 
    strmaxcat(s, "]", STRINGSIZE);
 
  }
 
  WrLstLine(s);
 
  for (Elem = Node->StructRec->Elems; Elem; Elem = Elem->Next)
 
  {
 
    as_tempres_set_int(&t, Elem->Offset);
 
    StrSym(&t, False, &pContext->num_str, ListRadixBase);
 
    as_snprintf(s, sizeof(s), "%3s", pContext->num_str.p_str);
 
    if (Elem->BitPos >= 0)
 
    {
 
      if (Elem->BitWidthM1 >= 0)
 
        as_snprintf(NumStr, sizeof(NumStr), ".%d-%d", Elem->BitPos, Elem->BitPos + Elem->BitWidthM1);
 
      else
 
        as_snprintf(NumStr, sizeof(NumStr), ".%d", Elem->BitPos);
 
    }
 
    else
 
      *NumStr = '\0';
 
    as_snprcatf(s, sizeof(s), "%-6s", NumStr);
 
    if (Elem->OpSize != eSymbolSizeUnknown)
 
      as_snprcatf(s, sizeof(s), "(%s)", GetSymbolSizeName(Elem->OpSize));
 
    else
 
      strmaxcat(s, "   ", STRINGSIZE);
 
    as_snprcatf(s, sizeof(s), " %s", Elem->pElemName);
 
    WrLstLine(s);
 
  }
 
  as_tempres_free(&t);
 
}
 
 
 
void PrintStructList(void)
 
{
 
  TPrintContext Context;
 
  String s;
 
 
 
  if (!StructRoot)
 
    return;
 
 
 
  NewPage(ChapDepth, True);
 
  WrLstLine(getmessage(Num_ListStructListHead1));
 
  WrLstLine(getmessage(Num_ListStructListHead2));
 
 
 
  Context.Sum = 0;
 
  as_dynstr_ini(&Context.num_str, STRINGSIZE);
 
  IterTree((PTree)StructRoot, PrintDef, &Context);
 
  as_dynstr_free(&Context.num_str);
 
  as_snprintf(s, sizeof(s), "%" PRILongInt "%s",
 
              Context.Sum,
 
              getmessage((Context.Sum == 1) ? Num_ListStructSumMsg : Num_ListStructSumsMsg));
 
  WrLstLine(s);
 
}
 
 
 
static void ClearNode(PTree Tree, void *pData)
 
{
 
  PStructNode Node = (PStructNode) Tree;
 
  UNUSED(pData);
 
 
 
  DestroyStructRec(Node->StructRec);
 
}
 
 
 
void ClearStructList(void)
 
{
 
  PTree TreeRoot;
 
 
 
  TreeRoot = &(StructRoot->Tree);
 
  StructRoot = NULL;
 
  DestroyTree(&TreeRoot, ClearNode, NULL);
 
}
 
 
 
static void ExpandStruct_One(PStructRec StructRec, char *pVarPrefix, char *pStructPrefix, LargeWord Base)
 
{
 
  PStructElem StructElem;
 
  int VarLen, RemVarLen, StructLen, RemStructLen;
 
  tStrComp TmpComp;
 
 
 
  pVarPrefix[VarLen] = StructRec->ExtChar;
 
  RemVarLen = STRINGSIZE - 3 - VarLen;
 
 
 
  StructLen 
= strlen(pStructPrefix
); 
  pStructPrefix[StructLen] = StructRec->ExtChar;
 
  RemStructLen = STRINGSIZE - 3 - StructLen;
 
 
 
  if ((RemVarLen > 1) && (RemStructLen > 1))
 
  {
 
    for (StructElem = StructRec->Elems; StructElem; StructElem = StructElem->Next)
 
    {
 
      strmaxcpy(pVarPrefix + VarLen + 1, StructElem->pElemName, RemVarLen);
 
      StrCompMkTemp(&TmpComp, pVarPrefix, 0);
 
      StructElem->ExpandFnc(&TmpComp, StructElem, Base);
 
      if (StructElem->IsStruct)
 
      {
 
        TStructRec *pSubStruct;
 
        Boolean Found;
 
 
 
        strmaxcpy(pStructPrefix + StructLen + 1, StructElem->pElemName, RemStructLen);
 
        Found = FoundStruct(&pSubStruct, pStructPrefix);
 
        if (Found)
 
          ExpandStruct_One(pSubStruct, pVarPrefix, pStructPrefix, Base + StructElem->Offset);
 
      }
 
    }
 
  }
 
  pVarPrefix[VarLen] = '\0';
 
  pStructPrefix[StructLen] = '\0';
 
}
 
 
 
/*!------------------------------------------------------------------------
 
 * \fn     ExpandStruct(PStructRec StructRec)
 
 * \brief  expand a defined structure
 
 * \param  StructRec structure to expand
 
 * ------------------------------------------------------------------------ */
 
 
 
#define DIMENSION_MAX 3
 
 
 
void ExpandStruct(PStructRec StructRec, const char *p_struct_name)
 
{
 
  String CompVarName, CompStructName;
 
  int z;
 
  unsigned DimensionCnt = 0, Dim;
 
  LargeInt Dimensions[DIMENSION_MAX];
 
  tStrComp Arg;
 
  tEvalResult EvalResult;
 
 
 
  if (!LabPart.str.p_str[0])
 
  {
 
    WrError(ErrNum_StructNameMissing);
 
    return;
 
  }
 
 
 
  /* currently, we only support array dimensions as arguments */
 
 
 
  for (z = 1; z <= ArgCnt; z++)
 
    if (IsIndirectGen(ArgStr[z].str.p_str, "[]"))
 
    {
 
      if (DimensionCnt >= DIMENSION_MAX)
 
      {
 
        WrStrErrorPos(ErrNum_TooManyArrayDimensions, &ArgStr[z]);
 
        return;
 
      }
 
      StrCompRefRight(&Arg, &ArgStr[z], 1);
 
      StrCompShorten(&Arg, 1);
 
      Dimensions[DimensionCnt++] = EvalStrIntExpressionWithResult(&Arg, UInt32, &EvalResult);
 
      if (!EvalResult.OK)
 
        return;
 
      if (EvalResult.Flags & eSymbolFlag_FirstPassUnknown)
 
      {
 
        WrStrErrorPos(ErrNum_FirstPassCalc, &Arg);
 
        return;
 
      }
 
      if (Dimensions[DimensionCnt - 1] <= 0)
 
      {
 
        WrStrErrorPos(ErrNum_UnderRange, &Arg);
 
        return;
 
      }
 
    }
 
    else
 
    {
 
      WrStrErrorPos(ErrNum_InvStructArgument, &ArgStr[z]);
 
      return;
 
    }
 
 
 
  strmaxcpy(CompStructName, p_struct_name, sizeof(CompStructName));
 
  strmaxcpy(CompVarName, LabPart.str.p_str, sizeof(CompVarName));
 
  if (!DimensionCnt)
 
  {
 
    ExpandStruct_One(StructRec, CompVarName, CompStructName, EProgCounter());
 
    CodeLen = StructRec->TotLen;
 
  }
 
  else
 
  {
 
    LargeInt Indices[DIMENSION_MAX];
 
    int CompVarNameLens[DIMENSION_MAX];
 
    tStrComp LabelComp;
 
 
 
    /* Start with element [0,...,0] and build associated names.
 
       Store length of names up to given dimension so we don't
 
       have to rebuild the name with all indices upon every elemnt: */
 
 
 
    for (Dim = 0; Dim < DimensionCnt; Dim++)
 
    {
 
      Indices[Dim] = 0;
 
      CompVarNameLens
[Dim
] = strlen(CompVarName
); 
      as_snprcatf(CompVarName, sizeof(CompVarName), "_%llu", (LargeWord)Indices[Dim]);
 
    }
 
    while (Indices[0] < Dimensions[0])
 
    {
 
      StrCompMkTemp(&LabelComp, CompVarName, sizeof(CompVarName));
 
      LabelHandle(&LabelComp, EProgCounter() + CodeLen, True);
 
      ExpandStruct_One(StructRec, CompVarName, CompStructName, EProgCounter() + CodeLen);
 
      CodeLen += StructRec->TotLen;
 
 
 
      /* increase indices, ripple through 'carry' from minor to major indices */
 
 
 
      Indices[DimensionCnt - 1]++;
 
      for (Dim = DimensionCnt - 1; Dim > 0; Dim--)
 
        if (Indices[Dim] >= Dimensions[Dim])
 
        {
 
          Indices[Dim] = 0;
 
          Indices[Dim - 1]++;
 
        }
 
        else
 
          break;
 
 
 
      /* Dim now holds the most major (leftmost) index that changed.  Build up new element
 
         name, starting from that: */
 
 
 
      CompVarName[CompVarNameLens[Dim]] = '\0';
 
      for (; Dim < DimensionCnt; Dim++)
 
      {
 
        as_snprcatf(CompVarName, sizeof(CompVarName), "_%llu", (LargeWord)Indices[Dim]);
 
        if (Dim + 1 < DimensionCnt)
 
          CompVarNameLens
[Dim 
+ 1] = strlen(CompVarName
); 
      }
 
    }
 
  }
 
  BookKeeping();
 
  DontPrint = True;
 
}
 
 
 
void asmstruct_init(void)
 
{
 
   StructRoot = NULL;
 
}