home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / smapp100.zip / sm10.zip / smgscanf.c < prev    next >
C/C++ Source or Header  |  2000-05-14  |  35KB  |  829 lines

  1. /* ------------------------------------------------------------------------
  2.  *
  3.  *        File: smgscanf.c
  4.  *     Project: Source Mapper.
  5.  *     Created: Mai 19, 1992.
  6.  * Description: Kildekode for å scanne en enkelt kildefil.
  7.  *
  8.  * Copyright (C) 2000 Leif-Erik Larsen.
  9.  * This file is part of the Source Mapper source package.
  10.  * Source Mapper is free software; you can redistribute it and/or modify
  11.  * it under the terms of the GNU General Public License as published
  12.  * by the Free Software Foundation, in version 2 as it comes in the
  13.  * "COPYING" file of the XWorkplace main distribution.
  14.  * This program is distributed in the hope that it will be useful,
  15.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.  * GNU General Public License for more details.
  18.  *
  19.  * ------------------------------------------------------------------------ */
  20.  
  21.  
  22.  
  23.  
  24. #include "smg.h"
  25.  
  26.  
  27.  
  28.  
  29. /* Lovlige tegn i funksjon og identifikator, ved syntaks for C: */
  30. char *legal = "_"
  31.               "0123456789"
  32.               "abcdefghijklmnopqrstuvwxyz"
  33.               "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  34.  
  35.  
  36. /* N¢kkelord, ved syntaks for C: */
  37. char *keywords[] =
  38. {
  39.    /* ANSI standard C: */
  40.    "auto",          "break",            "case",          "char",
  41.    "const",         "continue",         "default",       "do",
  42.    "double",        "else",             "enum",          "extern",
  43.    "float",         "for",              "goto",          "if",
  44.    "int",           "long",             "register",      "return",
  45.    "short",         "signed",           "sizeof",        "static",
  46.    "struct",        "switch",           "typedef",       "union",
  47.    "unsigned",      "void",             "volatile",      "while",
  48.  
  49.    /* Turbo C: */
  50.    "asm",           "__ss",             "interrupt",     "__cs",
  51.    "cdecl",         "near",             "__ds",          "far",
  52.    "pascal",        "__es",             "huge",
  53.  
  54.    /* Turbo C++ Versjon 3.1: */
  55.    "_asm",          "__asm",            "_cdecl",        "__cdecl",
  56.    "class",         "_cs",              "delete",        "_ds",
  57.    "_es",           "_export",          "__export",      "_far",
  58.    "__far",         "_fastcall",        "__fastcall",    "friend",
  59.    "_huge",         "__huge",           "inline",        "_interrupt",
  60.    "__interrupt",   "_loadds",          "__loadds",      "_near",
  61.    "__near",        "new",              "operator",      "_pascal",
  62.    "__pascal",      "private",          "protected",     "public",
  63.    "_saveregs",     "__saveregs",       "_seg",          "__seg",
  64.    "_ss",           "template",         "this",          "virtual",
  65. };
  66.  
  67.  
  68.  
  69.  
  70. #define MAXKEYWORD 83
  71.  
  72.  
  73.  
  74.  
  75. /*
  76. ** Filene nedenfor er gjordt globale for å slippe å oppgi dem som parameter
  77. ** til alle de funksjonene som skal bruke dem:
  78. */
  79. FILE *tempf;        /* For lagring av mellomfil */
  80. FILE *sourcef;      /* Aktiv kildefil */
  81. FILE *funcalf;      /* Midlertidig funksjonskall-liste */
  82. FILE *lininff;      /* Midlertidig linjeinfo/totalinfo */
  83. FILE *funregf;      /* Midlertidig funksjonsregister */
  84. FILE *idlistf;      /* Midlertidig identifikatorliste */
  85.  
  86.  
  87.  
  88.  
  89. static void DisplayCurrentLNr ( long iLNr )
  90. /* Display line number of which source line containing the error.
  91.    Created: February 04, 1996. By Leif-Erik Larsen. */
  92. {
  93.    Display (D_LOW, "%s (%ld)", _StrMSGINTERPRETLIN, iLNr);
  94. } /* DisplayCurrentLNr (); */
  95.  
  96.  
  97.  
  98.  
  99. int ifkeyword ( char *word )
  100. /* Opprettet: Torsdag 28. mai 1992.
  101.    Parameter: "word" Ord som skal skjekkes.
  102.    Retur    : TRUE hvis "word" er et n¢kkelord, eller FALSE.
  103.    Beskriv  : Sjekker om oppgitt ord er et n¢kkelord for C-syntaks
  104.               eller ikke.
  105. */
  106. {
  107.    int t1;
  108.  
  109.    for (t1 = 0; t1 < MAXKEYWORD; t1++)
  110.    {
  111.       if (strcmp (keywords[t1], word) == 0)
  112.          return (TRUE);
  113.    }
  114.    return (FALSE);
  115. } /* ifkeyword (); */
  116.  
  117.  
  118.  
  119.  
  120. int scan_sourcef ( char *sfnam, char *tfnam )
  121. /* Opprettet: Onsdag 10. juni 1992.
  122.    Parameter: "sfnam" Navn/katalog til kildefil som skal tolkes.
  123.               "tfnam" Navn/katalog hvor endelig mellomfil skal lagres.
  124.    Retur    : E/O.
  125.    Beskriv  : Scanner oppgitt kildefil og produserer midlertidige
  126.               filer av denne. Deretter kobles de midlertidige filene sammen
  127.               til den endelige mellomfile. Denne funksjonen kaller
  128.               "scan_sourcef_ ()" og utf¢rer n¢dvendige rutiner ved eventuell
  129.               returnert feilkode. Dessuten informerer denne funksjonen
  130.               bruker om hvilken kildefil som tolkes for ¢yeblikket.
  131. */
  132. {
  133.    int ok;                             /* Mellomlagring av returkode */
  134.  
  135.    Display (D_HEIGHEST, "%s:\n", sfnam);
  136.  
  137.    if ((sourcef = FOpen (sfnam, "rt")) == NULL)
  138.    {
  139.       RETERR (23, sfnam); /* Failed on open source file! */
  140.    }
  141.  
  142.    if ((tempf = FOpen (tfnam, "wb")) == NULL)
  143.    {
  144.       FClose (sourcef);
  145.       RETERR (16, tfnam); /* Failed on open file! */
  146.    }
  147.  
  148.    if ((funcalf = FOpen (tmpn.funcal, "w+b")) == NULL)
  149.    {
  150.       FClose (sourcef);
  151.       FClose (tempf);
  152.       RETERR (11, tmpn.funcal); /* Failed on open temporary file! */
  153.    }
  154.  
  155.    if ((lininff = FOpen (tmpn.lininf, "w+b")) == NULL)
  156.    {
  157.       FClose (sourcef);
  158.       FClose (tempf);
  159.       FClose (funcalf);
  160.       RETERR (11, tmpn.lininf); /* Failed on open temporary file! */
  161.    }
  162.  
  163.    if ((funregf = FOpen (tmpn.funreg, "w+b")) == NULL)
  164.    {
  165.       FClose (sourcef);
  166.       FClose (tempf);
  167.       FClose (funcalf);
  168.       FClose (lininff);
  169.       RETERR (11, tmpn.funreg); /* Failed on open temporary file! */
  170.    }
  171.  
  172.    if ((idlistf = FOpen (tmpn.idlist, "w+b")) == NULL)
  173.    {
  174.       FClose (sourcef);
  175.       FClose (tempf);
  176.       FClose (funcalf);
  177.       FClose (lininff);
  178.       FClose (funregf);
  179.       RETERR (11, tmpn.idlist); /* Failed on open temporary file! */
  180.    }
  181.  
  182.    ok = scan_sourcef_ (sfnam);
  183.  
  184.    FClose (sourcef);
  185.    FClose (tempf);
  186.    FClose (funcalf);
  187.    FClose (lininff);
  188.    FClose (funregf);
  189.    FClose (idlistf);
  190.  
  191.    if (ok != OK)
  192.       Remove (tfnam);    /* Remove unfinished .smg file */
  193.  
  194.    return (ok);
  195. } /* scan_sourcef (); */
  196.  
  197.  
  198.  
  199.  
  200. int scan_sourcef_ ( char *sfnam )
  201. /* Opprettet: Onsdag 10. juni 1992.
  202.    Parameter: "sfnam" Navn/katalog til kildefil som skal tolkes.
  203.    Retur    : E/O.
  204.    Beskriv  : Se funksjonen ovenfor: "scan_sourcef ()".
  205. */
  206. {
  207.    scanTYPE  scan;                 /* Info om aktiv linje under tolking */
  208.    funcTYPE  func;                 /* Info om potensiell/bekreftet funksjon */
  209.    finfTYPE  finf;                 /* Info om aktiv kildefil under tolking */
  210.    fcalTYPE  fcal;                 /* Info om funksjonskall */
  211.    idlstTYPE idlst;                /* Info om element i identifikatorliste */
  212.    char      inlin [MAXINLIN + 2]; /* Buffer for innlesing av hel linje */
  213.  
  214.    reset_scantype  (&scan);
  215.    reset_finftype  (&finf);
  216.    reset_functype  (&func);
  217.    reset_fcaltype  (&fcal);
  218.    reset_idlsttype (&idlst);
  219.  
  220.    Display (D_HEIGH, "%s", _StrMSGINTERPRETLIN);
  221.  
  222.    while (FGetS (inlin, MAXINLIN, sourcef) == OK)
  223.    {
  224.       if (strlen (inlin) > MAXINLIN)
  225.          RETERR (20, GetFNames (sourcef)); /* For lang linje i kildefil! */
  226.  
  227.       if (!intpret_line (inlin, &scan, &func, &finf, &idlst))
  228.          RETURN_ERR;
  229.  
  230.       /* Lagrer linjeinfo til midlertidig fil for dette: */
  231.       if (FWrite (&scan, sizeof (scanTYPE), 1, lininff) != 1)
  232.          return (ERROR);
  233.  
  234.       /* Lagring av midlertidig data om funksjonskall, identifikatorer og
  235.          funksjonsregister gj¢res internt i funksjonen "interpret_line()". */
  236.  
  237.       if (finf.ltot % 21 == 0)         /* Oppdater info for hver 21. */
  238.          DisplayCurrentLNr (finf.ltot);
  239.    }
  240.  
  241.    /* Lagre siste identifikator hvis potensiell identifikator: */
  242.    if(idlst.name[0])
  243.    {
  244.       /* Lagrer element til id-liste i midlertidig fil for dette: */
  245.       if (FWrite (&idlst, sizeof (idlstTYPE), 1, idlistf) != 1)
  246.          return (ERROR);
  247.       finf.cid++;                      /* Teller identifikatorer i kildefil */
  248.    }
  249.  
  250.    if (errno != 0)                     /* Feil ved lesing av linje fra kilde*/
  251.       return (ERROR);
  252.  
  253.    DisplayCurrentLNr (finf.ltot);
  254.  
  255.    FClose (sourcef);
  256.  
  257.    if (!ConnectTempFiles (sfnam, &finf))
  258.       RETURN_ERR;
  259.  
  260.    return (OK);
  261. } /* scan_sourcef_ (); */
  262.  
  263.  
  264.  
  265.  
  266. void reset_scantype ( scanTYPE *scan )
  267. /* Opprettet: Tirsdag 26. mai 1992.
  268.    Parameter: "scan" Scaninfo-strukturen som skal resettes.
  269.    Beskriv  : Resetter struktur som lagrer informasjon om aktiv linje under
  270.               tolking av kildefil.
  271.               Denne funksjonen må kalles mellom hver kildefil som skal tolkes.
  272. */
  273. {
  274.    scan->quot  = FALSE;
  275.    scan->drop  = FALSE;
  276.    scan->emp   = FALSE;
  277.    scan->code  = FALSE;
  278.    scan->ocom  = FALSE;
  279.    scan->dirl  = FALSE;
  280.    scan->com1  = FALSE;
  281.    scan->intfc = FALSE;
  282.    scan->comb  = 0;
  283.    scan->brack = 0;
  284.    scan->block = 0;
  285. } /* reset_scantype (); */
  286.  
  287.  
  288.  
  289.  
  290. void reset_functype ( funcTYPE *func )
  291. /* Opprettet: Tirsdag 26. mai 1992.
  292.    Parameter: "func" Funksjoninfo-struktur som skal resettes.
  293.    Beskriv  : Resetter struktur som lagrer informasjon om funksjon under
  294.               tolking av kildefil.
  295.               Denne funksjonen må kalles mellom hver funksjon som blir
  296.               bekreftes og avsluttet under tolkingen.
  297. */
  298. {
  299.    memset (func->name, 0, MAXFUNCN + 1);
  300.    func->fok        = FALSE;
  301.    func->blin       = 0;
  302.    func->blin_block = 0;
  303.    func->fcal       = 0;
  304.    func->lines      = 0;
  305.    func->empl       = 0;
  306.    func->coml       = 0;
  307.    func->codl       = 0;
  308.    func->com        = 0;
  309.    func->dirl       = 0;
  310. } /* reset_functype (); */
  311.  
  312.  
  313.  
  314.  
  315. void reset_fcaltype ( fcalTYPE *fcal )
  316. /* Opprettet: Torsdag 28. mai 1992.
  317.    Parameter: "fcal" Funksjonskallinfo-strukturen som skal resettes.
  318.    Beskriv  : Resetter struktur som lagrer informasjon om enkeltstående
  319.               funksjonskall under tolking av kildefil.
  320.               Denne funksjonen må kalles mellom hvert registrerte
  321.               bekreftede funksjonskall.
  322. */
  323. {
  324.    memset (fcal->name, 0, MAXFUNCN + 1);
  325.    fcal->lnr = 0;
  326. } /* reset_fcaltype (); */
  327.  
  328.  
  329.  
  330.  
  331. void reset_finftype ( finfTYPE *finf )
  332. /* Opprettet: Tirsdag 26. mai 1992.
  333.    Parameter: "finf" Struktur for lagring av global info om kildefil.
  334.    Beskriv  : Resetter struktur som lagrer global info om kildefil.
  335.               Denne funksjonen må kalles mellom hver kildefil som skal
  336.               tolkes.
  337. */
  338. {
  339.    finf->ltot = 0;
  340.    finf->elin = 0;
  341.    finf->coml = 0;
  342.    finf->codl = 0;
  343.    finf->com  = 0;
  344.    finf->func = 0;
  345.    finf->dirl = 0;
  346.    finf->fcal = 0;
  347.    finf->cid  = 0;
  348. } /* reset_finftype (); */
  349.  
  350.  
  351.  
  352.  
  353. void reset_idlsttype ( idlstTYPE *idlst )
  354. /* Opprettet: S¢ndag 31. mai 1992.
  355.    Parameter: "idlst" Struktur for lagring av id-liste-element.
  356.    Beskriv  : Resetter struktur som lagrer info om elementer i
  357.               liste over identifikatorer.
  358. */
  359. {
  360.    memset (idlst->name, 0, MAXFUNCN + 1);
  361.    idlst->lnr  = 0;
  362. } /* reset_idlsttype (); */
  363.  
  364.  
  365.  
  366.  
  367. int intpret_line ( char *line, scanTYPE *scan, funcTYPE *func,
  368.                    finfTYPE *finf, idlstTYPE *idlst )
  369. /* Opprettet: Tirsdag 26. mai 1992.
  370.    Parameter: "line"  Linjen som skal tolkes.
  371.               "scan"  Struktur for lagring av resultater av scanningen.
  372.               "func"  Struktur for lagring av info om funksjon.
  373.               "finf"  Struktur for lagring av funksjonsdata.
  374.               "idlst" Struktur for lagring av identifikatorliste.
  375.    Retur    : E/O.
  376.    Beskriv  : Tolker linjen "line" og setter strukturen "scan" i forrhold til
  377.               resultatet av tolkingen, samt lagrer data om funksjoner og
  378.               funksjonskall etter hvert som slik info samles i linjene
  379.               som tolkes. Det forutsettes at linjen som skal tolkes er
  380.               skrevet med syntaks for C.
  381.  
  382.               Både "scan", "finf", "idlst" og "func" -strukturene må resettes
  383.               utenfor denne funksjnen, mellom hver kildefil som skal tolkes.
  384.  
  385.               Lagring av liste over funksjonskall til midlertidig fil gj¢res
  386.               i denne funksjonen. I denne forbindelse forutsettes det at
  387.               den globale filen "funcalf" allerede er åpen og klar for
  388.               skriving.
  389.  
  390.               Tilsvarende gjelder for midlertidig fil for lagring av
  391.               funksjonsregsiter, og fil for lagring av identifikatorliste.
  392.               Det forutsettes at filene "funregf" og "idlistf" allerede
  393.               er åpnet og klar for skriving. Det forutsettes dessuten at
  394.               "finf" og "idlst" resettes f¢r denne funksjonen kalles ved
  395.               f¢rste linje i hver kildefil.
  396. */
  397. {
  398.    register int t1;                    /* Ved dannelse av funksjonsnavn */
  399.    char *res, *start = line;           /* For lagring av midlertidig posisjon*/
  400.    fcalTYPE fcal;                      /* For lagring av funksjonskallinfo */
  401.  
  402.    scan->drop = FALSE;                 /* Aldri anf¢rselnivå over fler linjer*/
  403.    scan->quot = FALSE;                 /* Aldri gåsenivå over fler linjer */
  404.    scan->ocom = TRUE;                  /* Utgangspunkt er at linjen er koment*/
  405.    scan->emp  = TRUE;                  /* FALSE hvis andre karakterer enn ' '*/
  406.    scan->code = FALSE;                 /* TRUE hvis kode i linjen */
  407.    scan->dirl = FALSE;                 /* TRUE hvis linjen er direktivlinje*/
  408.  
  409.    finf->ltot++;                       /* Ny linje i aktiv kildefil */
  410.  
  411.    if(func->name[0])                   /* Hvis innenfor funksjonshode */
  412.       func->lines++;                   /* Teller antall linjer i funksjon */
  413.  
  414.    if (scan->comb)                     /* Hvis 1. tegn i linje er i kom.blokk*/
  415.       scan->com1 = TRUE;
  416.    else
  417.       scan->com1 = FALSE;
  418.  
  419.    for (; *line; line++)               /* Alle karakterer skal tolkes */
  420.    {
  421.       if(*line == '#' &&               /* # innleder alle direktiver */
  422.          !scan->quot &&                /* Kun hvis utenfor streng mellom " " */
  423.          !scan->drop)                  /* Kun hvis utenfor annf¢rselstegnnivå*/
  424.       {
  425.          finf->dirl++;                 /* Teller direktivlinjer i aktiv kilde*/
  426.          scan->dirl = TRUE;            /* Bekrefter direktiv i linje */
  427.          scan->code = TRUE;            /* Bekrefter kode i aktiv linje */
  428.          scan->emp = FALSE;            /* Bekrefter annet tegn enn ' ' funnet*/
  429.          if (func->fok)                /* Hvis inne i bekreftet funksjon */
  430.             func->dirl++;              /* Teller direktivlinjer i funksjon */
  431.          break;                        /* Avbryt l¢kke for s¢k i linje */
  432.       }
  433.  
  434.       if(*line != ' ' &&               /* Annet tegn enn ' ' er registrert */
  435.          *line != '\t' &&              /* Tabulator-tegn */
  436.          *line != '\n')                /* Linjeskift */
  437.       {
  438.          scan->emp = FALSE;            /* Bekrefter annet tegn enn ' ' funnet*/
  439.          if(!scan->comb &&             /* Hvis utenfor komentarblokk */
  440.             !scan->dirl &&             /* Hvis linjen ikke er direktiv */
  441.             !(*line == '/' &&          /* Innledende komentarklamme... */
  442.               *(line + 1) == '/') &&   /* ...regnes ikke som kode */
  443.             !(*line == '/' &&          /* Innledende komentarklamme... */
  444.               *(line + 1) == '*'))     /* ...regnes ikke som kode */
  445.          {
  446.             scan->code = TRUE;         /* Bekrefter kode i aktiv linje */
  447.          }
  448.          if(idlst->name[0])            /* Hvis skjekking på identifikator */
  449.          {
  450.             if(*line != '(')           /* '(' betyr at id er funksjonskall */
  451.             {
  452.                /* Lagrer element til id-liste i midlertidig fil for dette: */
  453.                if (FWrite (idlst, sizeof (idlstTYPE), 1, idlistf) != 1)
  454.                   return (ERROR);
  455.                finf->cid++;            /* Teller identifikatorer i kildefil */
  456.             }
  457.             reset_idlsttype (idlst);
  458.          }
  459.       }
  460.  
  461.       if (scan->comb)                  /* Start s¢king etter komentarslutt */
  462.       {
  463.          for (; *(line + 1); line++)   /* S¢ke etter komentarslutt */
  464.          {
  465.             if(*line != ' ' &&         /* Annet tegn enn ' ' er registrert */
  466.                *line != '\t' &&        /* Tabulator-tegn */
  467.                *line != '\n')          /* Linjeskift */
  468.             {
  469.                scan->emp = FALSE;      /* Bekrefter annet tegn enn ' ' funnet*/
  470.             }
  471.             if(*line == '*' &&         /* F¢rste tegn i komentarslutt-merke */
  472.                *(line + 1) == '/')     /* Andre tegn i komentarslutt-merke */
  473.             {
  474.                scan->comb = FALSE;     /* Slutt på komentarblokk */
  475.                line++;                 /* Peker oppdateres til forbi komentar*/
  476.                if (!scan->comb)        /* Hvis utenfor komentarblokk */
  477.                   break;               /* Forlat komentarslutt-s¢k l¢kken */
  478.             }
  479.          }
  480.          continue;                     /* Fortsett scanning av linje */
  481.       }
  482.  
  483.       else
  484.       if(*line == '/' &&               /* F¢rste tegn til komentarblokk-start*/
  485.          *(line + 1) == '*' &&         /* Andre tegn til komentarblokk-slutt */
  486.          !scan->quot)                  /* Kun hvis utenfor gåse¢ynenivå */
  487.       {
  488.          scan->comb = TRUE;            /* Komentarblokk har startet */
  489.          finf->com++;                  /* En ny komentarblokk er registrert */
  490.          if (func->name[0])            /* Hvis innenfor mulig funksjonshode */
  491.             func->com++;               /* Teller komentarblokker i funksjon */
  492.          line++;                       /* Peker nå til selve komentarstarten */
  493.          continue;                     /* Fortsett scanning av linje */
  494.       }
  495.  
  496.       else
  497.       if(*line == '/' &&               /* F¢rste tegn til komentarblokk-start*/
  498.          *(line + 1) == '/' &&         /* Komentar kan også innledes med // */
  499.          !scan->quot)                  /* Kun hvis utenfor gåse¢ynenivå */
  500.       {
  501.          finf->com++;                  /* En ny komentarblokk er registrert */
  502.          if (func->fok)                /* Hvis inne i bekreftet funksjon */
  503.             func->com++;               /* Teller komentarblokker i funksjon */
  504.          line++;                       /* Peker nå til selve komentarstarten */
  505.          break;                        /* Avslutt tolking av linje */
  506.       }
  507.  
  508.       else
  509.       if(*line != ' ' &&               /* Tegn utenfor komentar */
  510.          *line != '\t' &&              /* Tabulatortegn */
  511.          *line != '\n')                /* Linjeskift */
  512.       {
  513.          scan->ocom = FALSE;           /* Bekrefter tegn utenfor komentar */
  514.       }
  515.  
  516.       if(*line == '\'' &&              /* Mulig kommende anf¢rselstegnnivå */
  517.          !scan->dirl &&                /* Kun hvis linje ikke er direktiv */
  518.          !scan->drop &&                /* Kun hvis ikke slikt nivå fra f¢r */
  519.          !scan->quot)                  /* Kun hvis utenfor gåse¢ynenivå */
  520.       {
  521.          scan->drop = TRUE;            /* Herved anf¢rselstegn nivå */
  522.       }
  523.  
  524.       else
  525.       if(*line == '\'' &&              /* Mulig avsluttende anf¢rselstegnnivå*/
  526.          !scan->dirl &&                /* Kun hvis linje ikke er direktiv */
  527.          scan->drop &&                 /* Kun hvis slikt nivå er aktivt */
  528.          !scan->quot)                  /* Kun hvis utenfor gåse¢ynenivå */
  529.       {
  530.          scan->drop = FALSE;           /* Herved avsluttet anf¢rselstegnnivå */
  531.       }
  532.  
  533.       else
  534.       if(*line == '"' &&               /* Mulig gåse¢ynenivå */
  535.          !scan->dirl &&                /* Kun hvis linje ikke er direktiv */
  536.          !scan->quot &&                /* Kun hvis ikke i slikt nivå fra f¢r */
  537.          !scan->drop)                  /* Kun hvis utenfor anf¢rselstegnnivå */
  538.       {
  539.          scan->quot = TRUE;            /* Herved aktivt gåse¢ynenivå */
  540.       }
  541.  
  542.       else
  543.       if(*line == '"' &&               /* Mulig avsluttende gåse¢ynenivå */
  544.          !scan->dirl &&                /* Kun hvis linje ikke er direktiv */
  545.          scan->quot &&                 /* Kun hvis slikt nivå er aktivt */
  546.          !scan->drop)                  /* Kun hvis utenfor anf¢rselstegnnivå */
  547.       {
  548.          scan->quot = FALSE;           /* Herved avsluttet gåse¢ynenivå */
  549.       }
  550.  
  551.       else
  552.       if(*line == '{' &&               /* Start av nytt blokknivå i kildefil */
  553.          !scan->dirl &&                /* Kun hvis linje ikke er direktiv */
  554.          !scan->quot &&                /* Kun hvis utenfor gåse¢ynenivå */
  555.          !scan->drop)                  /* Kun hvis utenfor anf¢rselstegnnivå */
  556.       {
  557.          if (scan->block == 15)        /* Maks blokknivå er 15 */
  558.          {
  559.             DisplayCurrentLNr (finf->ltot);
  560.             /* Too many block levels in source! */
  561.             RETERR (21, GetFNames (sourcef));
  562.          }
  563.          scan->block++;                /* Ett nytt blokknivå */
  564.          if(func->name[0] &&           /* Hvis det unders¢kes om funksjon */
  565.             !func->fok &&              /* Kun hvis utenfor funksjon */
  566.             scan->block == 1)          /* Hvis blokkstart { til f¢rste nivå */
  567.          {
  568.             func->fok = TRUE;          /* Hver funksjon innledes med { */
  569.             func->blin_block = finf->ltot; /* Linjenr for blokkstart i funk.*/
  570.             finf->func++;              /* Teller funksjoner i aktiv kildefil */
  571.          }
  572.       }
  573.  
  574.       else
  575.       if(*line == '}' &&               /* Slutt på blokknivå */
  576.          !scan->dirl &&                /* Kun hvis linje ikke er direktiv */
  577.          !scan->quot &&                /* Kun hvis utenfor gåse¢ynenivå */
  578.          !scan->drop)                  /* Kun hvis utenfor anf¢rselstegnnivå */
  579.       {
  580.          if (scan->block == 0)         /* If no block to terminate */
  581.          {
  582.             DisplayCurrentLNr (finf->ltot);
  583.             RETERR (25, GetFNames (sourcef)); /* Illegal level of block. Probably due to a syntax error. */
  584.          }
  585.          scan->block--;                /* Ute av siste blokknivå */
  586.          if(scan->block == 0 &&        /* Siste blokkslutt til funksjon */
  587.             func->fok)                 /* Kun hvis funksjonen er bekreftet */
  588.          {
  589.             /* Lagrer funksjonsinformasjon til midlertidig fil for dette: */
  590.             if (FWrite (func, sizeof (funcTYPE), 1, funregf) != 1)
  591.                return (ERROR);
  592.             reset_functype (func);
  593.          }
  594.       }
  595.  
  596.       else
  597.       if(*line == ')' &&               /* Mulig parantesnivå lavere */
  598.          !scan->dirl &&                /* Kun hvis linje ikke er direktiv */
  599.          !scan->quot &&                /* Innenfor gåse¢yne betyr i streng */
  600.          !scan->drop &&                /* Kun hvis utenfor anf¢rselstegnnivå */
  601.          scan->brack)                  /* Kun hvis innledende '(' */
  602.       {
  603.          scan->brack--;                /* Et parantesnivå lavere */
  604.          while(*(line + 1) == ' ' ||   /* S¢k etter neste karakter etter ) */
  605.                *(line + 1) == '\t')    /* Tabulator-karakter */
  606.          {
  607.             line++;                    /* Pek til neste karakter */
  608.          }
  609.          if(*(line + 1) == ';' &&      /* ';' betyr at kun funksjon-header */
  610.             !scan->block &&            /* Kun hvis utenfor blokknivå */
  611.             !scan->brack)              /* Kun hvis utenfor parantesnivå */
  612.          {
  613.             reset_functype (func);     /* Det var ingen funksjon likevel */
  614.          }
  615.       }
  616.  
  617.       else
  618.       if(*line == '(' &&               /* Parantesstart kan bety funksjon */
  619.          !scan->dirl &&                /* Kun hvis linje ikke er direktiv */
  620.          !func->name[0] &&             /* Hvis ikke allerede sjekk om funksjo*/
  621.          !scan->brack &&               /* Funksjonshoder kun utenfor parantes*/
  622.          !scan->drop &&                /* Kun hvis utenfor anf¢rselstegnnivå */
  623.          !scan->block &&               /* Kun hvis utenfor blokknivå */
  624.          !scan->quot)                  /* Innenfor gåse¢yne betyr i streng */
  625.       {
  626.          res = line--;                 /* Husk posisjon til (. Pek forran ( */
  627.          scan->brack++;                /* Et nytt parantesnivå */
  628.          while((*line == ' ' ||        /* Både ' ' og '\t' (tabulatortegn) */
  629.                 *line == '\t') &&      /* kan fårekomme mellom f.navn og '(' */
  630.                 line > start)          /* Ikke pek utenfor "str"'s start */
  631.          {
  632.             line--;                    /* S¢k etter slutten av funskjonsnavn */
  633.          }
  634.          if(!strchr(legal, *line))     /* Tegn som er ulovlig i funksjonsnavn*/
  635.          {
  636.             line = res;                /* Fram igjen til parantesstart */
  637.             continue;                  /* Fortsett tolking av linje */
  638.          }
  639.          while(strchr (legal, *line) != NULL && /* S¢k for tegn utenfor navn */
  640.                line > start)           /* Ikke pek utenfor "str"'s start */
  641.          {
  642.             line--;                    /* S¢k etter start av funksjonskall */
  643.          }
  644.          if (strchr (legal, *line) == NULL) /* Kompanser for siste "str--" */
  645.             line++;                    /* Peker nå til f¢rste kar. i funknavn*/
  646.          t1 = 0;                       /* Startposisjon til navn på funksjon */
  647.          while(*line != ' ' &&         /* Karakter som betyr slutt på navn */
  648.                *line != '\t' &&        /* Tabulator kan finnes forran ( */
  649.                *line != '(' &&         /* Karakter som betyr slutt på navn */
  650.                *line &&                /* Ikke utenfor slutten til "str" */
  651.                t1 < MAXFUNCN-1)        /* Antall lovlige tegn i funksjonnavn */
  652.          {
  653.             func->name[t1++] = *line++;/* Delkarakter til funskjonsnavnet */
  654.          }
  655.          if(t1 == MAXFUNCN-1 &&        /* Hvis funksjonnavnet er for langt */
  656.             *line != '(' &&            /* Det sjekkes også i l¢kken ovenfor */
  657.             *line != '\t' &&
  658.             *line != ' ')              /* '(' og ' ' => lenden var akkurat */
  659.          {
  660.             DisplayCurrentLNr (finf->ltot);
  661.             RETERR (27, NULL); /* Function name is to long! Max length is ... */
  662.          }
  663.          func->name[t1] = '\0';        /* Markerer slutten på funksjonsnavstr*/
  664.          func->blin = finf->ltot;      /* Lagre linjenummer til funksjonstart*/
  665.          func->lines++;                /* Også funksjonshodet utgj¢r en linje*/
  666.          line = res;                   /* Fram igjen til parantesstart */
  667.       }
  668.  
  669.       else
  670.       if(*line == '(' &&               /* Parantesstart kan bety funksjonskal*/
  671.          !scan->dirl &&                /* Kun hvis linje ikke er direktiv */
  672.          scan->block &&                /* Funksjonskall kun innenfor blokkniv*/
  673.          !scan->drop &&                /* Kun hvis utenfor anf¢rselstegnnivå */
  674.          !scan->quot)                  /* Innenfor gåse¢yner betyr streng */
  675.       {
  676.          res = line--;                 /* Husk posisjon til (. Pek forran ( */
  677.          scan->brack++;                /* Et nytt parantesnivå */
  678.          while ((*line == ' ' ||       /* Både ' ' og '\t' (tabulatortegn) */
  679.                  *line == '\t') &&     /* kan fårekomme mellom f.navn og '(' */
  680.                  line > start)         /* Ikke pek utenfor "str"'s start */
  681.          {
  682.             line--;                    /* S¢k etter slutten av funskjonsnavn */
  683.          }
  684.          if (!strchr(legal, *line))    /* Tegn som er ulovlig i funksjonsnavn*/
  685.          {
  686.             line = res;                /* Fram igjen til parantesstart */
  687.             continue;                  /* Fortsett tolking av linje */
  688.          }
  689.          while (strchr (legal, *line) != NULL && /* S¢k for tegn utenfor navn */
  690.                 line > start)          /* Ikke pek utenfor "str"'s start */
  691.          {
  692.             line--;                    /* S¢k etter start av funksjonskall */
  693.          }
  694.          if (strchr (legal, *line) == NULL) /* Kompanser for siste str-- */
  695.             line++;                    /* Peker nå til f¢rste kar. i funknavn*/
  696.          t1 = 0;                       /* Startposisjon til navn på funksjon */
  697.          while(*line != ' ' &&         /* Karakter som betyr slutt på navn */
  698.                *line != '\t' &&        /* Tabulator kan finnes forran ( */
  699.                *line != '(' &&         /* Karakter som betyr slutt på navn */
  700.                *line &&                /* Ikke utenfor slutten til "str" */
  701.                t1 < MAXFUNCN-1)        /* Antall lovlige tegn i funksjonnavn */
  702.          {
  703.             fcal.name[t1++] = *line++; /* Delkarakter til funskjonsnavnet */
  704.          }
  705.          if(t1 == MAXFUNCN-1 &&        /* Hvis funksjonnavnet er for langt */
  706.             *line != '(' &&            /* Det sjekkes også i l¢kken ovenfor */
  707.             *line != '\t' &&
  708.             *line != ' ')              /* '(' og ' ' => lenden var akkurat */
  709.          {
  710.             DisplayCurrentLNr (finf->ltot);
  711.             RETERR (27, NULL); /* Function name is to long! Max length is ... */
  712.          }
  713.          fcal.name[t1] = '\0';         /* Markerer slutten på funksjonsnavstr*/
  714.          fcal.lnr = finf->ltot;        /* Lagre linjenummer til funksjonskall*/
  715.  
  716.          /* Lagrer info om funksjonskall til midlertidig global fil "funcalf"*/
  717.          if (ifkeyword (fcal.name) == FALSE)
  718.          {
  719.             if (FWrite (&fcal, sizeof (fcalTYPE), 1, funcalf) != 1)
  720.                return (ERROR);
  721.             finf->fcal++;              /* Teller funksjonskall i kildefil */
  722.             func->fcal++;              /* Teller funksjonskall i funcksjon */
  723.          }
  724.          reset_fcaltype (&fcal);
  725.          line = res;                   /* Fram igjen til parantesstart */
  726.       }
  727.  
  728.       else
  729.       if(*line == '(' &&               /* Start av nytt parantesnivå */
  730.          !scan->dirl &&                /* Kun hvis linje ikke er direktiv */
  731.          !scan->drop &&                /* Kun hvis utenfor anf¢rselstegn */
  732.          !scan->quot)                  /* Kun hvis utenfor gåse¢ynenivå (".")*/
  733.       {
  734.          scan->brack++;                /* "scan.parantes" anngir parantesnivå*/
  735.       }
  736.  
  737.       else
  738.       if(*line == '\\' &&              /* I C/C++ definerer \ et neste tegn */
  739.          !scan->dirl)                  /* Kun hvis linje ikke er direktiv */
  740.       {
  741.          line += 1;                    /* Skjul neste tegn ved å hoppe over */
  742.          continue;                     /* Fortsett tolking av linje */
  743.       }
  744.  
  745.       else
  746.       if(strchr (legal, *line) &&      /* Potensiel bokstav i identifikator */
  747.          !scan->dirl &&                /* Kun hvis linje ikke er direktiv */
  748.          !scan->drop &&                /* Kun hvis utenfor anf¢rselstegn */
  749.          !scan->quot)                  /* Kun hvis utenfor gåse¢ynenivå (".")*/
  750.       {
  751.          if (isdigit (*line))          /* 0..9 ikke lov som f¢rste tegn */
  752.          {
  753.             /* This first character of a word is 0..9, so just skip the word */
  754.             /* S¢k etter slutten til identifikator */
  755.             while (*line && strchr (legal, *line) && !isspace (*line))
  756.                line++;                 /* Neste karakter, for å hoppe over */
  757.             line--;                    /* Kompanserer for siste line++ */
  758.             continue;
  759.          }
  760.  
  761.          idlst->lnr = finf->ltot;      /* Lagre linjenummer til identifikator*/
  762.          t1 = 0;                       /* Offset til streng for identifikator*/
  763.          while(*line &&                /* S¢k etter slutten til identifikator*/
  764.                t1 < MAXFUNCN-1 &&      /* Ikke utenfor strengområde */
  765.                (strchr (legal, *line) || /* Lovlige tegn i identifikator */
  766.                 *line == '.' ||          /* '.' skiller elementer i struktur */
  767.                (*line == '-' &&          /* "->" skiller elemeneter i struktu*/
  768.                 *(line + 1) == '>')))    /* '>' er det andre tegnet i "->" */
  769.          {
  770.             if(*line == '-' &&           /* Hvis "->"... */
  771.                *(line + 1) == '>')
  772.             {
  773.                idlst->name[t1++] = '.';  /* '.' erstatter "->" i buff for id */
  774.                line += 2;                /* Peker nå til f¢rste tegn bak "->"*/
  775.             }
  776.             else
  777.             {
  778.                idlst->name[t1++] = *line++; /* Neste karakter i identifikator*/
  779.             }
  780.          }
  781.          if(t1 == MAXFUNCN-1 &&        /* Hvis identifikator var for lang */
  782.             strchr (legal, *line))     /* Kun hvis neste tegn tilh¢rer idnavn*/
  783.          {
  784.             DisplayCurrentLNr (finf->ltot);
  785.             RETERR (28, NULL); /* Identifier name is to long! Max length is ... */
  786.          }
  787.          line--;                       /* Kompanserer for siste line++       */
  788.          idlst->name[t1] = 0;          /* Avslutter streng for identifikator */
  789.          if (ifkeyword (idlst->name))  /* Hvis identifikator er n¢kkelord */
  790.             reset_idlsttype (idlst);   /* Ikke identifikator likevel */
  791.       }
  792.    }
  793.  
  794.    if(scan->code ||                    /* Ikke kom.linje hvis kode i linjen */
  795.       scan->dirl ||                    /* Ikke kom.linje hvis direktiv */
  796.       (scan->emp && !scan->comb))      /* Ikke kom.lin hvis tom utenf. komblo*/
  797.    {
  798.       scan->ocom = FALSE;              /* Ikke komentarlinje */
  799.    }
  800.  
  801.    else                                /* Hele linjen var komentar */
  802.    {
  803.       finf->coml++;                    /* Teller kom.linjer i aktiv kildefil */
  804.       if (func->name[0])               /* Hvis inne i funksjonshode */
  805.          func->coml++;                 /* Teller komentarlinjer i funksjon */
  806.    }
  807.  
  808.    if (scan->emp)                      /* Hvis hele linjen var tom */
  809.    {
  810.       finf->elin++;                    /* Teller tomme linjer i aktiv kildefi*/
  811.       if (func->fok)                   /* Hvis innenfor funksjonblokk */
  812.          func->empl++;                 /* Teller tomme linjer i funksjon */
  813.    }
  814.  
  815.    if(scan->code)                      /* Hvis linjen ikke var tom */
  816.    {
  817.       finf->codl++;                    /* Teller kodelinjer i aktiv kildefil */
  818.       if (!scan->dirl &&               /* Hvis linje ikke er direktiv */
  819.           func->fok)                   /* Hvis inne i bekreftet funksjon */
  820.       {
  821.          func->codl++;                 /* Teller linjer med kode i funksjon */
  822.       }
  823.    }
  824.  
  825.    return (OK);
  826. } /* interpret_line (); */
  827.  
  828.  
  829.