Subversion Repositories pentevo

Rev

Blame | Last modification | View Log | Download | RSS feed | ?url?

  1. /* asmstructs.c */
  2. /*****************************************************************************/
  3. /* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
  4. /*                                                                           */
  5. /* AS-Portierung                                                             */
  6. /*                                                                           */
  7. /* structure handling                                                        */
  8. /*                                                                           */
  9. /*****************************************************************************/
  10.  
  11. #include "stdinc.h"
  12. #include <string.h>
  13.  
  14. #include "nls.h"
  15. #include "nlmessages.h"
  16. #include "strutil.h"
  17.  
  18. #include "trees.h"
  19. #include "errmsg.h"
  20. #include "symbolsize.h"
  21.  
  22. #include "as.h"
  23. #include "asmdef.h"
  24. #include "asmsub.h"
  25. #include "asmpars.h"
  26. #include "asmlabel.h"
  27. #include "asmstructs.h"
  28. #include "errmsg.h"
  29. #include "codepseudo.h"
  30.  
  31. #include "as.rsc"
  32.  
  33. /*****************************************************************************/
  34.  
  35. typedef struct sStructNode
  36. {
  37.   TTree Tree;
  38.   Boolean Defined;
  39.   PStructRec StructRec;
  40. } TStructNode, *PStructNode;
  41.  
  42. /*****************************************************************************/
  43.  
  44. PStructStack StructStack,        /* momentan offene Strukturen */
  45.              pInnermostNamedStruct;
  46. as_addrspace_t StructSaveSeg;    /* gesichertes Segment waehrend Strukturdef.*/
  47. PStructNode StructRoot = NULL;
  48.  
  49. /*****************************************************************************/
  50.  
  51. PStructRec CreateStructRec(void)
  52. {
  53.   PStructRec Neu;
  54.  
  55.   Neu = (PStructRec) malloc(sizeof(TStructRec));
  56.   if (Neu)
  57.   {
  58.     Neu->TotLen = 0;
  59.     Neu->Elems = NULL;
  60.     Neu->ExtChar = '\0';
  61.     Neu->DoExt = Neu->IsUnion = False;
  62.   }
  63.   return Neu;
  64. }
  65.  
  66. /*!------------------------------------------------------------------------
  67.  * \fn     DestroyStructElem(PStructElem pStructElem)
  68.  * \brief  destroy/free struct element
  69.  * \param  pStructElem element to destroy
  70.  * ------------------------------------------------------------------------ */
  71.  
  72. void DestroyStructElem(PStructElem pStructElem)
  73. {
  74.   if (pStructElem->pElemName) free(pStructElem->pElemName);
  75.   if (pStructElem->pRefElemName) free(pStructElem->pRefElemName);
  76.   free(pStructElem);
  77. }
  78.  
  79. void DestroyStructRec(PStructRec StructRec)
  80. {
  81.   PStructElem Old;
  82.  
  83.   while (StructRec->Elems)
  84.   {
  85.     Old = StructRec->Elems;
  86.     StructRec->Elems = Old->Next;
  87.     DestroyStructElem(Old);
  88.   }
  89.   free(StructRec);
  90. }
  91.  
  92. /*!------------------------------------------------------------------------
  93.  * \fn     CreateStructElem(const char *pElemName)
  94.  * \brief  create a new entry for a structure definition
  95.  * \param  pElemName name of the structure element
  96.  * \return * to element or NULL if allocation failed
  97.  * ------------------------------------------------------------------------ */
  98.  
  99. void ExpandStructStd(const tStrComp *pVarName, const struct sStructElem *pStructElem, LargeWord Base)
  100. {
  101.   LabelHandle(pVarName, Base + pStructElem->Offset, True);
  102.   if (pStructElem->OpSize != eSymbolSizeUnknown)
  103.   {
  104.     String ext_name_buf;
  105.     tStrComp ext_name;
  106.     const tStrComp *p_ext_name;
  107.  
  108.     StrCompMkTemp(&ext_name, ext_name_buf, sizeof(ext_name_buf));
  109.     p_ext_name = ExpandStrSymbol(&ext_name, pVarName, !CaseSensitive);
  110.     if (p_ext_name)
  111.       SetSymbolOrStructElemSize(p_ext_name, pStructElem->OpSize);
  112.   }
  113. }
  114.  
  115. PStructElem CreateStructElem(const tStrComp *pElemName)
  116. {
  117.   String ext_name_buf;
  118.   tStrComp ext_name;
  119.   const tStrComp *p_ext_name;
  120.   PStructElem pNeu;
  121.  
  122.   StrCompMkTemp(&ext_name, ext_name_buf, sizeof(ext_name_buf));
  123.   p_ext_name = ExpandStrSymbol(&ext_name, pElemName, !CaseSensitive);
  124.   if (!p_ext_name)
  125.     return NULL;
  126.  
  127.   pNeu = (PStructElem) calloc(1, sizeof(TStructElem));
  128.   if (pNeu)
  129.   {
  130.     pNeu->pElemName = as_strdup(p_ext_name->str.p_str);
  131.     pNeu->pRefElemName = NULL;
  132.     pNeu->ExpandFnc = ExpandStructStd;
  133.     pNeu->Offset = 0;
  134.     pNeu->BitPos = pNeu->BitWidthM1 = -1;
  135.     pNeu->OpSize = eSymbolSizeUnknown;
  136.     pNeu->Next = NULL;
  137.   }
  138.   return pNeu;
  139. }
  140.  
  141. /*!------------------------------------------------------------------------
  142.  * \fn     CloneStructElem(const struct sStrComp *pCloneElemName, const struct sStructElem *pSrc)
  143.  * \brief  generate copy of struct element, with different name
  144.  * \param  pCloneElemName new element's name
  145.  * \param  pSrc source to clone from
  146.  * \return * to new element or NULL
  147.  * ------------------------------------------------------------------------ */
  148.  
  149. PStructElem CloneStructElem(const struct sStrComp *pCloneElemName, const struct sStructElem *pSrc)
  150. {
  151.   PStructElem pResult = CreateStructElem(pCloneElemName);
  152.   if (!pResult)
  153.     return pResult;
  154.  
  155.   pResult->Offset = pSrc->Offset;
  156.   pResult->OpSize = pSrc->OpSize;
  157.   pResult->BitPos = pSrc->BitPos;
  158.   pResult->ExpandFnc = pSrc->ExpandFnc;
  159.   pResult->pRefElemName = as_strdup(pSrc->pRefElemName);
  160.   return pResult;
  161. }
  162.  
  163. /*!------------------------------------------------------------------------
  164.  * \fn     AddStructElem(PStructRec pStructRec, PStructElem pElement)
  165.  * \brief  add a new element to a structure definition
  166.  * \param  pStructRec structure to extend
  167.  * \param  pElement new element
  168.  * \return True if element was added
  169.  * ------------------------------------------------------------------------ */
  170.  
  171. Boolean AddStructElem(PStructRec pStructRec, PStructElem pElement)
  172. {
  173.   PStructElem pRun, pPrev;
  174.   Boolean Duplicate = False;
  175.  
  176.   if (!CaseSensitive && pElement->pRefElemName)
  177.     NLS_UpString(pElement->pRefElemName);
  178.  
  179.   for (pPrev = NULL, pRun = pStructRec->Elems; pRun; pPrev = pRun, pRun = pRun->Next)
  180.   {
  181.     Duplicate = CaseSensitive ? !strcmp(pElement->pElemName, pRun->pElemName) : !as_strcasecmp(pElement->pElemName, pRun->pElemName);
  182.     if (Duplicate)
  183.     {
  184.       WrXError(ErrNum_DuplicateStructElem, pElement->pElemName);
  185.       break;
  186.     }
  187.   }
  188.  
  189.   if (!Duplicate)
  190.   {
  191.     if (pPrev)
  192.       pPrev->Next = pElement;
  193.     else
  194.       pStructRec->Elems = pElement;
  195.   }
  196.   BumpStructLength(pStructRec, pElement->Offset);
  197.   if (Duplicate)
  198.     DestroyStructElem(pElement);
  199.   return !Duplicate;
  200. }
  201.  
  202. /*!------------------------------------------------------------------------
  203.  * \fn     SetStructElemSize(PStructRec pStructRec, const tStrComp *pElemName, tSymbolSize Size)
  204.  * \brief  set the operand size of a structure's element
  205.  * \param  pStructRec structure the element is contained in
  206.  * \param  pElemName element's name
  207.  * \param  Size operand size to set
  208.  * ------------------------------------------------------------------------ */
  209.  
  210. void SetStructElemSize(PStructRec pStructRec, const tStrComp *pElemName, tSymbolSize Size)
  211. {
  212.   PStructElem pRun;
  213.   String exp_name_buf;
  214.   tStrComp exp_name;
  215.   const tStrComp *p_exp_name;
  216.  
  217.   StrCompMkTemp(&exp_name, exp_name_buf, sizeof(exp_name_buf));
  218.   p_exp_name = ExpandStrSymbol(&exp_name, pElemName, !CaseSensitive);
  219.   if (!p_exp_name)
  220.     return;
  221.   for (pRun = pStructRec->Elems; pRun; pRun = pRun->Next)
  222.   {
  223.     if (!strcmp(p_exp_name->str.p_str, pRun->pElemName))
  224.     {
  225.       pRun->OpSize = Size;
  226.       return;
  227.     }
  228.   }
  229.   fprintf(stderr, "SetStructElemSize: cannot set size of '%s', something wicked is going on\n", p_exp_name->str.p_str);
  230. }
  231.  
  232. /*!------------------------------------------------------------------------
  233.  * \fn     ResolveStructReferences(PStructRec pStructRec)
  234.  * \brief  resolve referenced elements in structure
  235.  * \param  pStructRec structure to work on
  236.  * ------------------------------------------------------------------------ */
  237.  
  238. void ResolveStructReferences(PStructRec pStructRec)
  239. {
  240.   Boolean AllResolved, DidResolve;
  241.   PStructElem pRun, pRef;
  242.  
  243.   /* iterate over list until all symbols resolved, or we failed to resolve at least one per pass */
  244.  
  245.   do
  246.   {
  247.     AllResolved = True;
  248.     DidResolve = False;
  249.  
  250.     for (pRun = pStructRec->Elems; pRun; pRun = pRun->Next)
  251.       if (pRun->pRefElemName)
  252.       {
  253.         /* Only resolve to elements that already have been resolved.
  254.            That's why we may need more than one pass.  */
  255.  
  256.         for (pRef = pStructRec->Elems; pRef; pRef = pRef->Next)
  257.         {
  258.           if (!strcmp(pRun->pRefElemName, pRef->pElemName) && !pRef->pRefElemName)
  259.           {
  260.             pRun->Offset = pRef->Offset;
  261.             if (pRun->OpSize == eSymbolSizeUnknown)
  262.               pRun->OpSize = pRef->OpSize;
  263.             free(pRun->pRefElemName);
  264.             pRun->pRefElemName = NULL;
  265.             DidResolve = True;
  266.             break;
  267.           }
  268.         }
  269.         if (!pRef)
  270.           AllResolved = False;
  271.       }
  272.   }
  273.   while (!AllResolved && DidResolve);
  274.   if (!AllResolved)
  275.   {
  276.     String Str;
  277.  
  278.     for (pRun = pStructRec->Elems; pRun; pRun = pRun->Next)
  279.       if (pRun->pRefElemName)
  280.       {
  281.         strmaxcpy(Str, pRun->pElemName, STRINGSIZE);
  282.         strmaxcat(Str, " -> ", STRINGSIZE);
  283.         strmaxcat(Str, pRun->pRefElemName, STRINGSIZE);
  284.         WrXError(ErrNum_UnresolvedStructRef, Str);
  285.       }
  286.   }
  287. }
  288.  
  289. void BuildStructName(char *pResult, unsigned ResultLen, const char *pName)
  290. {
  291.   PStructStack ZStruct;
  292.   String tmp2;
  293.  
  294.   strmaxcpy(pResult, pName, ResultLen);
  295.   for (ZStruct = StructStack; ZStruct; ZStruct = ZStruct->Next)
  296.     if (ZStruct->StructRec->DoExt && ZStruct->Name[0])
  297.     {
  298.       as_snprintf(tmp2, sizeof(tmp2), "%s%c", ZStruct->pBaseName, ZStruct->StructRec->ExtChar);
  299.       strmaxprep(pResult, tmp2, ResultLen);
  300.     }
  301. }
  302.  
  303. void AddStructSymbol(const char *pName, LargeWord Value)
  304. {
  305.   PStructStack ZStruct;
  306.  
  307.   /* what we get is offset/length in current structure.  Add to
  308.      it all offsets in parent structures, i.e. leave out SaveCurrPC
  309.      of bottom of stack which contains saved PC of non-struct segment: */
  310.  
  311.   for (ZStruct = StructStack; ZStruct->Next; ZStruct = ZStruct->Next)
  312.     Value += ZStruct->SaveCurrPC;
  313.  
  314.   {
  315.     String tmp;
  316.     tStrComp TmpComp;
  317.  
  318.     as_snprintf(tmp, sizeof(tmp), "%s%c%s", pInnermostNamedStruct->Name, pInnermostNamedStruct->StructRec->ExtChar, pName);
  319.     StrCompMkTemp(&TmpComp, tmp, sizeof(tmp));
  320.     EnterIntSymbol(&TmpComp, Value, SegNone, False);
  321.   }
  322. }
  323.  
  324. void BumpStructLength(PStructRec StructRec, LongInt Length)
  325. {
  326.   if (StructRec->TotLen < Length)
  327.     StructRec->TotLen = Length;
  328. }
  329.  
  330. static Boolean StructAdder(PTree *PDest, PTree Neu, void *pData)
  331. {
  332.   PStructNode NewNode = (PStructNode) Neu, *Node;
  333.   Boolean Protest = *((Boolean*)pData), Result = False;
  334.  
  335.   if (!PDest)
  336.   {
  337.     NewNode->Defined = TRUE;
  338.     return True;
  339.   }
  340.  
  341.   Node = (PStructNode*) PDest;
  342.   if ((*Node)->Defined)
  343.   {
  344.     if (Protest)
  345.       WrXError(ErrNum_DoubleStruct, Neu->Name);
  346.     else
  347.     {
  348.       DestroyStructRec((*Node)->StructRec);
  349.       (*Node)->StructRec = NewNode->StructRec;
  350.     }
  351.   }
  352.   else
  353.   {
  354.     DestroyStructRec((*Node)->StructRec);
  355.     (*Node)->StructRec = NewNode->StructRec;
  356.     (*Node)->Defined = True;
  357.     return True;
  358.   }
  359.   return Result;
  360. }
  361.  
  362. void AddStruct(PStructRec StructRec, char *Name, Boolean Protest)
  363. {
  364.   PStructNode Node;
  365.   PTree TreeRoot;
  366.  
  367.   Node = (PStructNode) malloc(sizeof(TStructNode));
  368.   if (Node)
  369.   {
  370.     Node->Tree.Left = Node->Tree.Right = NULL;
  371.     Node->Tree.Name = as_strdup(Name);
  372.     if (!CaseSensitive)
  373.       NLS_UpString(Node->Tree.Name);
  374.     Node->Tree.Attribute = MomSectionHandle;
  375.     Node->Defined = FALSE;
  376.     Node->StructRec = StructRec;
  377.     TreeRoot = &(StructRoot->Tree);
  378.     EnterTree(&TreeRoot, &(Node->Tree), StructAdder, &Protest);
  379.     StructRoot = (PStructNode)TreeRoot;
  380.   }
  381. }
  382.  
  383. static PStructRec FoundStruct_FNode(LongInt Handle, const char *Name)
  384. {
  385.   PStructNode Lauf;
  386.  
  387.   Lauf = (PStructNode) SearchTree((PTree)StructRoot, Name, Handle);
  388.   return Lauf ? Lauf->StructRec : NULL;
  389. }
  390.  
  391. Boolean FoundStruct(PStructRec *Erg, const char *pName)
  392. {
  393.   PSaveSection Lauf;
  394.  
  395.   *Erg = FoundStruct_FNode(MomSectionHandle, pName);
  396.   if (*Erg)
  397.     return True;
  398.   Lauf = SectionStack;
  399.   while (Lauf)
  400.   {
  401.     *Erg = FoundStruct_FNode(Lauf->Handle, pName);
  402.     if (*Erg)
  403.       return True;
  404.     Lauf = Lauf->Next;
  405.   }
  406.   return False;
  407. }
  408.  
  409. static void ResDef(PTree Tree, void *pData)
  410. {
  411.   UNUSED(pData);
  412.  
  413.   ((PStructNode)Tree)->Defined = FALSE;
  414. }
  415.  
  416. void ResetStructDefines(void)
  417. {
  418.   IterTree((PTree)StructRoot, ResDef, NULL);
  419. }
  420.  
  421. typedef struct
  422. {
  423.   LongInt Sum;
  424.   as_dynstr_t num_str;
  425. } TPrintContext;
  426.  
  427. static void PrintDef(PTree Tree, void *pData)
  428. {
  429.   PStructNode Node = (PStructNode)Tree;
  430.   PStructElem Elem;
  431.   TPrintContext *pContext = (TPrintContext*)pData;
  432.   String s;
  433.   char NumStr[30];
  434.   TempResult t;
  435.  
  436.   UNUSED(pData);
  437.   as_tempres_ini(&t);
  438.  
  439.   WrLstLine("");
  440.   pContext->Sum++;
  441.   strmaxcpy(s, Node->Tree.Name, STRINGSIZE);
  442.   if (Node->Tree.Attribute != -1)
  443.   {
  444.     strmaxcat(s, "[", STRINGSIZE);
  445.     strmaxcat(s, GetSectionName(Node->Tree.Attribute), STRINGSIZE);
  446.     strmaxcat(s, "]", STRINGSIZE);
  447.   }
  448.   WrLstLine(s);
  449.   for (Elem = Node->StructRec->Elems; Elem; Elem = Elem->Next)
  450.   {
  451.     as_tempres_set_int(&t, Elem->Offset);
  452.     StrSym(&t, False, &pContext->num_str, ListRadixBase);
  453.     as_snprintf(s, sizeof(s), "%3s", pContext->num_str.p_str);
  454.     if (Elem->BitPos >= 0)
  455.     {
  456.       if (Elem->BitWidthM1 >= 0)
  457.         as_snprintf(NumStr, sizeof(NumStr), ".%d-%d", Elem->BitPos, Elem->BitPos + Elem->BitWidthM1);
  458.       else
  459.         as_snprintf(NumStr, sizeof(NumStr), ".%d", Elem->BitPos);
  460.     }
  461.     else
  462.       *NumStr = '\0';
  463.     as_snprcatf(s, sizeof(s), "%-6s", NumStr);
  464.     if (Elem->OpSize != eSymbolSizeUnknown)
  465.       as_snprcatf(s, sizeof(s), "(%s)", GetSymbolSizeName(Elem->OpSize));
  466.     else
  467.       strmaxcat(s, "   ", STRINGSIZE);
  468.     as_snprcatf(s, sizeof(s), " %s", Elem->pElemName);
  469.     WrLstLine(s);
  470.   }
  471.   as_tempres_free(&t);
  472. }
  473.  
  474. void PrintStructList(void)
  475. {
  476.   TPrintContext Context;
  477.   String s;
  478.  
  479.   if (!StructRoot)
  480.     return;
  481.  
  482.   NewPage(ChapDepth, True);
  483.   WrLstLine(getmessage(Num_ListStructListHead1));
  484.   WrLstLine(getmessage(Num_ListStructListHead2));
  485.  
  486.   Context.Sum = 0;
  487.   as_dynstr_ini(&Context.num_str, STRINGSIZE);
  488.   IterTree((PTree)StructRoot, PrintDef, &Context);
  489.   as_dynstr_free(&Context.num_str);
  490.   as_snprintf(s, sizeof(s), "%" PRILongInt "%s",
  491.               Context.Sum,
  492.               getmessage((Context.Sum == 1) ? Num_ListStructSumMsg : Num_ListStructSumsMsg));
  493.   WrLstLine(s);
  494. }
  495.  
  496. static void ClearNode(PTree Tree, void *pData)
  497. {
  498.   PStructNode Node = (PStructNode) Tree;
  499.   UNUSED(pData);
  500.  
  501.   DestroyStructRec(Node->StructRec);
  502. }
  503.  
  504. void ClearStructList(void)
  505. {
  506.   PTree TreeRoot;
  507.  
  508.   TreeRoot = &(StructRoot->Tree);
  509.   StructRoot = NULL;
  510.   DestroyTree(&TreeRoot, ClearNode, NULL);
  511. }
  512.  
  513. static void ExpandStruct_One(PStructRec StructRec, char *pVarPrefix, char *pStructPrefix, LargeWord Base)
  514. {
  515.   PStructElem StructElem;
  516.   int VarLen, RemVarLen, StructLen, RemStructLen;
  517.   tStrComp TmpComp;
  518.  
  519.   VarLen = strlen(pVarPrefix);
  520.   pVarPrefix[VarLen] = StructRec->ExtChar;
  521.   RemVarLen = STRINGSIZE - 3 - VarLen;
  522.  
  523.   StructLen = strlen(pStructPrefix);
  524.   pStructPrefix[StructLen] = StructRec->ExtChar;
  525.   RemStructLen = STRINGSIZE - 3 - StructLen;
  526.  
  527.   if ((RemVarLen > 1) && (RemStructLen > 1))
  528.   {
  529.     for (StructElem = StructRec->Elems; StructElem; StructElem = StructElem->Next)
  530.     {
  531.       strmaxcpy(pVarPrefix + VarLen + 1, StructElem->pElemName, RemVarLen);
  532.       StrCompMkTemp(&TmpComp, pVarPrefix, 0);
  533.       StructElem->ExpandFnc(&TmpComp, StructElem, Base);
  534.       if (StructElem->IsStruct)
  535.       {
  536.         TStructRec *pSubStruct;
  537.         Boolean Found;
  538.  
  539.         strmaxcpy(pStructPrefix + StructLen + 1, StructElem->pElemName, RemStructLen);
  540.         Found = FoundStruct(&pSubStruct, pStructPrefix);
  541.         if (Found)
  542.           ExpandStruct_One(pSubStruct, pVarPrefix, pStructPrefix, Base + StructElem->Offset);
  543.       }
  544.     }
  545.   }
  546.   pVarPrefix[VarLen] = '\0';
  547.   pStructPrefix[StructLen] = '\0';
  548. }
  549.  
  550. /*!------------------------------------------------------------------------
  551.  * \fn     ExpandStruct(PStructRec StructRec)
  552.  * \brief  expand a defined structure
  553.  * \param  StructRec structure to expand
  554.  * ------------------------------------------------------------------------ */
  555.  
  556. #define DIMENSION_MAX 3
  557.  
  558. void ExpandStruct(PStructRec StructRec, const char *p_struct_name)
  559. {
  560.   String CompVarName, CompStructName;
  561.   int z;
  562.   unsigned DimensionCnt = 0, Dim;
  563.   LargeInt Dimensions[DIMENSION_MAX];
  564.   tStrComp Arg;
  565.   tEvalResult EvalResult;
  566.  
  567.   if (!LabPart.str.p_str[0])
  568.   {
  569.     WrError(ErrNum_StructNameMissing);
  570.     return;
  571.   }
  572.  
  573.   /* currently, we only support array dimensions as arguments */
  574.  
  575.   for (z = 1; z <= ArgCnt; z++)
  576.     if (IsIndirectGen(ArgStr[z].str.p_str, "[]"))
  577.     {
  578.       if (DimensionCnt >= DIMENSION_MAX)
  579.       {
  580.         WrStrErrorPos(ErrNum_TooManyArrayDimensions, &ArgStr[z]);
  581.         return;
  582.       }
  583.       StrCompRefRight(&Arg, &ArgStr[z], 1);
  584.       StrCompShorten(&Arg, 1);
  585.       Dimensions[DimensionCnt++] = EvalStrIntExpressionWithResult(&Arg, UInt32, &EvalResult);
  586.       if (!EvalResult.OK)
  587.         return;
  588.       if (EvalResult.Flags & eSymbolFlag_FirstPassUnknown)
  589.       {
  590.         WrStrErrorPos(ErrNum_FirstPassCalc, &Arg);
  591.         return;
  592.       }
  593.       if (Dimensions[DimensionCnt - 1] <= 0)
  594.       {
  595.         WrStrErrorPos(ErrNum_UnderRange, &Arg);
  596.         return;
  597.       }
  598.     }
  599.     else
  600.     {
  601.       WrStrErrorPos(ErrNum_InvStructArgument, &ArgStr[z]);
  602.       return;
  603.     }
  604.  
  605.   strmaxcpy(CompStructName, p_struct_name, sizeof(CompStructName));
  606.   strmaxcpy(CompVarName, LabPart.str.p_str, sizeof(CompVarName));
  607.   if (!DimensionCnt)
  608.   {
  609.     ExpandStruct_One(StructRec, CompVarName, CompStructName, EProgCounter());
  610.     CodeLen = StructRec->TotLen;
  611.   }
  612.   else
  613.   {
  614.     LargeInt Indices[DIMENSION_MAX];
  615.     int CompVarNameLens[DIMENSION_MAX];
  616.     tStrComp LabelComp;
  617.  
  618.     /* Start with element [0,...,0] and build associated names.
  619.        Store length of names up to given dimension so we don't
  620.        have to rebuild the name with all indices upon every elemnt: */
  621.  
  622.     for (Dim = 0; Dim < DimensionCnt; Dim++)
  623.     {
  624.       Indices[Dim] = 0;
  625.       CompVarNameLens[Dim] = strlen(CompVarName);
  626.       as_snprcatf(CompVarName, sizeof(CompVarName), "_%llu", (LargeWord)Indices[Dim]);
  627.     }
  628.     while (Indices[0] < Dimensions[0])
  629.     {
  630.       StrCompMkTemp(&LabelComp, CompVarName, sizeof(CompVarName));
  631.       LabelHandle(&LabelComp, EProgCounter() + CodeLen, True);
  632.       ExpandStruct_One(StructRec, CompVarName, CompStructName, EProgCounter() + CodeLen);
  633.       CodeLen += StructRec->TotLen;
  634.  
  635.       /* increase indices, ripple through 'carry' from minor to major indices */
  636.  
  637.       Indices[DimensionCnt - 1]++;
  638.       for (Dim = DimensionCnt - 1; Dim > 0; Dim--)
  639.         if (Indices[Dim] >= Dimensions[Dim])
  640.         {
  641.           Indices[Dim] = 0;
  642.           Indices[Dim - 1]++;
  643.         }
  644.         else
  645.           break;
  646.  
  647.       /* Dim now holds the most major (leftmost) index that changed.  Build up new element
  648.          name, starting from that: */
  649.  
  650.       CompVarName[CompVarNameLens[Dim]] = '\0';
  651.       for (; Dim < DimensionCnt; Dim++)
  652.       {
  653.         as_snprcatf(CompVarName, sizeof(CompVarName), "_%llu", (LargeWord)Indices[Dim]);
  654.         if (Dim + 1 < DimensionCnt)
  655.           CompVarNameLens[Dim + 1] = strlen(CompVarName);
  656.       }
  657.     }
  658.   }
  659.   BookKeeping();
  660.   DontPrint = True;
  661. }
  662.  
  663. void asmstruct_init(void)
  664. {
  665.    StructRoot = NULL;
  666. }
  667.