Open64 (mfef90, whirl2f, and IR tools)  TAG: version-openad; SVN changeset: 916
token_buffer.cxx
Go to the documentation of this file.
00001 /*
00002 
00003   Copyright (C) 2000, 2001 Silicon Graphics, Inc.  All Rights Reserved.
00004 
00005   This program is free software; you can redistribute it and/or modify it
00006   under the terms of version 2 of the GNU General Public License as
00007   published by the Free Software Foundation.
00008 
00009   This program is distributed in the hope that it would be useful, but
00010   WITHOUT ANY WARRANTY; without even the implied warranty of
00011   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
00012 
00013   Further, this software is distributed without any warranty that it is
00014   free of the rightful claim of any third person regarding infringement 
00015   or the like.  Any license provided herein, whether implied or 
00016   otherwise, applies only to this software file.  Patent licenses, if 
00017   any, provided herein do not apply to combinations of this program with 
00018   other software, or any other product whatsoever.  
00019 
00020   You should have received a copy of the GNU General Public License along
00021   with this program; if not, write the Free Software Foundation, Inc., 59
00022   Temple Place - Suite 330, Boston MA 02111-1307, USA.
00023 
00024   Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pky,
00025   Mountain View, CA 94043, or:
00026 
00027   http://www.sgi.com
00028 
00029   For further information regarding this notice, see:
00030 
00031   http://oss.sgi.com/projects/GenInfo/NoticeExplan
00032 
00033 */
00034 
00035 
00036 /* ====================================================================
00037  * ====================================================================
00038  *
00039  *
00040  * Revision history:
00041  *  07-Oct-94 - Original Version
00042  *
00043  * Description:
00044  *
00045  *    This package implements the most basic form of token buffer,
00046  *    where we only distinguish between separators, special character
00047  *    string tokens, and source position directives.  
00048  *
00049  *    The purpose of a token_buffer is two-fold:  It writes token 
00050  *    sequences to an output-file, which is opened as a side-effect
00051  *    of initializing this module.  Secondly it provides facilities
00052  *    for buffering an ordered sequence of tokens.
00053  *
00054  *    We maintain a free-list (buffer_free_list) for reusing buffers.
00055  *    There are really three kinds of buffers:
00056  *
00057  *        TOKEN_BUFFER:  Contains information about a buffer and has its
00058  *                       own private string and token buffer area.  This
00059  *                       is the "abstract data type" exported by this
00060  *                       package.
00061  *
00062  *        tokens: A memory pool allocated for a given TOKEN_BUFFER,
00063  *                which contains all its tokens.  The token sequence
00064  *                will index into this memory pool of tokens.
00065  *
00066  *        strings: A memory pool allocated for a given TOKEN_BUFFER,
00067  *                 which contains all its character strings.  Each
00068  *                 token will index into this pool of characters.
00069  *
00070  *    The buffers and memory pools are never freed up from memory,
00071  *    unless an explicit request is recieved to do so, and they are 
00072  *    instead kept on a free_list.
00073  *
00074  *    The exported routines are described in token_buffer.h, and are
00075  *    implemented in terms of various static utility routines and
00076  *    variables local to this module "body".  The definitions are
00077  *    in the following order:
00078  *
00079  *       1) Macro definitions, data types, and local state.
00080  *
00081  *       2) Local utility routines.
00082  *
00083  *       3) Implementation of each of the exported routines.
00084  *
00085  * WARNING:
00086  *
00087  *    This module has been implemented very carefully without any
00088  *    interspersed assertion checking, so extreme care should be
00089  *    exercised in any modification to this module.  It is essential
00090  *    that the implementation of the token-buffer mechanism be as
00091  *    efficient as is possible.
00092  *
00093  * ====================================================================
00094  * ====================================================================
00095  */
00096 
00097 #ifdef _KEEP_RCS_ID
00098 #endif /* _KEEP_RCS_ID */
00099 
00100 #include <stdio.h>
00101 #include <string.h>
00102 #include "defs.h"
00103 #include "srcpos.h"
00104 #include "token_buffer.h"
00105 #include "errors.h"
00106 #include "mempool.h"
00107 #include "wn.h"
00108 #include "ir_reader.h"
00109 #include "unparse_target.h"
00110 
00111 
00112 /*------------------ macros, types, and local state -------------------*/
00113 /*---------------------------------------------------------------------*/
00114 
00115 /* Disallow any use of strcpy, since it potentially dangerous.  We operate
00116  * with strings that are not NULL-character terminated in the tokens, and
00117  * as such space is not allocated for such NULL-characters and a strcpy
00118  * may write a NULL character beyond the end of an allocated buffer.
00119  */
00120 #define strcpy DO_NOT_USE_STRCPY
00121 
00122 /* Macros for allocating, reallocating and freeing up memory.
00123  */
00124 #define TB_TYPE_ALLOC_N(type, count)\
00125    TYPE_MEM_POOL_ALLOC_N(type, Malloc_Mem_Pool, count)
00126 
00127 #define TB_TYPE_REALLOC_N(type, old_ptr, old_count, new_count)\
00128    TYPE_MEM_POOL_REALLOC_N(type, Malloc_Mem_Pool, old_ptr,\
00129                            old_count, new_count)
00130 
00131 #define TB_FREE(ptr)\
00132    MEM_POOL_FREE(Malloc_Mem_Pool, ptr)
00133 
00134 #include "token_names.h"
00135 
00136 /* The buffer structure and its index types */
00137 typedef mUINT32 STRING_IDX;
00138 typedef mUINT32 TOKEN_IDX;
00139 #define MAX_STRING_IDX (STRING_IDX)0x7fffffffU /* max string buffer size */
00140 #define MAX_TOKEN_IDX  (TOKEN_IDX)0x7fffffffU  /* max token buffer size */
00141 #define NO_STRING_IDX (STRING_IDX)0xffffffffU  /* Invalid string buffer index*/
00142 #define NO_TOKEN_IDX  (TOKEN_IDX)0xffffffffU   /* Invalid token buffer index*/
00143 #define INIT_STRING_BUFFER_SIZE 1024
00144 #define INIT_TOKEN_BUFFER_SIZE  512
00145 
00146 typedef enum Token_Kind
00147 {
00148    STRING_TOKEN = 0,
00149    SPECIAL_TOKEN = 1,
00150    SEPARATOR_TOKEN = 2,
00151    DIRECTIVE_TOKEN = 3,
00152    F77_SEQNO_TOKEN = 4,
00153    SRCPOS_MAP_TOKEN = 5,
00154    SRCPOS_DIRECTIVE_TOKEN = 6
00155 } TOKEN_KIND;
00156 
00157 typedef struct String_Value
00158 {
00159    STRING_IDX size; /* String size */
00160    union
00161    {
00162       char       ch[sizeof(STRING_IDX)]; /* SPECIAL_TOKEN and short strings */
00163       STRING_IDX idx;                    /* ... any longer char strings */
00164    } string;
00165 } STRING_VALUE;
00166 
00167 typedef union Token_Value
00168 {
00169    SRCPOS       srcpos;  /* SRCPOS value (64 bits) */
00170    STRING_VALUE str_val; /* string values (64 bits) */
00171 } TOKEN_VALUE;
00172 
00173 typedef struct Token
00174 {
00175    TOKEN_KIND  kind;  /* (32 bits) */
00176    TOKEN_IDX   next;  /* The next token in a token-sequence (32 bits) */
00177    TOKEN_VALUE value; /* The characters for the token (64 bits) */
00178 } TOKEN;
00179 
00180 #define TOKEN_kind(t) (t)->kind
00181 #define TOKEN_next(t) (t)->next
00182 #define TOKEN_srcpos(t) (t)->value.srcpos
00183 #define TOKEN_char(t) (t)->value.str_val.string.ch[0]
00184 #define TOKEN_short_string(t) (t)->value.str_val.string.ch
00185 #define TOKEN_string_idx(t) (t)->value.str_val.string.idx
00186 #define TOKEN_string_size(t) (t)->value.str_val.size
00187 
00188 #define TOKEN_is_short_string(t) (TOKEN_string_size(t) <= sizeof(STRING_IDX))
00189 #define TOKEN_is_string(t) \
00190    (TOKEN_kind(t) == STRING_TOKEN || \
00191     TOKEN_kind(t) == SPECIAL_TOKEN || \
00192     TOKEN_kind(t) == SEPARATOR_TOKEN || \
00193     TOKEN_kind(t) == DIRECTIVE_TOKEN || \
00194     TOKEN_kind(t) == F77_SEQNO_TOKEN)
00195 
00196 
00197 typedef struct Token_Sequence
00198 {
00199    TOKEN_IDX  first;      /* First token in the token-sequence */
00200    TOKEN_IDX  last;       /* Last token in the token-sequence */
00201 } TOKEN_SEQUENCE;
00202 
00203 struct Token_Buffer
00204 {
00205    char          *strings;
00206    TOKEN         *tokens;
00207    STRING_IDX     chars_allocated;  /* Number of characters allocated */
00208    STRING_IDX     chars_used;       /* Number of characters used */
00209    TOKEN_IDX      tokens_allocated; /* Number of tokens allocated */
00210    TOKEN_IDX      tokens_used;      /* Number of tokens used */
00211    TOKEN_SEQUENCE token_list;       /* The token-sequence */
00212    TOKEN_BUFFER   next;             /* Maintains free-list of buffers */
00213 };
00214 
00215 /* Given that the token is of a kind that has an associated char-string,
00216  * this macro will return the address to this string (currently, only
00217  * SRCPOS tokens do not have a char-string, while SPECIAL_CHAR tokens
00218  * are represented as a string with one char and can alternatively be
00219  * accessed with the TOKEN_char(a_token) macro call).  There is no
00220  * assertion checking on this access to the string.
00221  */
00222 #define TOKEN_BUFFER_get_char_string(buf, a_token)\
00223    (TOKEN_is_short_string(a_token)? \
00224     TOKEN_short_string(a_token) : \
00225     &buf->strings[TOKEN_string_idx(a_token)])
00226 
00227 /* Local state variables */
00228 static TOKEN_BUFFER buffer_free_list = NULL;
00229 
00230 
00231 #define WRITE_BUFFER_SIZE 256
00232 #define INVALID_SPLIT_PT -1
00233 static char write_buffer[WRITE_BUFFER_SIZE+1];
00234 static INT32 write_buffer_next = 0; /* Need to access the previous idx as -1 */
00235 static INT32 last_split_pt = INVALID_SPLIT_PT; /* To split too long lines */
00236 
00237 
00238 #define MAX_INDENTATION 40
00239 #define MAX_INDENTATION_STEP 10
00240 static UINT32 indentation_increment = 2; /* Ident by 2 spaces at a time */
00241 static INT32  current_indentation = 0;   /* Never to exceed MAX_INDENTATION */
00242 static INT32  requested_indentation = 0; /* May exceed MAX_INDENTATION */
00243 
00244 
00245 /* How do we format the output characters? */
00246 #define USE_UNLIMITED_LINE_LENGTH (Max_Line_Length == 0)
00247 static UINT32 Max_Line_Length = 0; /* Unlimited line-length */
00248 static FORMAT_KIND Output_Format = FREE_FORMAT;
00249 
00250 
00251 /* What is the current position in the output file, taking into
00252  * account the line currently being buffered for output.
00253  */
00254 static UINT32 Current_Output_Col = 1;
00255 static UINT32 Current_Output_Line = 1;
00256 
00257 
00258 /* What is the maxumum file-number encountered in any SRCPOS_MAP token.
00259  */
00260 static UINT32 Max_Srcpos_Map_Filenum = 0;
00261 
00262 /* What is the default maximum line lengths for the various formatting
00263  * kinds that we support.
00264  */
00265 static UINT32 Default_Max_Line_Length[NUM_FORMAT_KINDS+1] =
00266 {
00267    0,  /* FREE_FORMAT: no limit */
00268    0,  /* F77_TAB_FORMAT: no limit */
00269    72  /* F77_ANSI_FORMAT: limited to 72 characters */
00270 };
00271 
00272 /* Fortran directives are somewhat special in that they enforce a 72
00273  * character limit on line-lengths.
00274  */
00275 #define MAX_F77_DIRECTIVE_PREFIX_SIZE 24
00276 static BOOL   Inside_F77_Directive = FALSE;
00277 static UINT32 Max_Line_Length_Outside_F77_Directive;
00278 static char   F77_Directive_Continuation[MAX_F77_DIRECTIVE_PREFIX_SIZE+1];
00279 
00280 /* Use a special syntax for the ProMPF analysis file.
00281  */
00282 static BOOL Emit_Prompf_Srcpos_Map = FALSE;
00283 
00284 
00285 /*--------------- routines for debugging a token buffer ---------------*/
00286 /*---------------------------------------------------------------------*/
00287 
00288 #define DBGOUT stderr   /* debugging output file */
00289 
00290 void
00291 dbg_tokens(TOKEN_BUFFER buf, BOOL with_token_name)
00292 {
00293    const char *str;
00294    STRING_IDX  c;
00295    TOKEN_IDX   t;
00296    TOKEN      *a_token;
00297    USRCPOS     usrcpos;
00298    
00299    for (t = buf->token_list.first; t != NO_TOKEN_IDX; t = TOKEN_next(a_token))
00300    {
00301       a_token = &buf->tokens[t];
00302       
00303       switch (TOKEN_kind(a_token))
00304       {
00305       case F77_SEQNO_TOKEN:
00306          if (with_token_name)
00307             fputs("F77_SEQNO_TOKEN(", DBGOUT);
00308          str = TOKEN_BUFFER_get_char_string(buf, a_token);
00309          for (c = 0; c < TOKEN_string_size(a_token); c++)
00310             fputc(str[c], DBGOUT);
00311          break;
00312 
00313       case STRING_TOKEN:
00314          if (with_token_name)
00315             fputs("STRING_TOKEN(", DBGOUT);
00316          str = TOKEN_BUFFER_get_char_string(buf, a_token);
00317          for (c = 0; c < TOKEN_string_size(a_token); c++)
00318             fputc(str[c], DBGOUT);
00319          break;
00320 
00321       case SEPARATOR_TOKEN:
00322          if (with_token_name)
00323             fputs("SEPARATOR_TOKEN(", DBGOUT);
00324          str = TOKEN_BUFFER_get_char_string(buf, a_token);
00325          for (c = 0; c < TOKEN_string_size(a_token); c++)
00326             fputc(str[c], DBGOUT);
00327          break;
00328 
00329       case DIRECTIVE_TOKEN:
00330          if (with_token_name)
00331             fputs("DIRECTIVE_TOKEN(", DBGOUT);
00332          str = TOKEN_BUFFER_get_char_string(buf, a_token);
00333          for (c = 0; c < TOKEN_string_size(a_token); c++)
00334             fputc(str[c], DBGOUT);
00335          break;
00336 
00337       case SPECIAL_TOKEN:
00338          if (with_token_name)
00339             fputs("SPECIAL_TOKEN(", DBGOUT);
00340          fputc(TOKEN_char(a_token), DBGOUT);
00341          break;
00342 
00343       case SRCPOS_MAP_TOKEN:
00344          USRCPOS_srcpos(usrcpos) = TOKEN_srcpos(a_token);
00345          fprintf(DBGOUT,
00346                  "SRCPOS_MAP(%d, %d, %d)",
00347                  USRCPOS_column(usrcpos), 
00348                  USRCPOS_linenum(usrcpos), 
00349                  USRCPOS_filenum(usrcpos));
00350          break;
00351          
00352       case SRCPOS_DIRECTIVE_TOKEN:
00353          USRCPOS_srcpos(usrcpos) = TOKEN_srcpos(a_token);
00354          fprintf(DBGOUT,
00355                  "SRCPOS_DIRECTIVE(%d, %d, %d)",
00356                  USRCPOS_column(usrcpos), 
00357                  USRCPOS_linenum(usrcpos), 
00358                  USRCPOS_filenum(usrcpos));
00359          break;
00360 
00361       default:
00362          Is_True(FALSE, ("Attempt to write invalid token kind"));
00363          break;
00364       }
00365       if (with_token_name)
00366          fputs(")\n", DBGOUT);
00367    }
00368    if (!with_token_name)
00369       fputs("\n", DBGOUT);
00370 } /* dbg_tokens */
00371 
00372 
00373 /*------------------ general purpose hidden routines ------------------*/
00374 /*---------------------------------------------------------------------*/
00375 
00376 /* Determine whether we have exceeded the line-length limit and have
00377  * a place to insert a split-point.
00378  */
00379 #define CAN_SPLIT_LINE (last_split_pt != INVALID_SPLIT_PT)
00380 #define NEED_TO_SPLIT_LINE \
00381    (!USE_UNLIMITED_LINE_LENGTH && Current_Output_Col > Max_Line_Length)
00382 
00383 #define is_binary_or_tertiary_op(c) \
00384          W2X_Unparse_Target->Is_Binary_Or_Tertiary_Op(c)
00385 
00386 #define is_begin_grouping(c) \
00387    (c==LEFT_PAREN    || \
00388     c==LEFT_BRACKET  || \
00389     c==LEFT_BRACE)
00390 
00391 #define is_end_grouping(c) \
00392    (c==RIGHT_PAREN   || \
00393     c==RIGHT_BRACKET || \
00394     c==RIGHT_BRACE)
00395 
00396 
00397 /* Determine whether or not c2 is a unary operator, assuming the 
00398  * previous character c1 is also a special character.
00399  */
00400 #define is_unary_op(c1, c2) \
00401    ((is_binary_or_tertiary_op(c1) || \
00402      is_begin_grouping(c1)        || \
00403      is_comma_or_semicolon(c1))     && \
00404     is_binary_or_tertiary_op(c2)    && \
00405     c1 != c2                        && \
00406     c2 != EQUAL                     && \
00407     !is_end_grouping(c1)            && \
00408     !(c1==MINUS && c2==LARGER_THAN))   /* Field selection */
00409 
00410 
00411 #define is_comma_or_semicolon(c) (c==COMMA || c==SEMICOLON)
00412 
00413 
00414 static TOKEN_IDX 
00415 get_new_tokens(TOKEN_BUFFER buf, INT number_of_tokens)
00416 {
00417    /* Allocates number_of_tokens, with successive indices
00418     * starting at the returned idx.
00419     */
00420    const TOKEN_IDX return_idx = buf->tokens_used;
00421    TOKEN_IDX       max_tokens = buf->tokens_allocated;
00422 
00423    buf->tokens_used += number_of_tokens;
00424    Is_True(buf->tokens_used < MAX_TOKEN_IDX, ("Too many tokens!"));
00425    if (buf->tokens_used > max_tokens)
00426    {
00427       /* Need to reallocate tokens; double size if the number of tokens
00428        * is less than 8K, otherwise increment the number of tokens by 8K.
00429        */
00430       if (max_tokens < 0x2000)
00431          do {
00432             max_tokens *= 2;
00433          } while (buf->tokens_used > max_tokens);
00434       else
00435          do {
00436             max_tokens += 0x2000;
00437          } while (buf->tokens_used > max_tokens);
00438       
00439       buf->tokens =
00440          TB_TYPE_REALLOC_N(TOKEN,                 /* type */
00441                            buf->tokens,           /* old ptr */
00442                            buf->tokens_allocated, /* old count */
00443                            max_tokens);           /* new count */
00444       buf->tokens_allocated = max_tokens;
00445    }
00446    return (return_idx);
00447 } /* get_new_tokens */
00448 
00449 
00450 static STRING_IDX 
00451 get_new_string(TOKEN_BUFFER buf, INT16 stringsize)
00452 {
00453    /* Allocates number_of_char, with successive indices
00454     * starting at the returned idx.
00455     */
00456    const STRING_IDX return_idx = buf->chars_used;
00457    STRING_IDX       max_chars = buf->chars_allocated;
00458 
00459    buf->chars_used += stringsize;
00460    Is_True(buf->chars_used < MAX_STRING_IDX, ("Too many output characters!"));
00461    if (buf->chars_used > max_chars)
00462    {
00463       /* Need to reallocate string-buffer; double size if the buffer is 
00464        * less than 32K in size, otherwise increment size by 32K.
00465        */
00466       if (max_chars < 0x8000)
00467          do {
00468             max_chars *= 2;
00469          } while (buf->chars_used > max_chars);
00470       else
00471          do {
00472             max_chars += 0x8000;
00473          } while (buf->chars_used > max_chars);
00474       
00475       buf->strings =
00476          TB_TYPE_REALLOC_N(char,                 /* type */
00477                            buf->strings,         /* old ptr */
00478                            buf->chars_allocated, /* old count */
00479                            max_chars);           /* new count */
00480       buf->chars_allocated = max_chars;
00481    }
00482    return return_idx;
00483 } /* get_new_string */
00484 
00485 
00486 static char *
00487 Allocate_Token_String(TOKEN_BUFFER buf, TOKEN *a_token, STRING_IDX str_size)
00488 {
00489    char *str;
00490    
00491    TOKEN_string_size(a_token) = str_size;
00492    if (TOKEN_is_short_string(a_token))
00493    {
00494       str = TOKEN_short_string(a_token);
00495    }
00496    else
00497    {
00498       TOKEN_string_idx(a_token) = 
00499          get_new_string(buf, TOKEN_string_size(a_token));
00500       str = TOKEN_BUFFER_get_char_string(buf, a_token);
00501    }
00502    return str;
00503 } /* Allocate_Token_String */
00504 
00505 
00506 static void
00507 free_buffer_list(TOKEN_BUFFER free_list)
00508 {
00509    TOKEN_BUFFER to_be_freed, next = free_list;
00510 
00511    while (next != NULL)
00512    {
00513       TB_FREE(next->strings);
00514       TB_FREE(next->tokens);
00515       to_be_freed = next;
00516       next = next->next;
00517       TB_FREE(to_be_freed);
00518    }
00519 } /* free_buffer_list */
00520 
00521 
00522 static TOKEN_IDX
00523 indented_newline_token(TOKEN_BUFFER buffer, 
00524                        UINT         num_lines,
00525                        BOOL         continuation,
00526                        const char  *label)
00527 {
00528    /* Emit num_lines '\n' characters, followed by the Fortran
00529     * formatting offset and label, followed by the continuation
00530     * mark and the indentation amount.  Note that the indentation
00531     * for labels of more than 5 characters in F77_TAB_FORMAT will
00532     * be larger than expected (however, this should be very rare).
00533     */
00534    char      *str;
00535    STRING_IDX char_idx;
00536    INT32      label_size = (label==NULL? 0 : strlen(label));
00537    INT32      prefix_size;
00538    TOKEN_IDX  new_token_idx = get_new_tokens(buffer, 1);
00539    TOKEN     *a_token = &buffer->tokens[new_token_idx];
00540 
00541    Is_True(label_size < 6, ("Too large label at beginning for Fortran line"));
00542 
00543    /* Allocate a string for this SEPERATOR token */
00544    if (Output_Format == FREE_FORMAT)
00545       prefix_size = 0;
00546    else if (Output_Format == F77_TAB_FORMAT)
00547       prefix_size = label_size + (continuation? 2 : 1);
00548    else if (Output_Format == F77_ANSI_FORMAT)
00549       prefix_size = 6;
00550 
00551    /* Initiate the token */
00552    TOKEN_kind(a_token) = SEPARATOR_TOKEN;
00553    TOKEN_next(a_token) = NO_TOKEN_IDX;
00554    str = Allocate_Token_String(buffer, a_token, 
00555                                prefix_size + current_indentation + num_lines);
00556 
00557    /* Add the newline ('\n') characters to the string and 
00558     * advance char_idx one past the last newline character.
00559     */
00560    for (char_idx = 0; char_idx < num_lines; char_idx++)
00561       str[char_idx] = NEWLINE;
00562 
00563    /* Add the Fortran specific label (char_idx==num_lines) */
00564    if (label_size > 0)
00565    {
00566       (void)strncpy(&str[char_idx], &label[0], label_size);
00567       char_idx += label_size;
00568    }
00569       
00570    /* Add the fortran specific layout prefix and continuation marks
00571     * (char_idx==new_string_idx+num_lines+label_size)
00572     */
00573    if (Output_Format == F77_TAB_FORMAT)
00574    {
00575       str[char_idx++] = '\t';
00576       if (continuation)
00577          str[char_idx++] = '1';
00578    }
00579    else if (Output_Format == F77_ANSI_FORMAT && continuation)
00580    {
00581       while (char_idx < num_lines + prefix_size - 1)
00582          str[char_idx++] = SPACE;
00583       str[char_idx++] = '>';
00584    }
00585 
00586    /* Add the indentation (char_idx==new_string_idx+num_lines+prefix_size) */
00587    while (char_idx < num_lines + prefix_size + current_indentation)
00588       str[char_idx++] = SPACE;
00589 
00590    return new_token_idx;
00591 } /* indented_newline_token */
00592 
00593 
00594 static TOKEN_IDX
00595 F77_comment_line_token(TOKEN_BUFFER buffer,
00596                        UINT         num_lines,
00597                        const char  *comment_prefix,
00598                        BOOL         indent_last_line)
00599 {
00600    /* Emit num_lines '\n' characters, each followed by the
00601     * comment_prefix in column one.  Use the current Indent the last
00602     * line when "indent==TRUE".  Must be in one of the Fortran 
00603     * formatting modes.  With no indentation of the last line, we do 
00604     * not even insert the tab character or standard fomatting space
00605     * characters.
00606     */
00607    const INT32 comment_prefix_size = strlen(comment_prefix);
00608    char        indentation_str[MAX_INDENTATION+50]; /* E.g. "C$\t   " */
00609    INT32       indentation_size;
00610    INT32       num_spaces, lines;
00611    char       *str;
00612    TOKEN_IDX   new_token_idx = get_new_tokens(buffer, 1);
00613    TOKEN      *a_token = &buffer->tokens[new_token_idx];
00614 
00615    /* Get the string used to indent the last line (preceding actual comment).
00616     */
00617    strncpy(indentation_str, comment_prefix, comment_prefix_size);
00618    indentation_size = comment_prefix_size;
00619    if (indent_last_line)
00620    {
00621       /* Assume the comment_prefix is smaller than the F77 tab or space
00622        * prefix.
00623        */
00624       if (Output_Format == F77_TAB_FORMAT)
00625       {
00626          indentation_str[indentation_size++] = '\t';
00627       }
00628       else /* Output_Format == F77_ANSI_FORMAT */
00629       {
00630          while (indentation_size < 6)
00631             indentation_str[indentation_size++] = SPACE;
00632       }
00633       for (num_spaces = 0; num_spaces < current_indentation; num_spaces++)
00634       {
00635          indentation_str[indentation_size++] = SPACE;
00636       }
00637    } /* if indent last line */
00638 
00639    /* Allocate a string for this SEPERATOR token and initiate it */
00640    TOKEN_kind(a_token) = SEPARATOR_TOKEN;
00641    TOKEN_next(a_token) = NO_TOKEN_IDX;
00642    str = Allocate_Token_String(buffer, a_token,
00643                                num_lines + /* '\n' */
00644                                (num_lines - 1)*comment_prefix_size +
00645                                indentation_size);
00646 
00647    /* Add the newline ("\n<comment_prefix>") characters to the string */
00648    for (lines = 1; lines < num_lines; lines++)
00649    {
00650       *str++ = NEWLINE;
00651       str = strncpy(str, comment_prefix, comment_prefix_size);
00652       str += comment_prefix_size;
00653    }
00654    *str++ = NEWLINE;
00655 
00656    /* Add the last line indentation */
00657    str = strncpy(str, indentation_str, indentation_size);
00658 
00659    return new_token_idx;
00660 } /* F77_comment_line_token */
00661 
00662 
00663 static TOKEN_IDX
00664 F77_directive_line_token(TOKEN_BUFFER buffer,
00665                          const char  *directive_prefix)
00666 {
00667    /* Emit a Fortran directive, which must be specially tokenized since
00668     * it must NEVER exceed a line-length of 72 characters (there is no
00669     * tab formatting mode for directives).  The directive will be preceeded
00670     * by a newline character.  Note that all subsequent tokens, up till
00671     * the next explicit NEWLINE character, apply to this token.
00672     */
00673    const INT32 directive_prefix_size = strlen(directive_prefix);
00674    char       *str;
00675    TOKEN_IDX   new_token_idx = get_new_tokens(buffer, 1);
00676    TOKEN      *a_token = &buffer->tokens[new_token_idx];
00677 
00678    /* Allocate a string for this DIRECTIVE token and initiate it.
00679     */
00680    TOKEN_kind(a_token) = DIRECTIVE_TOKEN;
00681    TOKEN_next(a_token) = NO_TOKEN_IDX;
00682    str = Allocate_Token_String(buffer, a_token, 
00683                                1/*'\n'*/ + directive_prefix_size);
00684 
00685    /* Insert the new ("\n<diretcive_prefix>") characters into the token.
00686     */
00687    *str++ = NEWLINE;
00688    str = strncpy(str, directive_prefix, directive_prefix_size);
00689 
00690    return new_token_idx;
00691 } /* F77_directive_line_token */
00692 
00693 
00694 static TOKEN_IDX
00695 string_token(TOKEN_BUFFER buffer, const char *string)
00696 {
00697    char      *str;
00698    TOKEN_IDX  new_token_idx = get_new_tokens(buffer, 1);
00699    TOKEN     *a_token = &buffer->tokens[new_token_idx];
00700 
00701    /* Initiate the token */
00702    TOKEN_kind(a_token) = STRING_TOKEN;
00703    TOKEN_next(a_token) = NO_TOKEN_IDX;
00704    str = Allocate_Token_String(buffer, a_token, strlen(string));
00705 
00706    /* Initiate the string for this token */
00707    (void)strncpy(str, string, TOKEN_string_size(a_token));
00708 
00709    return new_token_idx;
00710 } /* string_token */
00711 
00712 
00713 static TOKEN_IDX
00714 f77_seqno_token(TOKEN_BUFFER buffer, const char *seqno)
00715 {
00716    TOKEN_IDX idx = string_token(buffer, seqno);
00717    TOKEN_kind(&buffer->tokens[idx]) = F77_SEQNO_TOKEN;
00718    return idx;
00719 } /* f77_seqno_token */
00720 
00721 
00722 static TOKEN_IDX
00723 special_char_token(TOKEN_BUFFER buffer, char special)
00724 {
00725    const TOKEN_IDX  new_token_idx = get_new_tokens(buffer, 1);
00726    TOKEN           *a_token = &buffer->tokens[new_token_idx];
00727 
00728    /* Initiate the token */
00729    TOKEN_kind(a_token) = SPECIAL_TOKEN;
00730    TOKEN_next(a_token) = NO_TOKEN_IDX;
00731    TOKEN_char(a_token) = special;
00732    TOKEN_string_size(a_token) = 1;
00733 
00734    return new_token_idx;
00735 }
00736 
00737 
00738 static TOKEN_IDX
00739 Srcpos_Map_Token(TOKEN_BUFFER buffer, SRCPOS srcpos)
00740 {
00741    const TOKEN_IDX  new_token_idx = get_new_tokens(buffer, 1);
00742    TOKEN           *a_token = &buffer->tokens[new_token_idx];
00743 
00744    /* Initiate the token */
00745    TOKEN_kind(a_token) = SRCPOS_MAP_TOKEN;
00746    TOKEN_next(a_token) = NO_TOKEN_IDX;
00747    TOKEN_srcpos(a_token) = srcpos;
00748 
00749    return new_token_idx;
00750 } /* Srcpos_Map_Token */
00751 
00752 
00753 static TOKEN_IDX
00754 Srcpos_Directive_Token(TOKEN_BUFFER buffer, SRCPOS srcpos)
00755 {
00756    const TOKEN_IDX  new_token_idx = get_new_tokens(buffer, 1);
00757    TOKEN           *a_token = &buffer->tokens[new_token_idx];
00758 
00759    /* Initiate the token */
00760    TOKEN_kind(a_token) = SRCPOS_DIRECTIVE_TOKEN;
00761    TOKEN_next(a_token) = NO_TOKEN_IDX;
00762    TOKEN_srcpos(a_token) = srcpos;
00763 
00764    return new_token_idx;
00765 } /* Srcpos_Directive_Token */
00766 
00767 
00768 static TOKEN_SEQUENCE
00769 copy_token_list(TOKEN_BUFFER to_buffer, TOKEN_BUFFER from_buffer)
00770 {
00771    /* Copy the tokens from from_buffer into to_buffer, and
00772     * return a pointer to the first and last tokens of the 
00773     * resultant token list without appending or prepending 
00774     * it to the existing tokens in the to_buffer.  The next
00775     * pointers for the token_sequence will all be correct.
00776     */
00777    TOKEN_IDX       token_offset, from_idx;
00778    STRING_IDX      char_offset, char_idx;
00779    TOKEN          *new_token;
00780    TOKEN_SEQUENCE  token_list;
00781 
00782    if (from_buffer->tokens_used == 0)
00783    {
00784       token_list.first = NO_TOKEN_IDX;
00785       token_list.last = NO_TOKEN_IDX;
00786    }
00787    else
00788    {
00789       /* We take advantage of the fact that token_lists and characters
00790        * will be allocated in consecutive regions of memory, and we
00791        * therefore allocate all we need immediately.
00792        */
00793       token_offset = get_new_tokens(to_buffer, from_buffer->tokens_used);
00794       char_offset = get_new_string(to_buffer, from_buffer->chars_used);
00795       token_list.first = from_buffer->token_list.first + token_offset;
00796       token_list.last = from_buffer->token_list.last + token_offset;
00797 
00798       /* Copy the string into the target buffer.
00799        */
00800       for (char_idx = 0; char_idx < from_buffer->chars_used; char_idx++)
00801          to_buffer->strings[char_offset + char_idx] = 
00802             from_buffer->strings[char_idx];
00803       
00804       /* Copy the tokens into the new token list, and update the string
00805        * indices and next indices accordingly.
00806        */
00807       for (from_idx = 0; from_idx < from_buffer->tokens_used; from_idx++)
00808       {
00809          new_token = &to_buffer->tokens[token_offset + from_idx];
00810          *new_token = from_buffer->tokens[from_idx]; /* copy token */
00811          TOKEN_next(new_token) += token_offset;      /* correct next idx */
00812 
00813          /* correct string idx, if relevant */
00814          if (TOKEN_is_string(new_token) && !TOKEN_is_short_string(new_token))
00815             TOKEN_string_idx(new_token) += char_offset;
00816       }
00817 
00818       /* Correct the next index for the last token in the copied sequence */
00819       to_buffer->tokens[token_list.last].next = NO_TOKEN_IDX;
00820    }
00821    return token_list;
00822 } /* copy_token_list */
00823 
00824 
00825 static void
00826 append_token_list(TOKEN_BUFFER buffer, TOKEN_SEQUENCE token_list)
00827 {
00828    Is_True(token_list.first != NO_TOKEN_IDX, 
00829            ("Cannot append empty token_sequence"));
00830    if (buffer->token_list.first == NO_TOKEN_IDX)
00831       buffer->token_list.first = token_list.first;
00832    else
00833       TOKEN_next(&buffer->tokens[buffer->token_list.last]) = token_list.first;
00834    buffer->token_list.last = token_list.last;
00835 } /* append_token_list */
00836 
00837 
00838 static void
00839 prepend_token_list(TOKEN_BUFFER buffer, TOKEN_SEQUENCE token_list)
00840 {
00841    Is_True(token_list.first != NO_TOKEN_IDX, 
00842            ("Cannot prepend empty token_sequence"));
00843    if (buffer->token_list.last == NO_TOKEN_IDX)
00844       buffer->token_list.last = token_list.last;
00845    else
00846       TOKEN_next(&buffer->tokens[token_list.last]) = buffer->token_list.first;
00847    buffer->token_list.first = token_list.first;
00848 } /* prepend_token_list */
00849 
00850 
00851 static void
00852 write_into_string_buf(const char *from, 
00853                       UINT        from_size,
00854                       char      **into, 
00855                       UINT       *into_size)
00856 {
00857    /* Write "from_size" characters into "into" and update
00858     * the "into" buffer and the "into_size" to refer to the
00859     * remaining part of the buffer.
00860     */
00861    if (from_size >= *into_size)
00862    {
00863       fprintf(stderr, 
00864               "ERROR: -flist/-clist string-buffer overflow in"
00865               "write_into_string_buf() !");
00866       from_size = *into_size - 1;
00867    }
00868    if (from_size > 0)
00869    {
00870       strncpy(*into, from, from_size);
00871       *into = *into + from_size;
00872       *into_size -= from_size;
00873    }
00874 } /* write_into_string_buf */
00875 
00876 
00877 static void
00878 flush_write_buffer(FILE *ofile, char **buffer, UINT *buflen)
00879 {
00880    /* NOTE: THIS SHOULD BE THE ONLY PLACE WHERE TOKENS ARE WRITTEN
00881     * TO FILE!
00882     *
00883     * Write buffer contents to file, but not beyond the 
00884     * last_split_pt.
00885     */
00886    UINT32 buffer_idx;
00887    char   saved_ch;
00888    
00889    if (write_buffer_next > 0)
00890    {
00891       /* If there is a splitpoint somewhere in the buffer, but not at
00892        * the very beginning of the buffer and not at the very end of
00893        * the buffer, then emit characters up till that point and 
00894        * restore the remaining characters into the buffer; 
00895        * otherwise, write out the whole buffer.
00896        */
00897       if (last_split_pt > 0 && last_split_pt < write_buffer_next)
00898       {
00899          saved_ch = write_buffer[last_split_pt]; /* save splitpoint */
00900          write_buffer[last_split_pt] = '\0';
00901          if (ofile != NULL)
00902             fputs(&write_buffer[0], ofile);
00903          else
00904             write_into_string_buf(
00905                &write_buffer[0], last_split_pt, buffer, buflen);
00906          
00907          /* Restore the characters following and including the last_split_pt
00908           * into the buffer.
00909           */
00910          write_buffer[0] = saved_ch;             /* restore splitpoint */
00911          for (buffer_idx = 1; 
00912               buffer_idx+last_split_pt < write_buffer_next;
00913               buffer_idx++)
00914          {
00915             write_buffer[buffer_idx] = write_buffer[buffer_idx+last_split_pt];
00916          }
00917          last_split_pt = 0;
00918          write_buffer_next = buffer_idx;
00919       }
00920       else
00921       {
00922          write_buffer[write_buffer_next] = '\0';
00923          if (ofile != NULL)
00924             fputs(&write_buffer[0], ofile);
00925          else
00926             write_into_string_buf(
00927                &write_buffer[0], write_buffer_next, buffer, buflen);
00928          if (last_split_pt == write_buffer_next)
00929             last_split_pt = 0;
00930          else
00931             last_split_pt = INVALID_SPLIT_PT;
00932          write_buffer_next = 0;
00933       }
00934    }
00935 } /* flush_write_buffer */
00936 
00937 
00938 static void Output_Character(FILE *ofile, char **strbuf, UINT *strlen, char c);
00939 
00940 static void
00941 Split_The_Current_Output_Line(FILE *ofile,  /* NULL when strbuf!=NULL */
00942                               char **strbuf, /* NULL when ofile!=NULL */
00943                               UINT  *strlen) /* Relevant for strbuf!=NULL */
00944 {
00945    UINT32      idx;
00946    UINT32      num_chars_after_split;
00947    const char *continuation_prefix;
00948    char        tmp_buffer[WRITE_BUFFER_SIZE+1];
00949    const BOOL  is_inside_directive = Inside_F77_Directive;
00950 
00951    /* Copy the characters following the split-point into a temporary
00952     * buffer, and set buffer_idx.
00953     */
00954    for (idx = last_split_pt; idx < write_buffer_next; idx++)
00955    {
00956       tmp_buffer[idx - last_split_pt] = write_buffer[idx];
00957    }
00958    num_chars_after_split = write_buffer_next - last_split_pt;
00959       
00960    /* Determine the continuation prefix for this line-split */
00961    if (is_inside_directive)
00962    {
00963       continuation_prefix = &F77_Directive_Continuation[0];
00964       Inside_F77_Directive = FALSE;
00965    }
00966    else if (Output_Format == FREE_FORMAT)
00967       continuation_prefix = "\\\n"; /* backslash followed by newline */
00968    else if (Output_Format == F77_TAB_FORMAT)
00969       continuation_prefix = "\n\t1 "; /* newline followed by tab and '1' */
00970    else /* if (Output_Format == F77_ANSI_FORMAT) */
00971       continuation_prefix = "\n     > "; /* newline followed by 5 spaces */
00972 
00973    /* Reset the buffer to only account for characters up to the
00974     * current split-point, then add back in the remaining characters
00975     * after having added in the split-point itself.
00976     */
00977    write_buffer_next = last_split_pt;
00978    last_split_pt = INVALID_SPLIT_PT;
00979    Current_Output_Col -= num_chars_after_split;
00980    Inside_F77_Directive = FALSE;
00981    for (idx = 0; continuation_prefix[idx] != '\0'; idx++)
00982       Output_Character(ofile, strbuf, strlen, continuation_prefix[idx]);
00983    for (idx = 0; idx < num_chars_after_split; idx++)
00984       Output_Character(ofile, strbuf, strlen, tmp_buffer[idx]);
00985 
00986    Inside_F77_Directive = is_inside_directive;
00987 } /* Split_The_Current_Output_Line */
00988 
00989 
00990 static void
00991 Output_Character(FILE  *ofile,  /* NULL when strbuf!=NULL */
00992                  char **strbuf, /* NULL when ofile!=NULL */
00993                  UINT  *strlen, /* Only relevant when strbuf!=NULL */
00994                  char   c)
00995 {
00996    /* Write the buffer to file once it is full */
00997    if (write_buffer_next+1 >= WRITE_BUFFER_SIZE)
00998       flush_write_buffer(ofile, strbuf, strlen);
00999 
01000    /* Add this character to file */
01001    write_buffer[write_buffer_next++] = c;
01002 
01003    /* Keep track of the current positioning in the output file */
01004    if (c == '\n')
01005    {
01006       Current_Output_Col = 1;
01007       Current_Output_Line++;
01008       last_split_pt = INVALID_SPLIT_PT;
01009       if (Inside_F77_Directive)
01010       {
01011          Inside_F77_Directive = FALSE;
01012          Max_Line_Length = Max_Line_Length_Outside_F77_Directive;
01013       }
01014    }
01015    else
01016    {
01017       Current_Output_Col++;
01018    }
01019    
01020    if (NEED_TO_SPLIT_LINE && CAN_SPLIT_LINE)
01021       Split_The_Current_Output_Line(ofile, strbuf, strlen);
01022 
01023 } /* Output_Character */
01024 
01025 
01026 static void 
01027 Output_Srcpos_Map(FILE *mapfile, SRCPOS srcpos)
01028 {
01029    /* Output the current source position, relative to the
01030     * Current_Output_Line and the Current_Output_Col in
01031     * a Lisp like predicate form.  If this token is
01032     * used in conjunction with a SRCPOS_DIRECTIVE token,
01033     * it should typically follow the indented newline token
01034     * that follows the SRCPOS_DIRECTIVE token to get the 
01035     * Current_Output_Line and Current_Output_Col right.
01036     * NOTE that this token is assumed output to a file 
01037     * different from the regular output-file, and hence
01038     * we do not use the Output_Character() function.
01039     */
01040    INT32 status;
01041    USRCPOS usrcpos;
01042    
01043    if (srcpos != 0)
01044    {
01045       USRCPOS_srcpos(usrcpos) = srcpos;
01046 
01047       /* Get the maximum file-number, such we later can write out the
01048        * whole file-table.
01049        */
01050       if (USRCPOS_filenum(usrcpos) > Max_Srcpos_Map_Filenum)
01051          Max_Srcpos_Map_Filenum = USRCPOS_filenum(usrcpos);
01052       
01053       if (Emit_Prompf_Srcpos_Map)
01054          status = fprintf(mapfile, 
01055                           " [%u %u]-->[%u %u %u]\n",
01056                           Current_Output_Line, 
01057                           Current_Output_Col,
01058                           USRCPOS_filenum(usrcpos),
01059                           USRCPOS_linenum(usrcpos),
01060                           USRCPOS_column(usrcpos));
01061       else
01062          status = fprintf(mapfile, 
01063                           " ((%u %u) (%u %u %u))\n",
01064                           Current_Output_Line, 
01065                           Current_Output_Col,
01066                           USRCPOS_filenum(usrcpos),
01067                           USRCPOS_linenum(usrcpos),
01068                           USRCPOS_column(usrcpos));
01069 
01070       Is_True(status >= 0, ("Output error to srcpos mapping file"));
01071    }
01072 } /* Output_Srcpos_Map */
01073 
01074 
01075 static void 
01076 Output_Srcpos_Directive(FILE  *ofile, 
01077                         char **strbuf, 
01078                         UINT  *strlen, 
01079                         SRCPOS srcpos)
01080 {
01081    /* Output the current source position in the form
01082     * of a "#line" preprocessing directive.  Since this
01083     * directive applies to everything that follows, it
01084     * implicitly causes a newline to precede it.  The
01085     * implicit newline should be known to users of this
01086     * module and means this token should precede the
01087     * indented newline that typically precedes a stmt.
01088     */
01089    char        Srcpos_Directive[1024];
01090    const char *fname;
01091    const char *dirname;
01092    STRING_IDX  ch_idx;
01093    USRCPOS     usrcpos;
01094    
01095    if (srcpos != 0)
01096    {
01097       IR_Srcpos_Filename(srcpos, &fname, &dirname);
01098       USRCPOS_srcpos(usrcpos) = srcpos;
01099       if (fname != NULL && dirname != NULL)
01100       {
01101          sprintf(Srcpos_Directive,
01102                  "\n#line %d \"%s/%s\"",
01103                  USRCPOS_linenum(usrcpos), dirname, fname);
01104       }
01105       else if (fname != NULL)
01106       {
01107          sprintf(Srcpos_Directive, 
01108                  "\n#line %d \"%s\"", USRCPOS_linenum(usrcpos), fname);
01109       }
01110       else
01111       {
01112          sprintf(Srcpos_Directive, "\n#line %d",  USRCPOS_linenum(usrcpos));
01113       }
01114 
01115       /* Write the directive to file.
01116        */
01117       for (ch_idx = 0; Srcpos_Directive[ch_idx] != '\0'; ch_idx++)
01118          Output_Character(ofile, strbuf, strlen, Srcpos_Directive[ch_idx]);
01119    }
01120 } /* Output_Srcpos_Directive */
01121 
01122 
01123 static void 
01124 write_token(FILE        *ofile,   /* NULL if strbuf!=NULL */
01125             char       **strbuf,  /* NULL if ofile!=NULL */
01126             UINT        *strlen,  /* Only relevant when strbuf!=NULL */
01127             TOKEN_BUFFER buffer, 
01128             TOKEN_IDX    this_token)
01129 {
01130    const char *str;
01131    STRING_IDX  ch_idx;
01132    TOKEN      *a_token = &buffer->tokens[this_token];
01133    
01134    Is_True(this_token != NO_TOKEN_IDX, ("Cannot write non-existent token"));
01135    
01136    switch (TOKEN_kind(a_token))
01137    {
01138    case F77_SEQNO_TOKEN:
01139       /* Fill up the current line to column 73, where the sequence number
01140        * will begin, before entering the sequence number.
01141        */
01142       for (ch_idx = Current_Output_Col; ch_idx < 73; ch_idx++)
01143          Output_Character(ofile, strbuf, strlen, SPACE);
01144 
01145       str = TOKEN_BUFFER_get_char_string(buffer, a_token);
01146       for (ch_idx = 0; ch_idx < TOKEN_string_size(a_token); ch_idx++)
01147          Output_Character(ofile, strbuf, strlen, str[ch_idx]);
01148       break;
01149 
01150    case STRING_TOKEN:
01151       str = TOKEN_BUFFER_get_char_string(buffer, a_token);
01152       for (ch_idx = 0; ch_idx < TOKEN_string_size(a_token); ch_idx++)
01153          Output_Character(ofile, strbuf, strlen, str[ch_idx]);
01154       last_split_pt = write_buffer_next;
01155       break;
01156 
01157    case SEPARATOR_TOKEN:
01158       str = TOKEN_BUFFER_get_char_string(buffer, a_token);
01159       for (ch_idx = 0; ch_idx < TOKEN_string_size(a_token); ch_idx++)
01160          Output_Character(ofile, strbuf, strlen, str[ch_idx]);
01161       break;
01162 
01163    case DIRECTIVE_TOKEN:
01164       /* Output the diretive prefix.
01165        */
01166       str = TOKEN_BUFFER_get_char_string(buffer, a_token);
01167       for (ch_idx = 0; ch_idx < TOKEN_string_size(a_token); ch_idx++)
01168          Output_Character(ofile, strbuf, strlen, str[ch_idx]);
01169 
01170       /* Note the fact that subsequent tokens apply to a Fortran directive
01171        * and that lines should be limited to 72 characters.
01172        */
01173       Is_True(TOKEN_string_size(a_token) < MAX_F77_DIRECTIVE_PREFIX_SIZE-2,
01174               ("Too large directive prefix (max = %d)", 
01175               MAX_F77_DIRECTIVE_PREFIX_SIZE-2));
01176 
01177       Inside_F77_Directive = TRUE;
01178       Max_Line_Length_Outside_F77_Directive = Max_Line_Length;
01179       Max_Line_Length = 72;
01180       strncpy(&F77_Directive_Continuation[0], &str[0],
01181               TOKEN_string_size(a_token));
01182       F77_Directive_Continuation[TOKEN_string_size(a_token)] = '&';
01183       F77_Directive_Continuation[TOKEN_string_size(a_token)+1] = ' ';
01184       F77_Directive_Continuation[TOKEN_string_size(a_token)+2] = '\0';
01185       break;
01186 
01187 
01188    case SPECIAL_TOKEN:
01189       Output_Character(ofile, strbuf, strlen, TOKEN_char(a_token));
01190       last_split_pt = write_buffer_next;
01191       break;
01192 
01193    case SRCPOS_MAP_TOKEN:
01194       Is_True(ofile != NULL, ("Cannot source position mapping to file"));
01195       Output_Srcpos_Map(ofile, TOKEN_srcpos(a_token));
01196       break;
01197 
01198    case SRCPOS_DIRECTIVE_TOKEN:
01199       Output_Srcpos_Directive(ofile, strbuf, strlen, TOKEN_srcpos(a_token));
01200       break;
01201 
01202    default:
01203       Is_True(FALSE, ("Attempt to write non-existent token"));
01204       break;
01205    }
01206 } /* write_token */
01207 
01208 
01209 static void 
01210 write_separator(FILE        *ofile,  /* NULL when strbuf!=NULL */
01211                 char       **strbuf, /* NULL when ofile!=NULL */
01212                 UINT        *strlen, /* Only relevant for strbuf!=NULL */
01213                 TOKEN_BUFFER buffer, 
01214                 TOKEN_IDX    idx1, 
01215                 TOKEN_IDX    idx2)
01216 {
01217    BOOL          separate;
01218    static UINT16 previous_token_kind = SEPARATOR_TOKEN; 
01219    static char   previous_token_ch = '\0';   
01220 
01221    if (idx1 == NO_TOKEN_IDX || idx2 == NO_TOKEN_IDX)
01222    {
01223       previous_token_kind = SEPARATOR_TOKEN;
01224       previous_token_ch = '\0';
01225       separate = FALSE;
01226    }
01227    else
01228    {
01229       TOKEN       *a_token1 = &buffer->tokens[idx1];
01230       TOKEN       *a_token2 = &buffer->tokens[idx2];
01231       const UINT16 kind1 = TOKEN_kind(a_token1);
01232       const UINT16 kind2 = TOKEN_kind(a_token2);
01233       char         ch1 = (kind1 == SPECIAL_TOKEN? TOKEN_char(a_token1) : 'a');
01234       char         ch2 = (kind2 == SPECIAL_TOKEN? TOKEN_char(a_token2) : 'a');
01235       
01236       if (kind1 == SEPARATOR_TOKEN        ||
01237           kind1 == DIRECTIVE_TOKEN        ||
01238           kind1 == SRCPOS_DIRECTIVE_TOKEN ||
01239           kind1 == SRCPOS_MAP_TOKEN       ||
01240           kind2 == SEPARATOR_TOKEN        ||
01241           kind2 == DIRECTIVE_TOKEN        ||
01242           kind2 == SRCPOS_DIRECTIVE_TOKEN ||
01243           kind2 == SRCPOS_MAP_TOKEN)
01244          separate = FALSE;
01245       else if (kind1 == STRING_TOKEN && kind2 == STRING_TOKEN)
01246          separate = TRUE;
01247       else if (kind1 == STRING_TOKEN && kind2 == SPECIAL_TOKEN)
01248          separate = (is_binary_or_tertiary_op(ch2) || ch2 == LEFT_BRACE);
01249       else if (kind1 == SPECIAL_TOKEN && kind2 == STRING_TOKEN)
01250          separate = ((is_binary_or_tertiary_op(ch1) &&
01251                       !(previous_token_kind == SPECIAL_TOKEN &&
01252                         is_unary_op(previous_token_ch, ch1))) ||
01253                      is_end_grouping(ch1)                     ||
01254                      is_comma_or_semicolon(ch1));
01255       else if (kind1 == SPECIAL_TOKEN && kind2 == SPECIAL_TOKEN)
01256          separate = (is_comma_or_semicolon(ch1)             ||
01257                      (is_binary_or_tertiary_op(ch1) && 
01258                       is_begin_grouping(ch2) &&
01259                       !is_unary_op(previous_token_ch, ch1)) ||
01260                      (is_end_grouping(ch1) &&
01261                       is_binary_or_tertiary_op(ch2))        ||
01262                      (!is_begin_grouping(ch1) &&
01263                       is_unary_op(ch1, ch2)));
01264       else
01265          Is_True(FALSE, ("Illegal token to separate"));
01266 
01267       previous_token_kind = kind1;
01268       previous_token_ch = ch1;
01269    }
01270    if (separate)
01271       Output_Character(ofile, strbuf, strlen, SPACE);
01272 } /* write_separator */
01273 
01274 static void 
01275 write_F77_separator(FILE        *ofile,  /* NULL when strbuf!=NULL */
01276                     char       **strbuf, /* NULL when ofile!=NULL */
01277                     UINT        *strlen, /* Relevant for strbuf!=NULL */
01278                     TOKEN_BUFFER buffer, 
01279                     TOKEN_IDX    idx1, 
01280                     TOKEN_IDX    idx2)
01281 {
01282    /* This can be targeted to Fortran requirements whenever necessary.
01283     * For now, simply call the FREE_FORMAT separator.
01284     */
01285    write_separator(ofile, strbuf, strlen, buffer, idx1, idx2);
01286 } /* write_F77_separator */
01287 
01288 
01289 static TOKEN_IDX
01290 Skip_Srcpos_Map(FILE *srcpos_map_file, TOKEN_BUFFER buf, TOKEN_IDX token_idx)
01291 {
01292    TOKEN_IDX return_idx;
01293    
01294    if (token_idx == NO_TOKEN_IDX ||
01295        TOKEN_kind(&buf->tokens[token_idx]) != SRCPOS_MAP_TOKEN)
01296    {
01297       return_idx = token_idx;
01298    }
01299    else /* TOKEN_kind == SRCPOS_MAP_TOKEN */
01300    {
01301       write_token(srcpos_map_file, NULL, 0, buf, token_idx);
01302       return_idx = TOKEN_next(&buf->tokens[token_idx]);
01303    }
01304    return return_idx;
01305 } /* Skip_Srcpos_Map */
01306 
01307 
01308 static TOKEN_IDX
01309 Str_Skip_Srcpos_Map(TOKEN_BUFFER buf, TOKEN_IDX token_idx)
01310 {
01311    TOKEN_IDX return_idx;
01312    
01313    if (token_idx == NO_TOKEN_IDX ||
01314        TOKEN_kind(&buf->tokens[token_idx]) != SRCPOS_MAP_TOKEN)
01315    {
01316       return_idx = token_idx;
01317    }
01318    else /* TOKEN_kind == SRCPOS_MAP_TOKEN */
01319    {
01320       return_idx = TOKEN_next(&buf->tokens[token_idx]);
01321    }
01322    return return_idx;
01323 } /* Str_Skip_Srcpos_Map */
01324 
01325       
01326 static void 
01327 Write_Srcpos_File_Map_Table(FILE *srcpos_map_file)
01328 {
01329    UINT32      filenum;
01330    const char *fname;
01331    const char *dirname;
01332    USRCPOS     usrcpos;
01333    INT32       status;
01334 
01335    if (Emit_Prompf_Srcpos_Map)
01336       fprintf(srcpos_map_file, "SRCFILE_MAP_BEGIN\n");
01337    else
01338       fprintf(srcpos_map_file, "(SRCPOS-FILEMAP\n");
01339    for (filenum = 1; filenum <= Max_Srcpos_Map_Filenum; filenum++)
01340    {
01341       USRCPOS_filenum(usrcpos) = filenum;
01342       IR_Srcpos_Filename(USRCPOS_srcpos(usrcpos), &fname, &dirname);
01343       if (fname != NULL && dirname != NULL)
01344       {
01345          status = fprintf(srcpos_map_file, 
01346                           " %c%u \"%s/%s\"%c\n",
01347                           Emit_Prompf_Srcpos_Map ? '[' : '(',
01348                           filenum, dirname, fname,
01349                           Emit_Prompf_Srcpos_Map ? ']' : ')');
01350          Is_True(status >= 0, ("Output error to srcpos mapping file"));
01351       }
01352       else if (fname != NULL)
01353       {
01354          status = fprintf(srcpos_map_file, 
01355                           " %c%u \"%s\"%c\n",
01356                           Emit_Prompf_Srcpos_Map ? '[' : '(',
01357                           filenum, fname,
01358                           Emit_Prompf_Srcpos_Map ? ']' : ')');
01359          Is_True(status >= 0, ("Output error to srcpos mapping file"));
01360       }
01361    } /* for */
01362    if (Emit_Prompf_Srcpos_Map)
01363       fprintf(srcpos_map_file, "SRCFILE_MAP_END\n");
01364    else
01365       fprintf(srcpos_map_file, ")\n");
01366 } /* Write_Srcpos_File_Map_Table */
01367 
01368 
01369 /*------------------------- exported routines -------------------------*/
01370 /*---------------------------------------------------------------------*/
01371 
01372 void
01373 Initialize_Token_Buffer(FORMAT_KIND output_format, BOOL prompf_srcmap_format)
01374 {
01375    Output_Format = output_format;
01376    Max_Line_Length = Default_Max_Line_Length[output_format];
01377 
01378    Emit_Prompf_Srcpos_Map = prompf_srcmap_format;
01379 
01380    write_buffer_next = 0;
01381    last_split_pt = INVALID_SPLIT_PT;
01382 
01383    Current_Output_Col = 1;
01384    Current_Output_Line = 1;
01385    Max_Srcpos_Map_Filenum = 0;
01386 } /* Initialize_Token_Buffer */
01387 
01388 
01389 void
01390 Terminate_Token_Buffer(FILE *srcpos_map_file)
01391 {
01392    /* Free up all malloced space! */
01393    free_buffer_list(buffer_free_list);
01394 
01395    /* Emit the file-number to file-name mapping table */
01396    if (Max_Srcpos_Map_Filenum > 0)
01397       Write_Srcpos_File_Map_Table(srcpos_map_file);
01398 
01399 } /* Terminate_Token_Buffer */
01400 
01401 
01402 void
01403 Set_Maximum_Linelength(UINT32 max_linelength)
01404 {
01405    if (max_linelength == 0) 
01406       Max_Line_Length = Default_Max_Line_Length[Output_Format];
01407    else
01408       Max_Line_Length = max_linelength;
01409 } /* Set_Maximum_Linelength */
01410 
01411 
01412 BOOL
01413 HAS_Maximum_Linelength(void)
01414 {
01415    return Max_Line_Length==0;
01416 } /* Get_Maximum_Linelength */
01417 
01418 
01419 UINT32
01420 Get_Maximum_Linelength(void)
01421 {
01422    return Max_Line_Length;
01423 } /* Get_Maximum_Linelength */
01424 
01425 
01426 void 
01427 Free_Token_Buffer_Memory(void)
01428 {
01429    free_buffer_list(buffer_free_list);
01430 } /* free_token_buffer_memory */
01431 
01432 
01433 TOKEN_BUFFER 
01434 New_Token_Buffer(void)
01435 {
01436    TOKEN_BUFFER new_buffer;
01437    
01438    if (buffer_free_list != NULL)
01439    {
01440       new_buffer = buffer_free_list;
01441       buffer_free_list = new_buffer->next;
01442    }
01443    else
01444    {
01445       new_buffer = 
01446          TB_TYPE_ALLOC_N(struct Token_Buffer, 1);
01447       new_buffer->chars_allocated = INIT_STRING_BUFFER_SIZE;
01448       new_buffer->strings = 
01449          TB_TYPE_ALLOC_N(char, new_buffer->chars_allocated);
01450       new_buffer->tokens_allocated = INIT_TOKEN_BUFFER_SIZE;
01451       new_buffer->tokens = 
01452          TB_TYPE_ALLOC_N(TOKEN, new_buffer->tokens_allocated);
01453    }
01454    new_buffer->chars_used = 0;
01455    new_buffer->tokens_used = 0;
01456    new_buffer->token_list.first = NO_TOKEN_IDX;
01457    new_buffer->token_list.last = NO_TOKEN_IDX;
01458    new_buffer->next = NULL;
01459 
01460    return new_buffer;
01461 } /* New_Token_Buffer */
01462 
01463 
01464 void 
01465 Reclaim_Token_Buffer(TOKEN_BUFFER *tokens)
01466 {
01467    (*tokens)->next = buffer_free_list;
01468    buffer_free_list = *tokens;
01469    *tokens = NULL;
01470 } /* Reclaim_Token_Buffer */
01471 
01472 
01473 BOOL 
01474 Is_Empty_Token_Buffer(TOKEN_BUFFER tokens)
01475 {
01476    Is_True(tokens != NULL, ("Invalid TOKEN_BUFFER in Is_Empty_Token_Buffer()"));
01477    return (tokens->tokens_used == 0);
01478 } /* Is_Empty_Token_Buffer */
01479 
01480 
01481 BOOL 
01482 Identical_Token_Lists(TOKEN_BUFFER tokens1, 
01483                       TOKEN_BUFFER tokens2)
01484 {
01485    BOOL        identical = (tokens1 == NULL && tokens2 == NULL);
01486    TOKEN_IDX   token_idx;
01487    TOKEN      *a_token1;
01488    TOKEN      *a_token2;
01489    const char *str1, *str2;
01490 
01491    if (!identical)
01492    {
01493       identical = (tokens1 != NULL && tokens2 != NULL &&
01494                    tokens1->tokens_used == tokens2->tokens_used);
01495    
01496       for (token_idx = 0; 
01497            identical && (token_idx < tokens1->tokens_used); 
01498            token_idx++)
01499       {
01500          a_token1 = &tokens1->tokens[token_idx];
01501          a_token2 = &tokens2->tokens[token_idx];
01502          identical = TOKEN_kind(a_token1) == TOKEN_kind(a_token2);
01503          if (identical)
01504          {
01505             switch (TOKEN_kind(a_token1))
01506             {
01507             case F77_SEQNO_TOKEN:
01508             case STRING_TOKEN:
01509             case SEPARATOR_TOKEN:
01510             case DIRECTIVE_TOKEN:
01511                str2 = TOKEN_BUFFER_get_char_string(tokens1, a_token1);
01512                str1 = TOKEN_BUFFER_get_char_string(tokens2, a_token2);
01513                identical = 
01514                   ((TOKEN_string_size(a_token1) == 
01515                     TOKEN_string_size(a_token2)) &&
01516                    (strncmp(str1, str2, TOKEN_string_size(a_token1)) == 0));
01517                break;
01518 
01519             case SPECIAL_TOKEN:
01520                identical = TOKEN_char(a_token1) == TOKEN_char(a_token2);
01521                break;
01522 
01523             case SRCPOS_MAP_TOKEN:
01524             case SRCPOS_DIRECTIVE_TOKEN:
01525                identical = TOKEN_srcpos(a_token1) == TOKEN_srcpos(a_token2);
01526                break;
01527 
01528             default:
01529                Is_True(FALSE, ("Attempt to access invalid token kind"));
01530                break;
01531             } /*switch*/
01532          } /*if*/
01533       } /*for*/
01534    } /*if*/
01535 
01536    return identical;
01537 } /* Identical_Token_Lists */
01538 
01539 
01540 UINT 
01541 Current_Indentation(void)
01542 {
01543    return requested_indentation;
01544 } /* Current_Indentation */
01545 
01546 
01547 void
01548 Set_Current_Indentation(UINT indent)
01549 {
01550    if (indent > MAX_INDENTATION)
01551    {
01552       requested_indentation = (INT32)indent;
01553       current_indentation = MAX_INDENTATION;
01554    }
01555    else
01556       requested_indentation = current_indentation = (INT32)indent;
01557 } /* Set_Current_Indentation */
01558 
01559 
01560 void 
01561 Set_Indentation_Step(UINT num_spaces)
01562 {
01563    if (num_spaces > MAX_INDENTATION_STEP)
01564       indentation_increment = MAX_INDENTATION_STEP;
01565    else
01566       indentation_increment = num_spaces;
01567 } /* Set_Indentation_Step */
01568 
01569 
01570 void 
01571 Increment_Indentation(void)
01572 {
01573    requested_indentation += indentation_increment;
01574    if (requested_indentation > MAX_INDENTATION)
01575       current_indentation = MAX_INDENTATION;
01576    else
01577       current_indentation = requested_indentation;
01578 } /* Increment_Indentation */
01579 
01580 
01581 void 
01582 Decrement_Indentation(void)
01583 {
01584    requested_indentation -= indentation_increment;
01585    if (requested_indentation < current_indentation)
01586    {
01587       if (requested_indentation < 0)
01588          requested_indentation = current_indentation = 0;
01589       else
01590          current_indentation = requested_indentation;
01591    }
01592 } /* Decrement_Indentation */
01593 
01594 
01595 void 
01596 Zero_Indentation(void)
01597 {
01598     requested_indentation = current_indentation = 0;
01599 } /* Zero_Indentation */
01600 
01601 
01602 void 
01603 Append_Indented_Newline(TOKEN_BUFFER tokens, UINT num_lines)
01604 {
01605    TOKEN_SEQUENCE token_list;
01606 
01607    Is_True(tokens != NULL, 
01608            ("Invalid TOKEN_BUFFER in Append_Indented_Newline()"));
01609    token_list.first = indented_newline_token(tokens, num_lines, FALSE, NULL);
01610    token_list.last = token_list.first;
01611    append_token_list(tokens, token_list);
01612 }
01613 
01614 
01615 void 
01616 Append_Token_String(TOKEN_BUFFER tokens, const char *string)
01617 {
01618    TOKEN_SEQUENCE token_list;
01619 
01620    Is_True(tokens != NULL, 
01621            ("Invalid TOKEN_BUFFER in Append_Token_String()"));
01622    if (string != NULL && string[0] != '\0')
01623    {
01624       token_list.first = string_token(tokens, string);
01625       token_list.last = token_list.first;
01626       append_token_list(tokens, token_list);
01627    }
01628 }
01629 
01630 
01631 void 
01632 Append_Token_Special(TOKEN_BUFFER tokens, char special)
01633 {
01634    TOKEN_SEQUENCE token_list;
01635 
01636    Is_True(tokens != NULL, 
01637            ("Invalid TOKEN_BUFFER in Append_Token_Special()"));
01638    token_list.first = special_char_token(tokens, special);
01639    token_list.last = token_list.first;
01640    append_token_list(tokens, token_list);
01641 }
01642 
01643 
01644 void 
01645 Append_And_Copy_Token_List(TOKEN_BUFFER result_tokens, 
01646                            TOKEN_BUFFER copy_tokens)
01647 {
01648    TOKEN_SEQUENCE token_list;
01649 
01650    Is_True(result_tokens != NULL, 
01651            ("Invalid TOKEN_BUFFER in Append_And_Copy_Token_List()"));
01652    token_list = copy_token_list(result_tokens, copy_tokens);
01653    if (token_list.first != NO_TOKEN_IDX)
01654       append_token_list(result_tokens, token_list);
01655 }
01656 
01657 
01658 void 
01659 Append_And_Reclaim_Token_List(TOKEN_BUFFER result_tokens, 
01660                               TOKEN_BUFFER *reclaim_tokens)
01661 {
01662    Append_And_Copy_Token_List(result_tokens, *reclaim_tokens);
01663    Reclaim_Token_Buffer(reclaim_tokens);
01664 }
01665 
01666 
01667 void 
01668 Prepend_Indented_Newline(TOKEN_BUFFER tokens, UINT num_lines)
01669 {
01670    TOKEN_SEQUENCE token_list;
01671 
01672    Is_True(tokens != NULL, 
01673            ("Invalid TOKEN_BUFFER in Prepend_Indented_Newline()"));
01674    token_list.first = indented_newline_token(tokens, num_lines, FALSE, NULL);
01675    token_list.last = token_list.first;
01676    prepend_token_list(tokens, token_list);
01677 }
01678 
01679 
01680 void 
01681 Prepend_Token_String(TOKEN_BUFFER tokens, const char *string)
01682 {
01683    TOKEN_SEQUENCE token_list;
01684 
01685    Is_True(tokens != NULL, 
01686            ("Invalid TOKEN_BUFFER in Prepend_Token_String()"));
01687    if (string != NULL && string[0] != '\0')
01688    {
01689       token_list.first = string_token(tokens, string);
01690       token_list.last = token_list.first;
01691       prepend_token_list(tokens, token_list);
01692    }
01693 }
01694 
01695 
01696 void 
01697 Prepend_Token_Special(TOKEN_BUFFER tokens, char special)
01698 {
01699    TOKEN_SEQUENCE token_list;
01700 
01701    Is_True(tokens != NULL, 
01702            ("Invalid TOKEN_BUFFER in Prepend_Token_Special()"));
01703    token_list.first = special_char_token(tokens, special);
01704    token_list.last = token_list.first;
01705    prepend_token_list(tokens, token_list);
01706 }
01707 
01708 
01709 void 
01710 Prepend_And_Copy_Token_List(TOKEN_BUFFER result_tokens, 
01711                             TOKEN_BUFFER copy_tokens)
01712 {
01713    TOKEN_SEQUENCE token_list;
01714 
01715    Is_True(result_tokens != NULL, 
01716            ("Invalid TOKEN_BUFFER in Prepend_And_Copy_Token_List()"));
01717    token_list = copy_token_list(result_tokens, copy_tokens);
01718    if (token_list.first != NO_TOKEN_IDX)
01719       prepend_token_list(result_tokens, token_list);
01720 }
01721 
01722 void 
01723 Prepend_And_Reclaim_Token_List(TOKEN_BUFFER result_tokens, 
01724                                TOKEN_BUFFER *reclaim_tokens)
01725 {
01726    Prepend_And_Copy_Token_List(result_tokens, *reclaim_tokens);
01727    Reclaim_Token_Buffer(reclaim_tokens);
01728 }
01729 
01730 
01731 void 
01732 Append_F77_Indented_Newline(TOKEN_BUFFER tokens,
01733                             UINT         num_lines, 
01734                             const char  *label)
01735 {
01736    TOKEN_SEQUENCE token_list;
01737 
01738    Is_True(tokens != NULL && 
01739            (Output_Format == F77_TAB_FORMAT || 
01740             Output_Format == F77_ANSI_FORMAT), 
01741            ("Invalid TOKEN_BUFFER in Append_F77_Indented_Newline()"));
01742    token_list.first = indented_newline_token(tokens, num_lines, FALSE, label);
01743    token_list.last = token_list.first;
01744    append_token_list(tokens, token_list);
01745 } /* Append_F77_Indented_Newline */
01746 
01747 
01748 void 
01749 Prepend_F77_Indented_Newline(TOKEN_BUFFER tokens, 
01750                             UINT         num_lines, 
01751                             const char  *label)
01752 {
01753    TOKEN_SEQUENCE token_list;
01754 
01755    Is_True(tokens != NULL && 
01756            (Output_Format == F77_TAB_FORMAT || 
01757             Output_Format == F77_ANSI_FORMAT), 
01758            ("Invalid TOKEN_BUFFER in Prepend_F77_Indented_Newline()"));
01759    token_list.first = indented_newline_token(tokens, num_lines, FALSE, label);
01760    token_list.last = token_list.first;
01761    prepend_token_list(tokens, token_list);
01762 } /* Prepend_F77_Indented_Newline */
01763 
01764 
01765 void 
01766 Append_F77_Indented_Continuation(TOKEN_BUFFER tokens)
01767 {
01768    TOKEN_SEQUENCE token_list;
01769 
01770    Is_True(tokens != NULL && 
01771            (Output_Format == F77_TAB_FORMAT || 
01772             Output_Format == F77_ANSI_FORMAT), 
01773            ("Invalid TOKEN_BUFFER in Append_F77_Indented_Newline()"));
01774    token_list.first = indented_newline_token(tokens, 1, TRUE, NULL);
01775    token_list.last = token_list.first;
01776    append_token_list(tokens, token_list);
01777 } /* Append_F77_Indented_Continuation */
01778 
01779 
01780 void 
01781 Prepend_F77_Indented_Continuation(TOKEN_BUFFER tokens)
01782 {
01783    TOKEN_SEQUENCE token_list;
01784 
01785    Is_True(tokens != NULL && 
01786            (Output_Format == F77_TAB_FORMAT || 
01787             Output_Format == F77_ANSI_FORMAT), 
01788            ("Invalid TOKEN_BUFFER in Prepend_F77_Indented_Continuation()"));
01789    token_list.first = indented_newline_token(tokens, 1, TRUE, NULL);
01790    token_list.last = token_list.first;
01791    prepend_token_list(tokens, token_list);
01792 } /* Prepend_F77_Indented_Newline */
01793 
01794 
01795 void 
01796 Append_F77_Comment_Newline(TOKEN_BUFFER tokens,
01797                            UINT         num_lines,
01798                            BOOL         indent_last_line)
01799 {
01800    TOKEN_SEQUENCE token_list;
01801 
01802    Is_True(tokens != NULL && 
01803            (Output_Format == F77_TAB_FORMAT || 
01804             Output_Format == F77_ANSI_FORMAT), 
01805            ("Invalid TOKEN_BUFFER in Append_F77_Commented_Newline()"));
01806    token_list.first = 
01807       F77_comment_line_token(tokens, num_lines, "C", indent_last_line);
01808    token_list.last = token_list.first;
01809    append_token_list(tokens, token_list);
01810 } /* Append_F77_Comment_Newline */
01811 
01812 
01813 void 
01814 Prepend_F77_Comment_Newline(TOKEN_BUFFER tokens, 
01815                             UINT         num_lines,
01816                             BOOL         indent_last_line)
01817 {
01818    TOKEN_SEQUENCE token_list;
01819 
01820    Is_True(tokens != NULL && 
01821            (Output_Format == F77_TAB_FORMAT || 
01822             Output_Format == F77_ANSI_FORMAT), 
01823            ("Invalid TOKEN_BUFFER in Prepend_F77_Commented_Newline()"));
01824    token_list.first = 
01825       F77_comment_line_token(tokens, num_lines, "C", indent_last_line);
01826    token_list.last = token_list.first;
01827    prepend_token_list(tokens, token_list);
01828 } /* Prepend_F77_Comment_Newline */
01829 
01830 
01831 void 
01832 Append_F77_Directive_Newline(TOKEN_BUFFER tokens,
01833                              const char  *directive_prefix)
01834 {
01835    TOKEN_SEQUENCE token_list;
01836 
01837    Is_True(tokens != NULL && 
01838            (Output_Format == F77_TAB_FORMAT || 
01839             Output_Format == F77_ANSI_FORMAT), 
01840            ("Invalid TOKEN_BUFFER in Append_F77_Directive_Newline()"));
01841    token_list.first = F77_directive_line_token(tokens, directive_prefix);
01842    token_list.last = token_list.first;
01843    append_token_list(tokens, token_list);
01844 } /* Append_F77_Directive_Newline */
01845 
01846 
01847 void 
01848 Prepend_F77_Directive_Newline(TOKEN_BUFFER tokens, 
01849                               const char  *directive_prefix)
01850 {
01851    TOKEN_SEQUENCE token_list;
01852 
01853    Is_True(tokens != NULL && 
01854            (Output_Format == F77_TAB_FORMAT || 
01855             Output_Format == F77_ANSI_FORMAT), 
01856            ("Invalid TOKEN_BUFFER in Prepend_F77_Directive_Newline()"));
01857    token_list.first = F77_directive_line_token(tokens, directive_prefix);
01858    token_list.last = token_list.first;
01859    prepend_token_list(tokens, token_list);
01860 } /* Prepend_F77_Directive_Newline */
01861 
01862 
01863 void
01864 Append_F77_Sequence_No(TOKEN_BUFFER tokens, 
01865                        const char  *seq_no)
01866 {
01867    TOKEN_SEQUENCE token_list;
01868 
01869    Is_True(tokens != NULL && Output_Format == F77_TAB_FORMAT, 
01870            ("Invalid TOKEN_BUFFER in Append_F77_Sequence_No()"));
01871    if (seq_no != NULL && seq_no[0] != '\0')
01872    {
01873       token_list.first = f77_seqno_token(tokens, seq_no);
01874       token_list.last = token_list.first;
01875       append_token_list(tokens, token_list);
01876    }
01877 } /* Append_F77_Sequence_No */
01878 
01879 
01880 void
01881 Prepend_F77_Sequence_No(TOKEN_BUFFER tokens, 
01882                         const char  *seq_no)
01883 {
01884    TOKEN_SEQUENCE token_list;
01885 
01886    Is_True(tokens != NULL && Output_Format == F77_TAB_FORMAT, 
01887            ("Invalid TOKEN_BUFFER in Append_F77_Sequence_No()"));
01888    if (seq_no != NULL && seq_no[0] != '\0')
01889    {
01890       token_list.first = f77_seqno_token(tokens, seq_no);
01891       token_list.last = token_list.first;
01892       prepend_token_list(tokens, token_list);
01893    }
01894 } /* Prepend_F77_Sequence_No */
01895 
01896 
01897 void 
01898 Append_Srcpos_Map(TOKEN_BUFFER tokens, SRCPOS srcpos)
01899 {
01900    TOKEN_SEQUENCE token_list;
01901 
01902    Is_True(tokens != NULL, 
01903            ("Invalid TOKEN_BUFFER in Append_Srcpos_Map()"));
01904    token_list.first = Srcpos_Map_Token(tokens, srcpos);
01905    token_list.last = token_list.first;
01906    append_token_list(tokens, token_list);
01907 } /* Append_Srcpos_Map */
01908 
01909 
01910 void 
01911 Append_Srcpos_Directive(TOKEN_BUFFER tokens, SRCPOS srcpos)
01912 {
01913    TOKEN_SEQUENCE token_list;
01914 
01915    Is_True(tokens != NULL, 
01916            ("Invalid TOKEN_BUFFER in Append_Srcpos_Directive()"));
01917    token_list.first = Srcpos_Directive_Token(tokens, srcpos);
01918    token_list.last = token_list.first;
01919    append_token_list(tokens, token_list);
01920 } /* Append_Srcpos_Directive */
01921 
01922 
01923 void 
01924 Prepend_Srcpos_Map(TOKEN_BUFFER tokens, SRCPOS srcpos)
01925 {
01926    TOKEN_SEQUENCE token_list;
01927 
01928    Is_True(tokens != NULL,
01929            ("Invalid TOKEN_BUFFER in Prepend_Srcpos_Map()"));
01930    token_list.first = Srcpos_Map_Token(tokens, srcpos);
01931    token_list.last = token_list.first;
01932    prepend_token_list(tokens, token_list);
01933 } /* Prepend_Srcpos_Map */
01934 
01935 
01936 void 
01937 Prepend_Srcpos_Directive(TOKEN_BUFFER tokens, SRCPOS srcpos)
01938 {
01939    TOKEN_SEQUENCE token_list;
01940 
01941    Is_True(tokens != NULL, 
01942            ("Invalid TOKEN_BUFFER in Prepend_Srcpos_Directive()"));
01943    token_list.first = Srcpos_Directive_Token(tokens, srcpos);
01944    token_list.last = token_list.first;
01945    prepend_token_list(tokens, token_list);
01946 } /* Prepend_Srcpos_Directive */
01947 
01948 
01949 void 
01950 Write_And_Reclaim_Tokens(FILE         *ofile,
01951                          FILE         *srcpos_map_file, 
01952                          TOKEN_BUFFER *tokens)
01953 {
01954    TOKEN_IDX this_token, next_token;
01955    UINT32    saved_output_col, saved_output_line;
01956 
01957    Is_True(tokens != NULL,
01958            ("Invalid TOKEN_BUFFER in Write_And_Reclaim_Tokens()"));
01959    
01960    if (srcpos_map_file == NULL)
01961    {
01962       /* Save the current source and column numbers and restore them
01963        * at the end.  These tokens do not apply to any srcpos map.
01964        */
01965       saved_output_line = Current_Output_Line;
01966       saved_output_col = Current_Output_Col;
01967    }
01968       
01969    /* Write tokens to the ofile, and all SRCPOS_MAP_TOKENs to 
01970     * the srcpos_map_file.
01971     */
01972    this_token = Skip_Srcpos_Map(srcpos_map_file, 
01973                                 *tokens,
01974                                 (*tokens)->token_list.first);
01975    while (this_token != NO_TOKEN_IDX)
01976    {
01977       write_token(ofile, NULL, 0, *tokens, this_token);
01978       next_token = Skip_Srcpos_Map(srcpos_map_file, 
01979                                    *tokens,
01980                                    TOKEN_next(&(*tokens)->tokens[this_token]));
01981       if (Output_Format == FREE_FORMAT)
01982          write_separator(ofile, NULL, 0, *tokens, this_token, next_token);
01983       else
01984          write_F77_separator(ofile, NULL, 0, *tokens, this_token, next_token);
01985       this_token = next_token;
01986    }
01987    Reclaim_Token_Buffer(tokens);
01988 
01989    /* Write out remaining characters, since the same buffer is used
01990     * to write to different files! 
01991     */
01992    flush_write_buffer(ofile, NULL, 0);
01993 
01994    if (srcpos_map_file == NULL)
01995    {
01996       /* Restore the current source and column numbers .
01997        */
01998       Current_Output_Line = saved_output_line;
01999       Current_Output_Col = saved_output_col;
02000    }
02001 } /* Write_And_Reclaim_Tokens */
02002 
02003 
02004 void 
02005 Str_Write_And_Reclaim_Tokens(char         *strbuf,
02006                              UINT32        buflen,
02007                              TOKEN_BUFFER *tokens)
02008 {
02009    TOKEN_IDX this_token, next_token;
02010    UINT32    saved_output_col, saved_output_line;
02011 
02012    Is_True(tokens != NULL,
02013            ("Invalid TOKEN_BUFFER in Str_Write_And_Reclaim_Tokens()"));
02014    
02015    /* Save the current source and column numbers and restore them
02016     * at the end.  These tokens do not apply to any srcpos map.
02017     */
02018    saved_output_line = Current_Output_Line;
02019    saved_output_col = Current_Output_Col;
02020 
02021    /* Write tokens to the string, but skip all SRCPOS_MAP_TOKENs */
02022    this_token = Str_Skip_Srcpos_Map(*tokens, (*tokens)->token_list.first);
02023    while (this_token != NO_TOKEN_IDX)
02024    {
02025       write_token(NULL, &strbuf, &buflen, *tokens, this_token);
02026       next_token = 
02027          Str_Skip_Srcpos_Map(
02028             *tokens, TOKEN_next(&(*tokens)->tokens[this_token]));
02029 
02030       if (Output_Format == FREE_FORMAT)
02031          write_separator(
02032             NULL, &strbuf, &buflen, *tokens, this_token, next_token);
02033       else
02034          write_F77_separator(
02035             NULL, &strbuf, &buflen, *tokens, this_token, next_token);
02036 
02037       this_token = next_token;
02038    }
02039    Reclaim_Token_Buffer(tokens);
02040 
02041    /* Write out remaining characters and terminate the string. 
02042     */
02043    flush_write_buffer(NULL, &strbuf, &buflen);
02044    Is_True(buflen > 0, ("String buffer overflow!"));
02045    *strbuf = '\0'; /* Terminate the output string */
02046 
02047    /* Restore the current source and column numbers .
02048     */
02049    Current_Output_Line = saved_output_line;
02050    Current_Output_Col = saved_output_col;
02051 } /* Str_Write_And_Reclaim_Tokens */
02052 
02053 
02054 void 
02055 Write_String(FILE *ofile, FILE *srcpos_map_file, const char *str)
02056 {
02057    INT32 str_idx;
02058    
02059    if (srcpos_map_file != NULL)
02060    {
02061       for (str_idx = 0; str[str_idx] != '\0'; str_idx++)
02062          if (str[str_idx] == '\n')
02063             Current_Output_Line++;
02064       Current_Output_Col += str_idx;
02065    }
02066    fputs(str, ofile);
02067 } /* Write_String */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines