Patchwork [Ada] Portability improvement for constants related to serial ports

login
register
mail settings
Submitter Arnaud Charlet
Date Aug. 6, 2012, 8:35 a.m.
Message ID <20120806083556.GA28514@adacore.com>
Download mbox | patch
Permalink /patch/175298/
State New
Headers show

Comments

Arnaud Charlet - Aug. 6, 2012, 8:35 a.m.
This change improves the process that generates s-oscons.ads so that
the proper unisgned values for serial ports related constants are
generated.

Tested on x86_64-pc-linux-gnu, committed on trunk

2012-08-06  Thomas Quinot  <quinot@adacore.com>

	* s-oscons-tmplt.c, xoscons.adb: Per the Single UNIX Specification,
	types cc_t, speed_t, and tcflag_t defined in <termios.h> all are
	unsigned types. Add required special handling to have their correct
	unsigned values in s-oscons.ads.

Patch

Index: s-oscons-tmplt.c
===================================================================
--- s-oscons-tmplt.c	(revision 190158)
+++ s-oscons-tmplt.c	(working copy)
@@ -169,6 +169,9 @@ 
 #define CND(name,comment) \
   printf ("\n->CND:$%d:" #name ":$%d:" comment, __LINE__, ((int) _VAL (name)));
 
+#define CNU(name,comment) \
+  printf ("\n->CNU:$%d:" #name ":$%u:" comment, __LINE__, ((unsigned int) _VAL (name)));
+
 #define CNS(name,comment) \
   printf ("\n->CNS:$%d:" #name ":" name ":" comment, __LINE__);
 
@@ -185,6 +188,13 @@ 
   : : "i" (__LINE__), "i" ((int) name));
 /* Decimal constant in the range of type "int" */
 
+#define CNU(name, comment) \
+  asm volatile("\n->CNU:%0:" #name ":%1:" comment \
+  : : "i" (__LINE__), "i" ((int) name));
+/* Decimal constant in the range of type "unsigned int" (note, assembler
+ * always wants a signed int, we convert back in xoscons).
+ */
+
 #define CNS(name, comment) \
   asm volatile("\n->CNS:%0:" #name ":" name ":" comment \
   : : "i" (__LINE__));
@@ -250,9 +260,9 @@ 
 
 /*
 
-   -----------------------------
-   -- Platform identification --
-   -----------------------------
+   ---------------------------------
+   -- General platform parameters --
+   ---------------------------------
 
    type OS_Type is (Windows, VMS, Other_OS);
 */
@@ -273,6 +283,10 @@ 
 */
 #define Target_Name TARGET
 CST(Target_Name, "")
+
+#define sizeof_unsigned_int sizeof (unsigned int)
+CND(sizeof_unsigned_int, "Size of unsigned int")
+
 /*
 
    -------------------
@@ -630,210 +644,215 @@ 
 #endif
 CND(TCIFLUSH, "Flush input")
 
+#ifndef IXON
+# define IXON -1
+#endif
+CNU(IXON, "Output sw flow control")
+
 #ifndef CLOCAL
 # define CLOCAL -1
 #endif
-CND(CLOCAL, "Local")
+CNU(CLOCAL, "Local")
 
 #ifndef CRTSCTS
 # define CRTSCTS -1
 #endif
-CND(CRTSCTS, "Hardware flow control")
+CNU(CRTSCTS, "Output hw flow control")
 
 #ifndef CREAD
 # define CREAD -1
 #endif
-CND(CREAD, "Read")
+CNU(CREAD, "Read")
 
 #ifndef CS5
 # define CS5 -1
 #endif
-CND(CS5, "5 data bits")
+CNU(CS5, "5 data bits")
 
 #ifndef CS6
 # define CS6 -1
 #endif
-CND(CS6, "6 data bits")
+CNU(CS6, "6 data bits")
 
 #ifndef CS7
 # define CS7 -1
 #endif
-CND(CS7, "7 data bits")
+CNU(CS7, "7 data bits")
 
 #ifndef CS8
 # define CS8 -1
 #endif
-CND(CS8, "8 data bits")
+CNU(CS8, "8 data bits")
 
 #ifndef CSTOPB
 # define CSTOPB -1
 #endif
-CND(CSTOPB, "2 stop bits")
+CNU(CSTOPB, "2 stop bits")
 
 #ifndef PARENB
 # define PARENB -1
 #endif
-CND(PARENB, "Parity enable")
+CNU(PARENB, "Parity enable")
 
 #ifndef PARODD
 # define PARODD -1
 #endif
-CND(PARODD, "Parity odd")
+CNU(PARODD, "Parity odd")
 
 #ifndef B0
 # define B0 -1
 #endif
-CND(B0, "0 bps")
+CNU(B0, "0 bps")
 
 #ifndef B50
 # define B50 -1
 #endif
-CND(B50, "50 bps")
+CNU(B50, "50 bps")
 
 #ifndef B75
 # define B75 -1
 #endif
-CND(B75, "75 bps")
+CNU(B75, "75 bps")
 
 #ifndef B110
 # define B110 -1
 #endif
-CND(B110, "110 bps")
+CNU(B110, "110 bps")
 
 #ifndef B134
 # define B134 -1
 #endif
-CND(B134, "134 bps")
+CNU(B134, "134 bps")
 
 #ifndef B150
 # define B150 -1
 #endif
-CND(B150, "150 bps")
+CNU(B150, "150 bps")
 
 #ifndef B200
 # define B200 -1
 #endif
-CND(B200, "200 bps")
+CNU(B200, "200 bps")
 
 #ifndef B300
 # define B300 -1
 #endif
-CND(B300, "300 bps")
+CNU(B300, "300 bps")
 
 #ifndef B600
 # define B600 -1
 #endif
-CND(B600, "600 bps")
+CNU(B600, "600 bps")
 
 #ifndef B1200
 # define B1200 -1
 #endif
-CND(B1200, "1200 bps")
+CNU(B1200, "1200 bps")
 
 #ifndef B1800
 # define B1800 -1
 #endif
-CND(B1800, "1800 bps")
+CNU(B1800, "1800 bps")
 
 #ifndef B2400
 # define B2400 -1
 #endif
-CND(B2400, "2400 bps")
+CNU(B2400, "2400 bps")
 
 #ifndef B4800
 # define B4800 -1
 #endif
-CND(B4800, "4800 bps")
+CNU(B4800, "4800 bps")
 
 #ifndef B9600
 # define B9600 -1
 #endif
-CND(B9600, "9600 bps")
+CNU(B9600, "9600 bps")
 
 #ifndef B19200
 # define B19200 -1
 #endif
-CND(B19200, "19200 bps")
+CNU(B19200, "19200 bps")
 
 #ifndef B38400
 # define B38400 -1
 #endif
-CND(B38400, "38400 bps")
+CNU(B38400, "38400 bps")
 
 #ifndef B57600
 # define B57600 -1
 #endif
-CND(B57600, "57600 bps")
+CNU(B57600, "57600 bps")
 
 #ifndef B115200
 # define B115200 -1
 #endif
-CND(B115200, "115200 bps")
+CNU(B115200, "115200 bps")
 
 #ifndef B230400
 # define B230400 -1
 #endif
-CND(B230400, "230400 bps")
+CNU(B230400, "230400 bps")
 
 #ifndef B460800
 # define B460800 -1
 #endif
-CND(B460800, "460800 bps")
+CNU(B460800, "460800 bps")
 
 #ifndef B500000
 # define B500000 -1
 #endif
-CND(B500000, "500000 bps")
+CNU(B500000, "500000 bps")
 
 #ifndef B576000
 # define B576000 -1
 #endif
-CND(B576000, "576000 bps")
+CNU(B576000, "576000 bps")
 
 #ifndef B921600
 # define B921600 -1
 #endif
-CND(B921600, "921600 bps")
+CNU(B921600, "921600 bps")
 
 #ifndef B1000000
 # define B1000000 -1
 #endif
-CND(B1000000, "1000000 bps")
+CNU(B1000000, "1000000 bps")
 
 #ifndef B1152000
 # define B1152000 -1
 #endif
-CND(B1152000, "1152000 bps")
+CNU(B1152000, "1152000 bps")
 
 #ifndef B1500000
 # define B1500000 -1
 #endif
-CND(B1500000, "1500000 bps")
+CNU(B1500000, "1500000 bps")
 
 #ifndef B2000000
 # define B2000000 -1
 #endif
-CND(B2000000, "2000000 bps")
+CNU(B2000000, "2000000 bps")
 
 #ifndef B2500000
 # define B2500000 -1
 #endif
-CND(B2500000, "2500000 bps")
+CNU(B2500000, "2500000 bps")
 
 #ifndef B3000000
 # define B3000000 -1
 #endif
-CND(B3000000, "3000000 bps")
+CNU(B3000000, "3000000 bps")
 
 #ifndef B3500000
 # define B3500000 -1
 #endif
-CND(B3500000, "3500000 bps")
+CNU(B3500000, "3500000 bps")
 
 #ifndef B4000000
 # define B4000000 -1
 #endif
-CND(B4000000, "4000000 bps")
+CNU(B4000000, "4000000 bps")
 
 /*
 
Index: xoscons.adb
===================================================================
--- xoscons.adb	(revision 190155)
+++ xoscons.adb	(working copy)
@@ -6,7 +6,7 @@ 
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---          Copyright (C) 2008-2009, Free Software Foundation, Inc.         --
+--          Copyright (C) 2008-2012, Free Software Foundation, Inc.         --
 --                                                                          --
 -- GNAT is free software;  you can  redistribute it  and/or modify it under --
 -- terms of the  GNU General Public License as published  by the Free Soft- --
@@ -73,13 +73,18 @@ 
 
    type Asm_Info_Kind is
      (CND,     --  Named number (decimal)
+      CNU,     --  Named number (decimal, unsigned)
       CNS,     --  Named number (freeform text)
       C,       --  Constant object
       TXT);    --  Literal text
    --  Recognized markers found in assembly file. These markers are produced by
    --  the same-named macros from the C template.
 
+   subtype Asm_Int_Kind is Asm_Info_Kind range CND .. CNU;
+   --  Asm_Info_Kind values with int values in input
+
    subtype Named_Number is Asm_Info_Kind range CND .. CNS;
+   --  Asm_Info_Kind values with named numbers in output
 
    type Asm_Info (Kind : Asm_Info_Kind := TXT) is record
       Line_Number   : Integer;
@@ -98,7 +103,7 @@ 
       --  Value for CNS / C constant
 
       Int_Value     : Int_Value_Type;
-      --  Value for CND constant
+      --  Value for CND / CNU constant
 
       Comment       : String_Access;
       --  Additional descriptive comment for constant, or free-form text (TXT)
@@ -116,6 +121,9 @@ 
    Max_Constant_Type_Len  : Natural := 0;
    --  Lengths of longest name and longest value
 
+   Size_Of_Unsigned_Int : Integer := 0;
+   --  Size of unsigned int on target
+
    type Language is (Lang_Ada, Lang_C);
 
    procedure Output_Info
@@ -195,11 +203,12 @@ 
                               - Info.Constant_Name'Length));
          end case;
 
-         if Info.Kind = CND then
+         if Info.Kind in Asm_Int_Kind then
             if not Info.Int_Value.Positive then
                Put ("-");
             end if;
             Put (Trim (Info.Int_Value.Abs_Value'Img, Side => Left));
+
          else
             declare
                Is_String : constant Boolean :=
@@ -246,7 +255,7 @@ 
       procedure Find_Colon (Index : in out Integer);
       --  Increment Index until the next colon in Line
 
-      function Parse_Int (S : String) return Int_Value_Type;
+      function Parse_Int (S : String; K : Asm_Int_Kind) return Int_Value_Type;
       --  Parse a decimal number, preceded by an optional '$' or '#' character,
       --  and return its value.
 
@@ -275,9 +284,12 @@ 
       -- Parse_Int --
       ---------------
 
-      function Parse_Int (S : String) return Int_Value_Type is
+      function Parse_Int
+        (S : String;
+         K : Asm_Int_Kind) return Int_Value_Type
+      is
          First    : Integer := S'First;
-         Positive : Boolean;
+         Result   : Int_Value_Type;
       begin
          --  On some platforms, immediate integer values are prefixed with
          --  a $ or # character in assembly output.
@@ -287,15 +299,26 @@ 
          end if;
 
          if S (First) = '-' then
-            Positive := False;
+            Result.Positive := False;
             First    := First + 1;
          else
-            Positive := True;
+            Result.Positive := True;
          end if;
 
-         return (Positive  => Positive,
-                 Abs_Value => Long_Unsigned'Value (S (First .. S'Last)));
+         Result.Abs_Value := Long_Unsigned'Value (S (First .. S'Last));
 
+         if not Result.Positive and then K = CNU then
+            --  Negative value, but unsigned expected: take 2's complement
+            --  reciprocical value.
+
+            Result.Abs_Value := ((not Result.Abs_Value) + 1)
+                                  and
+                                (Shift_Left (1, Size_Of_Unsigned_Int) - 1);
+            Result.Positive  := True;
+         end if;
+
+         return Result;
+
       exception
          when E : others =>
             Put_Line (Standard_Error, "can't parse decimal value: " & S);
@@ -315,10 +338,10 @@ 
          Find_Colon (Index2);
 
          Info.Line_Number :=
-           Integer (Parse_Int (Line (Index1 .. Index2 - 1)).Abs_Value);
+           Integer (Parse_Int (Line (Index1 .. Index2 - 1), CNU).Abs_Value);
 
          case Info.Kind is
-            when CND | CNS | C =>
+            when CND | CNU | CNS | C =>
                Index1 := Index2 + 1;
                Find_Colon (Index2);
 
@@ -340,15 +363,24 @@ 
                   Find_Colon (Index2);
                end if;
 
-               if Info.Kind = CND then
-                  Info.Int_Value := Parse_Int (Line (Index1 .. Index2 - 1));
-                  Info.Value_Len := Index2 - Index1 - 1;
+               if Info.Kind = CND or else Info.Kind = CNU then
+                  Info.Int_Value :=
+                    Parse_Int (Line (Index1 .. Index2 - 1), Info.Kind);
+                  Info.Value_Len := Info.Int_Value.Abs_Value'Img'Length - 1;
+                  if not Info.Int_Value.Positive then
+                     Info.Value_Len := Info.Value_Len + 1;
+                  end if;
 
                else
                   Info.Text_Value := Field_Alloc;
                   Info.Value_Len  := Info.Text_Value'Length;
                end if;
 
+               if Info.Constant_Name.all = "sizeof_unsigned_int" then
+                  Size_Of_Unsigned_Int :=
+                    8 * Integer (Info.Int_Value.Abs_Value);
+               end if;
+
             when others =>
                null;
          end case;