common.h 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392
  1. /*
  2. * Copyright 2001-2006 Adrian Thurston <thurston@complang.org>
  3. */
  4. /* This file is part of Ragel.
  5. *
  6. * Ragel is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * Ragel is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with Ragel; if not, write to the Free Software
  18. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  19. */
  20. #ifndef _COMMON_H
  21. #define _COMMON_H
  22. #include <fstream>
  23. #include <climits>
  24. #include "dlist.h"
  25. /* Location in an input file. */
  26. struct InputLoc
  27. {
  28. const char *fileName;
  29. long line;
  30. long col;
  31. };
  32. typedef unsigned long long Size;
  33. struct Key
  34. {
  35. private:
  36. long key;
  37. public:
  38. friend inline Key operator+(const Key key1, const Key key2);
  39. friend inline Key operator-(const Key key1, const Key key2);
  40. friend inline Key operator/(const Key key1, const Key key2);
  41. friend inline long operator&(const Key key1, const Key key2);
  42. friend inline bool operator<( const Key key1, const Key key2 );
  43. friend inline bool operator<=( const Key key1, const Key key2 );
  44. friend inline bool operator>( const Key key1, const Key key2 );
  45. friend inline bool operator>=( const Key key1, const Key key2 );
  46. friend inline bool operator==( const Key key1, const Key key2 );
  47. friend inline bool operator!=( const Key key1, const Key key2 );
  48. friend struct KeyOps;
  49. Key( ) {}
  50. Key( const Key &key ) : key(key.key) {}
  51. Key( long key ) : key(key) {}
  52. /* Returns the value used to represent the key. This value must be
  53. * interpreted based on signedness. */
  54. long getVal() const { return key; };
  55. /* Returns the key casted to a long long. This form of the key does not
  56. * require any signedness interpretation. */
  57. long long getLongLong() const;
  58. /* Returns the distance from the key value to the maximum value that the
  59. * key implementation can hold. */
  60. Size availableSpace() const;
  61. bool isUpper() const { return ( 'A' <= key && key <= 'Z' ); }
  62. bool isLower() const { return ( 'a' <= key && key <= 'z' ); }
  63. bool isPrintable() const
  64. {
  65. return ( 7 <= key && key <= 13 ) || ( 32 <= key && key < 127 );
  66. }
  67. Key toUpper() const
  68. { return Key( 'A' + ( key - 'a' ) ); }
  69. Key toLower() const
  70. { return Key( 'a' + ( key - 'A' ) ); }
  71. void operator+=( const Key other )
  72. {
  73. /* FIXME: must be made aware of isSigned. */
  74. key += other.key;
  75. }
  76. void operator-=( const Key other )
  77. {
  78. /* FIXME: must be made aware of isSigned. */
  79. key -= other.key;
  80. }
  81. void operator|=( const Key other )
  82. {
  83. /* FIXME: must be made aware of isSigned. */
  84. key |= other.key;
  85. }
  86. /* Decrement. Needed only for ranges. */
  87. inline void decrement();
  88. inline void increment();
  89. };
  90. struct HostType
  91. {
  92. const char *data1;
  93. const char *data2;
  94. const char *internalName;
  95. bool isSigned;
  96. bool isOrd;
  97. bool isChar;
  98. long long sMinVal;
  99. long long sMaxVal;
  100. unsigned long long uMinVal;
  101. unsigned long long uMaxVal;
  102. unsigned int size;
  103. };
  104. struct HostLang
  105. {
  106. /* Target language. */
  107. enum Lang
  108. {
  109. C, D, D2, Go, Java, Ruby, CSharp, OCaml
  110. };
  111. Lang lang;
  112. HostType *hostTypes;
  113. int numHostTypes;
  114. HostType *defaultAlphType;
  115. bool explicitUnsigned;
  116. };
  117. extern HostLang *hostLang;
  118. extern HostLang hostLangC;
  119. extern HostLang hostLangD;
  120. extern HostLang hostLangD2;
  121. extern HostLang hostLangGo;
  122. extern HostLang hostLangJava;
  123. extern HostLang hostLangRuby;
  124. extern HostLang hostLangCSharp;
  125. extern HostLang hostLangOCaml;
  126. HostType *findAlphType( const char *s1 );
  127. HostType *findAlphType( const char *s1, const char *s2 );
  128. HostType *findAlphTypeInternal( const char *s1 );
  129. /* An abstraction of the key operators that manages key operations such as
  130. * comparison and increment according the signedness of the key. */
  131. struct KeyOps
  132. {
  133. /* Default to signed alphabet. */
  134. KeyOps() :
  135. isSigned(true),
  136. alphType(0)
  137. {}
  138. /* Default to signed alphabet. */
  139. KeyOps( bool isSigned )
  140. :isSigned(isSigned) {}
  141. bool isSigned;
  142. Key minKey, maxKey;
  143. HostType *alphType;
  144. void setAlphType( HostType *alphType )
  145. {
  146. this->alphType = alphType;
  147. isSigned = alphType->isSigned;
  148. if ( isSigned ) {
  149. minKey = (long) alphType->sMinVal;
  150. maxKey = (long) alphType->sMaxVal;
  151. }
  152. else {
  153. minKey = (long) (unsigned long) alphType->uMinVal;
  154. maxKey = (long) (unsigned long) alphType->uMaxVal;
  155. }
  156. }
  157. /* Compute the distance between two keys. */
  158. Size span( Key key1, Key key2 )
  159. {
  160. return isSigned ?
  161. (unsigned long long)(
  162. (long long)key2.key -
  163. (long long)key1.key + 1) :
  164. (unsigned long long)(
  165. (unsigned long)key2.key) -
  166. (unsigned long long)((unsigned long)key1.key) + 1;
  167. }
  168. Size alphSize()
  169. { return span( minKey, maxKey ); }
  170. HostType *typeSubsumes( long long maxVal )
  171. {
  172. HostType *hostTypes = hostLang->hostTypes;
  173. for ( int i = 0; i < hostLang->numHostTypes; i++ ) {
  174. long long typeMaxVal = hostTypes[i].isSigned ? hostTypes[i].sMaxVal : hostTypes[i].uMaxVal;
  175. if ( maxVal <= typeMaxVal )
  176. return &hostLang->hostTypes[i];
  177. }
  178. return 0;
  179. }
  180. HostType *typeSubsumes( bool isSigned, long long maxVal )
  181. {
  182. HostType *hostTypes = hostLang->hostTypes;
  183. for ( int i = 0; i < hostLang->numHostTypes; i++ ) {
  184. long long typeMaxVal = hostTypes[i].isSigned ? hostTypes[i].sMaxVal : hostTypes[i].uMaxVal;
  185. if ( ( ( isSigned && hostTypes[i].isSigned ) || !isSigned ) &&
  186. maxVal <= typeMaxVal )
  187. return hostLang->hostTypes + i;
  188. }
  189. return 0;
  190. }
  191. };
  192. extern KeyOps *keyOps;
  193. inline bool operator<( const Key key1, const Key key2 )
  194. {
  195. return keyOps->isSigned ? key1.key < key2.key :
  196. (unsigned long)key1.key < (unsigned long)key2.key;
  197. }
  198. inline bool operator<=( const Key key1, const Key key2 )
  199. {
  200. return keyOps->isSigned ? key1.key <= key2.key :
  201. (unsigned long)key1.key <= (unsigned long)key2.key;
  202. }
  203. inline bool operator>( const Key key1, const Key key2 )
  204. {
  205. return keyOps->isSigned ? key1.key > key2.key :
  206. (unsigned long)key1.key > (unsigned long)key2.key;
  207. }
  208. inline bool operator>=( const Key key1, const Key key2 )
  209. {
  210. return keyOps->isSigned ? key1.key >= key2.key :
  211. (unsigned long)key1.key >= (unsigned long)key2.key;
  212. }
  213. inline bool operator==( const Key key1, const Key key2 )
  214. {
  215. return key1.key == key2.key;
  216. }
  217. inline bool operator!=( const Key key1, const Key key2 )
  218. {
  219. return key1.key != key2.key;
  220. }
  221. /* Decrement. Needed only for ranges. */
  222. inline void Key::decrement()
  223. {
  224. key = keyOps->isSigned ? key - 1 : ((unsigned long)key)-1;
  225. }
  226. /* Increment. Needed only for ranges. */
  227. inline void Key::increment()
  228. {
  229. key = keyOps->isSigned ? key+1 : ((unsigned long)key)+1;
  230. }
  231. inline long long Key::getLongLong() const
  232. {
  233. return keyOps->isSigned ? (long long)key : (long long)(unsigned long)key;
  234. }
  235. inline Size Key::availableSpace() const
  236. {
  237. if ( keyOps->isSigned )
  238. return (long long)LONG_MAX - (long long)key;
  239. else
  240. return (unsigned long long)ULONG_MAX - (unsigned long long)(unsigned long)key;
  241. }
  242. inline Key operator+(const Key key1, const Key key2)
  243. {
  244. /* FIXME: must be made aware of isSigned. */
  245. return Key( key1.key + key2.key );
  246. }
  247. inline Key operator-(const Key key1, const Key key2)
  248. {
  249. /* FIXME: must be made aware of isSigned. */
  250. return Key( key1.key - key2.key );
  251. }
  252. inline long operator&(const Key key1, const Key key2)
  253. {
  254. /* FIXME: must be made aware of isSigned. */
  255. return key1.key & key2.key;
  256. }
  257. inline Key operator/(const Key key1, const Key key2)
  258. {
  259. /* FIXME: must be made aware of isSigned. */
  260. return key1.key / key2.key;
  261. }
  262. /* Filter on the output stream that keeps track of the number of lines
  263. * output. */
  264. class output_filter : public std::filebuf
  265. {
  266. public:
  267. output_filter( const char *fileName ) : fileName(fileName), line(1) { }
  268. virtual int sync();
  269. virtual std::streamsize xsputn(const char* s, std::streamsize n);
  270. const char *fileName;
  271. int line;
  272. };
  273. class cfilebuf : public std::streambuf
  274. {
  275. public:
  276. cfilebuf( char *fileName, FILE* file ) : fileName(fileName), file(file) { }
  277. char *fileName;
  278. FILE *file;
  279. int sync()
  280. {
  281. fflush( file );
  282. return 0;
  283. }
  284. int overflow( int c )
  285. {
  286. if ( c != EOF )
  287. fputc( c, file );
  288. return 0;
  289. }
  290. std::streamsize xsputn( const char* s, std::streamsize n )
  291. {
  292. std::streamsize written = fwrite( s, 1, n, file );
  293. return written;
  294. }
  295. };
  296. class costream : public std::ostream
  297. {
  298. public:
  299. costream( cfilebuf *b ) :
  300. std::ostream(b), b(b) {}
  301. ~costream()
  302. { delete b; }
  303. void fclose()
  304. { ::fclose( b->file ); }
  305. cfilebuf *b;
  306. };
  307. const char *findFileExtension( const char *stemFile );
  308. const char *fileNameFromStem( const char *stemFile, const char *suffix );
  309. struct Export
  310. {
  311. Export( const char *name, Key key )
  312. : name(name), key(key) {}
  313. const char *name;
  314. Key key;
  315. Export *prev, *next;
  316. };
  317. typedef DList<Export> ExportList;
  318. struct exit_object { };
  319. extern exit_object endp;
  320. void operator<<( std::ostream &out, exit_object & );
  321. #endif