LCOV - code coverage report
Current view: top level - libreoffice/rsc/source/rscpp - cpp2.c (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 107 179 59.8 %
Date: 2012-12-27 Functions: 6 6 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include        <stdio.h>
      21             : #include        <ctype.h>
      22             : #include        "cppdef.h"
      23             : #include        "cpp.h"
      24             : #if HOST == SYS_VMS
      25             : /*
      26             :  * Include the rms stuff.  (We can't just include rms.h as it uses the
      27             :  * VaxC-specific library include syntax that Decus CPP doesn't support.
      28             :  * By including things by hand, we can CPP ourself.)
      29             :  */
      30             : #include        <nam.h>
      31             : #include        <fab.h>
      32             : #include        <rab.h>
      33             : #include        <rmsdef.h>
      34             : #endif
      35             : 
      36             : /*
      37             :  * Generate (by hand-inspection) a set of unique values for each control
      38             :  * operator.  Note that this is not guaranteed to work for non-Ascii
      39             :  * machines.  CPP won't compile if there are hash conflicts.
      40             :  */
      41             : 
      42             : #define L_assert        ('a' + ('s' << 1))
      43             : #define L_define        ('d' + ('f' << 1))
      44             : #define L_elif          ('e' + ('i' << 1))
      45             : #define L_else          ('e' + ('s' << 1))
      46             : #define L_endif         ('e' + ('d' << 1))
      47             : #define L_if            ('i' + (EOS << 1))
      48             : #define L_ifdef         ('i' + ('d' << 1))
      49             : #define L_ifndef        ('i' + ('n' << 1))
      50             : #define L_include       ('i' + ('c' << 1))
      51             : #define L_line          ('l' + ('n' << 1))
      52             : #define L_nogood        (EOS + (EOS << 1))      /* To catch #i          */
      53             : #define L_pragma        ('p' + ('a' << 1))
      54             : #define L_undef         ('u' + ('d' << 1))
      55             : #define L_error         ('e' + ('r' << 1))      /* BP 5.3.92, #error */
      56             : #define MAXLINE 80                              /* BP 5.3.92, #error */
      57             : #if OSL_DEBUG_LEVEL > 1
      58             : #define L_debug         ('d' + ('b' << 1))      /* #debug               */
      59             : #define L_nodebug       ('n' + ('d' << 1))      /* #nodebug             */
      60             : #endif
      61             : 
      62             : 
      63         630 : void InitCpp2()
      64             : {
      65             : 
      66         630 : }
      67             : 
      68             : 
      69             : int
      70     1486300 : control(int counter)
      71             : /*
      72             :  * Process #control lines.  Simple commands are processed inline,
      73             :  * while complex commands have their own subroutines.
      74             :  *
      75             :  * The counter is used to force out a newline before #line, and
      76             :  * #pragma commands.  This prevents these commands from ending up at
      77             :  * the end of the previous line if cpp is invoked with the -C option.
      78             :  */
      79             : {
      80             :         register int            c;
      81             :         register char           *tp;
      82             :         register int            hash;
      83             :         char                    *ep;
      84             : 
      85     1486300 :         c = skipws();
      86     1486300 :         if (c == '\n' || c == EOF_CHAR)
      87           0 :             return (counter + 1);
      88     1486300 :         if (!isdigit(c))
      89     1486300 :             scanid(c);                  /* Get #word to token[]         */
      90             :         else {
      91           0 :             unget();                    /* Hack -- allow #123 as a      */
      92           0 :             strcpy(token, "line");      /* synonym for #line 123        */
      93             :         }
      94     1486300 :         hash = (token[1] == EOS) ? L_nogood : (token[0] + (token[2] << 1));
      95     1486300 :         switch (hash) {
      96           0 :         case L_assert:  tp = "assert";          break;
      97     1447803 :         case L_define:  tp = "define";          break;
      98          40 :         case L_elif:    tp = "elif";            break;
      99          30 :         case L_else:    tp = "else";            break;
     100       13325 :         case L_endif:   tp = "endif";           break;
     101         742 :         case L_if:      tp = "if";              break;
     102         294 :         case L_ifdef:   tp = "ifdef";           break;
     103       12289 :         case L_ifndef:  tp = "ifndef";          break;
     104       10849 :         case L_include: tp = "include";         break;
     105           0 :         case L_line:    tp = "line";            break;
     106           0 :         case L_pragma:  tp = "pragma";          break;
     107         272 :         case L_undef:   tp = "undef";           break;
     108         656 :         case L_error:   tp = "error";           break;
     109             : #if OSL_DEBUG_LEVEL > 1
     110             :         case L_debug:   tp = "debug";           break;
     111             :         case L_nodebug: tp = "nodebug";         break;
     112             : #endif
     113           0 :         default:        hash = L_nogood;
     114           0 :         case L_nogood:  tp = "";                break;
     115             :         }
     116     1486300 :         if (!streq(tp, token))
     117           0 :             hash = L_nogood;
     118             :         /*
     119             :          * hash is set to a unique value corresponding to the
     120             :          * control keyword (or L_nogood if we think it's nonsense).
     121             :          */
     122     1486300 :         if (infile->fp == NULL)
     123           0 :             cwarn("Control line \"%s\" within macro expansion", token);
     124     1486300 :         if (!compiling) {                       /* Not compiling now    */
     125      409978 :             switch (hash) {
     126             :             case L_if:                          /* These can't turn     */
     127             :             case L_ifdef:                       /*  compilation on, but */
     128             :             case L_ifndef:                      /*   we must nest #if's */
     129          34 :                 if (++ifptr >= &ifstack[BLK_NEST])
     130           0 :                     goto if_nest_err;
     131          34 :                 *ifptr = 0;                     /* !WAS_COMPILING       */
     132             :             case L_line:                        /* Many                 */
     133             :             /*
     134             :              * Are pragma's always processed?
     135             :              */
     136             :             case L_pragma:                      /*  options             */
     137             :             case L_include:                     /*   are uninteresting  */
     138             :             case L_define:                      /*    if we             */
     139             :             case L_undef:                       /*     aren't           */
     140             :             case L_assert:                      /*      compiling.      */
     141             :             case L_error:                       /* BP 5.3.92, #error */
     142      404209 : dump_line:      skipnl();                       /* Ignore rest of line  */
     143      404209 :                 return (counter + 1);
     144             :             }
     145             :         }
     146             :         /*
     147             :          * Make sure that #line and #pragma are output on a fresh line.
     148             :          */
     149     1082111 :         if (counter > 0 && (hash == L_line || hash == L_pragma)) {
     150           0 :             PUTCHAR('\n');
     151           0 :             counter--;
     152             :         }
     153     1082111 :         switch (hash) {
     154             :         case L_line:
     155             :             /*
     156             :              * Parse the line to update the line number and "progname"
     157             :              * field and line number for the next input line.
     158             :              * Set wrongline to force it out later.
     159             :              */
     160           0 :             c = skipws();
     161           0 :             workp = work;                       /* Save name in work    */
     162           0 :             while (c != '\n' && c != EOF_CHAR) {
     163           0 :                 save(c);
     164           0 :                 c = get();
     165             :             }
     166           0 :             unget();
     167           0 :             save(EOS);
     168             :             /*
     169             :              * Split #line argument into <line-number> and <name>
     170             :              * We subtract 1 as we want the number of the next line.
     171             :              */
     172           0 :             line = atoi(work) - 1;              /* Reset line number    */
     173           0 :             for (tp = work; isdigit(*tp) || type[(int)*tp] == SPA; tp++)
     174             :                 ;                               /* Skip over digits     */
     175           0 :             if (*tp != EOS) {                   /* Got a filename, so:  */
     176           0 :                 if (*tp == '"' && (ep = strrchr(tp + 1, '"')) != NULL) {
     177           0 :                     tp++;                       /* Skip over left quote */
     178           0 :                     *ep = EOS;                  /* And ignore right one */
     179             :                 }
     180           0 :                 if (infile->progname != NULL)   /* Give up the old name */
     181           0 :                     free(infile->progname);     /* if it's allocated.   */
     182           0 :                 infile->progname = savestring(tp);
     183             :             }
     184           0 :             wrongline = TRUE;                   /* Force output later   */
     185           0 :             break;
     186             : 
     187             :         case L_include:
     188        8779 :             doinclude();
     189        8779 :             break;
     190             : 
     191             :         case L_define:
     192     1046577 :             dodefine();
     193     1046577 :             break;
     194             : 
     195             :         case L_undef:
     196          69 :             doundef();
     197          69 :             break;
     198             : 
     199             :         case L_else:
     200          30 :             if (ifptr == &ifstack[0])
     201           0 :                 goto nest_err;
     202          30 :             else if ((*ifptr & ELSE_SEEN) != 0)
     203           0 :                 goto else_seen_err;
     204          30 :             *ifptr |= ELSE_SEEN;
     205          30 :             if ((*ifptr & WAS_COMPILING) != 0) {
     206          29 :                 if (compiling || (*ifptr & TRUE_SEEN) != 0)
     207          27 :                     compiling = FALSE;
     208             :                 else {
     209           2 :                     compiling = TRUE;
     210             :                 }
     211             :             }
     212          30 :             break;
     213             : 
     214             :         case L_elif:
     215          40 :             if (ifptr == &ifstack[0])
     216           0 :                 goto nest_err;
     217          40 :             else if ((*ifptr & ELSE_SEEN) != 0) {
     218           0 : else_seen_err:  cerror("#%s may not follow #else", token);
     219           0 :                 goto dump_line;
     220             :             }
     221          40 :             if ((*ifptr & (WAS_COMPILING | TRUE_SEEN)) != WAS_COMPILING) {
     222          20 :                 compiling = FALSE;              /* Done compiling stuff */
     223          20 :                 goto dump_line;                 /* Skip this clause     */
     224             :             }
     225          20 :             doif(L_if);
     226          20 :             break;
     227             : 
     228             :         case L_if:
     229             :         case L_ifdef:
     230             :         case L_ifndef:
     231       13291 :             if (++ifptr >= &ifstack[BLK_NEST])
     232           0 : if_nest_err:    cfatal("Too many nested #%s statements", token);
     233       13291 :             *ifptr = WAS_COMPILING;
     234       13291 :             doif(hash);
     235       13291 :             break;
     236             : 
     237             :         case L_endif:
     238       13325 :             if (ifptr == &ifstack[0]) {
     239           0 : nest_err:       cerror("#%s must be in an #if", token);
     240           0 :                 goto dump_line;
     241             :             }
     242       13325 :             if (!compiling && (*ifptr & WAS_COMPILING) != 0)
     243        5732 :                 wrongline = TRUE;
     244       13325 :             compiling = ((*ifptr & WAS_COMPILING) != 0);
     245       13325 :             --ifptr;
     246       13325 :             break;
     247             : 
     248             :         case L_assert:
     249           0 :             if (eval() == 0)
     250           0 :                 cerror("Preprocessor assertion failure", NULLST);
     251           0 :             break;
     252             : 
     253             :         case L_pragma:
     254             :             /*
     255             :              * #pragma is provided to pass "options" to later
     256             :              * passes of the compiler.  cpp doesn't have any yet.
     257             :              */
     258           0 :             fprintf( pCppOut, "#pragma ");
     259           0 :             while ((c = get()) != '\n' && c != EOF_CHAR)
     260           0 :                 cput(c);
     261           0 :             unget();
     262           0 :             break;
     263             : 
     264             : #if OSL_DEBUG_LEVEL > 1
     265             :         case L_debug:
     266             :             if (debug == 0)
     267             :                 dumpdef("debug set on");
     268             :             debug++;
     269             :             break;
     270             : 
     271             :         case L_nodebug:
     272             :             debug--;
     273             :             break;
     274             : #endif
     275             :         case L_error:                       /* BP 5.3.92, #error */
     276             :         {
     277           0 :             fprintf( pCppOut, "cpp: line %u, Error directive: ", line );
     278           0 :             while ((c = get()) != '\n' && c != EOF_CHAR)
     279           0 :                 cput(c);
     280           0 :             fprintf( pCppOut, "\n" );
     281           0 :             exit( 1 );
     282             :             break;
     283             :         }
     284             :         default:
     285             :             /*
     286             :              * Undefined #control keyword.
     287             :              * Note: the correct behavior may be to warn and
     288             :              * pass the line to a subsequent compiler pass.
     289             :              * This would allow #asm or similar extensions.
     290             :              */
     291           0 :             cerror("Illegal # command \"%s\"", token);
     292           0 :             break;
     293             :         }
     294     1082091 :         if (hash != L_include) {
     295             : #if OLD_PREPROCESSOR
     296             :             /*
     297             :              * Ignore the rest of the #control line so you can write
     298             :              *          #if     foo
     299             :              *          #endif  foo
     300             :              */
     301             :             goto dump_line;                     /* Take common exit     */
     302             : #else
     303     1073312 :             if (skipws() != '\n') {
     304           0 :                 cwarn("Unexpected text in #control line ignored", NULLST);
     305           0 :                 skipnl();
     306             :             }
     307             : #endif
     308             :         }
     309     1082091 :         return (counter + 1);
     310             : }
     311             : 
     312             : FILE_LOCAL
     313       13311 : void doif(int hash)
     314             : /*
     315             :  * Process an #if, #ifdef, or #ifndef.  The latter two are straightforward,
     316             :  * while #if needs a subroutine of its own to evaluate the expression.
     317             :  *
     318             :  * doif() is called only if compiling is TRUE.  If false, compilation
     319             :  * is always supressed, so we don't need to evaluate anything.  This
     320             :  * supresses unnecessary warnings.
     321             :  */
     322             : {
     323             :         register int            c;
     324             :         register int            found;
     325             : 
     326       13311 :         if ((c = skipws()) == '\n' || c == EOF_CHAR) {
     327           0 :             unget();
     328           0 :             goto badif;
     329             :         }
     330       13311 :         if (hash == L_if) {
     331         743 :             unget();
     332         743 :             found = (eval() != 0);      /* Evaluate expr, != 0 is  TRUE */
     333         743 :             hash = L_ifdef;             /* #if is now like #ifdef       */
     334             :         }
     335             :         else {
     336       12568 :             if (type[c] != LET)         /* Next non-blank isn't letter  */
     337           0 :                 goto badif;             /* ... is an error              */
     338       12568 :             found = (lookid(c) != NULL); /* Look for it in symbol table */
     339             :         }
     340       13311 :         if (found == (hash == L_ifdef)) {
     341        7604 :             compiling = TRUE;
     342        7604 :             *ifptr |= TRUE_SEEN;
     343             :         }
     344             :         else {
     345        5707 :             compiling = FALSE;
     346             :         }
     347       13311 :         return;
     348             : 
     349           0 : badif:  cerror("#if, #ifdef, or #ifndef without an argument", NULLST);
     350             : #if !OLD_PREPROCESSOR
     351           0 :         skipnl();                               /* Prevent an extra     */
     352           0 :         unget();                                /* Error message        */
     353             : #endif
     354           0 :         return;
     355             : }
     356             : 
     357             : FILE_LOCAL
     358        8779 : void doinclude()
     359             : /*
     360             :  * Process the #include control line.
     361             :  * There are three variations:
     362             :  *      #include "file"         search somewhere relative to the
     363             :  *                              current source file, if not found,
     364             :  *                              treat as #include <file>.
     365             :  *      #include <file>         Search in an implementation-dependent
     366             :  *                              list of places.
     367             :  *      #include token          Expand the token, it must be one of
     368             :  *                              "file" or <file>, process as such.
     369             :  *
     370             :  * Note: the November 12 draft forbids '>' in the #include <file> format.
     371             :  * This restriction is unnecessary and not implemented.
     372             :  */
     373             : {
     374             :         register int            c;
     375             :         register int            delim;
     376             : #if HOST == SYS_VMS
     377             :         char                    def_filename[NAM$C_MAXRSS + 1];
     378             : #endif
     379             : 
     380        8779 :         delim = macroid(skipws());
     381        8779 :         if (delim != '<' && delim != '"')
     382           0 :             goto incerr;
     383        8779 :         if (delim == '<')
     384        6623 :             delim = '>';
     385        8779 :         workp = work;
     386        8779 :         instring = TRUE;                /* Accept all characters        */
     387             : #ifdef CONTROL_COMMENTS_NOT_ALLOWED
     388             :         while ((c = get()) != '\n' && c != EOF_CHAR)
     389             :             save(c);                    /* Put it away.                 */
     390             :         unget();                        /* Force nl after includee      */
     391             :         /*
     392             :          * The draft is unclear if the following should be done.
     393             :          */
     394             :         while (--workp >= work && *workp == ' ')
     395             :             ;                           /* Trim blanks from filename    */
     396             :         if (*workp != delim)
     397             :             goto incerr;
     398             : #else
     399      142753 :         while ((c = get()) != delim && c != EOF_CHAR)
     400      125195 :             save(c);
     401             : #endif
     402        8779 :         *workp = EOS;                   /* Terminate filename           */
     403        8779 :         instring = FALSE;
     404             : #if HOST == SYS_VMS
     405             :         /*
     406             :          * Assume the default .h filetype.
     407             :          */
     408             :         if (!vmsparse(work, ".H", def_filename)) {
     409             :             perror(work);               /* Oops.                        */
     410             :             goto incerr;
     411             :         }
     412             :         else if (openinclude(def_filename, (delim == '"')))
     413             :             return;
     414             : #else
     415        8779 :         if (openinclude(work, (delim == '"')))
     416        8779 :             return;
     417             : #endif
     418             :         /*
     419             :          * No sense continuing if #include file isn't there.
     420             :          */
     421           0 :         cfatal("Cannot open include file \"%s\"", work);
     422             : 
     423           0 : incerr: cerror("#include syntax error", NULLST);
     424           0 :         return;
     425             : }
     426             : 
     427             : FILE_LOCAL int
     428        8779 : openinclude(char* filename, int searchlocal)
     429             : /*
     430             :  * Actually open an include file.  This routine is only called from
     431             :  * doinclude() above, but was written as a separate subroutine for
     432             :  * programmer convenience.  It searches the list of directories
     433             :  * and actually opens the file, linking it into the list of
     434             :  * active files.  Returns TRUE if the file was opened, FALSE
     435             :  * if openinclude() fails.  No error message is printed.
     436             :  */
     437             : {
     438             :         register char           **incptr;
     439             : #if HOST == SYS_VMS
     440             : #if NFWORK < (NAM$C_MAXRSS + 1)
     441             :     << error, NFWORK is not greater than NAM$C_MAXRSS >>
     442             : #endif
     443             : #endif
     444             :         char                    tmpname[NFWORK]; /* Filename work area   */
     445             : 
     446        8779 :         if (searchlocal) {
     447             :             /*
     448             :              * Look in local directory first
     449             :              */
     450             : #if HOST == SYS_UNIX
     451             :             /*
     452             :              * Try to open filename relative to the directory of the current
     453             :              * source file (as opposed to the current directory). (ARF, SCK).
     454             :              */
     455        2156 :             if (filename[0] != '/'
     456        2156 :              && hasdirectory(infile->filename, tmpname))
     457        2156 :                 strcat(tmpname, filename);
     458             :             else {
     459           0 :                 strcpy(tmpname, filename);
     460             :             }
     461             : #else
     462             :             if (!hasdirectory(filename, tmpname)
     463             :              && hasdirectory(infile->filename, tmpname))
     464             :                 strcat(tmpname, filename);
     465             :             else {
     466             :                 strcpy(tmpname, filename);
     467             :             }
     468             : #endif
     469        2156 :             if (openfile(tmpname))
     470         921 :                 return (TRUE);
     471             :         }
     472             :         /*
     473             :          * Look in any directories specified by -I command line
     474             :          * arguments, then in the builtin search list.
     475             :          */
     476       30409 :         for (incptr = incdir; incptr < incend; incptr++) {
     477       30409 :             if (strlen(*incptr) + strlen(filename) >= (NFWORK - 1))
     478           0 :                 cfatal("Filename work buffer overflow", NULLST);
     479             :             else {
     480             : #if HOST == SYS_UNIX
     481       30409 :                 if (filename[0] == '/')
     482           0 :                     strcpy(tmpname, filename);
     483             :                 else {
     484       30409 :                     sprintf(tmpname, "%s/%s", *incptr, filename);
     485             :                 }
     486             : #elif HOST == SYS_UNKNOWN
     487             :                 if (filename[0] == '\\')
     488             :                     strcpy(tmpname, filename);
     489             :                 else {
     490             :                     sprintf(tmpname, "%s\\%s", *incptr, filename);
     491             :                 }
     492             : #else
     493             :                 if (!hasdirectory(filename, tmpname))
     494             :                     sprintf(tmpname, "%s%s", *incptr, filename);
     495             : #endif
     496       30409 :                 if (openfile(tmpname))
     497        7858 :                     return (TRUE);
     498             :             }
     499             :         }
     500           0 :         return (FALSE);
     501             : }
     502             : 
     503             : FILE_LOCAL int
     504        2156 : hasdirectory(char* source, char* result)
     505             : /*
     506             :  * If a device or directory is found in the source filename string, the
     507             :  * node/device/directory part of the string is copied to result and
     508             :  * hasdirectory returns TRUE.  Else, nothing is copied and it returns FALSE.
     509             :  */
     510             : {
     511             : #if HOST == SYS_UNIX
     512             :         register char           *tp;
     513             : 
     514        2156 :         if ((tp = strrchr(source, '/')) == NULL)
     515           0 :             return (FALSE);
     516             :         else {
     517        2156 :             strncpy(result, source, tp - source + 1);
     518        2156 :             result[tp - source + 1] = EOS;
     519        2156 :             return (TRUE);
     520             :         }
     521             : #else
     522             : #if HOST == SYS_VMS
     523             :         if (vmsparse(source, NULLST, result)
     524             :          && result[0] != EOS)
     525             :             return (TRUE);
     526             :         else {
     527             :             return (FALSE);
     528             :         }
     529             : #else
     530             :         /*
     531             :          * Random DEC operating system (RSX, RT11, RSTS/E)
     532             :          */
     533             :         register char           *tp;
     534             : 
     535             :         if ((tp = strrchr(source, ']')) == NULL
     536             :          && (tp = strrchr(source, ':')) == NULL)
     537             :             return (FALSE);
     538             :         else {
     539             :             strncpy(result, source, tp - source + 1);
     540             :             result[tp - source + 1] = EOS;
     541             :             return (TRUE);
     542             :         }
     543             : #endif
     544             : #endif
     545             : }
     546             : 
     547             : #if HOST == SYS_VMS
     548             : 
     549             : /*
     550             :  * EXP_DEV is set if a device was specified, EXP_DIR if a directory
     551             :  * is specified.  (Both set indicate a file-logical, but EXP_DEV
     552             :  * would be set by itself if you are reading, say, SYS$INPUT:)
     553             :  */
     554             : #define DEVDIR (NAM$M_EXP_DEV | NAM$M_EXP_DIR)
     555             : 
     556             : FILE_LOCAL int
     557             : vmsparse(source, defstring, result)
     558             : char            *source;
     559             : char            *defstring;     /* non-NULL -> default string.          */
     560             : char            *result;        /* Size is at least NAM$C_MAXRSS + 1    */
     561             : /*
     562             :  * Parse the source string, applying the default (properly, using
     563             :  * the system parse routine), storing it in result.
     564             :  * TRUE if it parsed, FALSE on error.
     565             :  *
     566             :  * If defstring is NULL, there are no defaults and result gets
     567             :  * (just) the node::[directory] part of the string (possibly "")
     568             :  */
     569             : {
     570             :         struct FAB      fab = cc$rms_fab;       /* File access block    */
     571             :         struct NAM      nam = cc$rms_nam;       /* File name block      */
     572             :         char            fullname[NAM$C_MAXRSS + 1];
     573             :         register char   *rp;                    /* Result pointer       */
     574             : 
     575             :         fab.fab$l_nam = &nam;                   /* fab -> nam           */
     576             :         fab.fab$l_fna = source;                 /* Source filename      */
     577             :         fab.fab$b_fns = strlen(source);         /* Size of source       */
     578             :         fab.fab$l_dna = defstring;              /* Default string       */
     579             :         if (defstring != NULLST)
     580             :             fab.fab$b_dns = strlen(defstring);  /* Size of default      */
     581             :         nam.nam$l_esa = fullname;               /* Expanded filename    */
     582             :         nam.nam$b_ess = NAM$C_MAXRSS;           /* Expanded name size   */
     583             :         if (sys$parse(&fab) == RMS$_NORMAL) {   /* Parse away           */
     584             :             fullname[nam.nam$b_esl] = EOS;      /* Terminate string     */
     585             :             result[0] = EOS;                    /* Just in case         */
     586             :             rp = &result[0];
     587             :             /*
     588             :              * Remove stuff added implicitly, accepting node names and
     589             :              * dev:[directory] strings (but not process-permanent files).
     590             :              */
     591             :             if ((nam.nam$l_fnb & NAM$M_PPF) == 0) {
     592             :                 if ((nam.nam$l_fnb & NAM$M_NODE) != 0) {
     593             :                     strncpy(result, nam.nam$l_node, nam.nam$b_node);
     594             :                     rp += nam.nam$b_node;
     595             :                     *rp = EOS;
     596             :                 }
     597             :                 if ((nam.nam$l_fnb & DEVDIR) == DEVDIR) {
     598             :                     strncpy(rp, nam.nam$l_dev, nam.nam$b_dev + nam.nam$b_dir);
     599             :                     rp += nam.nam$b_dev + nam.nam$b_dir;
     600             :                     *rp = EOS;
     601             :                 }
     602             :             }
     603             :             if (defstring != NULLST) {
     604             :                 strncpy(rp, nam.nam$l_name, nam.nam$b_name + nam.nam$b_type);
     605             :                 rp += nam.nam$b_name + nam.nam$b_type;
     606             :                 *rp = EOS;
     607             :                 if ((nam.nam$l_fnb & NAM$M_EXP_VER) != 0) {
     608             :                     strncpy(rp, nam.nam$l_ver, nam.nam$b_ver);
     609             :                     rp[nam.nam$b_ver] = EOS;
     610             :                 }
     611             :             }
     612             :             return (TRUE);
     613             :         }
     614             :         return (FALSE);
     615             : }
     616             : #endif
     617             : 
     618             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10