Top secrets sources NedoPC pentevo

Rev

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

/* asmif.c */
/*****************************************************************************/
/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
/*                                                                           */
/* AS-Portierung                                                             */
/*                                                                           */
/* Befehle zur bedingten Assemblierung                                       */
/*                                                                           */
/*****************************************************************************/

#include "stdinc.h"
#include <string.h>
#include <ctype.h>

#include "bpemu.h"
#include "chunks.h"
#include "strutil.h"
#include "errmsg.h"
#include "asmdef.h"
#include "asmsub.h"
#include "asmpars.h"

#include "asmif.h"


PIfSave FirstIfSave;
Boolean IfAsm;       /* FALSE: in einer neg. IF-Sequenz-->kein Code */

static Boolean ActiveIF;

/*!------------------------------------------------------------------------
 * \fn     ifsave_create(tIfState if_state, Boolean case_found)
 * \brief  create new IF stack element
 * \param  if_state initial state of related construct
 * \param  case_found in block enabled by IF/CASE?
 * \return * to new element
 * ------------------------------------------------------------------------ */


static PIfSave ifsave_create(tIfState if_state, Boolean case_found)
{
  PIfSave p_save;

  p_save = (PIfSave) malloc(sizeof(TIfSave));
  if (p_save)
  {
    p_save->Next = NULL;
    p_save->NestLevel = SaveIFs() + 1;
    p_save->SaveIfAsm = IfAsm;
    as_tempres_ini(&p_save->SaveExpr);
    p_save->CaseFound = case_found;
    p_save->State = if_state;
    p_save->StartLine = CurrLine;
  }
  return p_save;
}

/*!------------------------------------------------------------------------
 * \fn     ifsave_free(PIfSave p_save)
 * \brief  destroy IF stack element
 * \param  p_save element to destroy
 * ------------------------------------------------------------------------ */


static void ifsave_free(PIfSave p_save)
{
  as_tempres_free(&p_save->SaveExpr);
  free(p_save);
}

static LongInt GetIfVal(const tStrComp *pCond)
{
  Boolean IfOK;
  tSymbolFlags Flags;
  LongInt Tmp;

  Tmp = EvalStrIntExpressionWithFlags(pCond, Int32, &IfOK, &Flags);
  if (mFirstPassUnknown(Flags) || !IfOK)
  {
    Tmp = 1;
    if (mFirstPassUnknown(Flags)) WrError(ErrNum_FirstPassCalc);
  }

  return Tmp;
}


static void AddBoolFlag(Boolean Flag)
{
  strmaxcpy(ListLine, Flag ? "=>TRUE" : "=>FALSE", STRINGSIZE);
}


static void PushIF(LongInt IfExpr)
{
  PIfSave NewSave = ifsave_create(IfState_IFIF, IfExpr != 0);

  NewSave->Next = FirstIfSave;
  FirstIfSave = NewSave;
  IfAsm = IfAsm && NewSave->CaseFound;
}


static void CodeIF(void)
{
  LongInt IfExpr;

  ActiveIF = IfAsm;

  if (!IfAsm)
    IfExpr = 1;
  else if (!ChkArgCnt(1, 1))
    IfExpr = 1;
  else
    IfExpr = GetIfVal(&ArgStr[1]);
  if (IfAsm)
    AddBoolFlag(IfExpr != 0);
  PushIF(IfExpr);
}


static void CodeIFDEF(Word Negate)
{
  LongInt IfExpr;
  Boolean Defined;

  ActiveIF = IfAsm;

  if (!IfAsm) IfExpr = 1;
  else if (!ChkArgCnt(1, 1))
    IfExpr = 1;
  else
  {
    Defined = IsSymbolDefined(&ArgStr[1]);
    if (IfAsm)
      strmaxcpy(ListLine, (Defined) ? "=>DEFINED" : "=>UNDEFINED", STRINGSIZE);
    if (!Negate)
      IfExpr = (Defined) ? 1 : 0;
    else
      IfExpr = (Defined) ? 0 : 1;
  }
  PushIF(IfExpr);
}


static void CodeIFUSED(Word Negate)
{
  LongInt IfExpr;
  Boolean Used;

  ActiveIF = IfAsm;

  if (!IfAsm)
    IfExpr = 1;
  else if (!ChkArgCnt(1, 1))
    IfExpr = 1;
  else
  {
    Used = IsSymbolUsed(&ArgStr[1]);
    if (IfAsm)
      strmaxcpy(ListLine, (Used) ? "=>USED" : "=>UNUSED", STRINGSIZE);
    if (!Negate)
      IfExpr = (Used) ? 1 : 0;
    else
      IfExpr = (Used) ? 0 : 1;
  }
  PushIF(IfExpr);
}


void CodeIFEXIST(Word Negate)
{
  LongInt IfExpr;
  Boolean Found;
  String NPath;

  ActiveIF = IfAsm;

  if (!IfAsm)
    IfExpr = 1;
  else if (!ChkArgCnt(1, 1))
    IfExpr = 1;
  else
  {
    String FileName, Dummy;

    strmaxcpy(FileName, (ArgStr[1].str.p_str[0] == '"') ? ArgStr[1].str.p_str + 1 : ArgStr[1].str.p_str, STRINGSIZE);
    if (FileName[strlen(FileName) - 1] == '"')
      FileName[strlen(FileName) - 1] = '\0';
    AddSuffix(FileName, IncSuffix);
    strmaxcpy(NPath, IncludeList, STRINGSIZE);
    strmaxprep(NPath, SDIRSEP, STRINGSIZE);
    strmaxprep(NPath, ".", STRINGSIZE);
    Found = !FSearch(Dummy, sizeof(Dummy), FileName, CurrFileName, NPath);
    if (IfAsm)
      strmaxcpy(ListLine, Found ? "=>FOUND" : "=>NOT FOUND", STRINGSIZE);
    IfExpr = Negate ? !Found : Found;
  }
  PushIF(IfExpr);
}


static void CodeIFB(Word Negate)
{
  Boolean Blank = True;
  LongInt IfExpr;
  int z;

  ActiveIF = IfAsm;

  if (!IfAsm)
    IfExpr = 1;
  else
  {
    for (z = 1; z <= ArgCnt; z++)
      if (strlen(ArgStr[z++].str.p_str) > 0)
        Blank = False;
    if (IfAsm)
      strmaxcpy(ListLine, (Blank) ? "=>BLANK" : "=>NOT BLANK", STRINGSIZE);
    IfExpr = Negate ? !Blank : Blank;
  }
  PushIF(IfExpr);
}


static void CodeELSEIF(void)
{
  LongInt IfExpr;

  if (!FirstIfSave || (FirstIfSave->State != IfState_IFIF)) WrError(ErrNum_MissingIf);
  else if (ArgCnt == 0)
  {
    if (FirstIfSave->SaveIfAsm)
      AddBoolFlag(IfAsm = (!FirstIfSave->CaseFound));
    FirstIfSave->State = IfState_IFELSE;
  }
  else if (ArgCnt == 1)
  {
    if (!FirstIfSave->SaveIfAsm)
      IfExpr = 1;
    else if (FirstIfSave->CaseFound)
      IfExpr = 0;
    else
      IfExpr = GetIfVal(&ArgStr[1]);
    IfAsm = ((FirstIfSave->SaveIfAsm) && (IfExpr != 0) && (!FirstIfSave->CaseFound));
    if (FirstIfSave->SaveIfAsm)
      AddBoolFlag(IfExpr != 0);
    if (IfExpr != 0)
      FirstIfSave->CaseFound = True;
  }
  else
    (void)ChkArgCnt(0, 1);

  ActiveIF = (!FirstIfSave) || (FirstIfSave->SaveIfAsm);
}


static void CodeENDIF(void)
{
  if (!ChkArgCnt(0, 0));
  else if (!FirstIfSave || ((FirstIfSave->State != IfState_IFIF) && (FirstIfSave->State != IfState_IFELSE))) WrError(ErrNum_MissingIf);
  else
  {
    PIfSave NewSave;

    IfAsm = FirstIfSave->SaveIfAsm;
    NewSave = FirstIfSave;
    FirstIfSave = NewSave->Next;
    as_snprintf(ListLine, STRINGSIZE, "[%u]", (unsigned)NewSave->StartLine);
    ifsave_free(NewSave);
  }

  ActiveIF = IfAsm;
}


static void EvalIfExpression(const tStrComp *pCond, TempResult *erg)
{
  EvalStrExpression(pCond, erg);
  if ((erg->Typ == TempNone) || mFirstPassUnknown(erg->Flags))
  {
    as_tempres_set_int(erg, 1);
    if (mFirstPassUnknown(erg->Flags))
      WrError(ErrNum_FirstPassCalc);
  }
}


static void CodeSWITCH(void)
{
  PIfSave NewSave = ifsave_create(IfState_CASESWITCH, False);

  ActiveIF = IfAsm;

  if (ArgCnt != 1)
  {
    as_tempres_set_int(&NewSave->SaveExpr, 1);
    if (IfAsm)
      (void)ChkArgCnt(1, 1);
  }
  else
  {
    EvalIfExpression(&ArgStr[1], &NewSave->SaveExpr);
    SetListLineVal(&NewSave->SaveExpr);
  }
  NewSave->Next = FirstIfSave;
  FirstIfSave = NewSave;
}


static void CodeCASE(void)
{
  Boolean eq;
  int z;

  if (!FirstIfSave) WrError(ErrNum_MissingIf);
  else if (ChkArgCnt(1, ArgCntMax))
  {
    if ((FirstIfSave->State != IfState_CASESWITCH) && (FirstIfSave->State != IfState_CASECASE)) WrError(ErrNum_InvIfConst);
    else
    {
      if (!FirstIfSave->SaveIfAsm)
        eq = True;
      else if (FirstIfSave->CaseFound)
        eq = False;
      else
      {
        TempResult t;

        as_tempres_ini(&t);
        eq = False;
        z = 1;
        do
        {
          EvalIfExpression(&ArgStr[z], &t);
          eq = (FirstIfSave->SaveExpr.Typ == t.Typ);
          if (eq)
           switch (t.Typ)
           {
             case TempInt:
               eq = (t.Contents.Int == FirstIfSave->SaveExpr.Contents.Int);
               break;
             case TempFloat:
               eq = (t.Contents.Float == FirstIfSave->SaveExpr.Contents.Float);
               break;
             case TempString:
               eq = (as_nonz_dynstr_cmp(&t.Contents.str, &FirstIfSave->SaveExpr.Contents.str) == 0);
               break;
             default:
               eq = False;
               break;
           }
          z++;
        }
        while (!eq && (z <= ArgCnt));
        as_tempres_free(&t);
      }
      IfAsm = (FirstIfSave->SaveIfAsm && eq & !FirstIfSave->CaseFound);
      if (FirstIfSave->SaveIfAsm)
        AddBoolFlag(eq && !FirstIfSave->CaseFound);
      if (eq)
        FirstIfSave->CaseFound = True;
      FirstIfSave->State = IfState_CASECASE;
    }
  }

  ActiveIF = !FirstIfSave || FirstIfSave->SaveIfAsm;
}


static void CodeELSECASE(void)
{
  if (ChkArgCnt(0, 0))
  {
    if ((FirstIfSave->State != IfState_CASESWITCH) && (FirstIfSave->State != IfState_CASECASE)) WrError(ErrNum_InvIfConst);
    else
      IfAsm = (FirstIfSave->SaveIfAsm && (!FirstIfSave->CaseFound));
    if (FirstIfSave->SaveIfAsm)
      AddBoolFlag(!FirstIfSave->CaseFound);
    FirstIfSave->CaseFound = True;
    FirstIfSave->State = IfState_CASEELSE;
  }

  ActiveIF = (!FirstIfSave) || (FirstIfSave->SaveIfAsm);
}


static void CodeENDCASE(void)
{
  if (!ChkArgCnt(0, 0));
  else if (!FirstIfSave) WrError(ErrNum_MissingIf);
  else
  {
    if ((FirstIfSave->State != IfState_CASESWITCH)
    && (FirstIfSave->State != IfState_CASECASE)
    && (FirstIfSave->State != IfState_CASEELSE)) WrError(ErrNum_InvIfConst);
    else
    {
      PIfSave NewSave;

      IfAsm = FirstIfSave->SaveIfAsm;
      if (!FirstIfSave->CaseFound) WrError(ErrNum_NoCaseHit);
      NewSave = FirstIfSave;
      FirstIfSave = NewSave->Next;
      as_snprintf(ListLine, STRINGSIZE, "[%u]", (unsigned)NewSave->StartLine);
      ifsave_free(NewSave);
    }
  }

  ActiveIF = IfAsm;
}


Boolean CodeIFs(void)
{
  Boolean Result = True;

  ActiveIF = False;

  switch (as_toupper(*OpPart.str.p_str))
  {
    case 'I':
      if (Memo("IF")) CodeIF();
      else if (Memo("IFDEF")) CodeIFDEF(False);
      else if (Memo("IFNDEF")) CodeIFDEF(True);
      else if (Memo("IFUSED")) CodeIFUSED(False);
      else if (Memo("IFNUSED")) CodeIFUSED(True);
      else if (Memo("IFEXIST")) CodeIFEXIST(False);
      else if (Memo("IFNEXIST")) CodeIFEXIST(True);
      else if (Memo("IFB")) CodeIFB(False);
      else if (Memo("IFNB")) CodeIFB(True);
      else Result = False;
      break;
    case 'E':
      if ((Memo("ELSE")) || (Memo("ELSEIF"))) CodeELSEIF();
      else if (Memo("ENDIF")) CodeENDIF();
      else if (Memo("ELSECASE")) CodeELSECASE();
      else if (Memo("ENDCASE")) CodeENDCASE();
      else Result = False;
      break;
    case 'S':
      if (memo_switch_pseudo()) CodeSWITCH();
      else if (Memo("SELECT") && SwitchIsOccupied) CodeSWITCH();
      else Result = False;
      break;
    case 'C':
      if (Memo("CASE")) CodeCASE();
      else Result = False;
      break;
    case '.':
      if (Memo(".SWITCH")) CodeSWITCH();
      else Result = False;
      break;
    default:
      Result = False;
  }

  return Result;
}

Integer SaveIFs(void)
{
  return (!FirstIfSave) ? 0 : FirstIfSave->NestLevel;
}

void RestoreIFs(Integer Level)
{
  PIfSave OldSave;

  while (FirstIfSave && (FirstIfSave->NestLevel != Level))
  {
    OldSave = FirstIfSave;
    FirstIfSave = OldSave->Next;
    IfAsm = OldSave->SaveIfAsm;
    ifsave_free(OldSave);
  }
}

Boolean IFListMask(void)
{
  switch (ListOn)
  {
    case 0:
      return True;
    case 1:
      return False;
    case 2:
      return ((!ActiveIF) && (!IfAsm));
    case 3:
      return (ActiveIF || (!IfAsm));
  }
  return True;
}

void AsmIFInit(void)
{
  IfAsm = True;
}

void asmif_init(void)
{
}