1 /******************************************************************************
  2 *
  3 * Copyright (C) 2006, The Gentee Group. All rights reserved. 
  4 * This file is part of the Gentee open source project - http://www.gentee.com. 
  5 * 
  6 * THIS FILE IS PROVIDED UNDER THE TERMS OF THE GENTEE LICENSE ("AGREEMENT"). 
  7 * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS FILE CONSTITUTES RECIPIENTS 
  8 * ACCEPTANCE OF THE AGREEMENT.
  9 *
 10 * ID: define 18.10.06 0.0.A.
 11 *
 12 * Author: Alexey Krivonogov ( gentee )
 13 *
 14 * Summary: macro functions
 15 *
 16 ******************************************************************************/
 17 
 18 #include "../genteeapi/gentee.h"
 19 #include "macro.h"
 20 
 21 const pubyte defmacro[] = {
 22    "_FILE","_DATE", "_TIME", "_LINE", "_WINDOWS", "_LINUX", ""
 23 };
 24 
 25 /*-----------------------------------------------------------------------------
 26 *
 27 * ID: macro_init 22.11.06 0.0.A.
 28 * 
 29 * Summary: Create default macros
 30 *
 31 -----------------------------------------------------------------------------*/
 32 
 33 uint STDCALL macro_init( void )
 34 {
 35    uint   i = 0;
 36    pmacro pm;
 37 
 38    // Определяем предопределенные макросы
 39    while ( *defmacro[ i ] )
 40    {
 41       pm = ( pmacro )( hash_create( &_compile->macros, defmacro[ i ] ) + 1 );
 42       pm->mr.vallexem.type = LEXEM_STRING;
 43       pm->mr.vallexem.nameid = i++;
 44       pm->flag = MACROF_PREDEF;
 45    }
 46    return i;
 47 }
 48 
 49 /*-----------------------------------------------------------------------------
 50 *
 51 * ID: macro_set 22.11.06 0.0.A.
 52 * 
 53 * Summary: Set macro value
 54 *
 55 -----------------------------------------------------------------------------*/
 56 
 57 pmacro STDCALL macro_set( plexem plex, uint type, uint group )
 58 {
 59    ubyte     fullname[256];
 60    pmacro    pm;
 61    pubyte    name;
 62    phash     macrohash;
 63    uint      namedef = 0;
 64    
 65    if ( type & MACRO_NAMEDEF )
 66    {
 67       type &= ~MACRO_NAMEDEF;
 68       macrohash = &_compile->namedef;
 69       namedef = MACRO_NAMEDEF;
 70    }
 71    else
 72       macrohash = &_compile->macros;
 73 
 74    name = lexem_getname( plex );
 75    if ( group )
 76    {
 77       pmacro  palias = macro_set( plex, namedef, 0 );
 78       // nameid saves the identifier of the group name
 79       if ( !palias->mr.vallexem.type )
 80          palias->mr.vallexem.nameid = group - 1;
 81 
 82       wsprintf( fullname, "%s.%s", hash_name( &_compile->names, group - 1 ),
 83                 name );
 84       name = ( pubyte )&fullname;
 85 //      printf("GROUP=%i %s %s\n", group, groupname, name );
 86    }
 87    pm = ( pmacro )( hash_create( macrohash, name ) + 1 );
 88 
 89 //   print("create=%s\n", name );
 90    if ( pm->flag & MACROF_PREDEF || pm->flag & MACROF_GROUP )
 91       msg( MWrongname | MSG_LEXNAMEERR, plex );
 92 
 93    if ( !pm->mr.vallexem.type )
 94    {
 95       pm->mr.vallexem.type = ( ubyte )type;
 96 //      pm->mr.vallexem.nameid = id;
 97    }
 98    return pm;
 99 }
100 
101 /*-----------------------------------------------------------------------------
102 *
103 * ID: macro_get 22.11.06 0.0.A.
104 * 
105 * Summary: Get macro value
106 *
107 -----------------------------------------------------------------------------*/
108 
109 plexem STDCALL macro_get( plexem plex )
110 {
111    ubyte     temp[ 256 ];
112    uint      pos, off = 1;
113    pstr      out;
114    pmacro    pm;
115    plexem    plexsrc;
116    phashitem phi;
117    phash     macrohash;     
118 #ifdef LINUX
119    struct timespec ftime;
120 	//timezone ztime;
121    struct tm tmt;
122 #else   
123    SYSTEMTIME st;
124 #endif
125    if ( plex->type == LEXEM_NAME )
126    {
127       macrohash = &_compile->namedef;
128       off = 0;
129    }
130    else
131       macrohash = &_compile->macros;
132 
133    phi = hash_find( macrohash, lexem_getname( plex ) + off );
134    if ( !phi && plex->type != LEXEM_NAME )
135       phi = hash_find( macrohash, "_DEFAULT" );
136 
137 again:   
138 //   print("phi=%i name= %s\n", phi, lexem_getname( plex ) + off );
139    if ( !phi )
140       goto error;
141 
142    pm = ( pmacro )( phi + 1 );
143    plexsrc = &pm->mr.vallexem;
144    if ( !plexsrc->type )  // Alias macro
145    {
146       wsprintf( temp, "%s.%s", hash_name( &_compile->names, plexsrc->nameid ), 
147                 lexem_getname( plex ) + off );
148       phi = hash_find( macrohash, temp );
149       goto again;
150    }
151    if ( pm->flag & MACROF_GROUP  )   // Must be a dot in the next lexem
152    {
153       plexem nlex; 
154 
155       nlex = lexem_next( plex, 0 );
156       if ( !lexem_isys( nlex, LSYS_DOT ))
157          goto error;
158       nlex->type = LEXEM_SKIP;
159       nlex = lexem_next( nlex, LEXNEXT_NAMEDEF );
160       if ( nlex->type != LEXEM_NAME )
161          goto error;
162       nlex->type = LEXEM_SKIP;
163       wsprintf( temp, "%s.%s", lexem_getname( plex ) + off, 
164                 lexem_getname( nlex ));
165       phi = hash_find( macrohash, temp );
166       goto again;
167    }
168    if ( pm->flag & MACROF_PREDEF  )
169    {
170       if ( plexsrc->nameid > MACRO_TIME )
171       {
172          plex->type = LEXEM_NUMBER;
173          plex->num.type = TUint;
174       }
175       else
176       {
177          out = str_init( ( pstr )arr_append( &_compile->string ));
178          plex->type = LEXEM_STRING;
179          plex->strid = arr_count( &_compile->string ) - 1;
180 #ifdef LINUX    
181 	      gettimeofday( &ftime, 0 );
182          localtime_r( &ftime.tv_sec, &tmt );         
183 #else 
184          GetLocalTime( &st );
185 #endif
186       }
187       switch ( plexsrc->nameid  )
188       {
189          case MACRO_FILE:
190             str_copy( out, _compile->cur->filename );
191             break;
192          case MACRO_DATE:
193 #ifdef LINUX
194             wsprintf( temp, "%02i%02i%i", tmt.tm_mday, tmt.tm_mon, tmt.tm_year );
195 #else      
196             wsprintf( temp, "%02i%02i%i", st.wDay, st.wMonth, st.wYear );
197 #endif
198             str_copyzero( out, temp );
199             break;
200          case MACRO_TIME:
201 #ifdef LINUX      
202             wsprintf( temp, "%02i%02i%02i", tmt.tm_hour, tmt.tm_min, tmt.tm_sec );
203 #else
204             wsprintf( temp, "%02i%02i%02i", st.wHour, st.wMinute, st.wSecond );
205 #endif
206             str_copyzero( out, temp );
207             break;
208          case MACRO_LINE:
209             plex->num.vint = str_pos2line( _compile->cur->src, plex->pos, &pos );
210             break;
211          case MACRO_WINDOWS:
212 #ifdef WINDOWS
213             plex->num.vint = 1;
214 #else
215             plex->num.vint = 0;
216 #endif
217             break;
218          case MACRO_LINUX:
219 #ifdef LINUX
220             plex->num.vint = 1;
221 #else
222             plex->num.vint = 0;
223 #endif
224             break;
225       }
226    }
227    else
228    {
229       lexem_copy( plex, plexsrc );
230    }
231 //   printf("Macro=%s\n", lexem_getname( plex ));
232    return plex;
233 error:
234    if ( plex->type == LEXEM_NAME )
235       return plex;
236 
237    msg( MUndefmacro | MSG_LEXNAMEERR, plex );
238    return 0;
239 }
240