linux.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. /* contrib/arm-neon/linux.c
  2. *
  3. * Copyright (c) 2014 Glenn Randers-Pehrson
  4. * Written by John Bowler, 2014.
  5. * Last changed in libpng 1.6.10 [March 6, 2014]
  6. *
  7. * This code is released under the libpng license.
  8. * For conditions of distribution and use, see the disclaimer
  9. * and license in png.h
  10. *
  11. * SEE contrib/arm-neon/README before reporting bugs
  12. *
  13. * STATUS: SUPPORTED
  14. * BUG REPORTS: [email protected]
  15. *
  16. * png_have_neon implemented for Linux by reading the widely available
  17. * pseudo-file /proc/cpuinfo.
  18. *
  19. * This code is strict ANSI-C and is probably moderately portable, it does
  20. * however use <stdio.h> and assumes that /proc/cpuinfo is never localized.
  21. */
  22. #include <stdio.h>
  23. static int
  24. png_have_neon(png_structp png_ptr)
  25. {
  26. FILE *f = fopen("/proc/cpuinfo", "rb");
  27. if (f != NULL)
  28. {
  29. /* This is a simple state machine which reads the input byte-by-byte until
  30. * it gets a match on the 'neon' feature or reaches the end of the stream.
  31. */
  32. static const char ch_feature[] = { 70, 69, 65, 84, 85, 82, 69, 83 };
  33. static const char ch_neon[] = { 78, 69, 79, 78 };
  34. enum
  35. {
  36. StartLine, Feature, Colon, StartTag, Neon, HaveNeon, SkipTag, SkipLine
  37. } state;
  38. int counter;
  39. for (state=StartLine, counter=0;;)
  40. {
  41. int ch = fgetc(f);
  42. if (ch == EOF)
  43. {
  44. /* EOF means error or end-of-file, return false; neon at EOF is
  45. * assumed to be a mistake.
  46. */
  47. fclose(f);
  48. return 0;
  49. }
  50. switch (state)
  51. {
  52. case StartLine:
  53. /* Match spaces at the start of line */
  54. if (ch <= 32) /* skip control characters and space */
  55. break;
  56. counter=0;
  57. state = Feature;
  58. /* FALL THROUGH */
  59. case Feature:
  60. /* Match 'FEATURE', ASCII case insensitive. */
  61. if ((ch & ~0x20) == ch_feature[counter])
  62. {
  63. if (++counter == (sizeof ch_feature))
  64. state = Colon;
  65. break;
  66. }
  67. /* did not match 'feature' */
  68. state = SkipLine;
  69. /* FALL THROUGH */
  70. case SkipLine:
  71. skipLine:
  72. /* Skip everything until we see linefeed or carriage return */
  73. if (ch != 10 && ch != 13)
  74. break;
  75. state = StartLine;
  76. break;
  77. case Colon:
  78. /* Match any number of space or tab followed by ':' */
  79. if (ch == 32 || ch == 9)
  80. break;
  81. if (ch == 58) /* i.e. ':' */
  82. {
  83. state = StartTag;
  84. break;
  85. }
  86. /* Either a bad line format or a 'feature' prefix followed by
  87. * other characters.
  88. */
  89. state = SkipLine;
  90. goto skipLine;
  91. case StartTag:
  92. /* Skip space characters before a tag */
  93. if (ch == 32 || ch == 9)
  94. break;
  95. state = Neon;
  96. counter = 0;
  97. /* FALL THROUGH */
  98. case Neon:
  99. /* Look for 'neon' tag */
  100. if ((ch & ~0x20) == ch_neon[counter])
  101. {
  102. if (++counter == (sizeof ch_neon))
  103. state = HaveNeon;
  104. break;
  105. }
  106. state = SkipTag;
  107. /* FALL THROUGH */
  108. case SkipTag:
  109. /* Skip non-space characters */
  110. if (ch == 10 || ch == 13)
  111. state = StartLine;
  112. else if (ch == 32 || ch == 9)
  113. state = StartTag;
  114. break;
  115. case HaveNeon:
  116. /* Have seen a 'neon' prefix, but there must be a space or new
  117. * line character to terminate it.
  118. */
  119. if (ch == 10 || ch == 13 || ch == 32 || ch == 9)
  120. {
  121. fclose(f);
  122. return 1;
  123. }
  124. state = SkipTag;
  125. break;
  126. default:
  127. png_error(png_ptr, "png_have_neon: internal error (bug)");
  128. }
  129. }
  130. }
  131. else
  132. png_warning(png_ptr, "/proc/cpuinfo open failed");
  133. return 0;
  134. }